diff --git a/.dockerignore b/.dockerignore new file mode 100644 index 000000000..049db8fff --- /dev/null +++ b/.dockerignore @@ -0,0 +1,55 @@ + +# Dependencies +node_modules/ +**/node_modules/ +npm-debug.log* +yarn-debug.log* +yarn-error.log* + +# Build outputs +**/dist/ +**/build/ + +# Environment files +.env +.env.local +.env.development.local +.env.test.local +.env.production.local + +# OS files +.DS_Store +Thumbs.db + +# Git +.git +.gitignore + +# IDE +.vscode/ +.idea/ +*.swp +*.swo + +# Logs +logs/ +*.log + +# Runtime data +pids/ +*.pid +*.seed +*.pid.lock + +# Coverage directory used by tools like istanbul +coverage/ + +# Docker +Dockerfile* +docker-compose* +.dockerignore + +# Tests +**/tests/ +**/*.test.* +**/*.spec.* \ No newline at end of file diff --git a/.gitignore b/.gitignore index f25fbf61a..233912173 100644 --- a/.gitignore +++ b/.gitignore @@ -62,6 +62,7 @@ yarn-error.log* # env files (can opt-in for committing if needed) .env* +!.env.example # example env files !.env.example @@ -75,4 +76,5 @@ next-env.d.ts *.rdb -packages/useautumn + +shared/drizzle diff --git a/commands.sh b/commands.sh new file mode 100644 index 000000000..23a7329de --- /dev/null +++ b/commands.sh @@ -0,0 +1,19 @@ +RESTART EVERYTHING +docker system prune -a --volumes + +# DB +docker compose -f docker-compose.db.yml up --build + +# Create DB tables +pnpm + +# docker volume rm main-repo_shared-node-modules main-repo_root-node-modules main-repo_vite-node-modules +# Dev +docker compose -f docker-compose.dev.yml down +docker volume rm autumn-oss_shared-node-modules autumn-oss_root-node-modules autumn-oss_vite-node-modules +docker compose -f docker-compose.dev.yml build --no-cache +docker compose -f docker-compose.dev.yml up --build + +# Prod +docker compose -f docker-compose.prod.yml up --build +--- \ No newline at end of file diff --git a/docker-compose.dev.yml b/docker-compose.dev.yml new file mode 100644 index 000000000..82d23189c --- /dev/null +++ b/docker-compose.dev.yml @@ -0,0 +1,97 @@ +services: + valkey: + image: docker.io/bitnami/valkey:8.0 + environment: + - ALLOW_EMPTY_PASSWORD=yes + - VALKEY_DISABLE_COMMANDS=FLUSHDB,FLUSHALL + volumes: + - valkey-data:/bitnami/valkey/data + healthcheck: + test: ['CMD', 'redis-cli', '-h', 'localhost', '-p', '6379', 'ping'] + interval: 10s + timeout: 5s + retries: 5 + # ports: + # - "6379:6379" + restart: unless-stopped + + shared: + build: + dockerfile: docker/dev.dockerfile + context: . + target: shared + volumes: + - ./shared:/app/shared + - shared-dist:/app/shared/dist + - shared-node-modules:/app/shared/node_modules + - root-node-modules:/app/node_modules + environment: + - NODE_ENV=development + restart: unless-stopped + + # Vite frontend + vite: + build: + dockerfile: docker/dev.dockerfile + context: . + target: vite + ports: + - "3000:3000" + volumes: + - ./vite:/app/vite + - shared-dist:/app/shared/dist + - vite-node-modules:/app/vite/node_modules + - root-node-modules:/app/node_modules + environment: + - NODE_ENV=development + depends_on: + - shared + restart: unless-stopped + + # Main Express server + server: + build: + dockerfile: docker/dev.dockerfile + context: . + target: server + ports: + - "8080:8080" + volumes: + - ./server:/app/server + - shared-dist:/app/shared/dist + - root-node-modules:/app/node_modules + environment: + - NODE_ENV=development + - REDIS_URL=redis://valkey:6379 + depends_on: + - shared + restart: unless-stopped + + # BullMQ Workers + workers: + build: + dockerfile: docker/dev.dockerfile + context: . + target: workers + volumes: + # Mount server source for hot reload (workers use server code) + - ./server:/app/server + - shared-dist:/app/shared/dist + - root-node-modules:/app/node_modules + environment: + - NODE_ENV=development + - REDIS_URL=redis://valkey:6379 + depends_on: + - shared + restart: unless-stopped + +volumes: + # Shared package dist output + shared-dist: + valkey-data: + + # Node modules volumes to avoid host/container conflicts + shared-node-modules: + server-node-modules: + vite-node-modules: + root-node-modules: diff --git a/docker-compose.prod.yml b/docker-compose.prod.yml new file mode 100644 index 000000000..fe373de3f --- /dev/null +++ b/docker-compose.prod.yml @@ -0,0 +1,46 @@ +version: "3.8" +services: + valkey: + image: docker.io/bitnami/valkey:8.0 + environment: + - ALLOW_EMPTY_PASSWORD=yes + - VALKEY_DISABLE_COMMANDS=FLUSHDB,FLUSHALL + volumes: + - valkey-data:/bitnami/valkey/data + healthcheck: + test: ['CMD', 'redis-cli', '-h', 'localhost', '-p', '6379', 'ping'] + interval: 10s + timeout: 5s + retries: 5 + ports: + - "6379:6379" + restart: unless-stopped + + vite: + build: + context: . + dockerfile: docker/prod.dockerfile + target: vite-prod + ports: + - "3000:3000" + restart: always + + server: + environment: + - REDIS_URL=redis://valkey:6379 + build: + context: . + dockerfile: docker/prod.dockerfile + target: server-prod + ports: + - "8080:8080" + restart: always + + workers: + environment: + - REDIS_URL=redis://valkey:6379 + build: + context: . + dockerfile: docker/prod.dockerfile + target: workers-prod + restart: always \ No newline at end of file diff --git a/docker/dev.dockerfile b/docker/dev.dockerfile new file mode 100644 index 000000000..a022fdf97 --- /dev/null +++ b/docker/dev.dockerfile @@ -0,0 +1,43 @@ +# Multi-stage Dockerfile for Autumn development +FROM node:18-alpine AS base + +WORKDIR /app + +RUN npm install -g pnpm + +COPY package*.json ./ +COPY pnpm-workspace.yaml ./ +COPY pnpm-lock.yaml ./ +COPY shared/package*.json ./shared/ +COPY server/package*.json ./server/ +COPY vite/package*.json ./vite/ + +RUN pnpm install +RUN npm install -g nodemon tsx + +# Stage 2: /shared +FROM base AS shared +COPY shared/ ./shared/ +WORKDIR /app/shared +RUN pnpm run build +CMD ["pnpm", "run", "dev"] + +# Stage 3: /vite +FROM base AS vite +WORKDIR /app/vite +COPY vite/ ./ +EXPOSE 3000 +CMD ["pnpm", "run", "dev"] + +# Stage 4: /server +FROM base AS server +WORKDIR /app/server +COPY server/ ./ +EXPOSE 8080 +CMD ["pnpm", "run", "dev"] + +# Stage 5: Workers +FROM base AS workers +WORKDIR /app/server +COPY server/ ./ +CMD ["pnpm", "run", "workers"] \ No newline at end of file diff --git a/docker/docker-compose.db.yml b/docker/docker-compose.db.yml new file mode 100644 index 000000000..f6fe29b9e --- /dev/null +++ b/docker/docker-compose.db.yml @@ -0,0 +1,42 @@ +version: '3.8' + +services: + # Redis for caching and BullMQ + valkey: + image: docker.io/bitnami/valkey:8.0 + environment: + - ALLOW_EMPTY_PASSWORD=yes + - VALKEY_DISABLE_COMMANDS=FLUSHDB,FLUSHALL + volumes: + - valkey-data:/bitnami/valkey/data + healthcheck: + test: ['CMD', 'redis-cli', '-h', 'localhost', '-p', '6379', 'ping'] + interval: 10s + timeout: 5s + retries: 5 + + # PostgreSQL database + postgres: + image: postgres:15-alpine + container_name: autumn-postgres + ports: + - "5432:5432" + environment: + POSTGRES_DB: autumn + POSTGRES_USER: postgres + POSTGRES_PASSWORD: autumn_dev_password + volumes: + - postgres-data:/var/lib/postgresql/data + restart: unless-stopped + healthcheck: + test: ["CMD-SHELL", "pg_isready -U postgres"] + interval: 10s + timeout: 5s + retries: 5 + +volumes: + valkey-data: + postgres-data: + +networks: + autumn-network: \ No newline at end of file diff --git a/docker/prod.dockerfile b/docker/prod.dockerfile new file mode 100644 index 000000000..e585b2d01 --- /dev/null +++ b/docker/prod.dockerfile @@ -0,0 +1,60 @@ +# ---- Base dependencies ---- +FROM node:18-alpine AS base +WORKDIR /app +RUN npm install -g pnpm serve typescript tsc tsc-alias tsx + +COPY package*.json pnpm-workspace.yaml pnpm-lock.yaml ./ +COPY shared/package*.json ./shared/ +COPY server/package*.json ./server/ +COPY vite/package*.json ./vite/ + +RUN pnpm install + + +# # ---- Build shared ---- +# FROM base AS shared-build +# COPY shared/ ./shared/ +# RUN pnpm -F shared build + +# # ---- Build frontend (vite) ---- +FROM base AS vite-build +COPY . . +WORKDIR /app +RUN pnpm run vite:build + +# ---- Build backend (server) ---- +FROM base AS server-build +COPY . . +WORKDIR /app +RUN pnpm run server:build + +# ---- Production frontend image ---- +FROM vite-build AS vite-prod +EXPOSE 3000 +WORKDIR /app +CMD ["pnpm", "run", "vite:start"] + +FROM server-build AS server-prod +EXPOSE 8080 +WORKDIR /app +CMD ["pnpm", "run", "server:start"] + +FROM server-build AS workers-prod +EXPOSE 8080 +WORKDIR /app +CMD ["pnpm", "run", "server:workers"] + +# # ---- Production backend image ---- +# FROM node:18-alpine AS server-prod +# COPY --from=server-build /app/server/dist ./dist +# COPY --from=server-build /app/server/package.json ./ +# COPY --from=server-build /app/server/node_modules ./node_modules +# EXPOSE 8080 +# CMD ["pnpm", "run", "server:start"] + +# # ---- Production workers image ---- +# FROM node:18-alpine AS workers-prod +# COPY --from=server-build /app/server/dist ./dist +# COPY --from=server-build /app/server/package.json ./ +# COPY --from=server-build /app/server/node_modules ./node_modules +# CMD ["pnpm", "run", "server:workers"] \ No newline at end of file diff --git a/notes.txt b/notes.txt deleted file mode 100644 index 6bf5bceaf..000000000 --- a/notes.txt +++ /dev/null @@ -1,5 +0,0 @@ -https://docs.fontawesome.com/web/use-with/react - -https://docs.fontawesome.com/web/setup/packages#1-configure-access - -In the frontend (vite) run `npm link @useautumn/react` diff --git a/package.json b/package.json index 5cb9145af..3016f21cc 100644 --- a/package.json +++ b/package.json @@ -2,25 +2,32 @@ "name": "autumn", "private": true, "workspaces": [ - "frontend", "server", "shared", - "tests", "vite" ], "type": "module", "scripts": { - "frontend:build": "npm run build -w shared && npm run build -w frontend", - "frontend:start": "npm run start -w frontend", - "vite:build": "npm run build -w shared && npm run build -w vite", - "vite:start": "npm run start -w vite", - "server:build": "npm run build -w shared && npm run prod:build -w server", - "server:start": "npm run prod:start -w server", + "vite:build": "pnpm -F shared build && pnpm -F vite build", + "vite:start": "pnpm -F vite start", + "server:build": "pnpm -F shared build && pnpm -F server prod:build", + "server:start": "pnpm -F server prod:start", "server:cron": "npm run cron:start -w server", "server:workers": "npm run workers:start -w server", - "dev": "concurrently \"cd server && npm run dev\" \"cd vite && npm run dev\" \"redis-server\"" + "dev": "concurrently \"cd server && npm run dev\" \"cd vite && npm run dev\" \"redis-server\"", + "setup": "node setup.js", + "db:push": "pnpm -F shared db:push", + "db:generate": "pnpm -F shared db:generate", + "db:migrate": "pnpm -F shared db:migrate" + }, + "dependencies": { + "chalk": "^5.3.0", + "drizzle-kit": "^0.31.1" }, "devDependencies": { + "@types/node": "^24.0.3", + "dotenv": "^16.5.0", + "inquirer": "^12.6.3", "concurrently": "^9.1.2" } } diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml new file mode 100644 index 000000000..182975a43 --- /dev/null +++ b/pnpm-lock.yaml @@ -0,0 +1,10850 @@ +lockfileVersion: '9.0' + +settings: + autoInstallPeers: true + excludeLinksFromLockfile: false + +importers: + + .: + dependencies: + chalk: + specifier: ^5.3.0 + version: 5.4.1 + drizzle-kit: + specifier: ^0.31.1 + version: 0.31.1 + devDependencies: + '@types/node': + specifier: ^24.0.3 + version: 24.0.3 + dotenv: + specifier: ^16.5.0 + version: 16.5.0 + inquirer: + specifier: ^12.6.3 + version: 12.6.3(@types/node@24.0.3) + + server: + dependencies: + '@ai-sdk/anthropic': + specifier: ^1.2.10 + version: 1.2.12(zod@3.25.64) + '@anthropic-ai/sdk': + specifier: ^0.32.1 + version: 0.32.1 + '@autumn/shared': + specifier: workspace:* + version: link:../shared + '@clerk/express': + specifier: ^1.3.22 + version: 1.7.0(express@4.21.2)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@date-fns/tz': + specifier: ^1.2.0 + version: 1.2.0 + '@date-fns/utc': + specifier: ^2.1.0 + version: 2.1.0 + '@logtail/node': + specifier: ^0.5.2 + version: 0.5.5 + '@react-email/components': + specifier: ^0.0.42 + version: 0.0.42(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@supabase/supabase-js': + specifier: ^2.46.2 + version: 2.50.0 + '@types/cors': + specifier: ^2.8.17 + version: 2.8.19 + '@types/express': + specifier: ^5.0.0 + version: 5.0.3 + ai: + specifier: ^4.3.10 + version: 4.3.16(react@18.3.1)(zod@3.25.64) + autumn-js: + specifier: ^0.0.64 + version: 0.0.64(@tanstack/react-query@5.80.7(react@18.3.1))(react@18.3.1) + better-auth: + specifier: ^1.2.9 + version: 1.2.9 + body-parser: + specifier: ^1.20.3 + version: 1.20.3 + bullmq: + specifier: ^5.54.0 + version: 5.54.0 + chai: + specifier: ^5.1.2 + version: 5.2.0 + chai-http: + specifier: ^5.1.1 + version: 5.1.2 + chalk: + specifier: ^5.3.0 + version: 5.4.1 + cors: + specifier: ^2.8.5 + version: 2.8.5 + cron: + specifier: ^3.5.0 + version: 3.5.0 + csv-parse: + specifier: ^5.6.0 + version: 5.6.0 + csv-parser: + specifier: ^3.2.0 + version: 3.2.0 + currency-symbol-map: + specifier: ^5.1.0 + version: 5.1.0 + date-fns: + specifier: ^4.1.0 + version: 4.1.0 + decimal.js: + specifier: ^10.5.0 + version: 10.5.0 + detect-content-type: + specifier: ^1.2.0 + version: 1.2.0 + dotenv: + specifier: ^16.5.0 + version: 16.5.0 + drizzle-orm: + specifier: ^0.43.1 + version: 0.43.1(@opentelemetry/api@1.9.0)(@types/pg@8.15.4)(kysely@0.28.2)(pg@8.16.0)(postgres@3.4.7) + express: + specifier: ^4.21.1 + version: 4.21.2 + fetch-retry: + specifier: ^6.0.0 + version: 6.0.0 + http-status-codes: + specifier: ^2.3.0 + version: 2.3.0 + ioredis: + specifier: ^5.5.0 + version: 5.6.1 + ksuid: + specifier: ^3.0.0 + version: 3.0.0 + lodash-es: + specifier: ^4.17.21 + version: 4.17.21 + mime-detect: + specifier: ^1.3.0 + version: 1.3.0 + nodemon: + specifier: ^3.1.7 + version: 3.1.10 + openai: + specifier: ^4.85.2 + version: 4.104.0(ws@8.18.2)(zod@3.25.64) + pg: + specifier: ^8.13.1 + version: 8.16.0 + pino: + specifier: ^9.6.0 + version: 9.7.0 + pino-pretty: + specifier: ^13.0.0 + version: 13.0.0 + postgres: + specifier: ^3.4.7 + version: 3.4.7 + posthog-node: + specifier: ^4.17.2 + version: 4.18.0 + react: + specifier: ^18.2.0 + version: 18.3.1 + recaseai: + specifier: ^0.0.37 + version: 0.0.37(ws@8.18.2)(zod@3.25.64) + resend: + specifier: ^4.1.1 + version: 4.6.0(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + stripe: + specifier: ^17.5.0 + version: 17.7.0 + svix: + specifier: ^1.45.1 + version: 1.67.0 + tsc-alias: + specifier: ^1.8.16 + version: 1.8.16 + ws: + specifier: ^8.18.0 + version: 8.18.2 + zod: + specifier: ^3.25.23 + version: 3.25.64 + devDependencies: + '@types/chai': + specifier: ^5.0.1 + version: 5.2.2 + '@types/chai-http': + specifier: ^3.0.5 + version: 3.0.5 + '@types/lodash-es': + specifier: ^4.17.12 + version: 4.17.12 + '@types/mocha': + specifier: ^10.0.10 + version: 10.0.10 + '@types/node': + specifier: ^22.13.4 + version: 22.15.32 + '@types/pg': + specifier: ^8.11.10 + version: 8.15.4 + '@types/react': + specifier: ^18.3.18 + version: 18.3.23 + '@types/react-dom': + specifier: ^18.3.5 + version: 18.3.7(@types/react@18.3.23) + '@types/ws': + specifier: ^8.18.1 + version: 8.18.1 + drizzle-kit: + specifier: ^0.31.1 + version: 0.31.1 + mocha: + specifier: ^11.1.0 + version: 11.6.0 + puppeteer: + specifier: ^24.2.0 + version: 24.10.1(typescript@5.7.3) + react-email: + specifier: 4.0.16 + version: 4.0.16(@opentelemetry/api@1.9.0)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + ts-node: + specifier: ^10.9.2 + version: 10.9.2(@types/node@22.15.32)(typescript@5.7.3) + tsconfig-paths: + specifier: ^4.2.0 + version: 4.2.0 + tsx: + specifier: ^4.19.4 + version: 4.20.3 + typescript: + specifier: ^5.7.3 + version: 5.7.3 + + shared: + dependencies: + decimal.js: + specifier: ^10.5.0 + version: 10.5.0 + drizzle-orm: + specifier: ^0.43.1 + version: 0.43.1(@opentelemetry/api@1.9.0)(@types/pg@8.15.4)(kysely@0.28.2)(pg@8.16.0)(postgres@3.4.7) + drizzle-zod: + specifier: ^0.8.2 + version: 0.8.2(drizzle-orm@0.43.1(@opentelemetry/api@1.9.0)(@types/pg@8.15.4)(kysely@0.28.2)(pg@8.16.0)(postgres@3.4.7))(zod@3.25.64) + zod: + specifier: ^3.25.23 + version: 3.25.64 + devDependencies: + nodemon: + specifier: ^3.1.7 + version: 3.1.10 + tsx: + specifier: ^4.19.4 + version: 4.20.3 + typescript: + specifier: ^5.7.2 + version: 5.7.3 + + vite: + dependencies: + '@autumn/shared': + specifier: workspace:* + version: link:../shared + '@clerk/clerk-react': + specifier: ^5.24.2 + version: 5.32.0(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@fortawesome/free-brands-svg-icons': + specifier: ^6.7.2 + version: 6.7.2 + '@fortawesome/react-fontawesome': + specifier: ^0.2.2 + version: 0.2.2(@fortawesome/fontawesome-svg-core@6.7.2)(react@18.3.1) + '@radix-ui/react-accordion': + specifier: ^1.2.3 + version: 1.2.11(@types/react-dom@18.3.7(@types/react@18.3.23))(@types/react@18.3.23)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@radix-ui/react-checkbox': + specifier: ^1.1.4 + version: 1.3.2(@types/react-dom@18.3.7(@types/react@18.3.23))(@types/react@18.3.23)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@radix-ui/react-dialog': + specifier: ^1.1.14 + version: 1.1.14(@types/react-dom@18.3.7(@types/react@18.3.23))(@types/react@18.3.23)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@radix-ui/react-dropdown-menu': + specifier: ^2.1.6 + version: 2.1.15(@types/react-dom@18.3.7(@types/react@18.3.23))(@types/react@18.3.23)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@radix-ui/react-popover': + specifier: ^1.1.6 + version: 1.1.14(@types/react-dom@18.3.7(@types/react@18.3.23))(@types/react@18.3.23)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@radix-ui/react-scroll-area': + specifier: ^1.2.3 + version: 1.2.9(@types/react-dom@18.3.7(@types/react@18.3.23))(@types/react@18.3.23)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@radix-ui/react-select': + specifier: ^2.1.6 + version: 2.2.5(@types/react-dom@18.3.7(@types/react@18.3.23))(@types/react@18.3.23)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@radix-ui/react-separator': + specifier: ^1.1.2 + version: 1.1.7(@types/react-dom@18.3.7(@types/react@18.3.23))(@types/react@18.3.23)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@radix-ui/react-slot': + specifier: ^1.2.3 + version: 1.2.3(@types/react@18.3.23)(react@18.3.1) + '@radix-ui/react-switch': + specifier: ^1.2.5 + version: 1.2.5(@types/react-dom@18.3.7(@types/react@18.3.23))(@types/react@18.3.23)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@radix-ui/react-tabs': + specifier: ^1.1.3 + version: 1.1.12(@types/react-dom@18.3.7(@types/react@18.3.23))(@types/react@18.3.23)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@radix-ui/react-tooltip': + specifier: ^1.1.8 + version: 1.2.7(@types/react-dom@18.3.7(@types/react@18.3.23))(@types/react@18.3.23)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@supabase/ssr': + specifier: ^0.5.2 + version: 0.5.2(@supabase/supabase-js@2.50.0) + '@tailwindcss/vite': + specifier: ^4.0.13 + version: 4.1.10(vite@6.3.5(@types/node@22.15.32)(jiti@2.4.2)(lightningcss@1.30.1)(tsx@4.20.3)) + '@tanstack/react-table': + specifier: ^8.21.3 + version: 8.21.3(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@wooorm/starry-night': + specifier: ^3.6.0 + version: 3.8.0 + autumn-js: + specifier: ^0.0.41 + version: 0.0.41(@tanstack/react-query@5.80.7(react@18.3.1))(react@18.3.1) + axios: + specifier: ^1.8.3 + version: 1.10.0 + better-auth: + specifier: ^1.2.9 + version: 1.2.9 + class-variance-authority: + specifier: ^0.7.1 + version: 0.7.1 + clsx: + specifier: ^2.1.1 + version: 2.1.1 + cmdk: + specifier: ^1.0.0 + version: 1.1.1(@types/react-dom@18.3.7(@types/react@18.3.23))(@types/react@18.3.23)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + date-fns: + specifier: ^3.6.0 + version: 3.6.0 + decimal.js: + specifier: ^10.5.0 + version: 10.5.0 + hast-util-to-html: + specifier: ^9.0.5 + version: 9.0.5 + input-otp: + specifier: ^1.4.2 + version: 1.4.2(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + lodash: + specifier: ^4.17.21 + version: 4.17.21 + lucide-react: + specifier: ^0.511.0 + version: 0.511.0(react@18.3.1) + motion: + specifier: ^12.16.0 + version: 12.18.1(@emotion/is-prop-valid@0.7.3)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + next-themes: + specifier: ^0.4.6 + version: 0.4.6(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + posthog-js: + specifier: ^1.230.4 + version: 1.252.1 + prism-themes: + specifier: ^1.9.0 + version: 1.9.0 + prismjs: + specifier: ^1.29.0 + version: 1.30.0 + react: + specifier: ^18.2.0 + version: 18.3.1 + react-confetti-explosion: + specifier: ^2.1.2 + version: 2.1.2(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + react-day-picker: + specifier: ^8.10.1 + version: 8.10.1(date-fns@3.6.0)(react@18.3.1) + react-dom: + specifier: ^18.2.0 + version: 18.3.1(react@18.3.1) + react-dropzone: + specifier: ^14.3.8 + version: 14.3.8(react@18.3.1) + react-hot-toast: + specifier: ^2.5.2 + version: 2.5.2(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + react-hotkeys-hook: + specifier: ^4.6.1 + version: 4.6.2(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + react-router: + specifier: ^7.3.0 + version: 7.6.2(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + sonner: + specifier: ^2.0.1 + version: 2.0.5(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + svix-react: + specifier: ^1.13.3 + version: 1.13.4(@babel/core@7.27.4)(prop-types@15.8.1)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(svix@1.67.0) + swr: + specifier: ^2.3.3 + version: 2.3.3(react@18.3.1) + tailwind-merge: + specifier: ^3.0.2 + version: 3.3.1 + tailwindcss: + specifier: ^4.0.13 + version: 4.1.10 + tailwindcss-animate: + specifier: ^1.0.7 + version: 1.0.7(tailwindcss@4.1.10) + vaul: + specifier: ^1.1.2 + version: 1.1.2(@types/react-dom@18.3.7(@types/react@18.3.23))(@types/react@18.3.23)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + zod: + specifier: ^3.25.23 + version: 3.25.64 + devDependencies: + '@eslint/js': + specifier: ^9.21.0 + version: 9.29.0 + '@types/lodash': + specifier: ^4.17.16 + version: 4.17.17 + '@types/node': + specifier: ^22.13.10 + version: 22.15.32 + '@types/prismjs': + specifier: ^1.26.5 + version: 1.26.5 + '@types/react': + specifier: ^18.3.18 + version: 18.3.23 + '@types/react-dom': + specifier: ^18.3.5 + version: 18.3.7(@types/react@18.3.23) + '@vitejs/plugin-react': + specifier: ^4.3.4 + version: 4.5.2(vite@6.3.5(@types/node@22.15.32)(jiti@2.4.2)(lightningcss@1.30.1)(tsx@4.20.3)) + eslint: + specifier: ^9.21.0 + version: 9.29.0(jiti@2.4.2) + eslint-plugin-react-hooks: + specifier: ^5.1.0 + version: 5.2.0(eslint@9.29.0(jiti@2.4.2)) + eslint-plugin-react-refresh: + specifier: ^0.4.19 + version: 0.4.20(eslint@9.29.0(jiti@2.4.2)) + globals: + specifier: ^15.15.0 + version: 15.15.0 + typescript: + specifier: ~5.7.2 + version: 5.7.3 + typescript-eslint: + specifier: ^8.24.1 + version: 8.34.0(eslint@9.29.0(jiti@2.4.2))(typescript@5.7.3) + vite: + specifier: ^6.2.0 + version: 6.3.5(@types/node@22.15.32)(jiti@2.4.2)(lightningcss@1.30.1)(tsx@4.20.3) + +packages: + + '@ai-sdk/anthropic@1.2.12': + resolution: {integrity: sha512-YSzjlko7JvuiyQFmI9RN1tNZdEiZxc+6xld/0tq/VkJaHpEzGAb1yiNxxvmYVcjvfu/PcvCxAAYXmTYQQ63IHQ==} + engines: {node: '>=18'} + peerDependencies: + zod: ^3.0.0 + + '@ai-sdk/provider-utils@2.2.8': + resolution: {integrity: sha512-fqhG+4sCVv8x7nFzYnFo19ryhAa3w096Kmc3hWxMQfW/TubPOmt3A6tYZhl4mUfQWWQMsuSkLrtjlWuXBVSGQA==} + engines: {node: '>=18'} + peerDependencies: + zod: ^3.23.8 + + '@ai-sdk/provider@1.1.3': + resolution: {integrity: sha512-qZMxYJ0qqX/RfnuIaab+zp8UAeJn/ygXXAffR5I4N0n1IrvA6qBsjc8hXLmBiMV2zoXlifkacF7sEFnYnjBcqg==} + engines: {node: '>=18'} + + '@ai-sdk/react@1.2.12': + resolution: {integrity: sha512-jK1IZZ22evPZoQW3vlkZ7wvjYGYF+tRBKXtrcolduIkQ/m/sOAVcVeVDUDvh1T91xCnWCdUGCPZg2avZ90mv3g==} + engines: {node: '>=18'} + peerDependencies: + react: ^18 || ^19 || ^19.0.0-rc + zod: ^3.23.8 + peerDependenciesMeta: + zod: + optional: true + + '@ai-sdk/ui-utils@1.2.11': + resolution: {integrity: sha512-3zcwCc8ezzFlwp3ZD15wAPjf2Au4s3vAbKsXQVyhxODHcmu0iyPO2Eua6D/vicq/AUm/BAo60r97O6HU+EI0+w==} + engines: {node: '>=18'} + peerDependencies: + zod: ^3.23.8 + + '@ampproject/remapping@2.3.0': + resolution: {integrity: sha512-30iZtAPgz+LTIYoeivqYo853f02jBYSd5uGnGpkFV0M3xOt9aN73erkgYAmZU43x4VfqcnLxW9Kpg3R5LC4YYw==} + engines: {node: '>=6.0.0'} + + '@anthropic-ai/sdk@0.32.1': + resolution: {integrity: sha512-U9JwTrDvdQ9iWuABVsMLj8nJVwAyQz6QXvgLsVhryhCEPkLsbcP/MXxm+jYcAwLoV8ESbaTTjnD4kuAFa+Hyjg==} + + '@babel/code-frame@7.27.1': + resolution: {integrity: sha512-cjQ7ZlQ0Mv3b47hABuTevyTuYN4i+loJKGeV9flcCgIK37cCXRh+L1bd3iBHlynerhQ7BhCkn2BPbQUL+rGqFg==} + engines: {node: '>=6.9.0'} + + '@babel/compat-data@7.27.5': + resolution: {integrity: sha512-KiRAp/VoJaWkkte84TvUd9qjdbZAdiqyvMxrGl1N6vzFogKmaLgoM3L1kgtLicp2HP5fBJS8JrZKLVIZGVJAVg==} + engines: {node: '>=6.9.0'} + + '@babel/core@7.27.4': + resolution: {integrity: sha512-bXYxrXFubeYdvB0NhD/NBB3Qi6aZeV20GOWVI47t2dkecCEoneR4NPVcb7abpXDEvejgrUfFtG6vG/zxAKmg+g==} + engines: {node: '>=6.9.0'} + + '@babel/generator@7.27.5': + resolution: {integrity: sha512-ZGhA37l0e/g2s1Cnzdix0O3aLYm66eF8aufiVteOgnwxgnRP8GoyMj7VWsgWnQbVKXyge7hqrFh2K2TQM6t1Hw==} + engines: {node: '>=6.9.0'} + + '@babel/helper-annotate-as-pure@7.27.3': + resolution: {integrity: sha512-fXSwMQqitTGeHLBC08Eq5yXz2m37E4pJX1qAU1+2cNedz/ifv/bVXft90VeSav5nFO61EcNgwr0aJxbyPaWBPg==} + engines: {node: '>=6.9.0'} + + '@babel/helper-compilation-targets@7.27.2': + resolution: {integrity: sha512-2+1thGUUWWjLTYTHZWK1n8Yga0ijBz1XAhUXcKy81rd5g6yh7hGqMp45v7cadSbEHc9G3OTv45SyneRN3ps4DQ==} + engines: {node: '>=6.9.0'} + + '@babel/helper-create-class-features-plugin@7.27.1': + resolution: {integrity: sha512-QwGAmuvM17btKU5VqXfb+Giw4JcN0hjuufz3DYnpeVDvZLAObloM77bhMXiqry3Iio+Ai4phVRDwl6WU10+r5A==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0 + + '@babel/helper-member-expression-to-functions@7.27.1': + resolution: {integrity: sha512-E5chM8eWjTp/aNoVpcbfM7mLxu9XGLWYise2eBKGQomAk/Mb4XoxyqXTZbuTohbsl8EKqdlMhnDI2CCLfcs9wA==} + engines: {node: '>=6.9.0'} + + '@babel/helper-module-imports@7.27.1': + resolution: {integrity: sha512-0gSFWUPNXNopqtIPQvlD5WgXYI5GY2kP2cCvoT8kczjbfcfuIljTbcWrulD1CIPIX2gt1wghbDy08yE1p+/r3w==} + engines: {node: '>=6.9.0'} + + '@babel/helper-module-transforms@7.27.3': + resolution: {integrity: sha512-dSOvYwvyLsWBeIRyOeHXp5vPj5l1I011r52FM1+r1jCERv+aFXYk4whgQccYEGYxK2H3ZAIA8nuPkQ0HaUo3qg==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0 + + '@babel/helper-optimise-call-expression@7.27.1': + resolution: {integrity: sha512-URMGH08NzYFhubNSGJrpUEphGKQwMQYBySzat5cAByY1/YgIRkULnIy3tAMeszlL/so2HbeilYloUmSpd7GdVw==} + engines: {node: '>=6.9.0'} + + '@babel/helper-plugin-utils@7.27.1': + resolution: {integrity: sha512-1gn1Up5YXka3YYAHGKpbideQ5Yjf1tDa9qYcgysz+cNCXukyLl6DjPXhD3VRwSb8c0J9tA4b2+rHEZtc6R0tlw==} + engines: {node: '>=6.9.0'} + + '@babel/helper-replace-supers@7.27.1': + resolution: {integrity: sha512-7EHz6qDZc8RYS5ElPoShMheWvEgERonFCs7IAonWLLUTXW59DP14bCZt89/GKyreYn8g3S83m21FelHKbeDCKA==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0 + + '@babel/helper-skip-transparent-expression-wrappers@7.27.1': + resolution: {integrity: sha512-Tub4ZKEXqbPjXgWLl2+3JpQAYBJ8+ikpQ2Ocj/q/r0LwE3UhENh7EUabyHjz2kCEsrRY83ew2DQdHluuiDQFzg==} + engines: {node: '>=6.9.0'} + + '@babel/helper-string-parser@7.27.1': + resolution: {integrity: sha512-qMlSxKbpRlAridDExk92nSobyDdpPijUq2DW6oDnUqd0iOGxmQjyqhMIihI9+zv4LPyZdRje2cavWPbCbWm3eA==} + engines: {node: '>=6.9.0'} + + '@babel/helper-validator-identifier@7.27.1': + resolution: {integrity: sha512-D2hP9eA+Sqx1kBZgzxZh0y1trbuU+JoDkiEwqhQ36nodYqJwyEIhPSdMNd7lOm/4io72luTPWH20Yda0xOuUow==} + engines: {node: '>=6.9.0'} + + '@babel/helper-validator-option@7.27.1': + resolution: {integrity: sha512-YvjJow9FxbhFFKDSuFnVCe2WxXk1zWc22fFePVNEaWJEu8IrZVlda6N0uHwzZrUM1il7NC9Mlp4MaJYbYd9JSg==} + engines: {node: '>=6.9.0'} + + '@babel/helpers@7.27.6': + resolution: {integrity: sha512-muE8Tt8M22638HU31A3CgfSUciwz1fhATfoVai05aPXGor//CdWDCbnlY1yvBPo07njuVOCNGCSp/GTt12lIug==} + engines: {node: '>=6.9.0'} + + '@babel/parser@7.27.5': + resolution: {integrity: sha512-OsQd175SxWkGlzbny8J3K8TnnDD0N3lrIUtB92xwyRpzaenGZhxDvxN/JgU00U3CDZNj9tPuDJ5H0WS4Nt3vKg==} + engines: {node: '>=6.0.0'} + hasBin: true + + '@babel/plugin-proposal-private-property-in-object@7.21.11': + resolution: {integrity: sha512-0QZ8qP/3RLDVBwBFoWAwCtgcDZJVwA5LUJRZU8x2YFfKNuFq161wK3cuGrALu5yiPu+vzwTAg/sMWVNeWeNyaw==} + engines: {node: '>=6.9.0'} + deprecated: This proposal has been merged to the ECMAScript standard and thus this plugin is no longer maintained. Please use @babel/plugin-transform-private-property-in-object instead. + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-syntax-private-property-in-object@7.14.5': + resolution: {integrity: sha512-0wVnp9dxJ72ZUJDV27ZfbSj6iHLoytYZmh3rFcxNnvsJF3ktkzLDZPy/mA17HGsaQT3/DQsWYX1f1QGWkCoVUg==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-transform-react-jsx-self@7.27.1': + resolution: {integrity: sha512-6UzkCs+ejGdZ5mFFC/OCUrv028ab2fp1znZmCZjAOBKiBK2jXD1O+BPSfX8X2qjJ75fZBMSnQn3Rq2mrBJK2mw==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-transform-react-jsx-source@7.27.1': + resolution: {integrity: sha512-zbwoTsBruTeKB9hSq73ha66iFeJHuaFkUbwvqElnygoNbj/jHRsSeokowZFN3CZ64IvEqcmmkVe89OPXc7ldAw==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/runtime@7.27.6': + resolution: {integrity: sha512-vbavdySgbTTrmFE+EsiqUTzlOr5bzlnJtUv9PynGCAKvfQqjIXbvFdumPM/GxMDfyuGMJaJAU6TO4zc1Jf1i8Q==} + engines: {node: '>=6.9.0'} + + '@babel/template@7.27.2': + resolution: {integrity: sha512-LPDZ85aEJyYSd18/DkjNh4/y1ntkE5KwUHWTiqgRxruuZL2F1yuHligVHLvcHY2vMHXttKFpJn6LwfI7cw7ODw==} + engines: {node: '>=6.9.0'} + + '@babel/traverse@7.27.4': + resolution: {integrity: sha512-oNcu2QbHqts9BtOWJosOVJapWjBDSxGCpFvikNR5TGDYDQf3JwpIoMzIKrvfoti93cLfPJEG4tH9SPVeyCGgdA==} + engines: {node: '>=6.9.0'} + + '@babel/types@7.27.6': + resolution: {integrity: sha512-ETyHEk2VHHvl9b9jZP5IHPavHYk57EhanlRRuae9XCpb/j5bDCbPPMOBfCWhnl/7EDJz0jEMCi/RhccCE8r1+Q==} + engines: {node: '>=6.9.0'} + + '@better-auth/utils@0.2.5': + resolution: {integrity: sha512-uI2+/8h/zVsH8RrYdG8eUErbuGBk16rZKQfz8CjxQOyCE6v7BqFYEbFwvOkvl1KbUdxhqOnXp78+uE5h8qVEgQ==} + + '@better-fetch/fetch@1.1.18': + resolution: {integrity: sha512-rEFOE1MYIsBmoMJtQbl32PGHHXuG2hDxvEd7rUHE0vCBoFQVSDqaVs9hkZEtHCxRoY+CljXKFCOuJ8uxqw1LcA==} + + '@clerk/backend@2.1.0': + resolution: {integrity: sha512-Ltb3IzdGeahM1Jr+u0UAVnVjEIYXUsq9/mTb1adolsOc9oR2LCKHE7rTRnmkwY8y+IwCzXVuywIYW+zLTk47+Q==} + engines: {node: '>=18.17.0'} + + '@clerk/clerk-react@5.32.0': + resolution: {integrity: sha512-RdipOVBdbUbFaDb8kF3EzhJw0eh5LPxSWWRTu4k+pOdRB1gzETiToLchj5nDWFkl8qW/uL4gQbZH+Pfc7izO0A==} + engines: {node: '>=18.17.0'} + peerDependencies: + react: ^18.0.0 || ^19.0.0 || ^19.0.0-0 + react-dom: ^18.0.0 || ^19.0.0 || ^19.0.0-0 + + '@clerk/express@1.7.0': + resolution: {integrity: sha512-wE3Bb3EX4TGe690J8D71RmFhgSdenzIQ/RMjCcxdEGhLHRtaD4/SjbTc1EFf2G+/10Rd7iZrFBC0UhMCrLOzew==} + engines: {node: '>=18.17.0'} + peerDependencies: + express: ^4.17.0 || ^5.0.0 + + '@clerk/shared@3.9.7': + resolution: {integrity: sha512-D3iuzuDoadK6BKb7qFZEH332z4Sl5mxLuHMf8rKdIMHuOu1RQK0RqFJtKPcFvDxq0RvJ9MC+rK24P2Sa2tOoNA==} + engines: {node: '>=18.17.0'} + peerDependencies: + react: ^18.0.0 || ^19.0.0 || ^19.0.0-0 + react-dom: ^18.0.0 || ^19.0.0 || ^19.0.0-0 + peerDependenciesMeta: + react: + optional: true + react-dom: + optional: true + + '@clerk/types@4.60.1': + resolution: {integrity: sha512-Lbt0/Q9W9BJtGz1IITdmeqal7y1zp9EaxOEMvsTEDhOxKf/0F/M1d0gJmHEU0puQzYPp9zJsIWC2yJjbgy3Y3Q==} + engines: {node: '>=18.17.0'} + + '@cspotcode/source-map-support@0.8.1': + resolution: {integrity: sha512-IchNf6dN4tHoMFIn/7OE8LWZ19Y6q/67Bmf6vnGREv8RSbBVb9LPJxEcnwrcwX6ixSvaiGoomAUvu4YSxXrVgw==} + engines: {node: '>=12'} + + '@date-fns/tz@1.2.0': + resolution: {integrity: sha512-LBrd7MiJZ9McsOgxqWX7AaxrDjcFVjWH/tIKJd7pnR7McaslGYOP1QmmiBXdJH/H/yLCT+rcQ7FaPBUxRGUtrg==} + + '@date-fns/utc@2.1.0': + resolution: {integrity: sha512-176grgAgU2U303rD2/vcOmNg0kGPbhzckuH1TEP2al7n0AQipZIy9P15usd2TKQCG1g+E1jX/ZVQSzs4sUDwgA==} + + '@drizzle-team/brocli@0.10.2': + resolution: {integrity: sha512-z33Il7l5dKjUgGULTqBsQBQwckHh5AbIuxhdsIxDDiZAzBOrZO6q9ogcWC65kU382AfynTfgNumVcNIjuIua6w==} + + '@emnapi/runtime@1.4.3': + resolution: {integrity: sha512-pBPWdu6MLKROBX05wSNKcNb++m5Er+KQ9QkB+WVM+pW2Kx9hoSrVTnu3BdkI5eBLZoKu/J6mW/B6i6bJB2ytXQ==} + + '@emotion/is-prop-valid@0.7.3': + resolution: {integrity: sha512-uxJqm/sqwXw3YPA5GXX365OBcJGFtxUVkB6WyezqFHlNe9jqUWH5ur2O2M8dGBz61kn1g3ZBlzUunFQXQIClhA==} + + '@emotion/memoize@0.7.1': + resolution: {integrity: sha512-Qv4LTqO11jepd5Qmlp3M1YEjBumoTHcHFdgPTQ+sFlIL5myi/7xu/POwP7IRu6odBdmLXdtIs1D6TuW6kbwbbg==} + + '@esbuild-kit/core-utils@3.3.2': + resolution: {integrity: sha512-sPRAnw9CdSsRmEtnsl2WXWdyquogVpB3yZ3dgwJfe8zrOzTsV7cJvmwrKVa+0ma5BoiGJ+BoqkMvawbayKUsqQ==} + deprecated: 'Merged into tsx: https://tsx.is' + + '@esbuild-kit/esm-loader@2.6.5': + resolution: {integrity: sha512-FxEMIkJKnodyA1OaCUoEvbYRkoZlLZ4d/eXFu9Fh8CbBBgP5EmZxrfTRyN0qpXZ4vOvqnE5YdRdcrmUUXuU+dA==} + deprecated: 'Merged into tsx: https://tsx.is' + + '@esbuild/aix-ppc64@0.25.5': + resolution: {integrity: sha512-9o3TMmpmftaCMepOdA5k/yDw8SfInyzWWTjYTFCX3kPSDJMROQTb8jg+h9Cnwnmm1vOzvxN7gIfB5V2ewpjtGA==} + engines: {node: '>=18'} + cpu: [ppc64] + os: [aix] + + '@esbuild/android-arm64@0.18.20': + resolution: {integrity: sha512-Nz4rJcchGDtENV0eMKUNa6L12zz2zBDXuhj/Vjh18zGqB44Bi7MBMSXjgunJgjRhCmKOjnPuZp4Mb6OKqtMHLQ==} + engines: {node: '>=12'} + cpu: [arm64] + os: [android] + + '@esbuild/android-arm64@0.25.5': + resolution: {integrity: sha512-VGzGhj4lJO+TVGV1v8ntCZWJktV7SGCs3Pn1GRWI1SBFtRALoomm8k5E9Pmwg3HOAal2VDc2F9+PM/rEY6oIDg==} + engines: {node: '>=18'} + cpu: [arm64] + os: [android] + + '@esbuild/android-arm@0.18.20': + resolution: {integrity: sha512-fyi7TDI/ijKKNZTUJAQqiG5T7YjJXgnzkURqmGj13C6dCqckZBLdl4h7bkhHt/t0WP+zO9/zwroDvANaOqO5Sw==} + engines: {node: '>=12'} + cpu: [arm] + os: [android] + + '@esbuild/android-arm@0.25.5': + resolution: {integrity: sha512-AdJKSPeEHgi7/ZhuIPtcQKr5RQdo6OO2IL87JkianiMYMPbCtot9fxPbrMiBADOWWm3T2si9stAiVsGbTQFkbA==} + engines: {node: '>=18'} + cpu: [arm] + os: [android] + + '@esbuild/android-x64@0.18.20': + resolution: {integrity: sha512-8GDdlePJA8D6zlZYJV/jnrRAi6rOiNaCC/JclcXpB+KIuvfBN4owLtgzY2bsxnx666XjJx2kDPUmnTtR8qKQUg==} + engines: {node: '>=12'} + cpu: [x64] + os: [android] + + '@esbuild/android-x64@0.25.5': + resolution: {integrity: sha512-D2GyJT1kjvO//drbRT3Hib9XPwQeWd9vZoBJn+bu/lVsOZ13cqNdDeqIF/xQ5/VmWvMduP6AmXvylO/PIc2isw==} + engines: {node: '>=18'} + cpu: [x64] + os: [android] + + '@esbuild/darwin-arm64@0.18.20': + resolution: {integrity: sha512-bxRHW5kHU38zS2lPTPOyuyTm+S+eobPUnTNkdJEfAddYgEcll4xkT8DB9d2008DtTbl7uJag2HuE5NZAZgnNEA==} + engines: {node: '>=12'} + cpu: [arm64] + os: [darwin] + + '@esbuild/darwin-arm64@0.25.5': + resolution: {integrity: sha512-GtaBgammVvdF7aPIgH2jxMDdivezgFu6iKpmT+48+F8Hhg5J/sfnDieg0aeG/jfSvkYQU2/pceFPDKlqZzwnfQ==} + engines: {node: '>=18'} + cpu: [arm64] + os: [darwin] + + '@esbuild/darwin-x64@0.18.20': + resolution: {integrity: sha512-pc5gxlMDxzm513qPGbCbDukOdsGtKhfxD1zJKXjCCcU7ju50O7MeAZ8c4krSJcOIJGFR+qx21yMMVYwiQvyTyQ==} + engines: {node: '>=12'} + cpu: [x64] + os: [darwin] + + '@esbuild/darwin-x64@0.25.5': + resolution: {integrity: sha512-1iT4FVL0dJ76/q1wd7XDsXrSW+oLoquptvh4CLR4kITDtqi2e/xwXwdCVH8hVHU43wgJdsq7Gxuzcs6Iq/7bxQ==} + engines: {node: '>=18'} + cpu: [x64] + os: [darwin] + + '@esbuild/freebsd-arm64@0.18.20': + resolution: {integrity: sha512-yqDQHy4QHevpMAaxhhIwYPMv1NECwOvIpGCZkECn8w2WFHXjEwrBn3CeNIYsibZ/iZEUemj++M26W3cNR5h+Tw==} + engines: {node: '>=12'} + cpu: [arm64] + os: [freebsd] + + '@esbuild/freebsd-arm64@0.25.5': + resolution: {integrity: sha512-nk4tGP3JThz4La38Uy/gzyXtpkPW8zSAmoUhK9xKKXdBCzKODMc2adkB2+8om9BDYugz+uGV7sLmpTYzvmz6Sw==} + engines: {node: '>=18'} + cpu: [arm64] + os: [freebsd] + + '@esbuild/freebsd-x64@0.18.20': + resolution: {integrity: sha512-tgWRPPuQsd3RmBZwarGVHZQvtzfEBOreNuxEMKFcd5DaDn2PbBxfwLcj4+aenoh7ctXcbXmOQIn8HI6mCSw5MQ==} + engines: {node: '>=12'} + cpu: [x64] + os: [freebsd] + + '@esbuild/freebsd-x64@0.25.5': + resolution: {integrity: sha512-PrikaNjiXdR2laW6OIjlbeuCPrPaAl0IwPIaRv+SMV8CiM8i2LqVUHFC1+8eORgWyY7yhQY+2U2fA55mBzReaw==} + engines: {node: '>=18'} + cpu: [x64] + os: [freebsd] + + '@esbuild/linux-arm64@0.18.20': + resolution: {integrity: sha512-2YbscF+UL7SQAVIpnWvYwM+3LskyDmPhe31pE7/aoTMFKKzIc9lLbyGUpmmb8a8AixOL61sQ/mFh3jEjHYFvdA==} + engines: {node: '>=12'} + cpu: [arm64] + os: [linux] + + '@esbuild/linux-arm64@0.25.5': + resolution: {integrity: sha512-Z9kfb1v6ZlGbWj8EJk9T6czVEjjq2ntSYLY2cw6pAZl4oKtfgQuS4HOq41M/BcoLPzrUbNd+R4BXFyH//nHxVg==} + engines: {node: '>=18'} + cpu: [arm64] + os: [linux] + + '@esbuild/linux-arm@0.18.20': + resolution: {integrity: sha512-/5bHkMWnq1EgKr1V+Ybz3s1hWXok7mDFUMQ4cG10AfW3wL02PSZi5kFpYKrptDsgb2WAJIvRcDm+qIvXf/apvg==} + engines: {node: '>=12'} + cpu: [arm] + os: [linux] + + '@esbuild/linux-arm@0.25.5': + resolution: {integrity: sha512-cPzojwW2okgh7ZlRpcBEtsX7WBuqbLrNXqLU89GxWbNt6uIg78ET82qifUy3W6OVww6ZWobWub5oqZOVtwolfw==} + engines: {node: '>=18'} + cpu: [arm] + os: [linux] + + '@esbuild/linux-ia32@0.18.20': + resolution: {integrity: sha512-P4etWwq6IsReT0E1KHU40bOnzMHoH73aXp96Fs8TIT6z9Hu8G6+0SHSw9i2isWrD2nbx2qo5yUqACgdfVGx7TA==} + engines: {node: '>=12'} + cpu: [ia32] + os: [linux] + + '@esbuild/linux-ia32@0.25.5': + resolution: {integrity: sha512-sQ7l00M8bSv36GLV95BVAdhJ2QsIbCuCjh/uYrWiMQSUuV+LpXwIqhgJDcvMTj+VsQmqAHL2yYaasENvJ7CDKA==} + engines: {node: '>=18'} + cpu: [ia32] + os: [linux] + + '@esbuild/linux-loong64@0.18.20': + resolution: {integrity: sha512-nXW8nqBTrOpDLPgPY9uV+/1DjxoQ7DoB2N8eocyq8I9XuqJ7BiAMDMf9n1xZM9TgW0J8zrquIb/A7s3BJv7rjg==} + engines: {node: '>=12'} + cpu: [loong64] + os: [linux] + + '@esbuild/linux-loong64@0.25.5': + resolution: {integrity: sha512-0ur7ae16hDUC4OL5iEnDb0tZHDxYmuQyhKhsPBV8f99f6Z9KQM02g33f93rNH5A30agMS46u2HP6qTdEt6Q1kg==} + engines: {node: '>=18'} + cpu: [loong64] + os: [linux] + + '@esbuild/linux-mips64el@0.18.20': + resolution: {integrity: sha512-d5NeaXZcHp8PzYy5VnXV3VSd2D328Zb+9dEq5HE6bw6+N86JVPExrA6O68OPwobntbNJ0pzCpUFZTo3w0GyetQ==} + engines: {node: '>=12'} + cpu: [mips64el] + os: [linux] + + '@esbuild/linux-mips64el@0.25.5': + resolution: {integrity: sha512-kB/66P1OsHO5zLz0i6X0RxlQ+3cu0mkxS3TKFvkb5lin6uwZ/ttOkP3Z8lfR9mJOBk14ZwZ9182SIIWFGNmqmg==} + engines: {node: '>=18'} + cpu: [mips64el] + os: [linux] + + '@esbuild/linux-ppc64@0.18.20': + resolution: {integrity: sha512-WHPyeScRNcmANnLQkq6AfyXRFr5D6N2sKgkFo2FqguP44Nw2eyDlbTdZwd9GYk98DZG9QItIiTlFLHJHjxP3FA==} + engines: {node: '>=12'} + cpu: [ppc64] + os: [linux] + + '@esbuild/linux-ppc64@0.25.5': + resolution: {integrity: sha512-UZCmJ7r9X2fe2D6jBmkLBMQetXPXIsZjQJCjgwpVDz+YMcS6oFR27alkgGv3Oqkv07bxdvw7fyB71/olceJhkQ==} + engines: {node: '>=18'} + cpu: [ppc64] + os: [linux] + + '@esbuild/linux-riscv64@0.18.20': + resolution: {integrity: sha512-WSxo6h5ecI5XH34KC7w5veNnKkju3zBRLEQNY7mv5mtBmrP/MjNBCAlsM2u5hDBlS3NGcTQpoBvRzqBcRtpq1A==} + engines: {node: '>=12'} + cpu: [riscv64] + os: [linux] + + '@esbuild/linux-riscv64@0.25.5': + resolution: {integrity: sha512-kTxwu4mLyeOlsVIFPfQo+fQJAV9mh24xL+y+Bm6ej067sYANjyEw1dNHmvoqxJUCMnkBdKpvOn0Ahql6+4VyeA==} + engines: {node: '>=18'} + cpu: [riscv64] + os: [linux] + + '@esbuild/linux-s390x@0.18.20': + resolution: {integrity: sha512-+8231GMs3mAEth6Ja1iK0a1sQ3ohfcpzpRLH8uuc5/KVDFneH6jtAJLFGafpzpMRO6DzJ6AvXKze9LfFMrIHVQ==} + engines: {node: '>=12'} + cpu: [s390x] + os: [linux] + + '@esbuild/linux-s390x@0.25.5': + resolution: {integrity: sha512-K2dSKTKfmdh78uJ3NcWFiqyRrimfdinS5ErLSn3vluHNeHVnBAFWC8a4X5N+7FgVE1EjXS1QDZbpqZBjfrqMTQ==} + engines: {node: '>=18'} + cpu: [s390x] + os: [linux] + + '@esbuild/linux-x64@0.18.20': + resolution: {integrity: sha512-UYqiqemphJcNsFEskc73jQ7B9jgwjWrSayxawS6UVFZGWrAAtkzjxSqnoclCXxWtfwLdzU+vTpcNYhpn43uP1w==} + engines: {node: '>=12'} + cpu: [x64] + os: [linux] + + '@esbuild/linux-x64@0.25.5': + resolution: {integrity: sha512-uhj8N2obKTE6pSZ+aMUbqq+1nXxNjZIIjCjGLfsWvVpy7gKCOL6rsY1MhRh9zLtUtAI7vpgLMK6DxjO8Qm9lJw==} + engines: {node: '>=18'} + cpu: [x64] + os: [linux] + + '@esbuild/netbsd-arm64@0.25.5': + resolution: {integrity: sha512-pwHtMP9viAy1oHPvgxtOv+OkduK5ugofNTVDilIzBLpoWAM16r7b/mxBvfpuQDpRQFMfuVr5aLcn4yveGvBZvw==} + engines: {node: '>=18'} + cpu: [arm64] + os: [netbsd] + + '@esbuild/netbsd-x64@0.18.20': + resolution: {integrity: sha512-iO1c++VP6xUBUmltHZoMtCUdPlnPGdBom6IrO4gyKPFFVBKioIImVooR5I83nTew5UOYrk3gIJhbZh8X44y06A==} + engines: {node: '>=12'} + cpu: [x64] + os: [netbsd] + + '@esbuild/netbsd-x64@0.25.5': + resolution: {integrity: sha512-WOb5fKrvVTRMfWFNCroYWWklbnXH0Q5rZppjq0vQIdlsQKuw6mdSihwSo4RV/YdQ5UCKKvBy7/0ZZYLBZKIbwQ==} + engines: {node: '>=18'} + cpu: [x64] + os: [netbsd] + + '@esbuild/openbsd-arm64@0.25.5': + resolution: {integrity: sha512-7A208+uQKgTxHd0G0uqZO8UjK2R0DDb4fDmERtARjSHWxqMTye4Erz4zZafx7Di9Cv+lNHYuncAkiGFySoD+Mw==} + engines: {node: '>=18'} + cpu: [arm64] + os: [openbsd] + + '@esbuild/openbsd-x64@0.18.20': + resolution: {integrity: sha512-e5e4YSsuQfX4cxcygw/UCPIEP6wbIL+se3sxPdCiMbFLBWu0eiZOJ7WoD+ptCLrmjZBK1Wk7I6D/I3NglUGOxg==} + engines: {node: '>=12'} + cpu: [x64] + os: [openbsd] + + '@esbuild/openbsd-x64@0.25.5': + resolution: {integrity: sha512-G4hE405ErTWraiZ8UiSoesH8DaCsMm0Cay4fsFWOOUcz8b8rC6uCvnagr+gnioEjWn0wC+o1/TAHt+It+MpIMg==} + engines: {node: '>=18'} + cpu: [x64] + os: [openbsd] + + '@esbuild/sunos-x64@0.18.20': + resolution: {integrity: sha512-kDbFRFp0YpTQVVrqUd5FTYmWo45zGaXe0X8E1G/LKFC0v8x0vWrhOWSLITcCn63lmZIxfOMXtCfti/RxN/0wnQ==} + engines: {node: '>=12'} + cpu: [x64] + os: [sunos] + + '@esbuild/sunos-x64@0.25.5': + resolution: {integrity: sha512-l+azKShMy7FxzY0Rj4RCt5VD/q8mG/e+mDivgspo+yL8zW7qEwctQ6YqKX34DTEleFAvCIUviCFX1SDZRSyMQA==} + engines: {node: '>=18'} + cpu: [x64] + os: [sunos] + + '@esbuild/win32-arm64@0.18.20': + resolution: {integrity: sha512-ddYFR6ItYgoaq4v4JmQQaAI5s7npztfV4Ag6NrhiaW0RrnOXqBkgwZLofVTlq1daVTQNhtI5oieTvkRPfZrePg==} + engines: {node: '>=12'} + cpu: [arm64] + os: [win32] + + '@esbuild/win32-arm64@0.25.5': + resolution: {integrity: sha512-O2S7SNZzdcFG7eFKgvwUEZ2VG9D/sn/eIiz8XRZ1Q/DO5a3s76Xv0mdBzVM5j5R639lXQmPmSo0iRpHqUUrsxw==} + engines: {node: '>=18'} + cpu: [arm64] + os: [win32] + + '@esbuild/win32-ia32@0.18.20': + resolution: {integrity: sha512-Wv7QBi3ID/rROT08SABTS7eV4hX26sVduqDOTe1MvGMjNd3EjOz4b7zeexIR62GTIEKrfJXKL9LFxTYgkyeu7g==} + engines: {node: '>=12'} + cpu: [ia32] + os: [win32] + + '@esbuild/win32-ia32@0.25.5': + resolution: {integrity: sha512-onOJ02pqs9h1iMJ1PQphR+VZv8qBMQ77Klcsqv9CNW2w6yLqoURLcgERAIurY6QE63bbLuqgP9ATqajFLK5AMQ==} + engines: {node: '>=18'} + cpu: [ia32] + os: [win32] + + '@esbuild/win32-x64@0.18.20': + resolution: {integrity: sha512-kTdfRcSiDfQca/y9QIkng02avJ+NCaQvrMejlsB3RRv5sE9rRoeBPISaZpKxHELzRxZyLvNts1P27W3wV+8geQ==} + engines: {node: '>=12'} + cpu: [x64] + os: [win32] + + '@esbuild/win32-x64@0.25.5': + resolution: {integrity: sha512-TXv6YnJ8ZMVdX+SXWVBo/0p8LTcrUYngpWjvm91TMjjBQii7Oz11Lw5lbDV5Y0TzuhSJHwiH4hEtC1I42mMS0g==} + engines: {node: '>=18'} + cpu: [x64] + os: [win32] + + '@eslint-community/eslint-utils@4.7.0': + resolution: {integrity: sha512-dyybb3AcajC7uha6CvhdVRJqaKyn7w2YKqKyAN37NKYgZT36w+iRb0Dymmc5qEJ549c/S31cMMSFd75bteCpCw==} + engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} + peerDependencies: + eslint: ^6.0.0 || ^7.0.0 || >=8.0.0 + + '@eslint-community/regexpp@4.12.1': + resolution: {integrity: sha512-CCZCDJuduB9OUkFkY2IgppNZMi2lBQgD2qzwXkEia16cge2pijY/aXi96CJMquDMn3nJdlPV1A5KrJEXwfLNzQ==} + engines: {node: ^12.0.0 || ^14.0.0 || >=16.0.0} + + '@eslint/config-array@0.20.1': + resolution: {integrity: sha512-OL0RJzC/CBzli0DrrR31qzj6d6i6Mm3HByuhflhl4LOBiWxN+3i6/t/ZQQNii4tjksXi8r2CRW1wMpWA2ULUEw==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + + '@eslint/config-helpers@0.2.3': + resolution: {integrity: sha512-u180qk2Um1le4yf0ruXH3PYFeEZeYC3p/4wCTKrr2U1CmGdzGi3KtY0nuPDH48UJxlKCC5RDzbcbh4X0XlqgHg==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + + '@eslint/core@0.14.0': + resolution: {integrity: sha512-qIbV0/JZr7iSDjqAc60IqbLdsj9GDt16xQtWD+B78d/HAlvysGdZZ6rpJHGAc2T0FQx1X6thsSPdnoiGKdNtdg==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + + '@eslint/core@0.15.0': + resolution: {integrity: sha512-b7ePw78tEWWkpgZCDYkbqDOP8dmM6qe+AOC6iuJqlq1R/0ahMAeH3qynpnqKFGkMltrp44ohV4ubGyvLX28tzw==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + + '@eslint/eslintrc@3.3.1': + resolution: {integrity: sha512-gtF186CXhIl1p4pJNGZw8Yc6RlshoePRvE0X91oPGb3vZ8pM3qOS9W9NGPat9LziaBV7XrJWGylNQXkGcnM3IQ==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + + '@eslint/js@9.29.0': + resolution: {integrity: sha512-3PIF4cBw/y+1u2EazflInpV+lYsSG0aByVIQzAgb1m1MhHFSbqTyNqtBKHgWf/9Ykud+DhILS9EGkmekVhbKoQ==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + + '@eslint/object-schema@2.1.6': + resolution: {integrity: sha512-RBMg5FRL0I0gs51M/guSAj5/e14VQ4tpZnQNWwuDT66P14I43ItmPfIZRhO9fUVIPOAQXU47atlywZ/czoqFPA==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + + '@eslint/plugin-kit@0.3.2': + resolution: {integrity: sha512-4SaFZCNfJqvk/kenHpI8xvN42DMaoycy4PzKc5otHxRswww1kAt82OlBuwRVLofCACCTZEcla2Ydxv8scMXaTg==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + + '@floating-ui/core@1.7.1': + resolution: {integrity: sha512-azI0DrjMMfIug/ExbBaeDVJXcY0a7EPvPjb2xAJPa4HeimBX+Z18HK8QQR3jb6356SnDDdxx+hinMLcJEDdOjw==} + + '@floating-ui/dom@1.7.1': + resolution: {integrity: sha512-cwsmW/zyw5ltYTUeeYJ60CnQuPqmGwuGVhG9w0PRaRKkAyi38BT5CKrpIbb+jtahSwUl04cWzSx9ZOIxeS6RsQ==} + + '@floating-ui/react-dom@2.1.3': + resolution: {integrity: sha512-huMBfiU9UnQ2oBwIhgzyIiSpVgvlDstU8CX0AF+wS+KzmYMs0J2a3GwuFHV1Lz+jlrQGeC1fF+Nv0QoumyV0bA==} + peerDependencies: + react: '>=16.8.0' + react-dom: '>=16.8.0' + + '@floating-ui/utils@0.2.9': + resolution: {integrity: sha512-MDWhGtE+eHw5JW7lq4qhc5yRLS11ERl1c7Z6Xd0a58DozHES6EnNNwUWbMiG4J9Cgj053Bhk8zvlhFYKVhULwg==} + + '@fortawesome/fontawesome-common-types@6.7.2': + resolution: {integrity: sha512-Zs+YeHUC5fkt7Mg1l6XTniei3k4bwG/yo3iFUtZWd/pMx9g3fdvkSK9E0FOC+++phXOka78uJcYb8JaFkW52Xg==} + engines: {node: '>=6'} + + '@fortawesome/fontawesome-svg-core@6.7.2': + resolution: {integrity: sha512-yxtOBWDrdi5DD5o1pmVdq3WMCvnobT0LU6R8RyyVXPvFRd2o79/0NCuQoCjNTeZz9EzA9xS3JxNWfv54RIHFEA==} + engines: {node: '>=6'} + + '@fortawesome/free-brands-svg-icons@6.7.2': + resolution: {integrity: sha512-zu0evbcRTgjKfrr77/2XX+bU+kuGfjm0LbajJHVIgBWNIDzrhpRxiCPNT8DW5AdmSsq7Mcf9D1bH0aSeSUSM+Q==} + engines: {node: '>=6'} + + '@fortawesome/react-fontawesome@0.2.2': + resolution: {integrity: sha512-EnkrprPNqI6SXJl//m29hpaNzOp1bruISWaOiRtkMi/xSvHJlzc2j2JAYS7egxt/EbjSNV/k6Xy0AQI6vB2+1g==} + peerDependencies: + '@fortawesome/fontawesome-svg-core': ~1 || ~6 + react: '>=16.3' + + '@hexagon/base64@1.1.28': + resolution: {integrity: sha512-lhqDEAvWixy3bZ+UOYbPwUbBkwBq5C1LAJ/xPC8Oi+lL54oyakv/npbA0aU2hgCsx/1NUd4IBvV03+aUBWxerw==} + + '@humanfs/core@0.19.1': + resolution: {integrity: sha512-5DyQ4+1JEUzejeK1JGICcideyfUbGixgS9jNgex5nqkW+cY7WZhxBigmieN5Qnw9ZosSNVC9KQKyb+GUaGyKUA==} + engines: {node: '>=18.18.0'} + + '@humanfs/node@0.16.6': + resolution: {integrity: sha512-YuI2ZHQL78Q5HbhDiBA1X4LmYdXCKCMQIfw0pw7piHJwyREFebJUvrQN4cMssyES6x+vfUbx1CIpaQUKYdQZOw==} + engines: {node: '>=18.18.0'} + + '@humanwhocodes/module-importer@1.0.1': + resolution: {integrity: sha512-bxveV4V8v5Yb4ncFTT3rPSgZBOpCkjfK0y4oVVVJwIuDVBRMDXrPyXRL988i5ap9m9bnyEEjWfm5WkBmtffLfA==} + engines: {node: '>=12.22'} + + '@humanwhocodes/retry@0.3.1': + resolution: {integrity: sha512-JBxkERygn7Bv/GbN5Rv8Ul6LVknS+5Bp6RgDC/O8gEBU/yeH5Ui5C/OlWrTb6qct7LjjfT6Re2NxB0ln0yYybA==} + engines: {node: '>=18.18'} + + '@humanwhocodes/retry@0.4.3': + resolution: {integrity: sha512-bV0Tgo9K4hfPCek+aMAn81RppFKv2ySDQeMoSZuvTASywNTnVJCArCZE2FWqpvIatKu7VMRLWlR1EazvVhDyhQ==} + engines: {node: '>=18.18'} + + '@img/sharp-darwin-arm64@0.34.2': + resolution: {integrity: sha512-OfXHZPppddivUJnqyKoi5YVeHRkkNE2zUFT2gbpKxp/JZCFYEYubnMg+gOp6lWfasPrTS+KPosKqdI+ELYVDtg==} + engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0} + cpu: [arm64] + os: [darwin] + + '@img/sharp-darwin-x64@0.34.2': + resolution: {integrity: sha512-dYvWqmjU9VxqXmjEtjmvHnGqF8GrVjM2Epj9rJ6BUIXvk8slvNDJbhGFvIoXzkDhrJC2jUxNLz/GUjjvSzfw+g==} + engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0} + cpu: [x64] + os: [darwin] + + '@img/sharp-libvips-darwin-arm64@1.1.0': + resolution: {integrity: sha512-HZ/JUmPwrJSoM4DIQPv/BfNh9yrOA8tlBbqbLz4JZ5uew2+o22Ik+tHQJcih7QJuSa0zo5coHTfD5J8inqj9DA==} + cpu: [arm64] + os: [darwin] + + '@img/sharp-libvips-darwin-x64@1.1.0': + resolution: {integrity: sha512-Xzc2ToEmHN+hfvsl9wja0RlnXEgpKNmftriQp6XzY/RaSfwD9th+MSh0WQKzUreLKKINb3afirxW7A0fz2YWuQ==} + cpu: [x64] + os: [darwin] + + '@img/sharp-libvips-linux-arm64@1.1.0': + resolution: {integrity: sha512-IVfGJa7gjChDET1dK9SekxFFdflarnUB8PwW8aGwEoF3oAsSDuNUTYS+SKDOyOJxQyDC1aPFMuRYLoDInyV9Ew==} + cpu: [arm64] + os: [linux] + + '@img/sharp-libvips-linux-arm@1.1.0': + resolution: {integrity: sha512-s8BAd0lwUIvYCJyRdFqvsj+BJIpDBSxs6ivrOPm/R7piTs5UIwY5OjXrP2bqXC9/moGsyRa37eYWYCOGVXxVrA==} + cpu: [arm] + os: [linux] + + '@img/sharp-libvips-linux-ppc64@1.1.0': + resolution: {integrity: sha512-tiXxFZFbhnkWE2LA8oQj7KYR+bWBkiV2nilRldT7bqoEZ4HiDOcePr9wVDAZPi/Id5fT1oY9iGnDq20cwUz8lQ==} + cpu: [ppc64] + os: [linux] + + '@img/sharp-libvips-linux-s390x@1.1.0': + resolution: {integrity: sha512-xukSwvhguw7COyzvmjydRb3x/09+21HykyapcZchiCUkTThEQEOMtBj9UhkaBRLuBrgLFzQ2wbxdeCCJW/jgJA==} + cpu: [s390x] + os: [linux] + + '@img/sharp-libvips-linux-x64@1.1.0': + resolution: {integrity: sha512-yRj2+reB8iMg9W5sULM3S74jVS7zqSzHG3Ol/twnAAkAhnGQnpjj6e4ayUz7V+FpKypwgs82xbRdYtchTTUB+Q==} + cpu: [x64] + os: [linux] + + '@img/sharp-libvips-linuxmusl-arm64@1.1.0': + resolution: {integrity: sha512-jYZdG+whg0MDK+q2COKbYidaqW/WTz0cc1E+tMAusiDygrM4ypmSCjOJPmFTvHHJ8j/6cAGyeDWZOsK06tP33w==} + cpu: [arm64] + os: [linux] + + '@img/sharp-libvips-linuxmusl-x64@1.1.0': + resolution: {integrity: sha512-wK7SBdwrAiycjXdkPnGCPLjYb9lD4l6Ze2gSdAGVZrEL05AOUJESWU2lhlC+Ffn5/G+VKuSm6zzbQSzFX/P65A==} + cpu: [x64] + os: [linux] + + '@img/sharp-linux-arm64@0.34.2': + resolution: {integrity: sha512-D8n8wgWmPDakc83LORcfJepdOSN6MvWNzzz2ux0MnIbOqdieRZwVYY32zxVx+IFUT8er5KPcyU3XXsn+GzG/0Q==} + engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0} + cpu: [arm64] + os: [linux] + + '@img/sharp-linux-arm@0.34.2': + resolution: {integrity: sha512-0DZzkvuEOqQUP9mo2kjjKNok5AmnOr1jB2XYjkaoNRwpAYMDzRmAqUIa1nRi58S2WswqSfPOWLNOr0FDT3H5RQ==} + engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0} + cpu: [arm] + os: [linux] + + '@img/sharp-linux-s390x@0.34.2': + resolution: {integrity: sha512-EGZ1xwhBI7dNISwxjChqBGELCWMGDvmxZXKjQRuqMrakhO8QoMgqCrdjnAqJq/CScxfRn+Bb7suXBElKQpPDiw==} + engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0} + cpu: [s390x] + os: [linux] + + '@img/sharp-linux-x64@0.34.2': + resolution: {integrity: sha512-sD7J+h5nFLMMmOXYH4DD9UtSNBD05tWSSdWAcEyzqW8Cn5UxXvsHAxmxSesYUsTOBmUnjtxghKDl15EvfqLFbQ==} + engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0} + cpu: [x64] + os: [linux] + + '@img/sharp-linuxmusl-arm64@0.34.2': + resolution: {integrity: sha512-NEE2vQ6wcxYav1/A22OOxoSOGiKnNmDzCYFOZ949xFmrWZOVII1Bp3NqVVpvj+3UeHMFyN5eP/V5hzViQ5CZNA==} + engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0} + cpu: [arm64] + os: [linux] + + '@img/sharp-linuxmusl-x64@0.34.2': + resolution: {integrity: sha512-DOYMrDm5E6/8bm/yQLCWyuDJwUnlevR8xtF8bs+gjZ7cyUNYXiSf/E8Kp0Ss5xasIaXSHzb888V1BE4i1hFhAA==} + engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0} + cpu: [x64] + os: [linux] + + '@img/sharp-wasm32@0.34.2': + resolution: {integrity: sha512-/VI4mdlJ9zkaq53MbIG6rZY+QRN3MLbR6usYlgITEzi4Rpx5S6LFKsycOQjkOGmqTNmkIdLjEvooFKwww6OpdQ==} + engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0} + cpu: [wasm32] + + '@img/sharp-win32-arm64@0.34.2': + resolution: {integrity: sha512-cfP/r9FdS63VA5k0xiqaNaEoGxBg9k7uE+RQGzuK9fHt7jib4zAVVseR9LsE4gJcNWgT6APKMNnCcnyOtmSEUQ==} + engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0} + cpu: [arm64] + os: [win32] + + '@img/sharp-win32-ia32@0.34.2': + resolution: {integrity: sha512-QLjGGvAbj0X/FXl8n1WbtQ6iVBpWU7JO94u/P2M4a8CFYsvQi4GW2mRy/JqkRx0qpBzaOdKJKw8uc930EX2AHw==} + engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0} + cpu: [ia32] + os: [win32] + + '@img/sharp-win32-x64@0.34.2': + resolution: {integrity: sha512-aUdT6zEYtDKCaxkofmmJDJYGCf0+pJg3eU9/oBuqvEeoB9dKI6ZLc/1iLJCTuJQDO4ptntAlkUmHgGjyuobZbw==} + engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0} + cpu: [x64] + os: [win32] + + '@inquirer/checkbox@4.1.8': + resolution: {integrity: sha512-d/QAsnwuHX2OPolxvYcgSj7A9DO9H6gVOy2DvBTx+P2LH2iRTo/RSGV3iwCzW024nP9hw98KIuDmdyhZQj1UQg==} + engines: {node: '>=18'} + peerDependencies: + '@types/node': '>=18' + peerDependenciesMeta: + '@types/node': + optional: true + + '@inquirer/confirm@5.1.12': + resolution: {integrity: sha512-dpq+ielV9/bqgXRUbNH//KsY6WEw9DrGPmipkpmgC1Y46cwuBTNx7PXFWTjc3MQ+urcc0QxoVHcMI0FW4Ok0hg==} + engines: {node: '>=18'} + peerDependencies: + '@types/node': '>=18' + peerDependenciesMeta: + '@types/node': + optional: true + + '@inquirer/core@10.1.13': + resolution: {integrity: sha512-1viSxebkYN2nJULlzCxES6G9/stgHSepZ9LqqfdIGPHj5OHhiBUXVS0a6R0bEC2A+VL4D9w6QB66ebCr6HGllA==} + engines: {node: '>=18'} + peerDependencies: + '@types/node': '>=18' + peerDependenciesMeta: + '@types/node': + optional: true + + '@inquirer/editor@4.2.13': + resolution: {integrity: sha512-WbicD9SUQt/K8O5Vyk9iC2ojq5RHoCLK6itpp2fHsWe44VxxcA9z3GTWlvjSTGmMQpZr+lbVmrxdHcumJoLbMA==} + engines: {node: '>=18'} + peerDependencies: + '@types/node': '>=18' + peerDependenciesMeta: + '@types/node': + optional: true + + '@inquirer/expand@4.0.15': + resolution: {integrity: sha512-4Y+pbr/U9Qcvf+N/goHzPEXiHH8680lM3Dr3Y9h9FFw4gHS+zVpbj8LfbKWIb/jayIB4aSO4pWiBTrBYWkvi5A==} + engines: {node: '>=18'} + peerDependencies: + '@types/node': '>=18' + peerDependenciesMeta: + '@types/node': + optional: true + + '@inquirer/figures@1.0.12': + resolution: {integrity: sha512-MJttijd8rMFcKJC8NYmprWr6hD3r9Gd9qUC0XwPNwoEPWSMVJwA2MlXxF+nhZZNMY+HXsWa+o7KY2emWYIn0jQ==} + engines: {node: '>=18'} + + '@inquirer/input@4.1.12': + resolution: {integrity: sha512-xJ6PFZpDjC+tC1P8ImGprgcsrzQRsUh9aH3IZixm1lAZFK49UGHxM3ltFfuInN2kPYNfyoPRh+tU4ftsjPLKqQ==} + engines: {node: '>=18'} + peerDependencies: + '@types/node': '>=18' + peerDependenciesMeta: + '@types/node': + optional: true + + '@inquirer/number@3.0.15': + resolution: {integrity: sha512-xWg+iYfqdhRiM55MvqiTCleHzszpoigUpN5+t1OMcRkJrUrw7va3AzXaxvS+Ak7Gny0j2mFSTv2JJj8sMtbV2g==} + engines: {node: '>=18'} + peerDependencies: + '@types/node': '>=18' + peerDependenciesMeta: + '@types/node': + optional: true + + '@inquirer/password@4.0.15': + resolution: {integrity: sha512-75CT2p43DGEnfGTaqFpbDC2p2EEMrq0S+IRrf9iJvYreMy5mAWj087+mdKyLHapUEPLjN10mNvABpGbk8Wdraw==} + engines: {node: '>=18'} + peerDependencies: + '@types/node': '>=18' + peerDependenciesMeta: + '@types/node': + optional: true + + '@inquirer/prompts@7.5.3': + resolution: {integrity: sha512-8YL0WiV7J86hVAxrh3fE5mDCzcTDe1670unmJRz6ArDgN+DBK1a0+rbnNWp4DUB5rPMwqD5ZP6YHl9KK1mbZRg==} + engines: {node: '>=18'} + peerDependencies: + '@types/node': '>=18' + peerDependenciesMeta: + '@types/node': + optional: true + + '@inquirer/rawlist@4.1.3': + resolution: {integrity: sha512-7XrV//6kwYumNDSsvJIPeAqa8+p7GJh7H5kRuxirct2cgOcSWwwNGoXDRgpNFbY/MG2vQ4ccIWCi8+IXXyFMZA==} + engines: {node: '>=18'} + peerDependencies: + '@types/node': '>=18' + peerDependenciesMeta: + '@types/node': + optional: true + + '@inquirer/search@3.0.15': + resolution: {integrity: sha512-YBMwPxYBrADqyvP4nNItpwkBnGGglAvCLVW8u4pRmmvOsHUtCAUIMbUrLX5B3tFL1/WsLGdQ2HNzkqswMs5Uaw==} + engines: {node: '>=18'} + peerDependencies: + '@types/node': '>=18' + peerDependenciesMeta: + '@types/node': + optional: true + + '@inquirer/select@4.2.3': + resolution: {integrity: sha512-OAGhXU0Cvh0PhLz9xTF/kx6g6x+sP+PcyTiLvCrewI99P3BBeexD+VbuwkNDvqGkk3y2h5ZiWLeRP7BFlhkUDg==} + engines: {node: '>=18'} + peerDependencies: + '@types/node': '>=18' + peerDependenciesMeta: + '@types/node': + optional: true + + '@inquirer/type@3.0.7': + resolution: {integrity: sha512-PfunHQcjwnju84L+ycmcMKB/pTPIngjUJvfnRhKY6FKPuYXlM4aQCb/nIdTFR6BEhMjFvngzvng/vBAJMZpLSA==} + engines: {node: '>=18'} + peerDependencies: + '@types/node': '>=18' + peerDependenciesMeta: + '@types/node': + optional: true + + '@ioredis/commands@1.2.0': + resolution: {integrity: sha512-Sx1pU8EM64o2BrqNpEO1CNLtKQwyhuXuqyfH7oGKCk+1a33d2r5saW8zNwm3j6BTExtjrv2BxTgzzkMwts6vGg==} + + '@isaacs/balanced-match@4.0.1': + resolution: {integrity: sha512-yzMTt9lEb8Gv7zRioUilSglI0c0smZ9k5D65677DLWLtWJaXIS3CqcGyUFByYKlnUj6TkjLVs54fBl6+TiGQDQ==} + engines: {node: 20 || >=22} + + '@isaacs/brace-expansion@5.0.0': + resolution: {integrity: sha512-ZT55BDLV0yv0RBm2czMiZ+SqCGO7AvmOM3G/w2xhVPH+te0aKgFjmBvGlL1dH+ql2tgGO3MVrbb3jCKyvpgnxA==} + engines: {node: 20 || >=22} + + '@isaacs/cliui@8.0.2': + resolution: {integrity: sha512-O8jcjabXaleOG9DQ0+ARXWZBTfnP4WNAqzuiJK7ll44AmxGKv/J2M4TPjxjY3znBCfvBXFzucm1twdyFybFqEA==} + engines: {node: '>=12'} + + '@isaacs/fs-minipass@4.0.1': + resolution: {integrity: sha512-wgm9Ehl2jpeqP3zw/7mo3kRHFp5MEDhqAdwy1fTGkHAwnkGOVsgpvQhL8B5n1qlb01jV3n/bI0ZfZp5lWA1k4w==} + engines: {node: '>=18.0.0'} + + '@jridgewell/gen-mapping@0.3.8': + resolution: {integrity: sha512-imAbBGkb+ebQyxKgzv5Hu2nmROxoDOXHh80evxdoXNOrvAnVx7zimzc1Oo5h9RlfV4vPXaE2iM5pOFbvOCClWA==} + engines: {node: '>=6.0.0'} + + '@jridgewell/resolve-uri@3.1.2': + resolution: {integrity: sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw==} + engines: {node: '>=6.0.0'} + + '@jridgewell/set-array@1.2.1': + resolution: {integrity: sha512-R8gLRTZeyp03ymzP/6Lil/28tGeGEzhx1q2k703KGWRAI1VdvPIXdG70VJc2pAMw3NA6JKL5hhFu1sJX0Mnn/A==} + engines: {node: '>=6.0.0'} + + '@jridgewell/sourcemap-codec@1.5.0': + resolution: {integrity: sha512-gv3ZRaISU3fjPAgNsriBRqGWQL6quFx04YMPW/zD8XMLsU32mhCCbfbO6KZFLjvYpCZ8zyDEgqsgf+PwPaM7GQ==} + + '@jridgewell/trace-mapping@0.3.25': + resolution: {integrity: sha512-vNk6aEwybGtawWmy/PzwnGDOjCkLWSD2wqvjGGAgOAwCGWySYXfYoxt00IJkTF+8Lb57DwOb3Aa0o9CApepiYQ==} + + '@jridgewell/trace-mapping@0.3.9': + resolution: {integrity: sha512-3Belt6tdc8bPgAtbcmdtNJlirVoTmEb5e2gC94PnkwEW9jI6CAHUeoG85tjWP5WquqfavoMtMwiG4P926ZKKuQ==} + + '@levischuck/tiny-cbor@0.2.11': + resolution: {integrity: sha512-llBRm4dT4Z89aRsm6u2oEZ8tfwL/2l6BwpZ7JcyieouniDECM5AqNgr/y08zalEIvW3RSK4upYyybDcmjXqAow==} + + '@logtail/core@0.5.4': + resolution: {integrity: sha512-UlbxvUg5MDroqk6gEhtfKuuBShrvD/VaXl3T3jGU1U6I19Y1OwfB7e681LvH7RbsCAnOJFziM/7rMQib/CJTdg==} + + '@logtail/node@0.5.5': + resolution: {integrity: sha512-hSZDjl2wFRxe/+pxSlYNSpm0V3a2ZsiWqBifvtCBHTriwrNkd0LjQtedRlrjoBBumVxIMGdDOCPayAIbcux5YQ==} + + '@logtail/tools@0.5.4': + resolution: {integrity: sha512-S0PtfWOVVgvb36q8mLksMw910mO2TahDaqIYnUM/ZEYX+AwqKRGov4zt/X33zHRzCFVpSKoZFv7bFs8TBie/pQ==} + + '@logtail/types@0.5.3': + resolution: {integrity: sha512-5uKf1xQ7wRqSW0lYIwDpXdXcFHxPKH5EM22MoEjwTpd8suymOYuEdx9qCCHCYey4uOhPq7x6OkZf86bTO83JsA==} + + '@msgpack/msgpack@2.8.0': + resolution: {integrity: sha512-h9u4u/jiIRKbq25PM+zymTyW6bhTzELvOoUd+AvYriWOAKpLGnIamaET3pnHYoI5iYphAHBI4ayx0MehR+VVPQ==} + engines: {node: '>= 10'} + + '@msgpackr-extract/msgpackr-extract-darwin-arm64@3.0.3': + resolution: {integrity: sha512-QZHtlVgbAdy2zAqNA9Gu1UpIuI8Xvsd1v8ic6B2pZmeFnFcMWiPLfWXh7TVw4eGEZ/C9TH281KwhVoeQUKbyjw==} + cpu: [arm64] + os: [darwin] + + '@msgpackr-extract/msgpackr-extract-darwin-x64@3.0.3': + resolution: {integrity: sha512-mdzd3AVzYKuUmiWOQ8GNhl64/IoFGol569zNRdkLReh6LRLHOXxU4U8eq0JwaD8iFHdVGqSy4IjFL4reoWCDFw==} + cpu: [x64] + os: [darwin] + + '@msgpackr-extract/msgpackr-extract-linux-arm64@3.0.3': + resolution: {integrity: sha512-YxQL+ax0XqBJDZiKimS2XQaf+2wDGVa1enVRGzEvLLVFeqa5kx2bWbtcSXgsxjQB7nRqqIGFIcLteF/sHeVtQg==} + cpu: [arm64] + os: [linux] + + '@msgpackr-extract/msgpackr-extract-linux-arm@3.0.3': + resolution: {integrity: sha512-fg0uy/dG/nZEXfYilKoRe7yALaNmHoYeIoJuJ7KJ+YyU2bvY8vPv27f7UKhGRpY6euFYqEVhxCFZgAUNQBM3nw==} + cpu: [arm] + os: [linux] + + '@msgpackr-extract/msgpackr-extract-linux-x64@3.0.3': + resolution: {integrity: sha512-cvwNfbP07pKUfq1uH+S6KJ7dT9K8WOE4ZiAcsrSes+UY55E/0jLYc+vq+DO7jlmqRb5zAggExKm0H7O/CBaesg==} + cpu: [x64] + os: [linux] + + '@msgpackr-extract/msgpackr-extract-win32-x64@3.0.3': + resolution: {integrity: sha512-x0fWaQtYp4E6sktbsdAqnehxDgEc/VwM7uLsRCYWaiGu0ykYdZPiS8zCWdnjHwyiumousxfBm4SO31eXqwEZhQ==} + cpu: [x64] + os: [win32] + + '@next/env@15.3.3': + resolution: {integrity: sha512-OdiMrzCl2Xi0VTjiQQUK0Xh7bJHnOuET2s+3V+Y40WJBAXrJeGA3f+I8MZJ/YQ3mVGi5XGR1L66oFlgqXhQ4Vw==} + + '@next/swc-darwin-arm64@15.3.3': + resolution: {integrity: sha512-WRJERLuH+O3oYB4yZNVahSVFmtxRNjNF1I1c34tYMoJb0Pve+7/RaLAJJizyYiFhjYNGHRAE1Ri2Fd23zgDqhg==} + engines: {node: '>= 10'} + cpu: [arm64] + os: [darwin] + + '@next/swc-darwin-x64@15.3.3': + resolution: {integrity: sha512-XHdzH/yBc55lu78k/XwtuFR/ZXUTcflpRXcsu0nKmF45U96jt1tsOZhVrn5YH+paw66zOANpOnFQ9i6/j+UYvw==} + engines: {node: '>= 10'} + cpu: [x64] + os: [darwin] + + '@next/swc-linux-arm64-gnu@15.3.3': + resolution: {integrity: sha512-VZ3sYL2LXB8znNGcjhocikEkag/8xiLgnvQts41tq6i+wql63SMS1Q6N8RVXHw5pEUjiof+II3HkDd7GFcgkzw==} + engines: {node: '>= 10'} + cpu: [arm64] + os: [linux] + + '@next/swc-linux-arm64-musl@15.3.3': + resolution: {integrity: sha512-h6Y1fLU4RWAp1HPNJWDYBQ+e3G7sLckyBXhmH9ajn8l/RSMnhbuPBV/fXmy3muMcVwoJdHL+UtzRzs0nXOf9SA==} + engines: {node: '>= 10'} + cpu: [arm64] + os: [linux] + + '@next/swc-linux-x64-gnu@15.3.3': + resolution: {integrity: sha512-jJ8HRiF3N8Zw6hGlytCj5BiHyG/K+fnTKVDEKvUCyiQ/0r5tgwO7OgaRiOjjRoIx2vwLR+Rz8hQoPrnmFbJdfw==} + engines: {node: '>= 10'} + cpu: [x64] + os: [linux] + + '@next/swc-linux-x64-musl@15.3.3': + resolution: {integrity: sha512-HrUcTr4N+RgiiGn3jjeT6Oo208UT/7BuTr7K0mdKRBtTbT4v9zJqCDKO97DUqqoBK1qyzP1RwvrWTvU6EPh/Cw==} + engines: {node: '>= 10'} + cpu: [x64] + os: [linux] + + '@next/swc-win32-arm64-msvc@15.3.3': + resolution: {integrity: sha512-SxorONgi6K7ZUysMtRF3mIeHC5aA3IQLmKFQzU0OuhuUYwpOBc1ypaLJLP5Bf3M9k53KUUUj4vTPwzGvl/NwlQ==} + engines: {node: '>= 10'} + cpu: [arm64] + os: [win32] + + '@next/swc-win32-x64-msvc@15.3.3': + resolution: {integrity: sha512-4QZG6F8enl9/S2+yIiOiju0iCTFd93d8VC1q9LZS4p/Xuk81W2QDjCFeoogmrWWkAD59z8ZxepBQap2dKS5ruw==} + engines: {node: '>= 10'} + cpu: [x64] + os: [win32] + + '@noble/ciphers@0.6.0': + resolution: {integrity: sha512-mIbq/R9QXk5/cTfESb1OKtyFnk7oc1Om/8onA1158K9/OZUQFDEVy55jVTato+xmp3XX6F6Qh0zz0Nc1AxAlRQ==} + + '@noble/hashes@1.8.0': + resolution: {integrity: sha512-jCs9ldd7NwzpgXDIf6P3+NrHh9/sD6CQdxHyjQI+h/6rDNo88ypBxxz45UDuZHz9r3tNz7N/VInSVoVdtXEI4A==} + engines: {node: ^14.21.3 || >=16} + + '@nodelib/fs.scandir@2.1.5': + resolution: {integrity: sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==} + engines: {node: '>= 8'} + + '@nodelib/fs.stat@2.0.5': + resolution: {integrity: sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==} + engines: {node: '>= 8'} + + '@nodelib/fs.walk@1.2.8': + resolution: {integrity: sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==} + engines: {node: '>= 8'} + + '@opentelemetry/api@1.9.0': + resolution: {integrity: sha512-3giAOQvZiH5F9bMlMiv8+GSPMeqg0dbaeo58/0SlA9sxSqZhnUtxzX9/2FzyhS9sWQf5S0GJE0AKBrFqjpeYcg==} + engines: {node: '>=8.0.0'} + + '@paralleldrive/cuid2@2.2.2': + resolution: {integrity: sha512-ZOBkgDwEdoYVlSeRbYYXs0S9MejQofiVYoTbKzy/6GQa39/q5tQU2IX46+shYnUkpEl3wc+J6wRlar7r2EK2xA==} + + '@peculiar/asn1-android@2.3.16': + resolution: {integrity: sha512-a1viIv3bIahXNssrOIkXZIlI2ePpZaNmR30d4aBL99mu2rO+mT9D6zBsp7H6eROWGtmwv0Ionp5olJurIo09dw==} + + '@peculiar/asn1-ecc@2.3.15': + resolution: {integrity: sha512-/HtR91dvgog7z/WhCVdxZJ/jitJuIu8iTqiyWVgRE9Ac5imt2sT/E4obqIVGKQw7PIy+X6i8lVBoT6wC73XUgA==} + + '@peculiar/asn1-rsa@2.3.15': + resolution: {integrity: sha512-p6hsanvPhexRtYSOHihLvUUgrJ8y0FtOM97N5UEpC+VifFYyZa0iZ5cXjTkZoDwxJ/TTJ1IJo3HVTB2JJTpXvg==} + + '@peculiar/asn1-schema@2.3.15': + resolution: {integrity: sha512-QPeD8UA8axQREpgR5UTAfu2mqQmm97oUqahDtNdBcfj3qAnoXzFdQW+aNf/tD2WVXF8Fhmftxoj0eMIT++gX2w==} + + '@peculiar/asn1-x509@2.3.15': + resolution: {integrity: sha512-0dK5xqTqSLaxv1FHXIcd4Q/BZNuopg+u1l23hT9rOmQ1g4dNtw0g/RnEi+TboB0gOwGtrWn269v27cMgchFIIg==} + + '@pkgjs/parseargs@0.11.0': + resolution: {integrity: sha512-+1VkjdD0QBLPodGrJUeqarH8VAIvQODIbwh9XpP5Syisf7YoQgsJKPNFoqqLQlu+VQ/tVSshMR6loPMn8U+dPg==} + engines: {node: '>=14'} + + '@puppeteer/browsers@2.10.5': + resolution: {integrity: sha512-eifa0o+i8dERnngJwKrfp3dEq7ia5XFyoqB17S4gK8GhsQE4/P8nxOfQSE0zQHxzzLo/cmF+7+ywEQ7wK7Fb+w==} + engines: {node: '>=18'} + hasBin: true + + '@radix-ui/number@1.1.1': + resolution: {integrity: sha512-MkKCwxlXTgz6CFoJx3pCwn07GKp36+aZyu/u2Ln2VrA5DcdyCZkASEDBTd8x5whTQQL5CiYf4prXKLcgQdv29g==} + + '@radix-ui/primitive@1.1.2': + resolution: {integrity: sha512-XnbHrrprsNqZKQhStrSwgRUQzoCI1glLzdw79xiZPoofhGICeZRSQ3dIxAKH1gb3OHfNf4d6f+vAv3kil2eggA==} + + '@radix-ui/react-accordion@1.2.11': + resolution: {integrity: sha512-l3W5D54emV2ues7jjeG1xcyN7S3jnK3zE2zHqgn0CmMsy9lNJwmgcrmaxS+7ipw15FAivzKNzH3d5EcGoFKw0A==} + peerDependencies: + '@types/react': '*' + '@types/react-dom': '*' + react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc + react-dom: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc + peerDependenciesMeta: + '@types/react': + optional: true + '@types/react-dom': + optional: true + + '@radix-ui/react-arrow@1.1.7': + resolution: {integrity: sha512-F+M1tLhO+mlQaOWspE8Wstg+z6PwxwRd8oQ8IXceWz92kfAmalTRf0EjrouQeo7QssEPfCn05B4Ihs1K9WQ/7w==} + peerDependencies: + '@types/react': '*' + '@types/react-dom': '*' + react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc + react-dom: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc + peerDependenciesMeta: + '@types/react': + optional: true + '@types/react-dom': + optional: true + + '@radix-ui/react-checkbox@1.3.2': + resolution: {integrity: sha512-yd+dI56KZqawxKZrJ31eENUwqc1QSqg4OZ15rybGjF2ZNwMO+wCyHzAVLRp9qoYJf7kYy0YpZ2b0JCzJ42HZpA==} + peerDependencies: + '@types/react': '*' + '@types/react-dom': '*' + react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc + react-dom: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc + peerDependenciesMeta: + '@types/react': + optional: true + '@types/react-dom': + optional: true + + '@radix-ui/react-collapsible@1.1.11': + resolution: {integrity: sha512-2qrRsVGSCYasSz1RFOorXwl0H7g7J1frQtgpQgYrt+MOidtPAINHn9CPovQXb83r8ahapdx3Tu0fa/pdFFSdPg==} + peerDependencies: + '@types/react': '*' + '@types/react-dom': '*' + react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc + react-dom: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc + peerDependenciesMeta: + '@types/react': + optional: true + '@types/react-dom': + optional: true + + '@radix-ui/react-collection@1.1.7': + resolution: {integrity: sha512-Fh9rGN0MoI4ZFUNyfFVNU4y9LUz93u9/0K+yLgA2bwRojxM8JU1DyvvMBabnZPBgMWREAJvU2jjVzq+LrFUglw==} + peerDependencies: + '@types/react': '*' + '@types/react-dom': '*' + react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc + react-dom: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc + peerDependenciesMeta: + '@types/react': + optional: true + '@types/react-dom': + optional: true + + '@radix-ui/react-compose-refs@1.1.2': + resolution: {integrity: sha512-z4eqJvfiNnFMHIIvXP3CY57y2WJs5g2v3X0zm9mEJkrkNv4rDxu+sg9Jh8EkXyeqBkB7SOcboo9dMVqhyrACIg==} + peerDependencies: + '@types/react': '*' + react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc + peerDependenciesMeta: + '@types/react': + optional: true + + '@radix-ui/react-context@1.1.2': + resolution: {integrity: sha512-jCi/QKUM2r1Ju5a3J64TH2A5SpKAgh0LpknyqdQ4m6DCV0xJ2HG1xARRwNGPQfi1SLdLWZ1OJz6F4OMBBNiGJA==} + peerDependencies: + '@types/react': '*' + react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc + peerDependenciesMeta: + '@types/react': + optional: true + + '@radix-ui/react-dialog@1.1.14': + resolution: {integrity: sha512-+CpweKjqpzTmwRwcYECQcNYbI8V9VSQt0SNFKeEBLgfucbsLssU6Ppq7wUdNXEGb573bMjFhVjKVll8rmV6zMw==} + peerDependencies: + '@types/react': '*' + '@types/react-dom': '*' + react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc + react-dom: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc + peerDependenciesMeta: + '@types/react': + optional: true + '@types/react-dom': + optional: true + + '@radix-ui/react-direction@1.1.1': + resolution: {integrity: sha512-1UEWRX6jnOA2y4H5WczZ44gOOjTEmlqv1uNW4GAJEO5+bauCBhv8snY65Iw5/VOS/ghKN9gr2KjnLKxrsvoMVw==} + peerDependencies: + '@types/react': '*' + react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc + peerDependenciesMeta: + '@types/react': + optional: true + + '@radix-ui/react-dismissable-layer@1.1.10': + resolution: {integrity: sha512-IM1zzRV4W3HtVgftdQiiOmA0AdJlCtMLe00FXaHwgt3rAnNsIyDqshvkIW3hj/iu5hu8ERP7KIYki6NkqDxAwQ==} + peerDependencies: + '@types/react': '*' + '@types/react-dom': '*' + react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc + react-dom: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc + peerDependenciesMeta: + '@types/react': + optional: true + '@types/react-dom': + optional: true + + '@radix-ui/react-dropdown-menu@2.1.15': + resolution: {integrity: sha512-mIBnOjgwo9AH3FyKaSWoSu/dYj6VdhJ7frEPiGTeXCdUFHjl9h3mFh2wwhEtINOmYXWhdpf1rY2minFsmaNgVQ==} + peerDependencies: + '@types/react': '*' + '@types/react-dom': '*' + react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc + react-dom: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc + peerDependenciesMeta: + '@types/react': + optional: true + '@types/react-dom': + optional: true + + '@radix-ui/react-focus-guards@1.1.2': + resolution: {integrity: sha512-fyjAACV62oPV925xFCrH8DR5xWhg9KYtJT4s3u54jxp+L/hbpTY2kIeEFFbFe+a/HCE94zGQMZLIpVTPVZDhaA==} + peerDependencies: + '@types/react': '*' + react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc + peerDependenciesMeta: + '@types/react': + optional: true + + '@radix-ui/react-focus-scope@1.1.7': + resolution: {integrity: sha512-t2ODlkXBQyn7jkl6TNaw/MtVEVvIGelJDCG41Okq/KwUsJBwQ4XVZsHAVUkK4mBv3ewiAS3PGuUWuY2BoK4ZUw==} + peerDependencies: + '@types/react': '*' + '@types/react-dom': '*' + react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc + react-dom: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc + peerDependenciesMeta: + '@types/react': + optional: true + '@types/react-dom': + optional: true + + '@radix-ui/react-id@1.1.1': + resolution: {integrity: sha512-kGkGegYIdQsOb4XjsfM97rXsiHaBwco+hFI66oO4s9LU+PLAC5oJ7khdOVFxkhsmlbpUqDAvXw11CluXP+jkHg==} + peerDependencies: + '@types/react': '*' + react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc + peerDependenciesMeta: + '@types/react': + optional: true + + '@radix-ui/react-menu@2.1.15': + resolution: {integrity: sha512-tVlmA3Vb9n8SZSd+YSbuFR66l87Wiy4du+YE+0hzKQEANA+7cWKH1WgqcEX4pXqxUFQKrWQGHdvEfw00TjFiew==} + peerDependencies: + '@types/react': '*' + '@types/react-dom': '*' + react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc + react-dom: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc + peerDependenciesMeta: + '@types/react': + optional: true + '@types/react-dom': + optional: true + + '@radix-ui/react-popover@1.1.14': + resolution: {integrity: sha512-ODz16+1iIbGUfFEfKx2HTPKizg2MN39uIOV8MXeHnmdd3i/N9Wt7vU46wbHsqA0xoaQyXVcs0KIlBdOA2Y95bw==} + peerDependencies: + '@types/react': '*' + '@types/react-dom': '*' + react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc + react-dom: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc + peerDependenciesMeta: + '@types/react': + optional: true + '@types/react-dom': + optional: true + + '@radix-ui/react-popper@1.2.7': + resolution: {integrity: sha512-IUFAccz1JyKcf/RjB552PlWwxjeCJB8/4KxT7EhBHOJM+mN7LdW+B3kacJXILm32xawcMMjb2i0cIZpo+f9kiQ==} + peerDependencies: + '@types/react': '*' + '@types/react-dom': '*' + react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc + react-dom: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc + peerDependenciesMeta: + '@types/react': + optional: true + '@types/react-dom': + optional: true + + '@radix-ui/react-portal@1.1.9': + resolution: {integrity: sha512-bpIxvq03if6UNwXZ+HTK71JLh4APvnXntDc6XOX8UVq4XQOVl7lwok0AvIl+b8zgCw3fSaVTZMpAPPagXbKmHQ==} + peerDependencies: + '@types/react': '*' + '@types/react-dom': '*' + react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc + react-dom: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc + peerDependenciesMeta: + '@types/react': + optional: true + '@types/react-dom': + optional: true + + '@radix-ui/react-presence@1.1.4': + resolution: {integrity: sha512-ueDqRbdc4/bkaQT3GIpLQssRlFgWaL/U2z/S31qRwwLWoxHLgry3SIfCwhxeQNbirEUXFa+lq3RL3oBYXtcmIA==} + peerDependencies: + '@types/react': '*' + '@types/react-dom': '*' + react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc + react-dom: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc + peerDependenciesMeta: + '@types/react': + optional: true + '@types/react-dom': + optional: true + + '@radix-ui/react-primitive@2.1.3': + resolution: {integrity: sha512-m9gTwRkhy2lvCPe6QJp4d3G1TYEUHn/FzJUtq9MjH46an1wJU+GdoGC5VLof8RX8Ft/DlpshApkhswDLZzHIcQ==} + peerDependencies: + '@types/react': '*' + '@types/react-dom': '*' + react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc + react-dom: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc + peerDependenciesMeta: + '@types/react': + optional: true + '@types/react-dom': + optional: true + + '@radix-ui/react-roving-focus@1.1.10': + resolution: {integrity: sha512-dT9aOXUen9JSsxnMPv/0VqySQf5eDQ6LCk5Sw28kamz8wSOW2bJdlX2Bg5VUIIcV+6XlHpWTIuTPCf/UNIyq8Q==} + peerDependencies: + '@types/react': '*' + '@types/react-dom': '*' + react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc + react-dom: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc + peerDependenciesMeta: + '@types/react': + optional: true + '@types/react-dom': + optional: true + + '@radix-ui/react-scroll-area@1.2.9': + resolution: {integrity: sha512-YSjEfBXnhUELsO2VzjdtYYD4CfQjvao+lhhrX5XsHD7/cyUNzljF1FHEbgTPN7LH2MClfwRMIsYlqTYpKTTe2A==} + peerDependencies: + '@types/react': '*' + '@types/react-dom': '*' + react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc + react-dom: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc + peerDependenciesMeta: + '@types/react': + optional: true + '@types/react-dom': + optional: true + + '@radix-ui/react-select@2.2.5': + resolution: {integrity: sha512-HnMTdXEVuuyzx63ME0ut4+sEMYW6oouHWNGUZc7ddvUWIcfCva/AMoqEW/3wnEllriMWBa0RHspCYnfCWJQYmA==} + peerDependencies: + '@types/react': '*' + '@types/react-dom': '*' + react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc + react-dom: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc + peerDependenciesMeta: + '@types/react': + optional: true + '@types/react-dom': + optional: true + + '@radix-ui/react-separator@1.1.7': + resolution: {integrity: sha512-0HEb8R9E8A+jZjvmFCy/J4xhbXy3TV+9XSnGJ3KvTtjlIUy/YQ/p6UYZvi7YbeoeXdyU9+Y3scizK6hkY37baA==} + peerDependencies: + '@types/react': '*' + '@types/react-dom': '*' + react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc + react-dom: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc + peerDependenciesMeta: + '@types/react': + optional: true + '@types/react-dom': + optional: true + + '@radix-ui/react-slot@1.2.3': + resolution: {integrity: sha512-aeNmHnBxbi2St0au6VBVC7JXFlhLlOnvIIlePNniyUNAClzmtAUEY8/pBiK3iHjufOlwA+c20/8jngo7xcrg8A==} + peerDependencies: + '@types/react': '*' + react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc + peerDependenciesMeta: + '@types/react': + optional: true + + '@radix-ui/react-switch@1.2.5': + resolution: {integrity: sha512-5ijLkak6ZMylXsaImpZ8u4Rlf5grRmoc0p0QeX9VJtlrM4f5m3nCTX8tWga/zOA8PZYIR/t0p2Mnvd7InrJ6yQ==} + peerDependencies: + '@types/react': '*' + '@types/react-dom': '*' + react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc + react-dom: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc + peerDependenciesMeta: + '@types/react': + optional: true + '@types/react-dom': + optional: true + + '@radix-ui/react-tabs@1.1.12': + resolution: {integrity: sha512-GTVAlRVrQrSw3cEARM0nAx73ixrWDPNZAruETn3oHCNP6SbZ/hNxdxp+u7VkIEv3/sFoLq1PfcHrl7Pnp0CDpw==} + peerDependencies: + '@types/react': '*' + '@types/react-dom': '*' + react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc + react-dom: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc + peerDependenciesMeta: + '@types/react': + optional: true + '@types/react-dom': + optional: true + + '@radix-ui/react-tooltip@1.2.7': + resolution: {integrity: sha512-Ap+fNYwKTYJ9pzqW+Xe2HtMRbQ/EeWkj2qykZ6SuEV4iS/o1bZI5ssJbk4D2r8XuDuOBVz/tIx2JObtuqU+5Zw==} + peerDependencies: + '@types/react': '*' + '@types/react-dom': '*' + react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc + react-dom: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc + peerDependenciesMeta: + '@types/react': + optional: true + '@types/react-dom': + optional: true + + '@radix-ui/react-use-callback-ref@1.1.1': + resolution: {integrity: sha512-FkBMwD+qbGQeMu1cOHnuGB6x4yzPjho8ap5WtbEJ26umhgqVXbhekKUQO+hZEL1vU92a3wHwdp0HAcqAUF5iDg==} + peerDependencies: + '@types/react': '*' + react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc + peerDependenciesMeta: + '@types/react': + optional: true + + '@radix-ui/react-use-controllable-state@1.2.2': + resolution: {integrity: sha512-BjasUjixPFdS+NKkypcyyN5Pmg83Olst0+c6vGov0diwTEo6mgdqVR6hxcEgFuh4QrAs7Rc+9KuGJ9TVCj0Zzg==} + peerDependencies: + '@types/react': '*' + react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc + peerDependenciesMeta: + '@types/react': + optional: true + + '@radix-ui/react-use-effect-event@0.0.2': + resolution: {integrity: sha512-Qp8WbZOBe+blgpuUT+lw2xheLP8q0oatc9UpmiemEICxGvFLYmHm9QowVZGHtJlGbS6A6yJ3iViad/2cVjnOiA==} + peerDependencies: + '@types/react': '*' + react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc + peerDependenciesMeta: + '@types/react': + optional: true + + '@radix-ui/react-use-escape-keydown@1.1.1': + resolution: {integrity: sha512-Il0+boE7w/XebUHyBjroE+DbByORGR9KKmITzbR7MyQ4akpORYP/ZmbhAr0DG7RmmBqoOnZdy2QlvajJ2QA59g==} + peerDependencies: + '@types/react': '*' + react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc + peerDependenciesMeta: + '@types/react': + optional: true + + '@radix-ui/react-use-layout-effect@1.1.1': + resolution: {integrity: sha512-RbJRS4UWQFkzHTTwVymMTUv8EqYhOp8dOOviLj2ugtTiXRaRQS7GLGxZTLL1jWhMeoSCf5zmcZkqTl9IiYfXcQ==} + peerDependencies: + '@types/react': '*' + react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc + peerDependenciesMeta: + '@types/react': + optional: true + + '@radix-ui/react-use-previous@1.1.1': + resolution: {integrity: sha512-2dHfToCj/pzca2Ck724OZ5L0EVrr3eHRNsG/b3xQJLA2hZpVCS99bLAX+hm1IHXDEnzU6by5z/5MIY794/a8NQ==} + peerDependencies: + '@types/react': '*' + react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc + peerDependenciesMeta: + '@types/react': + optional: true + + '@radix-ui/react-use-rect@1.1.1': + resolution: {integrity: sha512-QTYuDesS0VtuHNNvMh+CjlKJ4LJickCMUAqjlE3+j8w+RlRpwyX3apEQKGFzbZGdo7XNG1tXa+bQqIE7HIXT2w==} + peerDependencies: + '@types/react': '*' + react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc + peerDependenciesMeta: + '@types/react': + optional: true + + '@radix-ui/react-use-size@1.1.1': + resolution: {integrity: sha512-ewrXRDTAqAXlkl6t/fkXWNAhFX9I+CkKlw6zjEwk86RSPKwZr3xpBRso655aqYafwtnbpHLj6toFzmd6xdVptQ==} + peerDependencies: + '@types/react': '*' + react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc + peerDependenciesMeta: + '@types/react': + optional: true + + '@radix-ui/react-visually-hidden@1.2.3': + resolution: {integrity: sha512-pzJq12tEaaIhqjbzpCuv/OypJY/BPavOofm+dbab+MHLajy277+1lLm6JFcGgF5eskJ6mquGirhXY2GD/8u8Ug==} + peerDependencies: + '@types/react': '*' + '@types/react-dom': '*' + react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc + react-dom: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc + peerDependenciesMeta: + '@types/react': + optional: true + '@types/react-dom': + optional: true + + '@radix-ui/rect@1.1.1': + resolution: {integrity: sha512-HPwpGIzkl28mWyZqG52jiqDJ12waP11Pa1lGoiyUkIEuMLBP0oeK/C89esbXrxsky5we7dfd8U58nm0SgAWpVw==} + + '@react-email/body@0.0.11': + resolution: {integrity: sha512-ZSD2SxVSgUjHGrB0Wi+4tu3MEpB4fYSbezsFNEJk2xCWDBkFiOeEsjTmR5dvi+CxTK691hQTQlHv0XWuP7ENTg==} + peerDependencies: + react: ^18.0 || ^19.0 || ^19.0.0-rc + + '@react-email/button@0.0.19': + resolution: {integrity: sha512-HYHrhyVGt7rdM/ls6FuuD6XE7fa7bjZTJqB2byn6/oGsfiEZaogY77OtoLL/mrQHjHjZiJadtAMSik9XLcm7+A==} + engines: {node: '>=18.0.0'} + peerDependencies: + react: ^18.0 || ^19.0 || ^19.0.0-rc + + '@react-email/code-block@0.0.13': + resolution: {integrity: sha512-4DE4yPSgKEOnZMzcrDvRuD6mxsNxOex0hCYEG9F9q23geYgb2WCCeGBvIUXVzK69l703Dg4Vzrd5qUjl+JfcwA==} + engines: {node: '>=18.0.0'} + peerDependencies: + react: ^18.0 || ^19.0 || ^19.0.0-rc + + '@react-email/code-inline@0.0.5': + resolution: {integrity: sha512-MmAsOzdJpzsnY2cZoPHFPk6uDO/Ncpb4Kh1hAt9UZc1xOW3fIzpe1Pi9y9p6wwUmpaeeDalJxAxH6/fnTquinA==} + engines: {node: '>=18.0.0'} + peerDependencies: + react: ^18.0 || ^19.0 || ^19.0.0-rc + + '@react-email/column@0.0.13': + resolution: {integrity: sha512-Lqq17l7ShzJG/d3b1w/+lVO+gp2FM05ZUo/nW0rjxB8xBICXOVv6PqjDnn3FXKssvhO5qAV20lHM6S+spRhEwQ==} + engines: {node: '>=18.0.0'} + peerDependencies: + react: ^18.0 || ^19.0 || ^19.0.0-rc + + '@react-email/components@0.0.42': + resolution: {integrity: sha512-KZtf7RjCoLgEwa5swrsbEF/liGrmfMlZCDNDXqaAjlgF3iRq0h5KY/HNMs6LbLmW7fEneRhnynrwApwbkEwe+A==} + engines: {node: '>=18.0.0'} + peerDependencies: + react: ^18.0 || ^19.0 || ^19.0.0-rc + + '@react-email/container@0.0.15': + resolution: {integrity: sha512-Qo2IQo0ru2kZq47REmHW3iXjAQaKu4tpeq/M8m1zHIVwKduL2vYOBQWbC2oDnMtWPmkBjej6XxgtZByxM6cCFg==} + engines: {node: '>=18.0.0'} + peerDependencies: + react: ^18.0 || ^19.0 || ^19.0.0-rc + + '@react-email/font@0.0.9': + resolution: {integrity: sha512-4zjq23oT9APXkerqeslPH3OZWuh5X4crHK6nx82mVHV2SrLba8+8dPEnWbaACWTNjOCbcLIzaC9unk7Wq2MIXw==} + peerDependencies: + react: ^18.0 || ^19.0 || ^19.0.0-rc + + '@react-email/head@0.0.12': + resolution: {integrity: sha512-X2Ii6dDFMF+D4niNwMAHbTkeCjlYYnMsd7edXOsi0JByxt9wNyZ9EnhFiBoQdqkE+SMDcu8TlNNttMrf5sJeMA==} + engines: {node: '>=18.0.0'} + peerDependencies: + react: ^18.0 || ^19.0 || ^19.0.0-rc + + '@react-email/heading@0.0.15': + resolution: {integrity: sha512-xF2GqsvBrp/HbRHWEfOgSfRFX+Q8I5KBEIG5+Lv3Vb2R/NYr0s8A5JhHHGf2pWBMJdbP4B2WHgj/VUrhy8dkIg==} + engines: {node: '>=18.0.0'} + peerDependencies: + react: ^18.0 || ^19.0 || ^19.0.0-rc + + '@react-email/hr@0.0.11': + resolution: {integrity: sha512-S1gZHVhwOsd1Iad5IFhpfICwNPMGPJidG/Uysy1AwmspyoAP5a4Iw3OWEpINFdgh9MHladbxcLKO2AJO+cA9Lw==} + engines: {node: '>=18.0.0'} + peerDependencies: + react: ^18.0 || ^19.0 || ^19.0.0-rc + + '@react-email/html@0.0.11': + resolution: {integrity: sha512-qJhbOQy5VW5qzU74AimjAR9FRFQfrMa7dn4gkEXKMB/S9xZN8e1yC1uA9C15jkXI/PzmJ0muDIWmFwatm5/+VA==} + engines: {node: '>=18.0.0'} + peerDependencies: + react: ^18.0 || ^19.0 || ^19.0.0-rc + + '@react-email/img@0.0.11': + resolution: {integrity: sha512-aGc8Y6U5C3igoMaqAJKsCpkbm1XjguQ09Acd+YcTKwjnC2+0w3yGUJkjWB2vTx4tN8dCqQCXO8FmdJpMfOA9EQ==} + engines: {node: '>=18.0.0'} + peerDependencies: + react: ^18.0 || ^19.0 || ^19.0.0-rc + + '@react-email/link@0.0.12': + resolution: {integrity: sha512-vF+xxQk2fGS1CN7UPQDbzvcBGfffr+GjTPNiWM38fhBfsLv6A/YUfaqxWlmL7zLzVmo0K2cvvV9wxlSyNba1aQ==} + engines: {node: '>=18.0.0'} + peerDependencies: + react: ^18.0 || ^19.0 || ^19.0.0-rc + + '@react-email/markdown@0.0.15': + resolution: {integrity: sha512-UQA9pVm5sbflgtg3EX3FquUP4aMBzmLReLbGJ6DZQZnAskBF36aI56cRykDq1o+1jT+CKIK1CducPYziaXliag==} + engines: {node: '>=18.0.0'} + peerDependencies: + react: ^18.0 || ^19.0 || ^19.0.0-rc + + '@react-email/preview@0.0.13': + resolution: {integrity: sha512-F7j9FJ0JN/A4d7yr+aw28p4uX7VLWs7hTHtLo7WRyw4G+Lit6Zucq4UWKRxJC8lpsUdzVmG7aBJnKOT+urqs/w==} + engines: {node: '>=18.0.0'} + peerDependencies: + react: ^18.0 || ^19.0 || ^19.0.0-rc + + '@react-email/render@1.1.2': + resolution: {integrity: sha512-RnRehYN3v9gVlNMehHPHhyp2RQo7+pSkHDtXPvg3s0GbzM9SQMW4Qrf8GRNvtpLC4gsI+Wt0VatNRUFqjvevbw==} + engines: {node: '>=18.0.0'} + peerDependencies: + react: ^18.0 || ^19.0 || ^19.0.0-rc + react-dom: ^18.0 || ^19.0 || ^19.0.0-rc + + '@react-email/row@0.0.12': + resolution: {integrity: sha512-HkCdnEjvK3o+n0y0tZKXYhIXUNPDx+2vq1dJTmqappVHXS5tXS6W5JOPZr5j+eoZ8gY3PShI2LWj5rWF7ZEtIQ==} + engines: {node: '>=18.0.0'} + peerDependencies: + react: ^18.0 || ^19.0 || ^19.0.0-rc + + '@react-email/section@0.0.16': + resolution: {integrity: sha512-FjqF9xQ8FoeUZYKSdt8sMIKvoT9XF8BrzhT3xiFKdEMwYNbsDflcjfErJe3jb7Wj/es/lKTbV5QR1dnLzGpL3w==} + engines: {node: '>=18.0.0'} + peerDependencies: + react: ^18.0 || ^19.0 || ^19.0.0-rc + + '@react-email/tailwind@1.0.5': + resolution: {integrity: sha512-BH00cZSeFfP9HiDASl+sPHi7Hh77W5nzDgdnxtsVr/m3uQD9g180UwxcE3PhOfx0vRdLzQUU8PtmvvDfbztKQg==} + engines: {node: '>=18.0.0'} + peerDependencies: + react: ^18.0 || ^19.0 || ^19.0.0-rc + + '@react-email/text@0.1.5': + resolution: {integrity: sha512-o5PNHFSE085VMXayxH+SJ1LSOtGsTv+RpNKnTiJDrJUwoBu77G3PlKOsZZQHCNyD28WsQpl9v2WcJLbQudqwPg==} + engines: {node: '>=18.0.0'} + peerDependencies: + react: ^18.0 || ^19.0 || ^19.0.0-rc + + '@rolldown/pluginutils@1.0.0-beta.11': + resolution: {integrity: sha512-L/gAA/hyCSuzTF1ftlzUSI/IKr2POHsv1Dd78GfqkR83KMNuswWD61JxGV2L7nRwBBBSDr6R1gCkdTmoN7W4ag==} + + '@rollup/rollup-android-arm-eabi@4.43.0': + resolution: {integrity: sha512-Krjy9awJl6rKbruhQDgivNbD1WuLb8xAclM4IR4cN5pHGAs2oIMMQJEiC3IC/9TZJ+QZkmZhlMO/6MBGxPidpw==} + cpu: [arm] + os: [android] + + '@rollup/rollup-android-arm64@4.43.0': + resolution: {integrity: sha512-ss4YJwRt5I63454Rpj+mXCXicakdFmKnUNxr1dLK+5rv5FJgAxnN7s31a5VchRYxCFWdmnDWKd0wbAdTr0J5EA==} + cpu: [arm64] + os: [android] + + '@rollup/rollup-darwin-arm64@4.43.0': + resolution: {integrity: sha512-eKoL8ykZ7zz8MjgBenEF2OoTNFAPFz1/lyJ5UmmFSz5jW+7XbH1+MAgCVHy72aG59rbuQLcJeiMrP8qP5d/N0A==} + cpu: [arm64] + os: [darwin] + + '@rollup/rollup-darwin-x64@4.43.0': + resolution: {integrity: sha512-SYwXJgaBYW33Wi/q4ubN+ldWC4DzQY62S4Ll2dgfr/dbPoF50dlQwEaEHSKrQdSjC6oIe1WgzosoaNoHCdNuMg==} + cpu: [x64] + os: [darwin] + + '@rollup/rollup-freebsd-arm64@4.43.0': + resolution: {integrity: sha512-SV+U5sSo0yujrjzBF7/YidieK2iF6E7MdF6EbYxNz94lA+R0wKl3SiixGyG/9Klab6uNBIqsN7j4Y/Fya7wAjQ==} + cpu: [arm64] + os: [freebsd] + + '@rollup/rollup-freebsd-x64@4.43.0': + resolution: {integrity: sha512-J7uCsiV13L/VOeHJBo5SjasKiGxJ0g+nQTrBkAsmQBIdil3KhPnSE9GnRon4ejX1XDdsmK/l30IYLiAaQEO0Cg==} + cpu: [x64] + os: [freebsd] + + '@rollup/rollup-linux-arm-gnueabihf@4.43.0': + resolution: {integrity: sha512-gTJ/JnnjCMc15uwB10TTATBEhK9meBIY+gXP4s0sHD1zHOaIh4Dmy1X9wup18IiY9tTNk5gJc4yx9ctj/fjrIw==} + cpu: [arm] + os: [linux] + + '@rollup/rollup-linux-arm-musleabihf@4.43.0': + resolution: {integrity: sha512-ZJ3gZynL1LDSIvRfz0qXtTNs56n5DI2Mq+WACWZ7yGHFUEirHBRt7fyIk0NsCKhmRhn7WAcjgSkSVVxKlPNFFw==} + cpu: [arm] + os: [linux] + + '@rollup/rollup-linux-arm64-gnu@4.43.0': + resolution: {integrity: sha512-8FnkipasmOOSSlfucGYEu58U8cxEdhziKjPD2FIa0ONVMxvl/hmONtX/7y4vGjdUhjcTHlKlDhw3H9t98fPvyA==} + cpu: [arm64] + os: [linux] + + '@rollup/rollup-linux-arm64-musl@4.43.0': + resolution: {integrity: sha512-KPPyAdlcIZ6S9C3S2cndXDkV0Bb1OSMsX0Eelr2Bay4EsF9yi9u9uzc9RniK3mcUGCLhWY9oLr6er80P5DE6XA==} + cpu: [arm64] + os: [linux] + + '@rollup/rollup-linux-loongarch64-gnu@4.43.0': + resolution: {integrity: sha512-HPGDIH0/ZzAZjvtlXj6g+KDQ9ZMHfSP553za7o2Odegb/BEfwJcR0Sw0RLNpQ9nC6Gy8s+3mSS9xjZ0n3rhcYg==} + cpu: [loong64] + os: [linux] + + '@rollup/rollup-linux-powerpc64le-gnu@4.43.0': + resolution: {integrity: sha512-gEmwbOws4U4GLAJDhhtSPWPXUzDfMRedT3hFMyRAvM9Mrnj+dJIFIeL7otsv2WF3D7GrV0GIewW0y28dOYWkmw==} + cpu: [ppc64] + os: [linux] + + '@rollup/rollup-linux-riscv64-gnu@4.43.0': + resolution: {integrity: sha512-XXKvo2e+wFtXZF/9xoWohHg+MuRnvO29TI5Hqe9xwN5uN8NKUYy7tXUG3EZAlfchufNCTHNGjEx7uN78KsBo0g==} + cpu: [riscv64] + os: [linux] + + '@rollup/rollup-linux-riscv64-musl@4.43.0': + resolution: {integrity: sha512-ruf3hPWhjw6uDFsOAzmbNIvlXFXlBQ4nk57Sec8E8rUxs/AI4HD6xmiiasOOx/3QxS2f5eQMKTAwk7KHwpzr/Q==} + cpu: [riscv64] + os: [linux] + + '@rollup/rollup-linux-s390x-gnu@4.43.0': + resolution: {integrity: sha512-QmNIAqDiEMEvFV15rsSnjoSmO0+eJLoKRD9EAa9rrYNwO/XRCtOGM3A5A0X+wmG+XRrw9Fxdsw+LnyYiZWWcVw==} + cpu: [s390x] + os: [linux] + + '@rollup/rollup-linux-x64-gnu@4.43.0': + resolution: {integrity: sha512-jAHr/S0iiBtFyzjhOkAics/2SrXE092qyqEg96e90L3t9Op8OTzS6+IX0Fy5wCt2+KqeHAkti+eitV0wvblEoQ==} + cpu: [x64] + os: [linux] + + '@rollup/rollup-linux-x64-musl@4.43.0': + resolution: {integrity: sha512-3yATWgdeXyuHtBhrLt98w+5fKurdqvs8B53LaoKD7P7H7FKOONLsBVMNl9ghPQZQuYcceV5CDyPfyfGpMWD9mQ==} + cpu: [x64] + os: [linux] + + '@rollup/rollup-win32-arm64-msvc@4.43.0': + resolution: {integrity: sha512-wVzXp2qDSCOpcBCT5WRWLmpJRIzv23valvcTwMHEobkjippNf+C3ys/+wf07poPkeNix0paTNemB2XrHr2TnGw==} + cpu: [arm64] + os: [win32] + + '@rollup/rollup-win32-ia32-msvc@4.43.0': + resolution: {integrity: sha512-fYCTEyzf8d+7diCw8b+asvWDCLMjsCEA8alvtAutqJOJp/wL5hs1rWSqJ1vkjgW0L2NB4bsYJrpKkiIPRR9dvw==} + cpu: [ia32] + os: [win32] + + '@rollup/rollup-win32-x64-msvc@4.43.0': + resolution: {integrity: sha512-SnGhLiE5rlK0ofq8kzuDkM0g7FN1s5VYY+YSMTibP7CqShxCQvqtNxTARS4xX4PFJfHjG0ZQYX9iGzI3FQh5Aw==} + cpu: [x64] + os: [win32] + + '@selderee/plugin-htmlparser2@0.11.0': + resolution: {integrity: sha512-P33hHGdldxGabLFjPPpaTxVolMrzrcegejx+0GxjrIb9Zv48D8yAIA/QTDR2dFl7Uz7urX8aX6+5bCZslr+gWQ==} + + '@simplewebauthn/browser@13.1.0': + resolution: {integrity: sha512-WuHZ/PYvyPJ9nxSzgHtOEjogBhwJfC8xzYkPC+rR/+8chl/ft4ngjiK8kSU5HtRJfczupyOh33b25TjYbvwAcg==} + + '@simplewebauthn/server@13.1.1': + resolution: {integrity: sha512-1hsLpRHfSuMB9ee2aAdh0Htza/X3f4djhYISrggqGe3xopNjOcePiSDkDDoPzDYaaMCrbqGP1H2TYU7bgL9PmA==} + engines: {node: '>=20.0.0'} + + '@socket.io/component-emitter@3.1.2': + resolution: {integrity: sha512-9BCxFwvbGg/RsZK9tjXd8s4UcwR0MWeFQ1XEKIQVVvAGJyINdrqKMcTRyLoK8Rse1GjzLV9cwjWV1olXRWEXVA==} + + '@stablelib/base64@1.0.1': + resolution: {integrity: sha512-1bnPQqSxSuc3Ii6MhBysoWCg58j97aUjuCSZrGSmDxNqtytIi0k8utUenAwTZN4V5mXXYGsVUI9zeBqy+jBOSQ==} + + '@supabase/auth-js@2.70.0': + resolution: {integrity: sha512-BaAK/tOAZFJtzF1sE3gJ2FwTjLf4ky3PSvcvLGEgEmO4BSBkwWKu8l67rLLIBZPDnCyV7Owk2uPyKHa0kj5QGg==} + + '@supabase/functions-js@2.4.4': + resolution: {integrity: sha512-WL2p6r4AXNGwop7iwvul2BvOtuJ1YQy8EbOd0dhG1oN1q8el/BIRSFCFnWAMM/vJJlHWLi4ad22sKbKr9mvjoA==} + + '@supabase/node-fetch@2.6.15': + resolution: {integrity: sha512-1ibVeYUacxWYi9i0cf5efil6adJ9WRyZBLivgjs+AUpewx1F3xPi7gLgaASI2SmIQxPoCEjAsLAzKPgMJVgOUQ==} + engines: {node: 4.x || >=6.0.0} + + '@supabase/postgrest-js@1.19.4': + resolution: {integrity: sha512-O4soKqKtZIW3olqmbXXbKugUtByD2jPa8kL2m2c1oozAO11uCcGrRhkZL0kVxjBLrXHE0mdSkFsMj7jDSfyNpw==} + + '@supabase/realtime-js@2.11.10': + resolution: {integrity: sha512-SJKVa7EejnuyfImrbzx+HaD9i6T784khuw1zP+MBD7BmJYChegGxYigPzkKX8CK8nGuDntmeSD3fvriaH0EGZA==} + + '@supabase/ssr@0.5.2': + resolution: {integrity: sha512-n3plRhr2Bs8Xun1o4S3k1CDv17iH5QY9YcoEvXX3bxV1/5XSasA0mNXYycFmADIdtdE6BG9MRjP5CGIs8qxC8A==} + peerDependencies: + '@supabase/supabase-js': ^2.43.4 + + '@supabase/storage-js@2.7.1': + resolution: {integrity: sha512-asYHcyDR1fKqrMpytAS1zjyEfvxuOIp1CIXX7ji4lHHcJKqyk+sLl/Vxgm4sN6u8zvuUtae9e4kDxQP2qrwWBA==} + + '@supabase/supabase-js@2.50.0': + resolution: {integrity: sha512-M1Gd5tPaaghYZ9OjeO1iORRqbTWFEz/cF3pPubRnMPzA+A8SiUsXXWDP+DWsASZcjEcVEcVQIAF38i5wrijYOg==} + + '@swc/counter@0.1.3': + resolution: {integrity: sha512-e2BR4lsJkkRlKZ/qCHPw9ZaSxc0MVUd7gtbtaB7aMvHeJVYe8sOB8DBZkP2DtISHGSku9sCK6T6cnY0CtXrOCQ==} + + '@swc/helpers@0.5.15': + resolution: {integrity: sha512-JQ5TuMi45Owi4/BIMAJBoSQoOJu12oOk/gADqlcUL9JEdHB8vyjUSsxqeNXnmXHjYKMi2WcYtezGEEhqUI/E2g==} + + '@tailwindcss/node@4.1.10': + resolution: {integrity: sha512-2ACf1znY5fpRBwRhMgj9ZXvb2XZW8qs+oTfotJ2C5xR0/WNL7UHZ7zXl6s+rUqedL1mNi+0O+WQr5awGowS3PQ==} + + '@tailwindcss/oxide-android-arm64@4.1.10': + resolution: {integrity: sha512-VGLazCoRQ7rtsCzThaI1UyDu/XRYVyH4/EWiaSX6tFglE+xZB5cvtC5Omt0OQ+FfiIVP98su16jDVHDEIuH4iQ==} + engines: {node: '>= 10'} + cpu: [arm64] + os: [android] + + '@tailwindcss/oxide-darwin-arm64@4.1.10': + resolution: {integrity: sha512-ZIFqvR1irX2yNjWJzKCqTCcHZbgkSkSkZKbRM3BPzhDL/18idA8uWCoopYA2CSDdSGFlDAxYdU2yBHwAwx8euQ==} + engines: {node: '>= 10'} + cpu: [arm64] + os: [darwin] + + '@tailwindcss/oxide-darwin-x64@4.1.10': + resolution: {integrity: sha512-eCA4zbIhWUFDXoamNztmS0MjXHSEJYlvATzWnRiTqJkcUteSjO94PoRHJy1Xbwp9bptjeIxxBHh+zBWFhttbrQ==} + engines: {node: '>= 10'} + cpu: [x64] + os: [darwin] + + '@tailwindcss/oxide-freebsd-x64@4.1.10': + resolution: {integrity: sha512-8/392Xu12R0cc93DpiJvNpJ4wYVSiciUlkiOHOSOQNH3adq9Gi/dtySK7dVQjXIOzlpSHjeCL89RUUI8/GTI6g==} + engines: {node: '>= 10'} + cpu: [x64] + os: [freebsd] + + '@tailwindcss/oxide-linux-arm-gnueabihf@4.1.10': + resolution: {integrity: sha512-t9rhmLT6EqeuPT+MXhWhlRYIMSfh5LZ6kBrC4FS6/+M1yXwfCtp24UumgCWOAJVyjQwG+lYva6wWZxrfvB+NhQ==} + engines: {node: '>= 10'} + cpu: [arm] + os: [linux] + + '@tailwindcss/oxide-linux-arm64-gnu@4.1.10': + resolution: {integrity: sha512-3oWrlNlxLRxXejQ8zImzrVLuZ/9Z2SeKoLhtCu0hpo38hTO2iL86eFOu4sVR8cZc6n3z7eRXXqtHJECa6mFOvA==} + engines: {node: '>= 10'} + cpu: [arm64] + os: [linux] + + '@tailwindcss/oxide-linux-arm64-musl@4.1.10': + resolution: {integrity: sha512-saScU0cmWvg/Ez4gUmQWr9pvY9Kssxt+Xenfx1LG7LmqjcrvBnw4r9VjkFcqmbBb7GCBwYNcZi9X3/oMda9sqQ==} + engines: {node: '>= 10'} + cpu: [arm64] + os: [linux] + + '@tailwindcss/oxide-linux-x64-gnu@4.1.10': + resolution: {integrity: sha512-/G3ao/ybV9YEEgAXeEg28dyH6gs1QG8tvdN9c2MNZdUXYBaIY/Gx0N6RlJzfLy/7Nkdok4kaxKPHKJUlAaoTdA==} + engines: {node: '>= 10'} + cpu: [x64] + os: [linux] + + '@tailwindcss/oxide-linux-x64-musl@4.1.10': + resolution: {integrity: sha512-LNr7X8fTiKGRtQGOerSayc2pWJp/9ptRYAa4G+U+cjw9kJZvkopav1AQc5HHD+U364f71tZv6XamaHKgrIoVzA==} + engines: {node: '>= 10'} + cpu: [x64] + os: [linux] + + '@tailwindcss/oxide-wasm32-wasi@4.1.10': + resolution: {integrity: sha512-d6ekQpopFQJAcIK2i7ZzWOYGZ+A6NzzvQ3ozBvWFdeyqfOZdYHU66g5yr+/HC4ipP1ZgWsqa80+ISNILk+ae/Q==} + engines: {node: '>=14.0.0'} + cpu: [wasm32] + bundledDependencies: + - '@napi-rs/wasm-runtime' + - '@emnapi/core' + - '@emnapi/runtime' + - '@tybys/wasm-util' + - '@emnapi/wasi-threads' + - tslib + + '@tailwindcss/oxide-win32-arm64-msvc@4.1.10': + resolution: {integrity: sha512-i1Iwg9gRbwNVOCYmnigWCCgow8nDWSFmeTUU5nbNx3rqbe4p0kRbEqLwLJbYZKmSSp23g4N6rCDmm7OuPBXhDA==} + engines: {node: '>= 10'} + cpu: [arm64] + os: [win32] + + '@tailwindcss/oxide-win32-x64-msvc@4.1.10': + resolution: {integrity: sha512-sGiJTjcBSfGq2DVRtaSljq5ZgZS2SDHSIfhOylkBvHVjwOsodBhnb3HdmiKkVuUGKD0I7G63abMOVaskj1KpOA==} + engines: {node: '>= 10'} + cpu: [x64] + os: [win32] + + '@tailwindcss/oxide@4.1.10': + resolution: {integrity: sha512-v0C43s7Pjw+B9w21htrQwuFObSkio2aV/qPx/mhrRldbqxbWJK6KizM+q7BF1/1CmuLqZqX3CeYF7s7P9fbA8Q==} + engines: {node: '>= 10'} + + '@tailwindcss/vite@4.1.10': + resolution: {integrity: sha512-QWnD5HDY2IADv+vYR82lOhqOlS1jSCUUAmfem52cXAhRTKxpDh3ARX8TTXJTCCO7Rv7cD2Nlekabv02bwP3a2A==} + peerDependencies: + vite: ^5.2.0 || ^6 + + '@tanstack/query-core@5.80.7': + resolution: {integrity: sha512-s09l5zeUKC8q7DCCCIkVSns8zZrK4ZDT6ryEjxNBFi68G4z2EBobBS7rdOY3r6W1WbUDpc1fe5oY+YO/+2UVUg==} + + '@tanstack/react-query@5.80.7': + resolution: {integrity: sha512-u2F0VK6+anItoEvB3+rfvTO9GEh2vb00Je05OwlUe/A0lkJBgW1HckiY3f9YZa+jx6IOe4dHPh10dyp9aY3iRQ==} + peerDependencies: + react: ^18 || ^19 + + '@tanstack/react-table@8.21.3': + resolution: {integrity: sha512-5nNMTSETP4ykGegmVkhjcS8tTLW6Vl4axfEGQN3v0zdHYbK4UfoqfPChclTrJ4EoK9QynqAu9oUf8VEmrpZ5Ww==} + engines: {node: '>=12'} + peerDependencies: + react: '>=16.8' + react-dom: '>=16.8' + + '@tanstack/table-core@8.21.3': + resolution: {integrity: sha512-ldZXEhOBb8Is7xLs01fR3YEc3DERiz5silj8tnGkFZytt1abEvl/GhUmCE0PMLaMPTa3Jk4HbKmRlHmu+gCftg==} + engines: {node: '>=12'} + + '@tootallnate/quickjs-emscripten@0.23.0': + resolution: {integrity: sha512-C5Mc6rdnsaJDjO3UpGW/CQTHtCKaYlScZTly4JIu97Jxo/odCiH0ITnDXSJPTOrEKk/ycSZ0AOgTmkDtkOsvIA==} + + '@tsconfig/node10@1.0.11': + resolution: {integrity: sha512-DcRjDCujK/kCk/cUe8Xz8ZSpm8mS3mNNpta+jGCA6USEDfktlNvm1+IuZ9eTcDbNk41BHwpHHeW+N1lKCz4zOw==} + + '@tsconfig/node12@1.0.11': + resolution: {integrity: sha512-cqefuRsh12pWyGsIoBKJA9luFu3mRxCA+ORZvA4ktLSzIuCUtWVxGIuXigEwO5/ywWFMZ2QEGKWvkZG1zDMTag==} + + '@tsconfig/node14@1.0.3': + resolution: {integrity: sha512-ysT8mhdixWK6Hw3i1V2AeRqZ5WfXg1G43mqoYlM2nc6388Fq5jcXyr5mRsqViLx/GJYdoL0bfXD8nmF+Zn/Iow==} + + '@tsconfig/node16@1.0.4': + resolution: {integrity: sha512-vxhUy4J8lyeyinH7Azl1pdd43GJhZH/tP2weN8TntQblOY+A0XbT8DJk1/oCPuOOyg/Ja757rG0CgHcWC8OfMA==} + + '@types/babel__core@7.20.5': + resolution: {integrity: sha512-qoQprZvz5wQFJwMDqeseRXWv3rqMvhgpbXFfVyWhbx9X47POIA6i/+dXefEmZKoAgOaTdaIgNSMqMIU61yRyzA==} + + '@types/babel__generator@7.27.0': + resolution: {integrity: sha512-ufFd2Xi92OAVPYsy+P4n7/U7e68fex0+Ee8gSG9KX7eo084CWiQ4sdxktvdl0bOPupXtVJPY19zk6EwWqUQ8lg==} + + '@types/babel__template@7.4.4': + resolution: {integrity: sha512-h/NUaSyG5EyxBIp8YRxo4RMe2/qQgvyowRwVMzhYhBCONbW8PUsg4lkFMrhgZhUe5z3L3MiLDuvyJ/CaPa2A8A==} + + '@types/babel__traverse@7.20.7': + resolution: {integrity: sha512-dkO5fhS7+/oos4ciWxyEyjWe48zmG6wbCheo/G2ZnHx4fs3EU6YC6UM8rk56gAjNJ9P3MTH2jo5jb92/K6wbng==} + + '@types/body-parser@1.19.6': + resolution: {integrity: sha512-HLFeCYgz89uk22N5Qg3dvGvsv46B8GLvKKo1zKG4NybA8U2DiEO3w9lqGg29t/tfLRJpJ6iQxnVw4OnB7MoM9g==} + + '@types/chai-http@3.0.5': + resolution: {integrity: sha512-nJ/oIvYley9+1Fec8xzDHsWrWSu5VTuhuF8iLabnRTQwRfSbAke6VuI7qBXvBN9Qqo/+gwsSaGyYndofTpiJ9A==} + + '@types/chai@5.2.2': + resolution: {integrity: sha512-8kB30R7Hwqf40JPiKhVzodJs2Qc1ZJ5zuT3uzw5Hq/dhNCl3G3l83jfpdI1e20BP348+fV7VIL/+FxaXkqBmWg==} + + '@types/connect@3.4.38': + resolution: {integrity: sha512-K6uROf1LD88uDQqJCktA4yzL1YYAK6NgfsI0v/mTgyPKWsX1CnJ0XPSDhViejru1GcRkLWb8RlzFYJRqGUbaug==} + + '@types/cookie@0.6.0': + resolution: {integrity: sha512-4Kh9a6B2bQciAhf7FSuMRRkUWecJgJu9nPnx3yzpsfXX/c50REIqpHY4C82bXP90qrLtXtkDxTZosYO3UpOwlA==} + + '@types/cookiejar@2.1.5': + resolution: {integrity: sha512-he+DHOWReW0nghN24E1WUqM0efK4kI9oTqDm6XmK8ZPe2djZ90BSNdGnIyCLzCPw7/pogPlGbzI2wHGGmi4O/Q==} + + '@types/cors@2.8.19': + resolution: {integrity: sha512-mFNylyeyqN93lfe/9CSxOGREz8cpzAhH+E93xJ4xWQf62V8sQ/24reV2nyzUWM6H6Xji+GGHpkbLe7pVoUEskg==} + + '@types/deep-eql@4.0.2': + resolution: {integrity: sha512-c9h9dVVMigMPc4bwTvC5dxqtqJZwQPePsWjPlpSOnojbor6pGqdk541lfA7AqFQr5pB1BRdq0juY9db81BwyFw==} + + '@types/diff-match-patch@1.0.36': + resolution: {integrity: sha512-xFdR6tkm0MWvBfO8xXCSsinYxHcqkQUlcHeSpMC2ukzOb6lwQAfDmW+Qt0AvlGd8HpsS28qKsB+oPeJn9I39jg==} + + '@types/estree@1.0.7': + resolution: {integrity: sha512-w28IoSUCJpidD/TGviZwwMJckNESJZXFu7NBZ5YJ4mEUnNraUn9Pm8HSZm/jDF1pDWYKspWE7oVphigUPRakIQ==} + + '@types/estree@1.0.8': + resolution: {integrity: sha512-dWHzHa2WqEXI/O1E9OjrocMTKJl2mSrEolh1Iomrv6U+JuNwaHXsXx9bLu5gG7BUWFIN0skIQJQ/L1rIex4X6w==} + + '@types/express-serve-static-core@5.0.6': + resolution: {integrity: sha512-3xhRnjJPkULekpSzgtoNYYcTWgEZkp4myc+Saevii5JPnHNvHMRlBSHDbs7Bh1iPPoVTERHEZXyhyLbMEsExsA==} + + '@types/express@5.0.3': + resolution: {integrity: sha512-wGA0NX93b19/dZC1J18tKWVIYWyyF2ZjT9vin/NRu0qzzvfVzWjs04iq2rQ3H65vCTQYlRqs3YHfY7zjdV+9Kw==} + + '@types/hast@3.0.4': + resolution: {integrity: sha512-WPs+bbQw5aCj+x6laNGWLH3wviHtoCv/P3+otBhbOhJgG8qtpdAMlTCxLtsTWA7LH1Oh/bFCHsBn0TPS5m30EQ==} + + '@types/http-errors@2.0.5': + resolution: {integrity: sha512-r8Tayk8HJnX0FztbZN7oVqGccWgw98T/0neJphO91KkmOzug1KkofZURD4UaD5uH8AqcFLfdPErnBod0u71/qg==} + + '@types/json-schema@7.0.15': + resolution: {integrity: sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA==} + + '@types/lodash-es@4.17.12': + resolution: {integrity: sha512-0NgftHUcV4v34VhXm8QBSftKVXtbkBG3ViCjs6+eJ5a6y6Mi/jiFGPc1sC7QK+9BFhWrURE3EOggmWaSxL9OzQ==} + + '@types/lodash@4.17.17': + resolution: {integrity: sha512-RRVJ+J3J+WmyOTqnz3PiBLA501eKwXl2noseKOrNo/6+XEHjTAxO4xHvxQB6QuNm+s4WRbn6rSiap8+EA+ykFQ==} + + '@types/luxon@3.4.2': + resolution: {integrity: sha512-TifLZlFudklWlMBfhubvgqTXRzLDI5pCbGa4P8a3wPyUQSW+1xQ5eDsreP9DWHX3tjq1ke96uYG/nwundroWcA==} + + '@types/mdast@4.0.4': + resolution: {integrity: sha512-kGaNbPh1k7AFzgpud/gMdvIm5xuECykRR+JnWKQno9TAXVa6WIVCGTPvYGekIDL4uwCZQSYbUxNBSb1aUo79oA==} + + '@types/methods@1.1.4': + resolution: {integrity: sha512-ymXWVrDiCxTBE3+RIrrP533E70eA+9qu7zdWoHuOmGujkYtzf4HQF96b8nwHLqhuf4ykX61IGRIB38CC6/sImQ==} + + '@types/mime@1.3.5': + resolution: {integrity: sha512-/pyBZWSLD2n0dcHE3hq8s8ZvcETHtEuF+3E7XVt0Ig2nvsVQXdghHVcEkIWjy9A0wKfTn97a/PSDYohKIlnP/w==} + + '@types/mocha@10.0.10': + resolution: {integrity: sha512-xPyYSz1cMPnJQhl0CLMH68j3gprKZaTjG3s5Vi+fDgx+uhG9NOXwbVt52eFS8ECyXhyKcjDLCBEqBExKuiZb7Q==} + + '@types/node-fetch@2.6.12': + resolution: {integrity: sha512-8nneRWKCg3rMtF69nLQJnOYUcbafYeFSjqkw3jCRLsqkWFlHaoQrr5mXmofFGOx3DKn7UfmBMyov8ySvLRVldA==} + + '@types/node@18.19.111': + resolution: {integrity: sha512-90sGdgA+QLJr1F9X79tQuEut0gEYIfkX9pydI4XGRgvFo9g2JWswefI+WUSUHPYVBHYSEfTEqBxA5hQvAZB3Mw==} + + '@types/node@22.15.32': + resolution: {integrity: sha512-3jigKqgSjsH6gYZv2nEsqdXfZqIFGAV36XYYjf9KGZ3PSG+IhLecqPnI310RvjutyMwifE2hhhNEklOUrvx/wA==} + + '@types/node@24.0.3': + resolution: {integrity: sha512-R4I/kzCYAdRLzfiCabn9hxWfbuHS573x+r0dJMkkzThEa7pbrcDWK+9zu3e7aBOouf+rQAciqPFMnxwr0aWgKg==} + + '@types/pg@8.15.4': + resolution: {integrity: sha512-I6UNVBAoYbvuWkkU3oosC8yxqH21f4/Jc4DK71JLG3dT2mdlGe1z+ep/LQGXaKaOgcvUrsQoPRqfgtMcvZiJhg==} + + '@types/phoenix@1.6.6': + resolution: {integrity: sha512-PIzZZlEppgrpoT2QgbnDU+MMzuR6BbCjllj0bM70lWoejMeNJAxCchxnv7J3XFkI8MpygtRpzXrIlmWUBclP5A==} + + '@types/prismjs@1.26.5': + resolution: {integrity: sha512-AUZTa7hQ2KY5L7AmtSiqxlhWxb4ina0yd8hNbl4TWuqnv/pFP0nDMb3YrfSBf4hJVGLh2YEIBfKaBW/9UEl6IQ==} + + '@types/prop-types@15.7.15': + resolution: {integrity: sha512-F6bEyamV9jKGAFBEmlQnesRPGOQqS2+Uwi0Em15xenOxHaf2hv6L8YCVn3rPdPJOiJfPiCnLIRyvwVaqMY3MIw==} + + '@types/qs@6.14.0': + resolution: {integrity: sha512-eOunJqu0K1923aExK6y8p6fsihYEn/BYuQ4g0CxAAgFc4b/ZLN4CrsRZ55srTdqoiLzU2B2evC+apEIxprEzkQ==} + + '@types/range-parser@1.2.7': + resolution: {integrity: sha512-hKormJbkJqzQGhziax5PItDUTMAM9uE2XXQmM37dyd4hVM+5aVl7oVxMVUiVQn2oCQFN/LKCZdvSM0pFRqbSmQ==} + + '@types/react-dom@18.3.7': + resolution: {integrity: sha512-MEe3UeoENYVFXzoXEWsvcpg6ZvlrFNlOQ7EOsvhI3CfAXwzPfO8Qwuxd40nepsYKqyyVQnTdEfv68q91yLcKrQ==} + peerDependencies: + '@types/react': ^18.0.0 + + '@types/react@18.3.23': + resolution: {integrity: sha512-/LDXMQh55EzZQ0uVAZmKKhfENivEvWz6E+EYzh+/MCjMhNsotd+ZHhBGIjFDTi6+fz0OhQQQLbTgdQIxxCsC0w==} + + '@types/send@0.17.5': + resolution: {integrity: sha512-z6F2D3cOStZvuk2SaP6YrwkNO65iTZcwA2ZkSABegdkAh/lf+Aa/YQndZVfmEXT5vgAp6zv06VQ3ejSVjAny4w==} + + '@types/serve-static@1.15.8': + resolution: {integrity: sha512-roei0UY3LhpOJvjbIP6ZZFngyLKl5dskOtDhxY5THRSpO+ZI+nzJ+m5yUMzGrp89YRa7lvknKkMYjqQFGwA7Sg==} + + '@types/stack-trace@0.0.33': + resolution: {integrity: sha512-O7in6531Bbvlb2KEsJ0dq0CHZvc3iWSR5ZYMtvGgnHA56VgriAN/AU2LorfmcvAl2xc9N5fbCTRyMRRl8nd74g==} + + '@types/superagent@8.1.9': + resolution: {integrity: sha512-pTVjI73witn+9ILmoJdajHGW2jkSaOzhiFYF1Rd3EQ94kymLqB9PjD9ISg7WaALC7+dCHT0FGe9T2LktLq/3GQ==} + + '@types/unist@3.0.3': + resolution: {integrity: sha512-ko/gIFJRv177XgZsZcBwnqJN5x/Gien8qNOn0D5bQU/zAzVf9Zt3BlcUiLqhV9y4ARk0GbT3tnUiPNgnTXzc/Q==} + + '@types/ws@8.18.1': + resolution: {integrity: sha512-ThVF6DCVhA8kUGy+aazFQ4kXQ7E1Ty7A3ypFOe0IcJV8O/M511G99AW24irKrW56Wt44yG9+ij8FaqoBGkuBXg==} + + '@types/yauzl@2.10.3': + resolution: {integrity: sha512-oJoftv0LSuaDZE3Le4DbKX+KS9G36NzOeSap90UIK0yMA/NhKJhqlSGtNDORNRaIbQfzjXDrQa0ytJ6mNRGz/Q==} + + '@typescript-eslint/eslint-plugin@8.34.0': + resolution: {integrity: sha512-QXwAlHlbcAwNlEEMKQS2RCgJsgXrTJdjXT08xEgbPFa2yYQgVjBymxP5DrfrE7X7iodSzd9qBUHUycdyVJTW1w==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + peerDependencies: + '@typescript-eslint/parser': ^8.34.0 + eslint: ^8.57.0 || ^9.0.0 + typescript: '>=4.8.4 <5.9.0' + + '@typescript-eslint/parser@8.34.0': + resolution: {integrity: sha512-vxXJV1hVFx3IXz/oy2sICsJukaBrtDEQSBiV48/YIV5KWjX1dO+bcIr/kCPrW6weKXvsaGKFNlwH0v2eYdRRbA==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + peerDependencies: + eslint: ^8.57.0 || ^9.0.0 + typescript: '>=4.8.4 <5.9.0' + + '@typescript-eslint/project-service@8.34.0': + resolution: {integrity: sha512-iEgDALRf970/B2YExmtPMPF54NenZUf4xpL3wsCRx/lgjz6ul/l13R81ozP/ZNuXfnLCS+oPmG7JIxfdNYKELw==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + peerDependencies: + typescript: '>=4.8.4 <5.9.0' + + '@typescript-eslint/scope-manager@8.34.0': + resolution: {integrity: sha512-9Ac0X8WiLykl0aj1oYQNcLZjHgBojT6cW68yAgZ19letYu+Hxd0rE0veI1XznSSst1X5lwnxhPbVdwjDRIomRw==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + + '@typescript-eslint/tsconfig-utils@8.34.0': + resolution: {integrity: sha512-+W9VYHKFIzA5cBeooqQxqNriAP0QeQ7xTiDuIOr71hzgffm3EL2hxwWBIIj4GuofIbKxGNarpKqIq6Q6YrShOA==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + peerDependencies: + typescript: '>=4.8.4 <5.9.0' + + '@typescript-eslint/type-utils@8.34.0': + resolution: {integrity: sha512-n7zSmOcUVhcRYC75W2pnPpbO1iwhJY3NLoHEtbJwJSNlVAZuwqu05zY3f3s2SDWWDSo9FdN5szqc73DCtDObAg==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + peerDependencies: + eslint: ^8.57.0 || ^9.0.0 + typescript: '>=4.8.4 <5.9.0' + + '@typescript-eslint/types@8.34.0': + resolution: {integrity: sha512-9V24k/paICYPniajHfJ4cuAWETnt7Ssy+R0Rbcqo5sSFr3QEZ/8TSoUi9XeXVBGXCaLtwTOKSLGcInCAvyZeMA==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + + '@typescript-eslint/typescript-estree@8.34.0': + resolution: {integrity: sha512-rOi4KZxI7E0+BMqG7emPSK1bB4RICCpF7QD3KCLXn9ZvWoESsOMlHyZPAHyG04ujVplPaHbmEvs34m+wjgtVtg==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + peerDependencies: + typescript: '>=4.8.4 <5.9.0' + + '@typescript-eslint/utils@8.34.0': + resolution: {integrity: sha512-8L4tWatGchV9A1cKbjaavS6mwYwp39jql8xUmIIKJdm+qiaeHy5KMKlBrf30akXAWBzn2SqKsNOtSENWUwg7XQ==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + peerDependencies: + eslint: ^8.57.0 || ^9.0.0 + typescript: '>=4.8.4 <5.9.0' + + '@typescript-eslint/visitor-keys@8.34.0': + resolution: {integrity: sha512-qHV7pW7E85A0x6qyrFn+O+q1k1p3tQCsqIZ1KZ5ESLXY57aTvUd3/a4rdPTeXisvhXn2VQG0VSKUqs8KHF2zcA==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + + '@ungap/structured-clone@1.3.0': + resolution: {integrity: sha512-WmoN8qaIAo7WTYWbAZuG8PYEhn5fkz7dZrqTBZ7dtt//lL2Gwms1IcnQ5yHqjDfX8Ft5j4YzDM23f87zBfDe9g==} + + '@vitejs/plugin-react@4.5.2': + resolution: {integrity: sha512-QNVT3/Lxx99nMQWJWF7K4N6apUEuT0KlZA3mx/mVaoGj3smm/8rc8ezz15J1pcbcjDK0V15rpHetVfya08r76Q==} + engines: {node: ^14.18.0 || >=16.0.0} + peerDependencies: + vite: ^4.2.0 || ^5.0.0 || ^6.0.0 || ^7.0.0-beta.0 + + '@wooorm/starry-night@3.8.0': + resolution: {integrity: sha512-BWRm0tCzWCmv1ucBh6frL2uFRvYFj/LWmJzr+rJsdF/JsJ1+bBkeiyExH1iWQS18IH22HFu7f4QgG99OU1nklA==} + + abort-controller@3.0.0: + resolution: {integrity: sha512-h8lQ8tacZYnR3vNQTgibj+tODHI5/+l06Au2Pcriv/Gmet0eaj4TwWH41sO9wnHDiQsEj19q0drzdWdeAHtweg==} + engines: {node: '>=6.5'} + + accepts@1.3.8: + resolution: {integrity: sha512-PYAthTa2m2VKxuvSD3DPC/Gy+U+sOA1LAuT8mkmRuvw+NACSaeXEQ+NHcVF7rONl6qcaxV3Uuemwawk+7+SJLw==} + engines: {node: '>= 0.6'} + + acorn-jsx@5.3.2: + resolution: {integrity: sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==} + peerDependencies: + acorn: ^6.0.0 || ^7.0.0 || ^8.0.0 + + acorn-walk@8.3.4: + resolution: {integrity: sha512-ueEepnujpqee2o5aIYnvHU6C0A42MNdsIDeqy5BydrkuC5R1ZuUFnm27EeFJGoEHJQgn3uleRvmTXaJgfXbt4g==} + engines: {node: '>=0.4.0'} + + acorn@8.15.0: + resolution: {integrity: sha512-NZyJarBfL7nWwIq+FDL6Zp/yHEhePMNnnJ0y3qfieCrmNvYct8uvtiV41UvlSe6apAfk0fY1FbWx+NwfmpvtTg==} + engines: {node: '>=0.4.0'} + hasBin: true + + agent-base@7.1.3: + resolution: {integrity: sha512-jRR5wdylq8CkOe6hei19GGZnxM6rBGwFl3Bg0YItGDimvjGtAvdZk4Pu6Cl4u4Igsws4a1fd1Vq3ezrhn4KmFw==} + engines: {node: '>= 14'} + + agentkeepalive@4.6.0: + resolution: {integrity: sha512-kja8j7PjmncONqaTsB8fQ+wE2mSU2DJ9D4XKoJ5PFWIdRMa6SLSN1ff4mOr4jCbfRSsxR4keIiySJU0N9T5hIQ==} + engines: {node: '>= 8.0.0'} + + ai@4.3.16: + resolution: {integrity: sha512-KUDwlThJ5tr2Vw0A1ZkbDKNME3wzWhuVfAOwIvFUzl1TPVDFAXDFTXio3p+jaKneB+dKNCvFFlolYmmgHttG1g==} + engines: {node: '>=18'} + peerDependencies: + react: ^18 || ^19 || ^19.0.0-rc + zod: ^3.23.8 + peerDependenciesMeta: + react: + optional: true + + ajv@6.12.6: + resolution: {integrity: sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==} + + ansi-escapes@4.3.2: + resolution: {integrity: sha512-gKXj5ALrKWQLsYG9jlTRmR/xKluxHV+Z9QEwNIgCfM1/uwPMCuzVVnh5mwTd+OuBZcwSIMbqssNWRm1lE51QaQ==} + engines: {node: '>=8'} + + ansi-regex@5.0.1: + resolution: {integrity: sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==} + engines: {node: '>=8'} + + ansi-regex@6.1.0: + resolution: {integrity: sha512-7HSX4QQb4CspciLpVFwyRe79O3xsIZDDLER21kERQ71oaPodF8jL725AgJMFAYbooIqolJoRLuM81SpeUkpkvA==} + engines: {node: '>=12'} + + ansi-styles@4.3.0: + resolution: {integrity: sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==} + engines: {node: '>=8'} + + ansi-styles@6.2.1: + resolution: {integrity: sha512-bN798gFfQX+viw3R7yrGWRqnrN2oRkEkUjjl4JNn4E8GxxbjtG3FbrEIIY3l8/hrwUwIeCZvi4QuOTP4MErVug==} + engines: {node: '>=12'} + + anymatch@3.1.3: + resolution: {integrity: sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw==} + engines: {node: '>= 8'} + + arg@4.1.3: + resolution: {integrity: sha512-58S9QDqG0Xx27YwPSt9fJxivjYl432YCwfDMfZ+71RAqUrZef7LrKQZ3LHLOwCS4FLNBplP533Zx895SeOCHvA==} + + argparse@2.0.1: + resolution: {integrity: sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==} + + aria-hidden@1.2.6: + resolution: {integrity: sha512-ik3ZgC9dY/lYVVM++OISsaYDeg1tb0VtP5uL3ouh1koGOaUMDPpbFIei4JkFimWUFPn90sbMNMXQAIVOlnYKJA==} + engines: {node: '>=10'} + + array-flatten@1.1.1: + resolution: {integrity: sha512-PCVAQswWemu6UdxsDFFX/+gVeYqKAod3D3UVm91jHwynguOwAvYPhx8nNlM++NqRcK6CxxpUafjmhIdKiHibqg==} + + array-union@2.1.0: + resolution: {integrity: sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw==} + engines: {node: '>=8'} + + asap@2.0.6: + resolution: {integrity: sha512-BSHWgDSAiKs50o2Re8ppvp3seVHXSRM44cdSsT9FfNEUUZLOGWVCsiWaRPWM1Znn+mqZ1OfVZ3z3DWEzSp7hRA==} + + asn1js@3.0.6: + resolution: {integrity: sha512-UOCGPYbl0tv8+006qks/dTgV9ajs97X2p0FAbyS2iyCRrmLSRolDaHdp+v/CLgnzHc3fVB+CwYiUmei7ndFcgA==} + engines: {node: '>=12.0.0'} + + assertion-error@2.0.1: + resolution: {integrity: sha512-Izi8RQcffqCeNVgFigKli1ssklIbpHnCYc6AknXGYoB6grJqyeby7jv12JUQgmTAnIDnbck1uxksT4dzN3PWBA==} + engines: {node: '>=12'} + + ast-types@0.13.4: + resolution: {integrity: sha512-x1FCFnFifvYDDzTaLII71vG5uvDwgtmDTEVWAxrgeiR8VjMONcCXJx7E+USjDtHlwFmt9MysbqgF9b9Vjr6w+w==} + engines: {node: '>=4'} + + async-listen@3.1.0: + resolution: {integrity: sha512-TkOhqze98lP+6e7SPbrBpyhTpfvqqX8VYKGn4uckrgPan4WQIHnTaUD2zZzZS18eVVDj4rHPcIZa1PGgvo1DfA==} + engines: {node: '>= 14'} + + asynckit@0.4.0: + resolution: {integrity: sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==} + + atomic-sleep@1.0.0: + resolution: {integrity: sha512-kNOjDqAh7px0XWNI+4QbzoiR/nTkHAWNud2uvnJquD1/x5a7EQZMJT0AczqK0Qn67oY/TTQ1LbUKajZpp3I9tQ==} + engines: {node: '>=8.0.0'} + + attr-accept@2.2.5: + resolution: {integrity: sha512-0bDNnY/u6pPwHDMoF0FieU354oBi0a8rD9FcsLwzcGWbc8KS8KPIi7y+s13OlVY+gMWc/9xEMUgNE6Qm8ZllYQ==} + engines: {node: '>=4'} + + autumn-js@0.0.41: + resolution: {integrity: sha512-oP6CMamBTm8LlJPZCt3JTdG2mRkY7NGKp4jgY5l2GY0LTtjtoKJsDyoNqL2nzWR30Sayct9EG4WDUFZQtrgAZA==} + peerDependencies: + '@tanstack/react-query': ^5.76.1 + react: ^18.0.0 || ^19.0.0 + peerDependenciesMeta: + react: + optional: true + + autumn-js@0.0.64: + resolution: {integrity: sha512-Fa5lr9A0ywYNcbny/dQBRKSGaqnTuUvqtiBegHrr5Z3wCw9A/Z2LRH/f8AqHYQSFOXVkS763ngLlGLxfJpYgQQ==} + peerDependencies: + '@tanstack/react-query': ^5.76.1 + react: ^18.0.0 || ^19.0.0 + peerDependenciesMeta: + react: + optional: true + + axios@1.10.0: + resolution: {integrity: sha512-/1xYAC4MP/HEG+3duIhFr4ZQXR4sQXOIe+o6sdqzeykGLx6Upp/1p8MHqhINOvGeP7xyNHe7tsiJByc4SSVUxw==} + + b4a@1.6.7: + resolution: {integrity: sha512-OnAYlL5b7LEkALw87fUVafQw5rVR9RjwGd4KUwNQ6DrrNmaVaUCgLipfVlzrPQ4tWOR9P0IXGNOx50jYCCdSJg==} + + balanced-match@1.0.2: + resolution: {integrity: sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==} + + bare-events@2.5.4: + resolution: {integrity: sha512-+gFfDkR8pj4/TrWCGUGWmJIkBwuxPS5F+a5yWjOHQt2hHvNZd5YLzadjmDUtFmMM4y429bnKLa8bYBMHcYdnQA==} + + bare-fs@4.1.5: + resolution: {integrity: sha512-1zccWBMypln0jEE05LzZt+V/8y8AQsQQqxtklqaIyg5nu6OAYFhZxPXinJTSG+kU5qyNmeLgcn9AW7eHiCHVLA==} + engines: {bare: '>=1.16.0'} + peerDependencies: + bare-buffer: '*' + peerDependenciesMeta: + bare-buffer: + optional: true + + bare-os@3.6.1: + resolution: {integrity: sha512-uaIjxokhFidJP+bmmvKSgiMzj2sV5GPHaZVAIktcxcpCyBFFWO+YlikVAdhmUo2vYFvFhOXIAlldqV29L8126g==} + engines: {bare: '>=1.14.0'} + + bare-path@3.0.0: + resolution: {integrity: sha512-tyfW2cQcB5NN8Saijrhqn0Zh7AnFNsnczRcuWODH0eYAXBsJ5gVxAUuNr7tsHSC6IZ77cA0SitzT+s47kot8Mw==} + + bare-stream@2.6.5: + resolution: {integrity: sha512-jSmxKJNJmHySi6hC42zlZnq00rga4jjxcgNZjY9N5WlOe/iOoGRtdwGsHzQv2RlH2KOYMwGUXhf2zXd32BA9RA==} + peerDependencies: + bare-buffer: '*' + bare-events: '*' + peerDependenciesMeta: + bare-buffer: + optional: true + bare-events: + optional: true + + base-convert-int-array@1.0.1: + resolution: {integrity: sha512-NWqzaoXx8L/SS32R+WmKqnQkVXVYl2PwNJ68QV3RAlRRL1uV+yxJT66abXI1cAvqCXQTyXr7/9NN4Af90/zDVw==} + + base64id@2.0.0: + resolution: {integrity: sha512-lGe34o6EHj9y3Kts9R4ZYs/Gr+6N7MCaMlIFA3F1R2O5/m7K06AxfSeO5530PEERE6/WyEg3lsuyw4GHlPZHog==} + engines: {node: ^4.5.0 || >= 5.9} + + basic-ftp@5.0.5: + resolution: {integrity: sha512-4Bcg1P8xhUuqcii/S0Z9wiHIrQVPMermM1any+MX5GeGD7faD3/msQUDGLol9wOcz4/jbg/WJnGqoJF6LiBdtg==} + engines: {node: '>=10.0.0'} + + better-auth@1.2.9: + resolution: {integrity: sha512-WLqBXDzuaCQetQctLGC5oTfGmL32zUvxnM4Y+LZkhwseMaZWq5EKI+c/ZATgz2YkFt7726q659PF8CfB9P1VuA==} + + better-call@1.0.9: + resolution: {integrity: sha512-Qfm0gjk0XQz0oI7qvTK1hbqTsBY4xV2hsHAxF8LZfUYl3RaECCIifXuVqtPpZJWvlCCMlQSvkvhhyuApGUba6g==} + + binary-extensions@2.3.0: + resolution: {integrity: sha512-Ceh+7ox5qe7LJuLHoY0feh3pHuUDHAcRUeyL2VYghZwfpkNIy/+8Ocg0a3UuSoYzavmylwuLWQOf3hl0jjMMIw==} + engines: {node: '>=8'} + + body-parser@1.20.3: + resolution: {integrity: sha512-7rAxByjUMqQ3/bHJy7D6OGXvx/MMc4IqBn/X0fcM1QUcAItpZrBEYhWGem+tzXH90c+G01ypMcYJBO9Y30203g==} + engines: {node: '>= 0.8', npm: 1.2.8000 || >= 1.4.16} + + brace-expansion@1.1.12: + resolution: {integrity: sha512-9T9UjW3r0UW5c1Q7GTwllptXwhvYmEzFhzMfZ9H7FQWt+uZePjZPjBP/W1ZEyZ1twGWom5/56TF4lPcqjnDHcg==} + + brace-expansion@2.0.2: + resolution: {integrity: sha512-Jt0vHyM+jmUBqojB7E1NIYadt0vI0Qxjxd2TErW94wDz+E2LAm5vKMXXwg6ZZBTHPuUlDgQHKXvjGBdfcF1ZDQ==} + + braces@3.0.3: + resolution: {integrity: sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==} + engines: {node: '>=8'} + + browser-stdout@1.3.1: + resolution: {integrity: sha512-qhAVI1+Av2X7qelOfAIYwXONood6XlZE/fXaBSmW/T5SzLAmCgzi+eiWE7fUvbHaeNBQH13UftjpXxsfLkMpgw==} + + browserslist@4.25.0: + resolution: {integrity: sha512-PJ8gYKeS5e/whHBh8xrwYK+dAvEj7JXtz6uTucnMRB8OiGTsKccFekoRrjajPBHV8oOY+2tI4uxeceSimKwMFA==} + engines: {node: ^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7} + hasBin: true + + buffer-crc32@0.2.13: + resolution: {integrity: sha512-VO9Ht/+p3SN7SKWqcrgEzjGbRSJYTx+Q1pTQC0wrWqHx0vpJraQ6GtHx8tvcg1rlK1byhU5gccxgOgj7B0TDkQ==} + + buffer-from@1.1.2: + resolution: {integrity: sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==} + + bullmq@5.54.0: + resolution: {integrity: sha512-M7iElJJ2fItGRCfTysGb6EGxs334cUArucRXROzxasJ5df4CD0uetazaFTVASFUYxhnNIIC7JNa27ZikBeuKiA==} + + busboy@1.6.0: + resolution: {integrity: sha512-8SFQbg/0hQ9xy3UNTB0YEnsNBbWfhf7RtnzpL7TkBiTBRfrQ9Fxcnz7VJsleJpyp6rVLvXiuORqjlHi5q+PYuA==} + engines: {node: '>=10.16.0'} + + bytes@3.1.2: + resolution: {integrity: sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg==} + engines: {node: '>= 0.8'} + + call-bind-apply-helpers@1.0.2: + resolution: {integrity: sha512-Sp1ablJ0ivDkSzjcaJdxEunN5/XvksFJ2sMBFfq6x0ryhQV/2b/KwFe21cMpmHtPOSij8K99/wSfoEuTObmuMQ==} + engines: {node: '>= 0.4'} + + call-bound@1.0.4: + resolution: {integrity: sha512-+ys997U96po4Kx/ABpBCqhA9EuxJaQWDQg7295H4hBphv3IZg0boBKuwYpt4YXp6MZ5AmZQnU/tyMTlRpaSejg==} + engines: {node: '>= 0.4'} + + callsites@3.1.0: + resolution: {integrity: sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==} + engines: {node: '>=6'} + + camelcase@6.3.0: + resolution: {integrity: sha512-Gmy6FhYlCY7uOElZUSbxo2UCDH8owEk996gkbrpsgGtrJLM3J7jGxl9Ic7Qwwj4ivOE5AWZWRMecDdF7hqGjFA==} + engines: {node: '>=10'} + + caniuse-lite@1.0.30001723: + resolution: {integrity: sha512-1R/elMjtehrFejxwmexeXAtae5UO9iSyFn6G/I806CYC/BLyyBk1EPhrKBkWhy6wM6Xnm47dSJQec+tLJ39WHw==} + + ccount@2.0.1: + resolution: {integrity: sha512-eyrF0jiFpY+3drT6383f1qhkbGsLSifNAjA61IUjZjmLCWjItY6LB9ft9YhoDgwfmclB2zhu51Lc7+95b8NRAg==} + + chai-http@5.1.2: + resolution: {integrity: sha512-UFup7mUGkkjmi9bGA7F6vfp3lzGQZjtL//CEd+a4C+vlynSv756XHDUK8PoYk/UpTBBXqSghjQaJOUMUxJXNaA==} + engines: {node: '>=18.20.0'} + + chai@5.2.0: + resolution: {integrity: sha512-mCuXncKXk5iCLhfhwTc0izo0gtEmpz5CtG2y8GiOINBlMVS6v8TMRc5TaLWKS6692m9+dVVfzgeVxR5UxWHTYw==} + engines: {node: '>=12'} + + chalk@4.1.2: + resolution: {integrity: sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==} + engines: {node: '>=10'} + + chalk@5.4.1: + resolution: {integrity: sha512-zgVZuo2WcZgfUEmsn6eO3kINexW8RAE4maiQ8QNs8CtpPCSyMiYsULR3HQYkm3w8FIA3SberyMJMSldGsW+U3w==} + engines: {node: ^12.17.0 || ^14.13 || >=16.0.0} + + character-entities-html4@2.1.0: + resolution: {integrity: sha512-1v7fgQRj6hnSwFpq1Eu0ynr/CDEw0rXo2B61qXrLNdHZmPKgb7fqS1a2JwF0rISo9q77jDI8VMEHoApn8qDoZA==} + + character-entities-legacy@3.0.0: + resolution: {integrity: sha512-RpPp0asT/6ufRm//AJVwpViZbGM/MkjQFxJccQRHmISF/22NBtsHqAWmL+/pmkPWoIUJdWyeVleTl1wydHATVQ==} + + chardet@0.7.0: + resolution: {integrity: sha512-mT8iDcrh03qDGRRmoA2hmBJnxpllMR+0/0qlzjqZES6NdiWDcZkCNAk4rPFZ9Q85r27unkiNNg8ZOiwZXBHwcA==} + + charset@1.0.1: + resolution: {integrity: sha512-6dVyOOYjpfFcL1Y4qChrAoQLRHvj2ziyhcm0QJlhOcAhykL/k1kTUPbeo+87MNRTRdk2OIIsIXbuF3x2wi5EXg==} + engines: {node: '>=4.0.0'} + + check-error@2.1.1: + resolution: {integrity: sha512-OAlb+T7V4Op9OwdkjmguYRqncdlx5JiofwOAUkmTF+jNdHwzTaTs4sRAGpzLF3oOz5xAyDGrPgeIDFQmDOTiJw==} + engines: {node: '>= 16'} + + chokidar@3.6.0: + resolution: {integrity: sha512-7VT13fmjotKpGipCW9JEQAusEPE+Ei8nl6/g4FBAmIm0GOOLMua9NDDo/DWp0ZAxCr3cPq5ZpBqmPAQgDda2Pw==} + engines: {node: '>= 8.10.0'} + + chokidar@4.0.3: + resolution: {integrity: sha512-Qgzu8kfBvo+cA4962jnP1KkS6Dop5NS6g7R5LFYJr4b8Ub94PPQXUksCw9PvXoeXPRRddRNC5C1JQUR2SMGtnA==} + engines: {node: '>= 14.16.0'} + + chownr@3.0.0: + resolution: {integrity: sha512-+IxzY9BZOQd/XuYPRmrvEVjF/nqj5kgT4kEq7VofrDoM1MxoRjEWkrCC3EtLi59TVawxTAn+orJwFQcrqEN1+g==} + engines: {node: '>=18'} + + chromium-bidi@5.1.0: + resolution: {integrity: sha512-9MSRhWRVoRPDG0TgzkHrshFSJJNZzfY5UFqUMuksg7zL1yoZIZ3jLB0YAgHclbiAxPI86pBnwDX1tbzoiV8aFw==} + peerDependencies: + devtools-protocol: '*' + + class-variance-authority@0.7.1: + resolution: {integrity: sha512-Ka+9Trutv7G8M6WT6SeiRWz792K5qEqIGEGzXKhAE6xOWAY6pPH8U+9IY3oCMv6kqTmLsv7Xh/2w2RigkePMsg==} + + cli-cursor@5.0.0: + resolution: {integrity: sha512-aCj4O5wKyszjMmDT4tZj93kxyydN/K5zPWSCe6/0AV/AA1pqe5ZBIw0a2ZfPQV7lL5/yb5HsUreJ6UFAF1tEQw==} + engines: {node: '>=18'} + + cli-spinners@2.9.2: + resolution: {integrity: sha512-ywqV+5MmyL4E7ybXgKys4DugZbX0FC6LnwrhjuykIjnK9k8OQacQ7axGKnjDXWNhns0xot3bZI5h55H8yo9cJg==} + engines: {node: '>=6'} + + cli-width@4.1.0: + resolution: {integrity: sha512-ouuZd4/dm2Sw5Gmqy6bGyNNNe1qt9RpmxveLSO7KcgsTnU7RXfsw+/bukWGo1abgBiMAic068rclZsO4IWmmxQ==} + engines: {node: '>= 12'} + + client-only@0.0.1: + resolution: {integrity: sha512-IV3Ou0jSMzZrd3pZ48nLkT9DA7Ag1pnPzaiQhpW7c3RbcqqzvzzVu+L8gfqMp/8IM2MQtSiqaCxrrcfu8I8rMA==} + + cliui@8.0.1: + resolution: {integrity: sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ==} + engines: {node: '>=12'} + + clone-regexp@3.0.0: + resolution: {integrity: sha512-ujdnoq2Kxb8s3ItNBtnYeXdm07FcU0u8ARAT1lQ2YdMwQC+cdiXX8KoqMVuglztILivceTtp4ivqGSmEmhBUJw==} + engines: {node: '>=12'} + + clsx@2.1.1: + resolution: {integrity: sha512-eYm0QWBtUrBWZWG0d386OGAw16Z995PiOVo2B7bjWSbHedGl5e0ZWaq65kOGgUSNesEIDkB9ISbTg/JK9dhCZA==} + engines: {node: '>=6'} + + cluster-key-slot@1.1.2: + resolution: {integrity: sha512-RMr0FhtfXemyinomL4hrWcYJxmX6deFdCxpJzhDttxgO1+bcCnkk+9drydLVDmAMG7NE6aN/fl4F7ucU/90gAA==} + engines: {node: '>=0.10.0'} + + cmdk@1.1.1: + resolution: {integrity: sha512-Vsv7kFaXm+ptHDMZ7izaRsP70GgrW9NBNGswt9OZaVBLlE0SNpDq8eu/VGXyF9r7M0azK3Wy7OlYXsuyYLFzHg==} + peerDependencies: + react: ^18 || ^19 || ^19.0.0-rc + react-dom: ^18 || ^19 || ^19.0.0-rc + + color-convert@2.0.1: + resolution: {integrity: sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==} + engines: {node: '>=7.0.0'} + + color-name@1.1.4: + resolution: {integrity: sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==} + + color-string@1.9.1: + resolution: {integrity: sha512-shrVawQFojnZv6xM40anx4CkoDP+fZsw/ZerEMsW/pyzsRbElpsL/DBVW7q3ExxwusdNXI3lXpuhEZkzs8p5Eg==} + + color@4.2.3: + resolution: {integrity: sha512-1rXeuUUiGGrykh+CeBdu5Ie7OJwinCgQY0bc7GCRxy5xVHy+moaqkpL/jqQq0MtQOeYcrqEz4abc5f0KtU7W4A==} + engines: {node: '>=12.5.0'} + + colorette@2.0.20: + resolution: {integrity: sha512-IfEDxwoWIjkeXL1eXcDiow4UbKjhLdq6/EuSVR9GMN7KVH3r9gQ83e73hsz1Nd1T3ijd5xv1wcWRYO+D6kCI2w==} + + combined-stream@1.0.8: + resolution: {integrity: sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==} + engines: {node: '>= 0.8'} + + comma-separated-tokens@2.0.3: + resolution: {integrity: sha512-Fu4hJdvzeylCfQPp9SGWidpzrMs7tTrlu6Vb8XGaRGck8QSNZJJp538Wrb60Lax4fPwR64ViY468OIUTbRlGZg==} + + commander@12.1.0: + resolution: {integrity: sha512-Vw8qHK3bZM9y/P10u3Vib8o/DdkvA2OtPtZvD871QKjy74Wj1WSKFILMPRPSdUSx5RFK1arlJzEtA4PkFgnbuA==} + engines: {node: '>=18'} + + commander@13.1.0: + resolution: {integrity: sha512-/rFeCpNJQbhSZjGVwO9RFV3xPqbnERS8MmIQzCtD/zl6gpJuV/bMLuN92oG3F7d8oDEHHRrujSXNUr8fpjntKw==} + engines: {node: '>=18'} + + commander@9.5.0: + resolution: {integrity: sha512-KRs7WVDKg86PWiuAqhDrAQnTXZKraVcCc6vFdL14qrZ/DcWwuRo7VoiYXalXO7S5GKpqYiVEwCbgFDfxNHKJBQ==} + engines: {node: ^12.20.0 || >=14} + + component-emitter@1.3.1: + resolution: {integrity: sha512-T0+barUSQRTUQASh8bx02dl+DhF54GtIDY13Y3m9oWTklKbb3Wv974meRpeZ3lp1JpLVECWWNHC4vaG2XHXouQ==} + + concat-map@0.0.1: + resolution: {integrity: sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==} + + content-disposition@0.5.4: + resolution: {integrity: sha512-FveZTNuGw04cxlAiWbzi6zTAL/lhehaWbTtgluJh4/E95DqMwTmha3KZN1aAWA8cFIhHzMZUvLevkw5Rqk+tSQ==} + engines: {node: '>= 0.6'} + + content-type@1.0.5: + resolution: {integrity: sha512-nTjqfcBFEipKdXCv4YDQWCfmcLZKm81ldF0pAopTvyrFGVbcR6P/VAAd5G7N+0tTr8QqiU0tFadD6FK4NtJwOA==} + engines: {node: '>= 0.6'} + + convert-hrtime@5.0.0: + resolution: {integrity: sha512-lOETlkIeYSJWcbbcvjRKGxVMXJR+8+OQb/mTPbA4ObPMytYIsUbuOE0Jzy60hjARYszq1id0j8KgVhC+WGZVTg==} + engines: {node: '>=12'} + + convert-source-map@2.0.0: + resolution: {integrity: sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg==} + + cookie-signature@1.0.6: + resolution: {integrity: sha512-QADzlaHc8icV8I7vbaJXJwod9HWYp8uCqf1xa4OfNu1T7JVxQIrUgOWtHdNDtPiywmFbiS12VjotIXLrKM3orQ==} + + cookie@0.7.1: + resolution: {integrity: sha512-6DnInpx7SJ2AK3+CTUE/ZM0vWTUboZCegxhC2xiIydHR9jNuTAASBrfEpHhiGOZw/nX51bHt6YQl8jsGo4y/0w==} + engines: {node: '>= 0.6'} + + cookie@0.7.2: + resolution: {integrity: sha512-yki5XnKuf750l50uGTllt6kKILY4nQ1eNIQatoXEByZ5dWgnKqbnqmTrBE5B4N7lrMJKQ2ytWMiTO2o0v6Ew/w==} + engines: {node: '>= 0.6'} + + cookie@1.0.2: + resolution: {integrity: sha512-9Kr/j4O16ISv8zBBhJoi4bXOYNTkFLOqSL3UDB0njXxCXNezjeyVrJyGOWtgfs/q2km1gwBcfH8q1yEGoMYunA==} + engines: {node: '>=18'} + + cookiejar@2.1.4: + resolution: {integrity: sha512-LDx6oHrK+PhzLKJU9j5S7/Y3jM/mUHvD/DeI1WQmJn652iPC5Y4TBzC9l+5OMOXlyTTA+SmVUPm0HQUwpD5Jqw==} + + core-js@3.43.0: + resolution: {integrity: sha512-N6wEbTTZSYOY2rYAn85CuvWWkCK6QweMn7/4Nr3w+gDBeBhk/x4EJeY6FPo4QzDoJZxVTv8U7CMvgWk6pOHHqA==} + + cors@2.8.5: + resolution: {integrity: sha512-KIHbLJqu73RGr/hnbrO9uBeixNGuvSQjul/jdFvS/KFSIH1hWVd1ng7zOHx+YrEfInLG7q4n6GHQ9cDtxv/P6g==} + engines: {node: '>= 0.10'} + + cosmiconfig@9.0.0: + resolution: {integrity: sha512-itvL5h8RETACmOTFc4UfIyB2RfEHi71Ax6E/PivVxq9NseKbOWpeyHEOIbmAw1rs8Ak0VursQNww7lf7YtUwzg==} + engines: {node: '>=14'} + peerDependencies: + typescript: '>=4.9.5' + peerDependenciesMeta: + typescript: + optional: true + + create-require@1.1.1: + resolution: {integrity: sha512-dcKFX3jn0MpIaXjisoRvexIJVEKzaq7z2rZKxf+MSr9TkdmHmsU4m2lcLojrj/FHl8mk5VxMmYA+ftRkP/3oKQ==} + + cron-parser@4.9.0: + resolution: {integrity: sha512-p0SaNjrHOnQeR8/VnfGbmg9te2kfyYSQ7Sc/j/6DtPL3JQvKxmjO9TSjNFpujqV3vEYYBvNNvXSxzyksBWAx1Q==} + engines: {node: '>=12.0.0'} + + cron@3.5.0: + resolution: {integrity: sha512-0eYZqCnapmxYcV06uktql93wNWdlTmmBFP2iYz+JPVcQqlyFYcn1lFuIk4R54pkOmE7mcldTAPZv6X5XA4Q46A==} + + cross-spawn@7.0.6: + resolution: {integrity: sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA==} + engines: {node: '>= 8'} + + css-jss@10.10.0: + resolution: {integrity: sha512-YyMIS/LsSKEGXEaVJdjonWe18p4vXLo8CMA4FrW/kcaEyqdIGKCFXao31gbJddXEdIxSXFFURWrenBJPlKTgAA==} + + css-vendor@2.0.8: + resolution: {integrity: sha512-x9Aq0XTInxrkuFeHKbYC7zWY8ai7qJ04Kxd9MnvbC1uO5DagxoHQjm4JvG+vCdXOoFtCjbL2XSZfxmoYa9uQVQ==} + + csstype@3.1.3: + resolution: {integrity: sha512-M1uQkMl8rQK/szD0LNhtqxIPLpimGm8sOBwU7lLnCpSbTyY3yeU1Vc7l4KT5zT4s/yOxHH5O7tIuuLOCnLADRw==} + + csv-parse@5.6.0: + resolution: {integrity: sha512-l3nz3euub2QMg5ouu5U09Ew9Wf6/wQ8I++ch1loQ0ljmzhmfZYrH9fflS22i/PQEvsPvxCwxgz5q7UB8K1JO4Q==} + + csv-parser@3.2.0: + resolution: {integrity: sha512-fgKbp+AJbn1h2dcAHKIdKNSSjfp43BZZykXsCjzALjKy80VXQNHPFJ6T9Afwdzoj24aMkq8GwDS7KGcDPpejrA==} + engines: {node: '>= 10'} + hasBin: true + + currency-symbol-map@5.1.0: + resolution: {integrity: sha512-LO/lzYRw134LMDVnLyAf1dHE5tyO6axEFkR3TXjQIOmMkAM9YL6QsiUwuXzZAmFnuDJcs4hayOgyIYtViXFrLw==} + + data-uri-to-buffer@6.0.2: + resolution: {integrity: sha512-7hvf7/GW8e86rW0ptuwS3OcBGDjIi6SZva7hCyWC0yYry2cOPmLIjXAUHI6DK2HsnwJd9ifmt57i8eV2n4YNpw==} + engines: {node: '>= 14'} + + date-fns@3.6.0: + resolution: {integrity: sha512-fRHTG8g/Gif+kSh50gaGEdToemgfj74aRX3swtiouboip5JDLAyDE9F11nHMIcvOaXeOC6D7SpNhi7uFyB7Uww==} + + date-fns@4.1.0: + resolution: {integrity: sha512-Ukq0owbQXxa/U3EGtsdVBkR1w7KOQ5gIBqdH2hkvknzZPYvBxb/aa6E8L7tmjFtkwZBu3UXBbjIgPo/Ez4xaNg==} + + dateformat@4.6.3: + resolution: {integrity: sha512-2P0p0pFGzHS5EMnhdxQi7aJN+iMheud0UhG4dlE1DLAlvL8JHjJJTX/CSm4JXwV0Ka5nGk3zC5mcb5bUQUxxMA==} + + debounce@2.2.0: + resolution: {integrity: sha512-Xks6RUDLZFdz8LIdR6q0MTH44k7FikOmnh5xkSjMig6ch45afc8sjTjRQf3P6ax8dMgcQrYO/AR2RGWURrruqw==} + engines: {node: '>=18'} + + debug@2.6.9: + resolution: {integrity: sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==} + peerDependencies: + supports-color: '*' + peerDependenciesMeta: + supports-color: + optional: true + + debug@4.3.7: + resolution: {integrity: sha512-Er2nc/H7RrMXZBFCEim6TCmMk02Z8vLC2Rbi1KEBggpo0fS6l0S1nnapwmIi3yW/+GOJap1Krg4w0Hg80oCqgQ==} + engines: {node: '>=6.0'} + peerDependencies: + supports-color: '*' + peerDependenciesMeta: + supports-color: + optional: true + + debug@4.4.1: + resolution: {integrity: sha512-KcKCqiftBJcZr++7ykoDIEwSa3XWowTfNPo92BYxjXiyYEVrUQh2aLyhxBCwww+heortUFxEJYcRzosstTEBYQ==} + engines: {node: '>=6.0'} + peerDependencies: + supports-color: '*' + peerDependenciesMeta: + supports-color: + optional: true + + decamelize@4.0.0: + resolution: {integrity: sha512-9iE1PgSik9HeIIw2JO94IidnE3eBoQrFJ3w7sFuzSX4DpmZ3v5sZpUiV5Swcf6mQEF+Y0ru8Neo+p+nyh2J+hQ==} + engines: {node: '>=10'} + + decimal.js@10.5.0: + resolution: {integrity: sha512-8vDa8Qxvr/+d94hSh5P3IJwI5t8/c0KsMp+g8bNw9cY2icONa5aPfvKeieW1WlG0WQYwwhJ7mjui2xtiePQSXw==} + + deep-eql@5.0.2: + resolution: {integrity: sha512-h5k/5U50IJJFpzfL6nO9jaaumfjO/f2NjK/oYB2Djzm4p9L+3T9qWpZqZ2hAbLPuuYq9wrU08WQyBTL5GbPk5Q==} + engines: {node: '>=6'} + + deep-is@0.1.4: + resolution: {integrity: sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==} + + deepmerge@4.3.1: + resolution: {integrity: sha512-3sUqbMEc77XqpdNO7FRyRog+eW3ph+GYCbj+rK+uYyRMuwsVy0rMiVtPn+QJlKFvWP/1PYpapqYn0Me2knFn+A==} + engines: {node: '>=0.10.0'} + + defu@6.1.4: + resolution: {integrity: sha512-mEQCMmwJu317oSz8CwdIOdwf3xMif1ttiM8LTufzc3g6kR+9Pe236twL8j3IYT1F7GfRgGcW6MWxzZjLIkuHIg==} + + degenerator@5.0.1: + resolution: {integrity: sha512-TllpMR/t0M5sqCXfj85i4XaAzxmS5tVA16dqvdkMwGmzI+dXLXnw3J+3Vdv7VKw+ThlTMboK6i9rnZ6Nntj5CQ==} + engines: {node: '>= 14'} + + delayed-stream@1.0.0: + resolution: {integrity: sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==} + engines: {node: '>=0.4.0'} + + denque@2.1.0: + resolution: {integrity: sha512-HVQE3AAb/pxF8fQAoiqpvg9i3evqug3hoiwakOyZAwJm+6vZehbkYXZ0l4JxS+I3QxM97v5aaRNhj8v5oBhekw==} + engines: {node: '>=0.10'} + + depd@2.0.0: + resolution: {integrity: sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw==} + engines: {node: '>= 0.8'} + + dequal@2.0.3: + resolution: {integrity: sha512-0je+qPKHEMohvfRTCEo3CrPG6cAzAYgmzKyxRiYSSDkS6eGJdyVJm7WaYA5ECaAD9wLB2T4EEeymA5aFVcYXCA==} + engines: {node: '>=6'} + + destroy@1.2.0: + resolution: {integrity: sha512-2sJGJTaXIIaR1w4iJSNoN0hnMY7Gpc/n8D4qSCJw8QqFWXf7cuAgnEHxBpweaVcPevC2l3KpjYCx3NypQQgaJg==} + engines: {node: '>= 0.8', npm: 1.2.8000 || >= 1.4.16} + + detect-content-type@1.2.0: + resolution: {integrity: sha512-YCBxuqJLY9rMxV44Ict2kNgjYFN3v1dnsn6sJvd6sUwwU1TWP3D+K2dr/S9AF/fio2/RsAKYdRiEOtNoRbmiag==} + + detect-libc@2.0.4: + resolution: {integrity: sha512-3UDv+G9CsCKO1WKMGw9fwq/SWJYbI0c5Y7LU1AXYoDdbhE2AHQ6N6Nb34sG8Fj7T5APy8qXDCKuuIHd1BR0tVA==} + engines: {node: '>=8'} + + detect-node-es@1.1.0: + resolution: {integrity: sha512-ypdmJU/TbBby2Dxibuv7ZLW3Bs1QEmM7nHjEANfohJLvE0XVujisn1qPJcZxg+qDucsr+bP6fLD1rPS3AhJ7EQ==} + + devlop@1.1.0: + resolution: {integrity: sha512-RWmIqhcFf1lRYBvNmr7qTNuyCt/7/ns2jbpp1+PalgE/rDQcBT0fioSMUpJ93irlUhC5hrg4cYqe6U+0ImW0rA==} + + devtools-protocol@0.0.1452169: + resolution: {integrity: sha512-FOFDVMGrAUNp0dDKsAU1TorWJUx2JOU1k9xdgBKKJF3IBh/Uhl2yswG5r3TEAOrCiGY2QRp1e6LVDQrCsTKO4g==} + + dezalgo@1.0.4: + resolution: {integrity: sha512-rXSP0bf+5n0Qonsb+SVVfNfIsimO4HEtmnIpPHY8Q1UCzKlQrDMfdobr8nJOOsRgWCyMRqeSBQzmWUMq7zvVig==} + + diff-match-patch@1.0.5: + resolution: {integrity: sha512-IayShXAgj/QMXgB0IWmKx+rOPuGMhqm5w6jvFxmVenXKIzRqTAAsbBPT3kWQeGANj3jGgvcvv4yK6SxqYmikgw==} + + diff@4.0.2: + resolution: {integrity: sha512-58lmxKSA4BNyLz+HHMUzlOEpg09FV+ev6ZMe3vJihgdxzgcwZ8VoEEPmALCZG9LmqfVoNMMKpttIYTVG6uDY7A==} + engines: {node: '>=0.3.1'} + + diff@7.0.0: + resolution: {integrity: sha512-PJWHUb1RFevKCwaFA9RlG5tCd+FO5iRh9A8HEtkmBH2Li03iJriB6m6JIN4rGz3K3JLawI7/veA1xzRKP6ISBw==} + engines: {node: '>=0.3.1'} + + dir-glob@3.0.1: + resolution: {integrity: sha512-WkrWp9GR4KXfKGYzOLmTuGVi1UWFfws377n9cc55/tb6DuqyF6pcQ5AbiHEshaDpY9v6oaSr2XCDidGmMwdzIA==} + engines: {node: '>=8'} + + dom-serializer@2.0.0: + resolution: {integrity: sha512-wIkAryiqt/nV5EQKqQpo3SToSOV9J0DnbJqwK7Wv/Trc92zIAYZ4FlMu+JPFW1DfGFt81ZTCGgDEabffXeLyJg==} + + domelementtype@2.3.0: + resolution: {integrity: sha512-OLETBj6w0OsagBwdXnPdN0cnMfF9opN69co+7ZrbfPGrdpPVNBUj02spi6B1N7wChLQiPn4CSH/zJvXw56gmHw==} + + domhandler@5.0.3: + resolution: {integrity: sha512-cgwlv/1iFQiFnU96XXgROh8xTeetsnJiDsTc7TYCLFd9+/WNkIqPTxiM/8pSd8VIrhXGTf1Ny1q1hquVqDJB5w==} + engines: {node: '>= 4'} + + domutils@3.2.2: + resolution: {integrity: sha512-6kZKyUajlDuqlHKVX1w7gyslj9MPIXzIFiz/rGu35uC1wMi+kMhQwGhl4lt9unC9Vb9INnY9Z3/ZA3+FhASLaw==} + + dot-case@3.0.4: + resolution: {integrity: sha512-Kv5nKlh6yRrdrGvxeJ2e5y2eRUpkUosIW4A2AS38zwSz27zu7ufDwQPi5Jhs3XAlGNetl3bmnGhQsMtkKJnj3w==} + + dotenv@16.5.0: + resolution: {integrity: sha512-m/C+AwOAr9/W1UOIZUo232ejMNnJAJtYQjUbHoNTBNTJSvqzzDh7vnrei3o3r3m9blf6ZoDkvcw0VmozNRFJxg==} + engines: {node: '>=12'} + + drizzle-kit@0.31.1: + resolution: {integrity: sha512-PUjYKWtzOzPtdtQlTHQG3qfv4Y0XT8+Eas6UbxCmxTj7qgMf+39dDujf1BP1I+qqZtw9uzwTh8jYtkMuCq+B0Q==} + hasBin: true + + drizzle-orm@0.43.1: + resolution: {integrity: sha512-dUcDaZtE/zN4RV/xqGrVSMpnEczxd5cIaoDeor7Zst9wOe/HzC/7eAaulywWGYXdDEc9oBPMjayVEDg0ziTLJA==} + peerDependencies: + '@aws-sdk/client-rds-data': '>=3' + '@cloudflare/workers-types': '>=4' + '@electric-sql/pglite': '>=0.2.0' + '@libsql/client': '>=0.10.0' + '@libsql/client-wasm': '>=0.10.0' + '@neondatabase/serverless': '>=0.10.0' + '@op-engineering/op-sqlite': '>=2' + '@opentelemetry/api': ^1.4.1 + '@planetscale/database': '>=1.13' + '@prisma/client': '*' + '@tidbcloud/serverless': '*' + '@types/better-sqlite3': '*' + '@types/pg': '*' + '@types/sql.js': '*' + '@vercel/postgres': '>=0.8.0' + '@xata.io/client': '*' + better-sqlite3: '>=7' + bun-types: '*' + expo-sqlite: '>=14.0.0' + gel: '>=2' + knex: '*' + kysely: '*' + mysql2: '>=2' + pg: '>=8' + postgres: '>=3' + prisma: '*' + sql.js: '>=1' + sqlite3: '>=5' + peerDependenciesMeta: + '@aws-sdk/client-rds-data': + optional: true + '@cloudflare/workers-types': + optional: true + '@electric-sql/pglite': + optional: true + '@libsql/client': + optional: true + '@libsql/client-wasm': + optional: true + '@neondatabase/serverless': + optional: true + '@op-engineering/op-sqlite': + optional: true + '@opentelemetry/api': + optional: true + '@planetscale/database': + optional: true + '@prisma/client': + optional: true + '@tidbcloud/serverless': + optional: true + '@types/better-sqlite3': + optional: true + '@types/pg': + optional: true + '@types/sql.js': + optional: true + '@vercel/postgres': + optional: true + '@xata.io/client': + optional: true + better-sqlite3: + optional: true + bun-types: + optional: true + expo-sqlite: + optional: true + gel: + optional: true + knex: + optional: true + kysely: + optional: true + mysql2: + optional: true + pg: + optional: true + postgres: + optional: true + prisma: + optional: true + sql.js: + optional: true + sqlite3: + optional: true + + drizzle-zod@0.8.2: + resolution: {integrity: sha512-9Do/16OjFFNrQDZgvMtxtDDwKWbFOxUAIwNPKX98SfxrP8H18vhN1BvNXbhelLcdgCE7GEaXDJqBjMExSkhpkA==} + peerDependencies: + drizzle-orm: '>=0.36.0' + zod: ^3.25.1 + + dunder-proto@1.0.1: + resolution: {integrity: sha512-KIN/nDJBQRcXw0MLVhZE9iQHmG68qAVIBg9CqmUYjmQIhgij9U5MFvrqkUL5FbtyyzZuOeOt0zdeRe4UY7ct+A==} + engines: {node: '>= 0.4'} + + eastasianwidth@0.2.0: + resolution: {integrity: sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA==} + + ee-first@1.1.1: + resolution: {integrity: sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow==} + + electron-to-chromium@1.5.167: + resolution: {integrity: sha512-LxcRvnYO5ez2bMOFpbuuVuAI5QNeY1ncVytE/KXaL6ZNfzX1yPlAO0nSOyIHx2fVAuUprMqPs/TdVhUFZy7SIQ==} + + emoji-regex@10.4.0: + resolution: {integrity: sha512-EC+0oUMY1Rqm4O6LLrgjtYDvcVYTy7chDnM4Q7030tP4Kwj3u/pR6gP9ygnp2CJMK5Gq+9Q2oqmrFJAz01DXjw==} + + emoji-regex@8.0.0: + resolution: {integrity: sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==} + + emoji-regex@9.2.2: + resolution: {integrity: sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==} + + encodeurl@1.0.2: + resolution: {integrity: sha512-TPJXq8JqFaVYm2CWmPvnP2Iyo4ZSM7/QKcSmuMLDObfpH5fi7RUGmd/rTDf+rut/saiDiQEeVTNgAmJEdAOx0w==} + engines: {node: '>= 0.8'} + + encodeurl@2.0.0: + resolution: {integrity: sha512-Q0n9HRi4m6JuGIV1eFlmvJB7ZEVxu93IrMyiMsGC0lrMJMWzRgx6WGquyfQgZVb31vhGgXnfmPNNXmxnOkRBrg==} + engines: {node: '>= 0.8'} + + end-of-stream@1.4.4: + resolution: {integrity: sha512-+uw1inIHVPQoaVuHzRyXd21icM+cnt4CzD5rW+NC1wjOUSTOs+Te7FOv7AhN7vS9x/oIyhLP5PR1H+phQAHu5Q==} + + engine.io-parser@5.2.3: + resolution: {integrity: sha512-HqD3yTBfnBxIrbnM1DoD6Pcq8NECnh8d4As1Qgh0z5Gg3jRRIqijury0CL3ghu/edArpUYiYqQiDUQBIs4np3Q==} + engines: {node: '>=10.0.0'} + + engine.io@6.6.4: + resolution: {integrity: sha512-ZCkIjSYNDyGn0R6ewHDtXgns/Zre/NT6Agvq1/WobF7JXgFff4SeDroKiCO3fNJreU9YG429Sc81o4w5ok/W5g==} + engines: {node: '>=10.2.0'} + + enhanced-resolve@5.18.1: + resolution: {integrity: sha512-ZSW3ma5GkcQBIpwZTSRAI8N71Uuwgs93IezB7mf7R60tC8ZbJideoDNKjHn2O9KIlx6rkGTTEk1xUCK2E1Y2Yg==} + engines: {node: '>=10.13.0'} + + entities@4.5.0: + resolution: {integrity: sha512-V0hjH4dGPh9Ao5p0MoRY6BVqtwCjhz6vI5LT8AJ55H+4g9/4vbHx1I54fS0XuclLhDHArPQCiMjDxjaL8fPxhw==} + engines: {node: '>=0.12'} + + env-paths@2.2.1: + resolution: {integrity: sha512-+h1lkLKhZMTYjog1VEpJNG7NZJWcuc2DDk/qsqSTRRCOXiLjeQ1d1/udrUGhqMxUgAlwKNZ0cf2uqan5GLuS2A==} + engines: {node: '>=6'} + + error-ex@1.3.2: + resolution: {integrity: sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g==} + + es-define-property@1.0.1: + resolution: {integrity: sha512-e3nRfgfUZ4rNGL232gUgX06QNyyez04KdjFrF+LTRoOXmrOgFKDg4BCdsjW8EnT69eqdYGmRpJwiPVYNrCaW3g==} + engines: {node: '>= 0.4'} + + es-errors@1.3.0: + resolution: {integrity: sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw==} + engines: {node: '>= 0.4'} + + es-object-atoms@1.1.1: + resolution: {integrity: sha512-FGgH2h8zKNim9ljj7dankFPcICIK9Cp5bm+c2gQSYePhpaG5+esrLODihIorn+Pe6FGJzWhXQotPv73jTaldXA==} + engines: {node: '>= 0.4'} + + es-set-tostringtag@2.1.0: + resolution: {integrity: sha512-j6vWzfrGVfyXxge+O0x5sh6cvxAog0a/4Rdd2K36zCMV5eJ+/+tOAngRO8cODMNWbVRdVlmGZQL2YS3yR8bIUA==} + engines: {node: '>= 0.4'} + + es6-promise@4.2.8: + resolution: {integrity: sha512-HJDGx5daxeIvxdBxvG2cb9g4tEvwIk3i8+nhX0yGrYmZUzbkdg8QbDevheDB8gd0//uPj4c1EQua8Q+MViT0/w==} + + esbuild-register@3.6.0: + resolution: {integrity: sha512-H2/S7Pm8a9CL1uhp9OvjwrBh5Pvx0H8qVOxNu8Wed9Y7qv56MPtq+GGM8RJpq6glYJn9Wspr8uw7l55uyinNeg==} + peerDependencies: + esbuild: '>=0.12 <1' + + esbuild@0.18.20: + resolution: {integrity: sha512-ceqxoedUrcayh7Y7ZX6NdbbDzGROiyVBgC4PriJThBKSVPWnnFHZAkfI1lJT8QFkOwH4qOS2SJkS4wvpGl8BpA==} + engines: {node: '>=12'} + hasBin: true + + esbuild@0.25.5: + resolution: {integrity: sha512-P8OtKZRv/5J5hhz0cUAdu/cLuPIKXpQl1R9pZtvmHWQvrAUVd0UNIPT4IB4W3rNOqVO0rlqHmCIbSwxh/c9yUQ==} + engines: {node: '>=18'} + hasBin: true + + escalade@3.2.0: + resolution: {integrity: sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA==} + engines: {node: '>=6'} + + escape-html@1.0.3: + resolution: {integrity: sha512-NiSupZ4OeuGwr68lGIeym/ksIZMJodUGOSCZ/FSnTxcrekbvqrgdUxlJOMpijaKZVjAJrWrGs/6Jy8OMuyj9ow==} + + escape-string-regexp@4.0.0: + resolution: {integrity: sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==} + engines: {node: '>=10'} + + escodegen@2.1.0: + resolution: {integrity: sha512-2NlIDTwUWJN0mRPQOdtQBzbUHvdGY2P1VXSyU83Q3xKxM7WHX2Ql8dKq782Q9TgQUNOLEzEYu9bzLNj1q88I5w==} + engines: {node: '>=6.0'} + hasBin: true + + eslint-plugin-react-hooks@5.2.0: + resolution: {integrity: sha512-+f15FfK64YQwZdJNELETdn5ibXEUQmW1DZL6KXhNnc2heoy/sg9VJJeT7n8TlMWouzWqSWavFkIhHyIbIAEapg==} + engines: {node: '>=10'} + peerDependencies: + eslint: ^3.0.0 || ^4.0.0 || ^5.0.0 || ^6.0.0 || ^7.0.0 || ^8.0.0-0 || ^9.0.0 + + eslint-plugin-react-refresh@0.4.20: + resolution: {integrity: sha512-XpbHQ2q5gUF8BGOX4dHe+71qoirYMhApEPZ7sfhF/dNnOF1UXnCMGZf79SFTBO7Bz5YEIT4TMieSlJBWhP9WBA==} + peerDependencies: + eslint: '>=8.40' + + eslint-scope@8.4.0: + resolution: {integrity: sha512-sNXOfKCn74rt8RICKMvJS7XKV/Xk9kA7DyJr8mJik3S7Cwgy3qlkkmyS2uQB3jiJg6VNdZd/pDBJu0nvG2NlTg==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + + eslint-visitor-keys@3.4.3: + resolution: {integrity: sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag==} + engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} + + eslint-visitor-keys@4.2.1: + resolution: {integrity: sha512-Uhdk5sfqcee/9H/rCOJikYz67o0a2Tw2hGRPOG2Y1R2dg7brRe1uG0yaNQDHu+TO/uQPF/5eCapvYSmHUjt7JQ==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + + eslint@9.29.0: + resolution: {integrity: sha512-GsGizj2Y1rCWDu6XoEekL3RLilp0voSePurjZIkxL3wlm5o5EC9VpgaP7lrCvjnkuLvzFBQWB3vWB3K5KQTveQ==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + hasBin: true + peerDependencies: + jiti: '*' + peerDependenciesMeta: + jiti: + optional: true + + espree@10.4.0: + resolution: {integrity: sha512-j6PAQ2uUr79PZhBjP5C5fhl8e39FmRnOjsD5lGnWrFU8i2G776tBK7+nP8KuQUTTyAZUwfQqXAgrVH5MbH9CYQ==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + + esprima@4.0.1: + resolution: {integrity: sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==} + engines: {node: '>=4'} + hasBin: true + + esquery@1.6.0: + resolution: {integrity: sha512-ca9pw9fomFcKPvFLXhBKUK90ZvGibiGOvRJNbjljY7s7uq/5YO4BOzcYtJqExdx99rF6aAcnRxHmcUHcz6sQsg==} + engines: {node: '>=0.10'} + + esrecurse@4.3.0: + resolution: {integrity: sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==} + engines: {node: '>=4.0'} + + estraverse@5.3.0: + resolution: {integrity: sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==} + engines: {node: '>=4.0'} + + esutils@2.0.3: + resolution: {integrity: sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==} + engines: {node: '>=0.10.0'} + + etag@1.8.1: + resolution: {integrity: sha512-aIL5Fx7mawVa300al2BnEE4iNvo1qETxLrPI/o05L7z6go7fCw1J6EQmbK4FmJ2AS7kgVF/KEZWufBfdClMcPg==} + engines: {node: '>= 0.6'} + + event-target-shim@5.0.1: + resolution: {integrity: sha512-i/2XbnSz/uxRCU6+NdVJgKWDTM427+MqYbkQzD321DuCQJUqOuJKIA0IM2+W2xtYHdKOmZ4dR6fExsd4SXL+WQ==} + engines: {node: '>=6'} + + express@4.21.2: + resolution: {integrity: sha512-28HqgMZAmih1Czt9ny7qr6ek2qddF4FclbMzwhCREB6OFfH+rXAnuNCwo1/wFvrtbgsQDb4kSbX9de9lFbrXnA==} + engines: {node: '>= 0.10.0'} + + external-editor@3.1.0: + resolution: {integrity: sha512-hMQ4CX1p1izmuLYyZqLMO/qGNw10wSv9QDCPfzXfyFrOaCSSoRfqE1Kf1s5an66J5JZC62NewG+mK49jOCtQew==} + engines: {node: '>=4'} + + extract-zip@2.0.1: + resolution: {integrity: sha512-GDhU9ntwuKyGXdZBUgTIe+vXnWj0fppUEtMDL0+idd5Sta8TGpHssn/eusA9mrPr9qNDym6SxAYZjNvCn/9RBg==} + engines: {node: '>= 10.17.0'} + hasBin: true + + fast-copy@3.0.2: + resolution: {integrity: sha512-dl0O9Vhju8IrcLndv2eU4ldt1ftXMqqfgN4H1cpmGV7P6jeB9FwpN9a2c8DPGE1Ys88rNUJVYDHq73CGAGOPfQ==} + + fast-deep-equal@2.0.1: + resolution: {integrity: sha512-bCK/2Z4zLidyB4ReuIsvALH6w31YfAQDmXMqMx6FyfHqvBxtjC0eRumeSu4Bs3XtXwpyIywtSTrVT99BxY1f9w==} + + fast-deep-equal@3.1.3: + resolution: {integrity: sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==} + + fast-fifo@1.3.2: + resolution: {integrity: sha512-/d9sfos4yxzpwkDkuN7k2SqFKtYNmCTzgfEpz82x34IM9/zc8KGxQoXg1liNC/izpRM/MBdt44Nmx41ZWqk+FQ==} + + fast-glob@3.3.3: + resolution: {integrity: sha512-7MptL8U0cqcFdzIzwOTHoilX9x5BrNqye7Z/LuC7kCMRio1EMSyqRK3BEAUD7sXRq4iT4AzTVuZdhgQ2TCvYLg==} + engines: {node: '>=8.6.0'} + + fast-json-stable-stringify@2.1.0: + resolution: {integrity: sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==} + + fast-levenshtein@2.0.6: + resolution: {integrity: sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw==} + + fast-redact@3.5.0: + resolution: {integrity: sha512-dwsoQlS7h9hMeYUq1W++23NDcBLV4KqONnITDV9DjfS3q1SgDGVrBdvvTLUotWtPSD7asWDV9/CmsZPy8Hf70A==} + engines: {node: '>=6'} + + fast-safe-stringify@2.1.1: + resolution: {integrity: sha512-W+KJc2dmILlPplD/H4K9l9LcAHAfPtP6BY84uVLXQ6Evcz9Lcg33Y2z1IVblT6xdY54PXYVHEv+0Wpq8Io6zkA==} + + fast-sha256@1.3.0: + resolution: {integrity: sha512-n11RGP/lrWEFI/bWdygLxhI+pVeo1ZYIVwvvPkW7azl/rOy+F3HYRZ2K5zeE9mmkhQppyv9sQFx0JM9UabnpPQ==} + + fastq@1.19.1: + resolution: {integrity: sha512-GwLTyxkCXjXbxqIhTsMI2Nui8huMPtnxg7krajPJAjnEG/iiOS7i+zCtWGZR9G0NBKbXKh6X9m9UIsYX/N6vvQ==} + + fd-slicer@1.1.0: + resolution: {integrity: sha512-cE1qsB/VwyQozZ+q1dGxR8LBYNZeofhEdUNGSMbQD3Gw2lAzX9Zb3uIU6Ebc/Fmyjo9AWWfnn0AUCHqtevs/8g==} + + fdir@6.4.6: + resolution: {integrity: sha512-hiFoqpyZcfNm1yc4u8oWCf9A2c4D3QjCrks3zmoVKVxpQRzmPNar1hUJcBG2RQHvEVGDN+Jm81ZheVLAQMK6+w==} + peerDependencies: + picomatch: ^3 || ^4 + peerDependenciesMeta: + picomatch: + optional: true + + fetch-retry@6.0.0: + resolution: {integrity: sha512-BUFj1aMubgib37I3v4q78fYo63Po7t4HUPTpQ6/QE6yK6cIQrP+W43FYToeTEyg5m2Y7eFUtijUuAv/PDlWuag==} + + fflate@0.4.8: + resolution: {integrity: sha512-FJqqoDBR00Mdj9ppamLa/Y7vxm+PRmNWA67N846RvsoYVMKB4q3y/de5PA7gUmRMYK/8CMz2GDZQmCRN1wBcWA==} + + figures@6.1.0: + resolution: {integrity: sha512-d+l3qxjSesT4V7v2fh+QnmFnUWv9lSpjarhShNTgBOfA0ttejbQUAlHLitbjkoRiDulW0OPoQPYIGhIC8ohejg==} + engines: {node: '>=18'} + + file-entry-cache@8.0.0: + resolution: {integrity: sha512-XXTUwCvisa5oacNGRP9SfNtYBNAMi+RPwBFmblZEF7N7swHYQS6/Zfk7SRwx4D5j3CH211YNRco1DEMNVfZCnQ==} + engines: {node: '>=16.0.0'} + + file-selector@2.1.2: + resolution: {integrity: sha512-QgXo+mXTe8ljeqUFaX3QVHc5osSItJ/Km+xpocx0aSqWGMSCf6qYs/VnzZgS864Pjn5iceMRFigeAV7AfTlaig==} + engines: {node: '>= 12'} + + fill-range@7.1.1: + resolution: {integrity: sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==} + engines: {node: '>=8'} + + finalhandler@1.3.1: + resolution: {integrity: sha512-6BN9trH7bp3qvnrRyzsBz+g3lZxTNZTbVO2EV1CS0WIcDbawYVdYvGflME/9QP0h0pYlCDBCTjYa9nZzMDpyxQ==} + engines: {node: '>= 0.8'} + + find-up@5.0.0: + resolution: {integrity: sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==} + engines: {node: '>=10'} + + flat-cache@4.0.1: + resolution: {integrity: sha512-f7ccFPK3SXFHpx15UIGyRJ/FJQctuKZ0zVuN3frBo4HnK3cay9VEW0R6yPYFHC0AgqhukPzKjq22t5DmAyqGyw==} + engines: {node: '>=16'} + + flat@5.0.2: + resolution: {integrity: sha512-b6suED+5/3rTpUBdG1gupIl8MPFCAMA0QXwmljLhvCUKcUvdE4gWky9zpuGCcXHOsz4J9wPGNWq6OKpmIzz3hQ==} + hasBin: true + + flatted@3.3.3: + resolution: {integrity: sha512-GX+ysw4PBCz0PzosHDepZGANEuFCMLrnRTiEy9McGjmkCQYwRq4A/X786G/fjM/+OjsWSU1ZrY5qyARZmO/uwg==} + + follow-redirects@1.15.9: + resolution: {integrity: sha512-gew4GsXizNgdoRyqmyfMHyAmXsZDk6mHkSxZFCzW9gwlbtOW44CDtYavM+y+72qD/Vq2l550kMF52DT8fOLJqQ==} + engines: {node: '>=4.0'} + peerDependencies: + debug: '*' + peerDependenciesMeta: + debug: + optional: true + + foreground-child@3.3.1: + resolution: {integrity: sha512-gIXjKqtFuWEgzFRJA9WCQeSJLZDjgJUOMCMzxtvFq/37KojM1BFGufqsCy0r4qSQmYLsZYMeyRqzIWOMup03sw==} + engines: {node: '>=14'} + + form-data-encoder@1.7.2: + resolution: {integrity: sha512-qfqtYan3rxrnCk1VYaA4H+Ms9xdpPqvLZa6xmMgFvhO32x7/3J/ExcTd6qpxM0vH2GdMI+poehyBZvqfMTto8A==} + + form-data@4.0.3: + resolution: {integrity: sha512-qsITQPfmvMOSAdeyZ+12I1c+CKSstAFAwu+97zrnWAbIr5u8wfsExUzCesVLC8NgHuRUqNN4Zy6UPWUTRGslcA==} + engines: {node: '>= 6'} + + formdata-node@4.4.1: + resolution: {integrity: sha512-0iirZp3uVDjVGt9p49aTaqjk84TrglENEDuqfdlZQ1roC9CWlPk6Avf8EEnZNcAqPonwkG35x4n3ww/1THYAeQ==} + engines: {node: '>= 12.20'} + + formidable@3.5.4: + resolution: {integrity: sha512-YikH+7CUTOtP44ZTnUhR7Ic2UASBPOqmaRkRKxRbywPTe5VxF7RRCck4af9wutiZ/QKM5nME9Bie2fFaPz5Gug==} + engines: {node: '>=14.0.0'} + + forwarded@0.2.0: + resolution: {integrity: sha512-buRG0fpBtRHSTCOASe6hD258tEubFoRLb4ZNA6NxMVHNw2gOcwHo9wyablzMzOA5z9xA9L1KNjk/Nt6MT9aYow==} + engines: {node: '>= 0.6'} + + framer-motion@12.18.1: + resolution: {integrity: sha512-6o4EDuRPLk4LSZ1kRnnEOurbQ86MklVk+Y1rFBUKiF+d2pCdvMjWVu0ZkyMVCTwl5UyTH2n/zJEJx+jvTYuxow==} + peerDependencies: + '@emotion/is-prop-valid': '*' + react: ^18.0.0 || ^19.0.0 + react-dom: ^18.0.0 || ^19.0.0 + peerDependenciesMeta: + '@emotion/is-prop-valid': + optional: true + react: + optional: true + react-dom: + optional: true + + fresh@0.5.2: + resolution: {integrity: sha512-zJ2mQYM18rEFOudeV4GShTGIQ7RbzA7ozbU9I/XBpm7kqgMywgmylMwXHxZJmkVoYkna9d2pVXVXPdYTP9ej8Q==} + engines: {node: '>= 0.6'} + + fsevents@2.3.3: + resolution: {integrity: sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==} + engines: {node: ^8.16.0 || ^10.6.0 || >=11.0.0} + os: [darwin] + + function-bind@1.1.2: + resolution: {integrity: sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==} + + function-timeout@0.1.1: + resolution: {integrity: sha512-0NVVC0TaP7dSTvn1yMiy6d6Q8gifzbvQafO46RtLG/kHJUBNd+pVRGOBoK44wNBvtSPUJRfdVvkFdD3p0xvyZg==} + engines: {node: '>=14.16'} + + gensync@1.0.0-beta.2: + resolution: {integrity: sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg==} + engines: {node: '>=6.9.0'} + + get-caller-file@2.0.5: + resolution: {integrity: sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==} + engines: {node: 6.* || 8.* || >= 10.*} + + get-east-asian-width@1.3.0: + resolution: {integrity: sha512-vpeMIQKxczTD/0s2CdEWHcb0eeJe6TFjxb+J5xgX7hScxqrGuyjmv4c1D4A/gelKfyox0gJJwIHF+fLjeaM8kQ==} + engines: {node: '>=18'} + + get-intrinsic@1.3.0: + resolution: {integrity: sha512-9fSjSaos/fRIVIp+xSJlE6lfwhES7LNtKaCBIamHsjr2na1BiABJPo0mOjjz8GJDURarmCPGqaiVg5mfjb98CQ==} + engines: {node: '>= 0.4'} + + get-nonce@1.0.1: + resolution: {integrity: sha512-FJhYRoDaiatfEkUK8HKlicmu/3SGFD51q3itKDGoSTysQJBnfOcxU5GxnhE1E6soB76MbT0MBtnKJuXyAx+96Q==} + engines: {node: '>=6'} + + get-proto@1.0.1: + resolution: {integrity: sha512-sTSfBjoXBp89JvIKIefqw7U2CCebsc74kiY6awiGogKtoSGbgjYE/G/+l9sF3MWFPNc9IcoOC4ODfKHfxFmp0g==} + engines: {node: '>= 0.4'} + + get-stream@5.2.0: + resolution: {integrity: sha512-nBF+F1rAZVCu/p7rjzgA+Yb4lfYXrpl7a6VmJrU8wF9I1CKvP/QwPNZHnOlwbTkY6dvtFIzFMSyQXbLoTQPRpA==} + engines: {node: '>=8'} + + get-tsconfig@4.10.1: + resolution: {integrity: sha512-auHyJ4AgMz7vgS8Hp3N6HXSmlMdUyhSUrfBF16w153rxtLIEOE+HGqaBppczZvnHLqQJfiHotCYpNhl0lUROFQ==} + + get-uri@6.0.4: + resolution: {integrity: sha512-E1b1lFFLvLgak2whF2xDBcOy6NLVGZBqqjJjsIhvopKfWWEi64pLVTWWehV8KlLerZkfNTA95sTe2OdJKm1OzQ==} + engines: {node: '>= 14'} + + glob-parent@5.1.2: + resolution: {integrity: sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==} + engines: {node: '>= 6'} + + glob-parent@6.0.2: + resolution: {integrity: sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==} + engines: {node: '>=10.13.0'} + + glob-to-regexp@0.4.1: + resolution: {integrity: sha512-lkX1HJXwyMcprw/5YUZc2s7DrpAiHB21/V+E1rHUrVNokkvB6bqMzT0VfV6/86ZNabt1k14YOIaT7nDvOX3Iiw==} + + glob@10.4.5: + resolution: {integrity: sha512-7Bv8RF0k6xjo7d4A/PxYLbUCfb6c+Vpd2/mB2yRDlew7Jb5hEXiCD9ibfO7wpk8i4sevK6DFny9h7EYbM3/sHg==} + hasBin: true + + glob@11.0.3: + resolution: {integrity: sha512-2Nim7dha1KVkaiF4q6Dj+ngPPMdfvLJEOpZk/jKiUAkqKebpGAWQXAq9z1xu9HKu5lWfqw/FASuccEjyznjPaA==} + engines: {node: 20 || >=22} + hasBin: true + + globals@11.12.0: + resolution: {integrity: sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA==} + engines: {node: '>=4'} + + globals@14.0.0: + resolution: {integrity: sha512-oahGvuMGQlPw/ivIYBjVSrWAfWLBeku5tpPE2fOPLi+WHffIWbuh2tCjhyQhTBPMf5E9jDEH4FOmTYgYwbKwtQ==} + engines: {node: '>=18'} + + globals@15.15.0: + resolution: {integrity: sha512-7ACyT3wmyp3I61S4fG682L0VA2RGD9otkqGJIwNUMF1SWUombIIk+af1unuDYgMm082aHYwD+mzJvv9Iu8dsgg==} + engines: {node: '>=18'} + + globby@11.1.0: + resolution: {integrity: sha512-jhIXaOzy1sb8IyocaruWSn1TjmnBVs8Ayhcy83rmxNJ8q2uWKCAj3CnJY+KpGSXCueAPc0i05kVvVKtP1t9S3g==} + engines: {node: '>=10'} + + goober@2.1.16: + resolution: {integrity: sha512-erjk19y1U33+XAMe1VTvIONHYoSqE4iS7BYUZfHaqeohLmnC0FdxEh7rQU+6MZ4OajItzjZFSRtVANrQwNq6/g==} + peerDependencies: + csstype: ^3.0.10 + + gopd@1.2.0: + resolution: {integrity: sha512-ZUKRh6/kUFoAiTAtTYPZJ3hw9wNxx+BIBOijnlG9PnrJsCcSjs1wyyD6vJpaYtgnzDrKYRSqf3OO6Rfa93xsRg==} + engines: {node: '>= 0.4'} + + graceful-fs@4.2.11: + resolution: {integrity: sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==} + + graphemer@1.4.0: + resolution: {integrity: sha512-EtKwoO6kxCL9WO5xipiHTZlSzBm7WLT627TqC/uVRd0HKmq8NXyebnNYxDoBi7wt8eTWrUrKXCOVaFq9x1kgag==} + + has-flag@3.0.0: + resolution: {integrity: sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==} + engines: {node: '>=4'} + + has-flag@4.0.0: + resolution: {integrity: sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==} + engines: {node: '>=8'} + + has-symbols@1.1.0: + resolution: {integrity: sha512-1cDNdwJ2Jaohmb3sg4OmKaMBwuC48sYni5HUw2DvsC8LjGTLK9h+eb1X6RyuOHe4hT0ULCW68iomhjUoKUqlPQ==} + engines: {node: '>= 0.4'} + + has-tostringtag@1.0.2: + resolution: {integrity: sha512-NqADB8VjPFLM2V0VvHUewwwsw0ZWBaIdgo+ieHtK3hasLz4qeCRjYcqfB6AQrBggRKppKF8L52/VqdVsO47Dlw==} + engines: {node: '>= 0.4'} + + hasown@2.0.2: + resolution: {integrity: sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==} + engines: {node: '>= 0.4'} + + hast-util-to-html@9.0.5: + resolution: {integrity: sha512-OguPdidb+fbHQSU4Q4ZiLKnzWo8Wwsf5bZfbvu7//a9oTYoqD/fWpe96NuHkoS9h0ccGOTe0C4NGXdtS0iObOw==} + + hast-util-whitespace@3.0.0: + resolution: {integrity: sha512-88JUN06ipLwsnv+dVn+OIYOvAuvBMy/Qoi6O7mQHxdPXpjy+Cd6xRkWwux7DKO+4sYILtLBRIKgsdpS2gQc7qw==} + + he@1.2.0: + resolution: {integrity: sha512-F/1DnUGPopORZi0ni+CvrCgHQ5FyEAHRLSApuYWMmrbSwoN2Mn/7k+Gl38gJnR7yyDZk6WLXwiGod1JOWNDKGw==} + hasBin: true + + help-me@5.0.0: + resolution: {integrity: sha512-7xgomUX6ADmcYzFik0HzAxh/73YlKR9bmFzf51CZwR+b6YtzU2m0u49hQCqV6SvlqIqsaxovfwdvbnsw3b/zpg==} + + hoist-non-react-statics@3.3.2: + resolution: {integrity: sha512-/gGivxi8JPKWNm/W0jSmzcMPpfpPLc3dY/6GxhX2hQ9iGj3aDfklV4ET7NjKpSinLpJ5vafa9iiGIEZg10SfBw==} + + html-to-text@9.0.5: + resolution: {integrity: sha512-qY60FjREgVZL03vJU6IfMV4GDjGBIoOyvuFdpBDIX9yTlDw0TjxVBQp+P8NvpdIXNJvfWBTNul7fsAQJq2FNpg==} + engines: {node: '>=14'} + + html-void-elements@3.0.0: + resolution: {integrity: sha512-bEqo66MRXsUGxWHV5IP0PUiAWwoEjba4VCzg0LjFJBpchPaTfyfCKTG6bc5F8ucKec3q5y6qOdGyYTSBEvhCrg==} + + htmlparser2@8.0.2: + resolution: {integrity: sha512-GYdjWKDkbRLkZ5geuHs5NY1puJ+PXwP7+fHPRz06Eirsb9ugf6d8kkXav6ADhcODhFFPMIXyxkxSuMf3D6NCFA==} + + http-errors@2.0.0: + resolution: {integrity: sha512-FtwrG/euBzaEjYeRqOgly7G0qviiXoJWnvEH2Z1plBdXgbyjv34pHTSb9zoeHMyDy33+DWy5Wt9Wo+TURtOYSQ==} + engines: {node: '>= 0.8'} + + http-proxy-agent@7.0.2: + resolution: {integrity: sha512-T1gkAiYYDWYx3V5Bmyu7HcfcvL7mUrTWiM6yOfa3PIphViJ/gFPbvidQ+veqSOHci/PxBcDabeUNCzpOODJZig==} + engines: {node: '>= 14'} + + http-status-codes@2.3.0: + resolution: {integrity: sha512-RJ8XvFvpPM/Dmc5SV+dC4y5PCeOhT3x1Hq0NU3rjGeg5a/CqlhZ7uudknPwZFz4aeAXDcbAyaeP7GAo9lvngtA==} + + https-proxy-agent@7.0.6: + resolution: {integrity: sha512-vK9P5/iUfdl95AI+JVyUuIcVtd4ofvtrOr3HNtM2yxC9bnMbEdp3x01OhQNnjb8IJYi38VlTE3mBXwcfvywuSw==} + engines: {node: '>= 14'} + + humanize-ms@1.2.1: + resolution: {integrity: sha512-Fl70vYtsAFb/C06PTS9dZBo7ihau+Tu/DNCk/OyHhea07S+aeMWpFFkUaXRa8fI+ScZbEI8dfSxwY7gxZ9SAVQ==} + + hyphenate-style-name@1.1.0: + resolution: {integrity: sha512-WDC/ui2VVRrz3jOVi+XtjqkDjiVjTtFaAGiW37k6b+ohyQ5wYDOGkvCZa8+H0nx3gyvv0+BST9xuOgIyGQ00gw==} + + iconv-lite@0.4.24: + resolution: {integrity: sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==} + engines: {node: '>=0.10.0'} + + iframe-resizer-react@1.1.1: + resolution: {integrity: sha512-s0EUUekv58FGbuWBanSCVsEKmmyBdWmdwQ8qx8g04jlNlCR7pNuDz7fw7zo5T5sdssl6yRMDl97NBdwD1gfDyQ==} + engines: {node: '>=16', npm: '>=5'} + peerDependencies: + prop-types: ^15.7.2 + react: ^16.13.1 || ^18.0.0 + react-dom: ^16.13.1 || ^18.0.0 + + iframe-resizer@4.4.5: + resolution: {integrity: sha512-U8bCywf/Gh07O69RXo6dXAzTtODQrxaHGHRI7Nt4ipXsuq6EMxVsOP/jjaP43YtXz/ibESS0uSVDN3sOGCzSmw==} + engines: {node: '>=0.8.0'} + + ignore-by-default@1.0.1: + resolution: {integrity: sha512-Ius2VYcGNk7T90CppJqcIkS5ooHUZyIQK+ClZfMfMNFEF9VSE73Fq+906u/CWu92x4gzZMWOwfFYckPObzdEbA==} + + ignore@5.3.2: + resolution: {integrity: sha512-hsBTNUqQTDwkWtcdYI2i06Y/nUBEsNEDJKjWdigLvegy8kDuJAS8uRlpkkcQpyEXL0Z/pjDy5HBmMjRCJ2gq+g==} + engines: {node: '>= 4'} + + ignore@7.0.5: + resolution: {integrity: sha512-Hs59xBNfUIunMFgWAbGX5cq6893IbWg4KnrjbYwX3tx0ztorVgTDA6B2sxf8ejHJ4wz8BqGUMYlnzNBer5NvGg==} + engines: {node: '>= 4'} + + import-fresh@3.3.1: + resolution: {integrity: sha512-TR3KfrTZTYLPB6jUjfx6MF9WcWrHL9su5TObK4ZkYgBdWKPOFoSoQIdEuTuR82pmtxH2spWG9h6etwfr1pLBqQ==} + engines: {node: '>=6'} + + import-meta-resolve@4.1.0: + resolution: {integrity: sha512-I6fiaX09Xivtk+THaMfAwnA3MVA5Big1WHF1Dfx9hFuvNIWpXnorlkzhcQf6ehrqQiiZECRt1poOAkPmer3ruw==} + + imurmurhash@0.1.4: + resolution: {integrity: sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==} + engines: {node: '>=0.8.19'} + + inherits@2.0.4: + resolution: {integrity: sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==} + + input-otp@1.4.2: + resolution: {integrity: sha512-l3jWwYNvrEa6NTCt7BECfCm48GvwuZzkoeG3gBL2w4CHeOXW3eKFmf9UNYkNfYc3mxMrthMnxjIE07MT0zLBQA==} + peerDependencies: + react: ^16.8 || ^17.0 || ^18.0 || ^19.0.0 || ^19.0.0-rc + react-dom: ^16.8 || ^17.0 || ^18.0 || ^19.0.0 || ^19.0.0-rc + + inquirer@12.6.3: + resolution: {integrity: sha512-eX9beYAjr1MqYsIjx1vAheXsRk1jbZRvHLcBu5nA9wX0rXR1IfCZLnVLp4Ym4mrhqmh7AuANwcdtgQ291fZDfQ==} + engines: {node: '>=18'} + peerDependencies: + '@types/node': '>=18' + peerDependenciesMeta: + '@types/node': + optional: true + + ioredis@5.6.1: + resolution: {integrity: sha512-UxC0Yv1Y4WRJiGQxQkP0hfdL0/5/6YvdfOOClRgJ0qppSarkhneSa6UvkMkms0AkdGimSH3Ikqm+6mkMmX7vGA==} + engines: {node: '>=12.22.0'} + + ip-address@9.0.5: + resolution: {integrity: sha512-zHtQzGojZXTwZTHQqra+ETKd4Sn3vgi7uBmlPoXVWZqYvuKmtI0l/VZTjqGmJY9x88GGOaZ9+G9ES8hC4T4X8g==} + engines: {node: '>= 12'} + + ip-regex@5.0.0: + resolution: {integrity: sha512-fOCG6lhoKKakwv+C6KdsOnGvgXnmgfmp0myi3bcNwj3qfwPAxRKWEuFhvEFF7ceYIz6+1jRZ+yguLFAmUNPEfw==} + engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} + + ipaddr.js@1.9.1: + resolution: {integrity: sha512-0KI/607xoxSToH7GjN1FfSbLoU0+btTicjsQSWQlh/hZykN8KpmMf7uYwPW3R+akZ6R/w18ZlXSHBYXiYUPO3g==} + engines: {node: '>= 0.10'} + + is-arrayish@0.2.1: + resolution: {integrity: sha512-zz06S8t0ozoDXMG+ube26zeCTNXcKIPJZJi8hBrF4idCLms4CG9QtK7qBl1boi5ODzFpjswb5JPmHCbMpjaYzg==} + + is-arrayish@0.3.2: + resolution: {integrity: sha512-eVRqCvVlZbuw3GrM63ovNSNAeA1K16kaR/LRY/92w0zxQ5/1YzwblUX652i4Xs9RwAGjW9d9y6X88t8OaAJfWQ==} + + is-binary-path@2.1.0: + resolution: {integrity: sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==} + engines: {node: '>=8'} + + is-extglob@2.1.1: + resolution: {integrity: sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==} + engines: {node: '>=0.10.0'} + + is-fullwidth-code-point@3.0.0: + resolution: {integrity: sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==} + engines: {node: '>=8'} + + is-glob@4.0.3: + resolution: {integrity: sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==} + engines: {node: '>=0.10.0'} + + is-in-browser@1.1.3: + resolution: {integrity: sha512-FeXIBgG/CPGd/WUxuEyvgGTEfwiG9Z4EKGxjNMRqviiIIfsmgrpnHLffEDdwUHqNva1VEW91o3xBT/m8Elgl9g==} + + is-interactive@2.0.0: + resolution: {integrity: sha512-qP1vozQRI+BMOPcjFzrjXuQvdak2pHNUMZoeG2eRbiSqyvbEf/wQtEOTOX1guk6E3t36RkaqiSt8A/6YElNxLQ==} + engines: {node: '>=12'} + + is-ip@5.0.1: + resolution: {integrity: sha512-FCsGHdlrOnZQcp0+XT5a+pYowf33itBalCl+7ovNXC/7o5BhIpG14M3OrpPPdBSIQJCm+0M5+9mO7S9VVTTCFw==} + engines: {node: '>=14.16'} + + is-number@7.0.0: + resolution: {integrity: sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==} + engines: {node: '>=0.12.0'} + + is-plain-obj@2.1.0: + resolution: {integrity: sha512-YWnfyRwxL/+SsrWYfOpUtz5b3YD+nyfkHvjbcanzk8zgyO4ASD67uVMRt8k5bM4lLMDnXfriRhOpemw+NfT1eA==} + engines: {node: '>=8'} + + is-regexp@3.1.0: + resolution: {integrity: sha512-rbku49cWloU5bSMI+zaRaXdQHXnthP6DZ/vLnfdSKyL4zUzuWnomtOEiZZOd+ioQ+avFo/qau3KPTc7Fjy1uPA==} + engines: {node: '>=12'} + + is-unicode-supported@0.1.0: + resolution: {integrity: sha512-knxG2q4UC3u8stRGyAVJCOdxFmv5DZiRcdlIaAQXAbSfJya+OhopNotLQrstBhququ4ZpuKbDc/8S6mgXgPFPw==} + engines: {node: '>=10'} + + is-unicode-supported@1.3.0: + resolution: {integrity: sha512-43r2mRvz+8JRIKnWJ+3j8JtjRKZ6GmjzfaE/qiBJnikNnYv/6bagRJ1kUhNk8R5EX/GkobD+r+sfxCPJsiKBLQ==} + engines: {node: '>=12'} + + is-unicode-supported@2.1.0: + resolution: {integrity: sha512-mE00Gnza5EEB3Ds0HfMyllZzbBrmLOX3vfWoj9A9PEnTfratQ/BcaJOuMhnkhjXvb2+FkY3VuHqtAGpTPmglFQ==} + engines: {node: '>=18'} + + isexe@2.0.0: + resolution: {integrity: sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==} + + jackspeak@3.4.3: + resolution: {integrity: sha512-OGlZQpz2yfahA/Rd1Y8Cd9SIEsqvXkLVoSw/cgwhnhFMDbsQFeZYoJJ7bIZBS9BcamUW96asq/npPWugM+RQBw==} + + jackspeak@4.1.1: + resolution: {integrity: sha512-zptv57P3GpL+O0I7VdMJNBZCu+BPHVQUk55Ft8/QCJjTVxrnJHuVuX/0Bl2A6/+2oyR/ZMEuFKwmzqqZ/U5nPQ==} + engines: {node: 20 || >=22} + + jiti@2.4.2: + resolution: {integrity: sha512-rg9zJN+G4n2nfJl5MW3BMygZX56zKPNVEYYqq7adpmMh4Jn2QNEwhvQlFy6jPVdcod7txZtKHWnyZiA3a0zP7A==} + hasBin: true + + jose@5.10.0: + resolution: {integrity: sha512-s+3Al/p9g32Iq+oqXxkW//7jk2Vig6FF1CFqzVXoTUXt2qz89YWbL+OwS17NFYEvxC35n0FKeGO2LGYSxeM2Gg==} + + joycon@3.1.1: + resolution: {integrity: sha512-34wB/Y7MW7bzjKRjUKTa46I2Z7eV62Rkhva+KkopW7Qvv/OSWBqvkSY7vusOPrNuZcUG3tApvdVgNB8POj3SPw==} + engines: {node: '>=10'} + + js-cookie@3.0.5: + resolution: {integrity: sha512-cEiJEAEoIbWfCZYKWhVwFuvPX1gETRYPw6LlaTKoxD3s2AkXzkCjnp6h0V77ozyqj0jakteJ4YqDJT830+lVGw==} + engines: {node: '>=14'} + + js-tokens@4.0.0: + resolution: {integrity: sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==} + + js-yaml@4.1.0: + resolution: {integrity: sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==} + hasBin: true + + jsbn@1.1.0: + resolution: {integrity: sha512-4bYVV3aAMtDTTu4+xsDYa6sy9GyJ69/amsu9sYF2zqjiEoZA5xJi3BrfX3uY+/IekIu7MwdObdbDWpoZdBv3/A==} + + jsesc@3.1.0: + resolution: {integrity: sha512-/sM3dO2FOzXjKQhJuo0Q173wf2KOo8t4I8vHy6lF9poUp7bKT0/NHE8fPX23PwfhnykfqnC2xRxOnVw5XuGIaA==} + engines: {node: '>=6'} + hasBin: true + + json-buffer@3.0.1: + resolution: {integrity: sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ==} + + json-parse-even-better-errors@2.3.1: + resolution: {integrity: sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w==} + + json-schema-traverse@0.4.1: + resolution: {integrity: sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==} + + json-schema@0.4.0: + resolution: {integrity: sha512-es94M3nTIfsEPisRafak+HDLfHXnKBhV3vU5eqPcS3flIWqcxJWgXHXiey3YrpaNsanY5ei1VoYEbOzijuq9BA==} + + json-stable-stringify-without-jsonify@1.0.1: + resolution: {integrity: sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw==} + + json5@2.2.3: + resolution: {integrity: sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg==} + engines: {node: '>=6'} + hasBin: true + + jsondiffpatch@0.6.0: + resolution: {integrity: sha512-3QItJOXp2AP1uv7waBkao5nCvhEv+QmJAd38Ybq7wNI74Q+BBmnLn4EDKz6yI9xGAIQoUF87qHt+kc1IVxB4zQ==} + engines: {node: ^18.0.0 || >=20.0.0} + hasBin: true + + jss-plugin-camel-case@10.10.0: + resolution: {integrity: sha512-z+HETfj5IYgFxh1wJnUAU8jByI48ED+v0fuTuhKrPR+pRBYS2EDwbusU8aFOpCdYhtRc9zhN+PJ7iNE8pAWyPw==} + + jss-plugin-compose@10.10.0: + resolution: {integrity: sha512-F5kgtWpI2XfZ3Z8eP78tZEYFdgTIbpA/TMuX3a8vwrNolYtN1N4qJR/Ob0LAsqIwCMLojtxN7c7Oo/+Vz6THow==} + + jss-plugin-default-unit@10.10.0: + resolution: {integrity: sha512-SvpajxIECi4JDUbGLefvNckmI+c2VWmP43qnEy/0eiwzRUsafg5DVSIWSzZe4d2vFX1u9nRDP46WCFV/PXVBGQ==} + + jss-plugin-expand@10.10.0: + resolution: {integrity: sha512-ymT62W2OyDxBxr7A6JR87vVX9vTq2ep5jZLIdUSusfBIEENLdkkc0lL/Xaq8W9s3opUq7R0sZQpzRWELrfVYzA==} + + jss-plugin-extend@10.10.0: + resolution: {integrity: sha512-sKYrcMfr4xxigmIwqTjxNcHwXJIfvhvjTNxF+Tbc1NmNdyspGW47Ey6sGH8BcQ4FFQhLXctpWCQSpDwdNmXSwg==} + + jss-plugin-global@10.10.0: + resolution: {integrity: sha512-icXEYbMufiNuWfuazLeN+BNJO16Ge88OcXU5ZDC2vLqElmMybA31Wi7lZ3lf+vgufRocvPj8443irhYRgWxP+A==} + + jss-plugin-nested@10.10.0: + resolution: {integrity: sha512-9R4JHxxGgiZhurDo3q7LdIiDEgtA1bTGzAbhSPyIOWb7ZubrjQe8acwhEQ6OEKydzpl8XHMtTnEwHXCARLYqYA==} + + jss-plugin-props-sort@10.10.0: + resolution: {integrity: sha512-5VNJvQJbnq/vRfje6uZLe/FyaOpzP/IH1LP+0fr88QamVrGJa0hpRRyAa0ea4U/3LcorJfBFVyC4yN2QC73lJg==} + + jss-plugin-rule-value-function@10.10.0: + resolution: {integrity: sha512-uEFJFgaCtkXeIPgki8ICw3Y7VMkL9GEan6SqmT9tqpwM+/t+hxfMUdU4wQ0MtOiMNWhwnckBV0IebrKcZM9C0g==} + + jss-plugin-rule-value-observable@10.10.0: + resolution: {integrity: sha512-ZLMaYrR3QE+vD7nl3oNXuj79VZl9Kp8/u6A1IbTPDcuOu8b56cFdWRZNZ0vNr8jHewooEeq2doy8Oxtymr2ZPA==} + + jss-plugin-template@10.10.0: + resolution: {integrity: sha512-ocXZBIOJOA+jISPdsgkTs8wwpK6UbsvtZK5JI7VUggTD6LWKbtoxUzadd2TpfF+lEtlhUmMsCkTRNkITdPKa6w==} + + jss-plugin-vendor-prefixer@10.10.0: + resolution: {integrity: sha512-UY/41WumgjW8r1qMCO8l1ARg7NHnfRVWRhZ2E2m0DMYsr2DD91qIXLyNhiX83hHswR7Wm4D+oDYNC1zWCJWtqg==} + + jss-preset-default@10.10.0: + resolution: {integrity: sha512-GL175Wt2FGhjE+f+Y3aWh+JioL06/QWFgZp53CbNNq6ZkVU0TDplD8Bxm9KnkotAYn3FlplNqoW5CjyLXcoJ7Q==} + + jss@10.10.0: + resolution: {integrity: sha512-cqsOTS7jqPsPMjtKYDUpdFC0AbhYFLTcuGRqymgmdJIeQ8cH7+AgX7YSgQy79wXloZq2VvATYxUOUQEvS1V/Zw==} + + keyv@4.5.4: + resolution: {integrity: sha512-oxVHkHR/EJf2CNXnWxRLW6mg7JyCCUcG0DtEGmL2ctUo1PNTin1PUil+r/+4r5MpVgC/fn1kjsx7mjSujKqIpw==} + + ksuid@3.0.0: + resolution: {integrity: sha512-81CkBGn/06ZVAjGvFZi6fVG8VcPeMH0JpJ4V1Z9VwrMMaGIeAjY4jrVdrIcxhL9I2ZUU6t5uiyswcmkk+KZegA==} + + kysely@0.28.2: + resolution: {integrity: sha512-4YAVLoF0Sf0UTqlhgQMFU9iQECdah7n+13ANkiuVfRvlK+uI0Etbgd7bVP36dKlG+NXWbhGua8vnGt+sdhvT7A==} + engines: {node: '>=18.0.0'} + + leac@0.6.0: + resolution: {integrity: sha512-y+SqErxb8h7nE/fiEX07jsbuhrpO9lL8eca7/Y1nuWV2moNlXhyd59iDGcRf6moVyDMbmTNzL40SUyrFU/yDpg==} + + levn@0.4.1: + resolution: {integrity: sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==} + engines: {node: '>= 0.8.0'} + + lightningcss-darwin-arm64@1.30.1: + resolution: {integrity: sha512-c8JK7hyE65X1MHMN+Viq9n11RRC7hgin3HhYKhrMyaXflk5GVplZ60IxyoVtzILeKr+xAJwg6zK6sjTBJ0FKYQ==} + engines: {node: '>= 12.0.0'} + cpu: [arm64] + os: [darwin] + + lightningcss-darwin-x64@1.30.1: + resolution: {integrity: sha512-k1EvjakfumAQoTfcXUcHQZhSpLlkAuEkdMBsI/ivWw9hL+7FtilQc0Cy3hrx0AAQrVtQAbMI7YjCgYgvn37PzA==} + engines: {node: '>= 12.0.0'} + cpu: [x64] + os: [darwin] + + lightningcss-freebsd-x64@1.30.1: + resolution: {integrity: sha512-kmW6UGCGg2PcyUE59K5r0kWfKPAVy4SltVeut+umLCFoJ53RdCUWxcRDzO1eTaxf/7Q2H7LTquFHPL5R+Gjyig==} + engines: {node: '>= 12.0.0'} + cpu: [x64] + os: [freebsd] + + lightningcss-linux-arm-gnueabihf@1.30.1: + resolution: {integrity: sha512-MjxUShl1v8pit+6D/zSPq9S9dQ2NPFSQwGvxBCYaBYLPlCWuPh9/t1MRS8iUaR8i+a6w7aps+B4N0S1TYP/R+Q==} + engines: {node: '>= 12.0.0'} + cpu: [arm] + os: [linux] + + lightningcss-linux-arm64-gnu@1.30.1: + resolution: {integrity: sha512-gB72maP8rmrKsnKYy8XUuXi/4OctJiuQjcuqWNlJQ6jZiWqtPvqFziskH3hnajfvKB27ynbVCucKSm2rkQp4Bw==} + engines: {node: '>= 12.0.0'} + cpu: [arm64] + os: [linux] + + lightningcss-linux-arm64-musl@1.30.1: + resolution: {integrity: sha512-jmUQVx4331m6LIX+0wUhBbmMX7TCfjF5FoOH6SD1CttzuYlGNVpA7QnrmLxrsub43ClTINfGSYyHe2HWeLl5CQ==} + engines: {node: '>= 12.0.0'} + cpu: [arm64] + os: [linux] + + lightningcss-linux-x64-gnu@1.30.1: + resolution: {integrity: sha512-piWx3z4wN8J8z3+O5kO74+yr6ze/dKmPnI7vLqfSqI8bccaTGY5xiSGVIJBDd5K5BHlvVLpUB3S2YCfelyJ1bw==} + engines: {node: '>= 12.0.0'} + cpu: [x64] + os: [linux] + + lightningcss-linux-x64-musl@1.30.1: + resolution: {integrity: sha512-rRomAK7eIkL+tHY0YPxbc5Dra2gXlI63HL+v1Pdi1a3sC+tJTcFrHX+E86sulgAXeI7rSzDYhPSeHHjqFhqfeQ==} + engines: {node: '>= 12.0.0'} + cpu: [x64] + os: [linux] + + lightningcss-win32-arm64-msvc@1.30.1: + resolution: {integrity: sha512-mSL4rqPi4iXq5YVqzSsJgMVFENoa4nGTT/GjO2c0Yl9OuQfPsIfncvLrEW6RbbB24WtZ3xP/2CCmI3tNkNV4oA==} + engines: {node: '>= 12.0.0'} + cpu: [arm64] + os: [win32] + + lightningcss-win32-x64-msvc@1.30.1: + resolution: {integrity: sha512-PVqXh48wh4T53F/1CCu8PIPCxLzWyCnn/9T5W1Jpmdy5h9Cwd+0YQS6/LwhHXSafuc61/xg9Lv5OrCby6a++jg==} + engines: {node: '>= 12.0.0'} + cpu: [x64] + os: [win32] + + lightningcss@1.30.1: + resolution: {integrity: sha512-xi6IyHML+c9+Q3W0S4fCQJOym42pyurFiJUHEcEyHS0CeKzia4yZDEsLlqOFykxOdHpNy0NmvVO31vcSqAxJCg==} + engines: {node: '>= 12.0.0'} + + lines-and-columns@1.2.4: + resolution: {integrity: sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg==} + + locate-path@6.0.0: + resolution: {integrity: sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==} + engines: {node: '>=10'} + + lodash-es@4.17.21: + resolution: {integrity: sha512-mKnC+QJ9pWVzv+C4/U3rRsHapFfHvQFoFB92e52xeyGMcX6/OlIl78je1u8vePzYZSkkogMPJ2yjxxsb89cxyw==} + + lodash.defaults@4.2.0: + resolution: {integrity: sha512-qjxPLHd3r5DnsdGacqOMU6pb/avJzdh9tFX2ymgoZE27BmjXrNy/y4LoaiTeAb+O3gL8AfpJGtqfX/ae2leYYQ==} + + lodash.isarguments@3.1.0: + resolution: {integrity: sha512-chi4NHZlZqZD18a0imDHnZPrDeBbTtVN7GXMwuGdRH9qotxAjYs3aVLKc7zNOG9eddR5Ksd8rvFEBc9SsggPpg==} + + lodash.merge@4.6.2: + resolution: {integrity: sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==} + + lodash@4.17.21: + resolution: {integrity: sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==} + + log-symbols@4.1.0: + resolution: {integrity: sha512-8XPvpAA8uyhfteu8pIvQxpJZ7SYYdpUivZpGy6sFsBuKRY/7rQGavedeB8aK+Zkyq6upMFVL/9AW6vOYzfRyLg==} + engines: {node: '>=10'} + + log-symbols@6.0.0: + resolution: {integrity: sha512-i24m8rpwhmPIS4zscNzK6MSEhk0DUWa/8iYQWxhffV8jkI4Phvs3F+quL5xvS0gdQR0FyTCMMH33Y78dDTzzIw==} + engines: {node: '>=18'} + + log-symbols@7.0.1: + resolution: {integrity: sha512-ja1E3yCr9i/0hmBVaM0bfwDjnGy8I/s6PP4DFp+yP+a+mrHO4Rm7DtmnqROTUkHIkqffC84YY7AeqX6oFk0WFg==} + engines: {node: '>=18'} + + loose-envify@1.4.0: + resolution: {integrity: sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q==} + hasBin: true + + loupe@3.1.3: + resolution: {integrity: sha512-kkIp7XSkP78ZxJEsSxW3712C6teJVoeHHwgo9zJ380de7IYyJ2ISlxojcH2pC5OFLewESmnRi/+XCDIEEVyoug==} + + lower-case@2.0.2: + resolution: {integrity: sha512-7fm3l3NAF9WfN6W3JOmf5drwpVqX78JtoGJ3A6W0a6ZnldM41w2fV5D490psKFTpMds8TJse/eHLFFsNHHjHgg==} + + lru-cache@10.4.3: + resolution: {integrity: sha512-JNAzZcXrCt42VGLuYz0zfAzDfAvJWW6AfYlDBQyDV5DClI2m5sAmK+OIO7s59XfsRsWHp02jAJrRadPRGTt6SQ==} + + lru-cache@11.1.0: + resolution: {integrity: sha512-QIXZUBJUx+2zHUdQujWejBkcD9+cs94tLn0+YL8UrCh+D5sCXZ4c7LaEH48pNwRY3MLDgqUFyhlCyjJPf1WP0A==} + engines: {node: 20 || >=22} + + lru-cache@5.1.1: + resolution: {integrity: sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w==} + + lru-cache@7.18.3: + resolution: {integrity: sha512-jumlc0BIUrS3qJGgIkWZsyfAM7NCWiBcCDhnd+3NNM5KbBmLTgHVfWBcg6W+rLUsIpzpERPsvwUP7CckAQSOoA==} + engines: {node: '>=12'} + + lucide-react@0.511.0: + resolution: {integrity: sha512-VK5a2ydJ7xm8GvBeKLS9mu1pVK6ucef9780JVUjw6bAjJL/QXnd4Y0p7SPeOUMC27YhzNCZvm5d/QX0Tp3rc0w==} + peerDependencies: + react: ^16.5.1 || ^17.0.0 || ^18.0.0 || ^19.0.0 + + luxon@3.5.0: + resolution: {integrity: sha512-rh+Zjr6DNfUYR3bPwJEnuwDdqMbxZW7LOQfUN4B54+Cl+0o5zaU9RJ6bcidfDtC1cWCZXQ+nvX8bf6bAji37QQ==} + engines: {node: '>=12'} + + luxon@3.6.1: + resolution: {integrity: sha512-tJLxrKJhO2ukZ5z0gyjY1zPh3Rh88Ej9P7jNrZiHMUXHae1yvI2imgOZtL1TO8TW6biMMKfTtAOoEJANgtWBMQ==} + engines: {node: '>=12'} + + magic-string@0.30.17: + resolution: {integrity: sha512-sNPKHvyjVf7gyjwS4xGTaW/mCnF8wnjtifKBEhxfZ7E/S8tQ0rssrwGNn6q8JH/ohItJfSQp9mBtQYuTlH5QnA==} + + make-error@1.3.6: + resolution: {integrity: sha512-s8UhlNe7vPKomQhC1qFelMokr/Sc3AgNbso3n74mVPA5LTZwkB9NlXf4XPamLxJE8h0gh73rM94xvwRT2CVInw==} + + map-obj@4.3.0: + resolution: {integrity: sha512-hdN1wVrZbb29eBGiGjJbeP8JbKjq1urkHJ/LIP/NY48MZ1QVXUsQBV1G1zvYFHn1XE06cwjBsOI2K3Ulnj1YXQ==} + engines: {node: '>=8'} + + marked@7.0.4: + resolution: {integrity: sha512-t8eP0dXRJMtMvBojtkcsA7n48BkauktUKzfkPSCq85ZMTJ0v76Rke4DYz01omYpPTUh4p/f7HePgRo3ebG8+QQ==} + engines: {node: '>= 16'} + hasBin: true + + math-intrinsics@1.1.0: + resolution: {integrity: sha512-/IXtbwEk5HTPyEwyKX6hGkYXxM9nbj64B+ilVJnC/R6B0pH5G4V3b0pVbL7DBj4tkhBAppbQUlf6F6Xl9LHu1g==} + engines: {node: '>= 0.4'} + + md-to-react-email@5.0.5: + resolution: {integrity: sha512-OvAXqwq57uOk+WZqFFNCMZz8yDp8BD3WazW1wAKHUrPbbdr89K9DWS6JXY09vd9xNdPNeurI8DU/X4flcfaD8A==} + peerDependencies: + react: ^18.0 || ^19.0 + + mdast-util-to-hast@13.2.0: + resolution: {integrity: sha512-QGYKEuUsYT9ykKBCMOEDLsU5JRObWQusAolFMeko/tYPufNkRffBAQjIE+99jbA87xv6FgmjLtwjh9wBWajwAA==} + + media-typer@0.3.0: + resolution: {integrity: sha512-dq+qelQ9akHpcOl/gUVRTxVIOkAJ1wR3QAvb4RsVjS8oVoFjDGTc679wJYmUmknUF5HwMLOgb5O+a3KxfWapPQ==} + engines: {node: '>= 0.6'} + + merge-descriptors@1.0.3: + resolution: {integrity: sha512-gaNvAS7TZ897/rVaZ0nMtAyxNyi/pdbjbAwUpFQpN70GqnVfOiXpeUUMKRBmzXaSQ8DdTX4/0ms62r2K+hE6mQ==} + + merge2@1.4.1: + resolution: {integrity: sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==} + engines: {node: '>= 8'} + + methods@1.1.2: + resolution: {integrity: sha512-iclAHeNqNm68zFtnZ0e+1L2yUIdvzNoauKU4WBA3VvH/vPFieF7qfRlwUZU+DA9P9bPXIS90ulxoUoCH23sV2w==} + engines: {node: '>= 0.6'} + + micromark-util-character@2.1.1: + resolution: {integrity: sha512-wv8tdUTJ3thSFFFJKtpYKOYiGP2+v96Hvk4Tu8KpCAsTMs6yi+nVmGh1syvSCsaxz45J6Jbw+9DD6g97+NV67Q==} + + micromark-util-encode@2.0.1: + resolution: {integrity: sha512-c3cVx2y4KqUnwopcO9b/SCdo2O67LwJJ/UyqGfbigahfegL9myoEFoDYZgkT7f36T0bLrM9hZTAaAyH+PCAXjw==} + + micromark-util-sanitize-uri@2.0.1: + resolution: {integrity: sha512-9N9IomZ/YuGGZZmQec1MbgxtlgougxTodVwDzzEouPKo3qFWvymFHWcnDi2vzV1ff6kas9ucW+o3yzJK9YB1AQ==} + + micromark-util-symbol@2.0.1: + resolution: {integrity: sha512-vs5t8Apaud9N28kgCrRUdEed4UJ+wWNvicHLPxCa9ENlYuAY31M0ETy5y1vA33YoNPDFTghEbnh6efaE8h4x0Q==} + + micromark-util-types@2.0.2: + resolution: {integrity: sha512-Yw0ECSpJoViF1qTU4DC6NwtC4aWGt1EkzaQB8KPPyCRR8z9TWeV0HbEFGTO+ZY1wB22zmxnJqhPyTpOVCpeHTA==} + + micromatch@4.0.8: + resolution: {integrity: sha512-PXwfBhYu0hBCPw8Dn0E+WDYb7af3dSLVWKi3HGv84IdF4TyFoC0ysxFd0Goxw7nSv4T/PzEJQxsYsEiFCKo2BA==} + engines: {node: '>=8.6'} + + mime-db@1.52.0: + resolution: {integrity: sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==} + engines: {node: '>= 0.6'} + + mime-db@1.54.0: + resolution: {integrity: sha512-aU5EJuIN2WDemCcAp2vFBfp/m4EAhWJnUNSSw0ixs7/kXbd6Pg64EmwJkNdFhB8aWt1sH2CTXrLxo/iAGV3oPQ==} + engines: {node: '>= 0.6'} + + mime-detect@1.3.0: + resolution: {integrity: sha512-SFFkIWONYQdDoiA3iq2abd68kCy+ifzsgWyytMDa/v8Jiu5UhVhgb4upoKDVKTlCz663jqM9PksyM99m+MnSaQ==} + + mime-types@2.1.35: + resolution: {integrity: sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==} + engines: {node: '>= 0.6'} + + mime-types@3.0.1: + resolution: {integrity: sha512-xRc4oEhT6eaBpU1XF7AjpOFD+xQmXNB5OVKwp4tqCuBpHLS/ZbBDrc07mYTDqVMg6PfxUjjNp85O6Cd2Z/5HWA==} + engines: {node: '>= 0.6'} + + mime@1.6.0: + resolution: {integrity: sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg==} + engines: {node: '>=4'} + hasBin: true + + mime@2.6.0: + resolution: {integrity: sha512-USPkMeET31rOMiarsBNIHZKLGgvKc/LrjofAnBlOttf5ajRvqiRA8QsenbcooctK6d6Ts6aqZXBA+XbkKthiQg==} + engines: {node: '>=4.0.0'} + hasBin: true + + mimic-function@5.0.1: + resolution: {integrity: sha512-VP79XUPxV2CigYP3jWwAUFSku2aKqBH7uTAapFWCBqutsbmDo96KY5o8uh6U+/YSIn5OxJnXp73beVkpqMIGhA==} + engines: {node: '>=18'} + + minimatch@10.0.3: + resolution: {integrity: sha512-IPZ167aShDZZUMdRk66cyQAW3qr0WzbHkPdMYa8bzZhlHhO3jALbKdxcaak7W9FfT2rZNpQuUu4Od7ILEpXSaw==} + engines: {node: 20 || >=22} + + minimatch@3.1.2: + resolution: {integrity: sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==} + + minimatch@9.0.5: + resolution: {integrity: sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow==} + engines: {node: '>=16 || 14 >=14.17'} + + minimist@1.2.8: + resolution: {integrity: sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==} + + minipass@7.1.2: + resolution: {integrity: sha512-qOOzS1cBTWYF4BH8fVePDBOO9iptMnGUEZwNc/cMWnTV2nVLZ7VoNWEPHkYczZA0pdoA7dl6e7FL659nX9S2aw==} + engines: {node: '>=16 || 14 >=14.17'} + + minizlib@3.0.2: + resolution: {integrity: sha512-oG62iEk+CYt5Xj2YqI5Xi9xWUeZhDI8jjQmC5oThVH5JGCTgIjr7ciJDzC7MBzYd//WvR1OTmP5Q38Q8ShQtVA==} + engines: {node: '>= 18'} + + mitt@3.0.1: + resolution: {integrity: sha512-vKivATfr97l2/QBCYAkXYDbrIWPM2IIKEl7YPhjCvKlG3kE2gm+uBo6nEXK3M5/Ffh/FLpKExzOQ3JJoJGFKBw==} + + mkdirp@3.0.1: + resolution: {integrity: sha512-+NsyUUAZDmo6YVHzL/stxSu3t9YS1iljliy3BSDrXJ/dkn1KYdmtZODGGjLcc9XLgVVpH4KshHB8XmZgMhaBXg==} + engines: {node: '>=10'} + hasBin: true + + mocha@11.6.0: + resolution: {integrity: sha512-i0JVb+OUBqw63X/1pC3jCyJsqYisgxySBbsQa8TKvefpA1oEnw7JXxXnftfMHRsw7bEEVGRtVlHcDYXBa7FzVw==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + hasBin: true + + motion-dom@12.18.1: + resolution: {integrity: sha512-dR/4EYT23Snd+eUSLrde63Ws3oXQtJNw/krgautvTfwrN/2cHfCZMdu6CeTxVfRRWREW3Fy1f5vobRDiBb/q+w==} + + motion-utils@12.18.1: + resolution: {integrity: sha512-az26YDU4WoDP0ueAkUtABLk2BIxe28d8NH1qWT8jPGhPyf44XTdDUh8pDk9OPphaSrR9McgpcJlgwSOIw/sfkA==} + + motion@12.18.1: + resolution: {integrity: sha512-w1ns2hWQ4COhOvnZf4rg4mW0Pl36mzcShpgt0fSfI6qJxKUbi3kHho/HSKeJFRoY0TO1m5/7C8lG1+Li0uC9Fw==} + peerDependencies: + '@emotion/is-prop-valid': '*' + react: ^18.0.0 || ^19.0.0 + react-dom: ^18.0.0 || ^19.0.0 + peerDependenciesMeta: + '@emotion/is-prop-valid': + optional: true + react: + optional: true + react-dom: + optional: true + + ms@2.0.0: + resolution: {integrity: sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==} + + ms@2.1.3: + resolution: {integrity: sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==} + + msgpackr-extract@3.0.3: + resolution: {integrity: sha512-P0efT1C9jIdVRefqjzOQ9Xml57zpOXnIuS+csaB4MdZbTdmGDLo8XhzBG1N7aO11gKDDkJvBLULeFTo46wwreA==} + hasBin: true + + msgpackr@1.11.4: + resolution: {integrity: sha512-uaff7RG9VIC4jacFW9xzL3jc0iM32DNHe4jYVycBcjUePT/Klnfj7pqtWJt9khvDFizmjN2TlYniYmSS2LIaZg==} + + mute-stream@2.0.0: + resolution: {integrity: sha512-WWdIxpyjEn+FhQJQQv9aQAYlHoNVdzIzUySNV1gHUPDSdZJ3yZn7pAAbQcV7B56Mvu881q9FZV+0Vx2xC44VWA==} + engines: {node: ^18.17.0 || >=20.5.0} + + mylas@2.1.13: + resolution: {integrity: sha512-+MrqnJRtxdF+xngFfUUkIMQrUUL0KsxbADUkn23Z/4ibGg192Q+z+CQyiYwvWTsYjJygmMR8+w3ZDa98Zh6ESg==} + engines: {node: '>=12.0.0'} + + nanoid@3.3.11: + resolution: {integrity: sha512-N8SpfPUnUp1bK+PMYW8qSWdl9U+wwNWI4QKxOYDy9JAro3WMX7p2OeVRF9v+347pnakNevPmiHhNmZ2HbFA76w==} + engines: {node: ^10 || ^12 || ^13.7 || ^14 || >=15.0.1} + hasBin: true + + nanoid@5.1.5: + resolution: {integrity: sha512-Ir/+ZpE9fDsNH0hQ3C68uyThDXzYcim2EqcZ8zn8Chtt1iylPT9xXJB0kPCnqzgcEGikO9RxSrh63MsmVCU7Fw==} + engines: {node: ^18 || >=20} + hasBin: true + + nanostores@0.11.4: + resolution: {integrity: sha512-k1oiVNN4hDK8NcNERSZLQiMfRzEGtfnvZvdBvey3SQbgn8Dcrk0h1I6vpxApjb10PFUflZrgJ2WEZyJQ+5v7YQ==} + engines: {node: ^18.0.0 || >=20.0.0} + + natural-compare@1.4.0: + resolution: {integrity: sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==} + + negotiator@0.6.3: + resolution: {integrity: sha512-+EUsqGPLsM+j/zdChZjsnX51g4XrHFOIXwfnCVPGlQk/k5giakcKsuxCObBRu6DSm9opw/O6slWbJdghQM4bBg==} + engines: {node: '>= 0.6'} + + netmask@2.0.2: + resolution: {integrity: sha512-dBpDMdxv9Irdq66304OLfEmQ9tbNRFnFTuZiLo+bD+r332bBmMJ8GBLXklIXXgxd3+v9+KUnZaUR5PJMa75Gsg==} + engines: {node: '>= 0.4.0'} + + next-themes@0.4.6: + resolution: {integrity: sha512-pZvgD5L0IEvX5/9GWyHMf3m8BKiVQwsCMHfoFosXtXBMnaS0ZnIJ9ST4b4NqLVKDEm8QBxoNNGNaBv2JNF6XNA==} + peerDependencies: + react: ^16.8 || ^17 || ^18 || ^19 || ^19.0.0-rc + react-dom: ^16.8 || ^17 || ^18 || ^19 || ^19.0.0-rc + + next@15.3.3: + resolution: {integrity: sha512-JqNj29hHNmCLtNvd090SyRbXJiivQ+58XjCcrC50Crb5g5u2zi7Y2YivbsEfzk6AtVI80akdOQbaMZwWB1Hthw==} + engines: {node: ^18.18.0 || ^19.8.0 || >= 20.0.0} + hasBin: true + peerDependencies: + '@opentelemetry/api': ^1.1.0 + '@playwright/test': ^1.41.2 + babel-plugin-react-compiler: '*' + react: ^18.2.0 || 19.0.0-rc-de68d2f4-20241204 || ^19.0.0 + react-dom: ^18.2.0 || 19.0.0-rc-de68d2f4-20241204 || ^19.0.0 + sass: ^1.3.0 + peerDependenciesMeta: + '@opentelemetry/api': + optional: true + '@playwright/test': + optional: true + babel-plugin-react-compiler: + optional: true + sass: + optional: true + + no-case@3.0.4: + resolution: {integrity: sha512-fgAN3jGAh+RoxUGZHTSOLJIqUc2wmoBwGR4tbpNAKmmovFoWq0OdRkb0VkldReO2a2iBT/OEulG9XSUc10r3zg==} + + node-abort-controller@3.1.1: + resolution: {integrity: sha512-AGK2yQKIjRuqnc6VkX2Xj5d+QW8xZ87pa1UK6yA6ouUyuxfHuMP6umE5QK7UmTeOAymo+Zx1Fxiuw9rVx8taHQ==} + + node-domexception@1.0.0: + resolution: {integrity: sha512-/jKZoMpw0F8GRwl4/eLROPA3cfcXtLApP0QzLmUT/HuPCZWyB7IY9ZrMeKw2O/nFIqPQB3PVM9aYm0F312AXDQ==} + engines: {node: '>=10.5.0'} + deprecated: Use your platform's native DOMException instead + + node-fetch@2.7.0: + resolution: {integrity: sha512-c4FRfUm/dbcWZ7U+1Wq0AwCyFL+3nt2bEw05wfxSz+DWpWsitgmSgYmy2dQdWyKC1694ELPqMs/YzUSNozLt8A==} + engines: {node: 4.x || >=6.0.0} + peerDependencies: + encoding: ^0.1.0 + peerDependenciesMeta: + encoding: + optional: true + + node-gyp-build-optional-packages@5.2.2: + resolution: {integrity: sha512-s+w+rBWnpTMwSFbaE0UXsRlg7hU4FjekKU4eyAih5T8nJuNZT1nNsskXpxmeqSK9UzkBl6UgRlnKc8hz8IEqOw==} + hasBin: true + + node-releases@2.0.19: + resolution: {integrity: sha512-xxOWJsBKtzAq7DY0J+DTzuz58K8e7sJbdgwkbMWQe8UYB6ekmsQ45q0M/tJDsGaZmbC+l7n57UV8Hl5tHxO9uw==} + + nodemon@3.1.10: + resolution: {integrity: sha512-WDjw3pJ0/0jMFmyNDp3gvY2YizjLmmOUQo6DEBY+JgdvW/yQ9mEeSw6H5ythl5Ny2ytb7f9C2nIbjSxMNzbJXw==} + engines: {node: '>=10'} + hasBin: true + + normalize-path@3.0.0: + resolution: {integrity: sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==} + engines: {node: '>=0.10.0'} + + object-assign@4.1.1: + resolution: {integrity: sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==} + engines: {node: '>=0.10.0'} + + object-inspect@1.13.4: + resolution: {integrity: sha512-W67iLl4J2EXEGTbfeHCffrjDfitvLANg0UlX3wFUUSTx92KXRFegMHUVgSqE+wvhAbi4WqjGg9czysTV2Epbew==} + engines: {node: '>= 0.4'} + + on-exit-leak-free@2.1.2: + resolution: {integrity: sha512-0eJJY6hXLGf1udHwfNftBqH+g73EU4B504nZeKpz1sYRKafAghwxEJunB2O7rDZkL4PGfsMVnTXZ2EjibbqcsA==} + engines: {node: '>=14.0.0'} + + on-finished@2.4.1: + resolution: {integrity: sha512-oVlzkg3ENAhCk2zdv7IJwd/QUD4z2RxRwpkcGY8psCVcCYZNq4wYnVWALHM+brtuJjePWiYF/ClmuDr8Ch5+kg==} + engines: {node: '>= 0.8'} + + once@1.4.0: + resolution: {integrity: sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==} + + onetime@7.0.0: + resolution: {integrity: sha512-VXJjc87FScF88uafS3JllDgvAm+c/Slfz06lorj2uAY34rlUu0Nt+v8wreiImcrgAjjIHp1rXpTDlLOGw29WwQ==} + engines: {node: '>=18'} + + openai@4.104.0: + resolution: {integrity: sha512-p99EFNsA/yX6UhVO93f5kJsDRLAg+CTA2RBqdHK4RtK8u5IJw32Hyb2dTGKbnnFmnuoBv5r7Z2CURI9sGZpSuA==} + hasBin: true + peerDependencies: + ws: ^8.18.0 + zod: ^3.23.8 + peerDependenciesMeta: + ws: + optional: true + zod: + optional: true + + optionator@0.9.4: + resolution: {integrity: sha512-6IpQ7mKUxRcZNLIObR0hz7lxsapSSIYNZJwXPGeF0mTVqGKFIXj1DQcMoT22S3ROcLyY/rz0PWaWZ9ayWmad9g==} + engines: {node: '>= 0.8.0'} + + ora@8.2.0: + resolution: {integrity: sha512-weP+BZ8MVNnlCm8c0Qdc1WSWq4Qn7I+9CJGm7Qali6g44e/PUzbjNqJX5NJ9ljlNMosfJvg1fKEGILklK9cwnw==} + engines: {node: '>=18'} + + os-tmpdir@1.0.2: + resolution: {integrity: sha512-D2FR03Vir7FIu45XBY20mTb+/ZSWB00sjU9jdQXt83gDrI4Ztz5Fs7/yy74g2N5SVQY4xY1qDr4rNddwYRVX0g==} + engines: {node: '>=0.10.0'} + + p-limit@3.1.0: + resolution: {integrity: sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==} + engines: {node: '>=10'} + + p-locate@5.0.0: + resolution: {integrity: sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==} + engines: {node: '>=10'} + + pac-proxy-agent@7.2.0: + resolution: {integrity: sha512-TEB8ESquiLMc0lV8vcd5Ql/JAKAoyzHFXaStwjkzpOpC5Yv+pIzLfHvjTSdf3vpa2bMiUQrg9i6276yn8666aA==} + engines: {node: '>= 14'} + + pac-resolver@7.0.1: + resolution: {integrity: sha512-5NPgf87AT2STgwa2ntRMr45jTKrYBGkVU36yT0ig/n/GMAa3oPqhZfIQ2kMEimReg0+t9kZViDVZ83qfVUlckg==} + engines: {node: '>= 14'} + + package-json-from-dist@1.0.1: + resolution: {integrity: sha512-UEZIS3/by4OC8vL3P2dTXRETpebLI2NiI5vIrjaD/5UtrkFX/tNbwjTSRAGC/+7CAo2pIcBaRgWmcBBHcsaCIw==} + + parent-module@1.0.1: + resolution: {integrity: sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==} + engines: {node: '>=6'} + + parse-json@5.2.0: + resolution: {integrity: sha512-ayCKvm/phCGxOkYRSCM82iDwct8/EonSEgCSxWxD7ve6jHggsFl4fZVQBPRNgQoKiuV/odhFrGzQXZwbifC8Rg==} + engines: {node: '>=8'} + + parseley@0.12.1: + resolution: {integrity: sha512-e6qHKe3a9HWr0oMRVDTRhKce+bRO8VGQR3NyVwcjwrbhMmFCX9KszEV35+rn4AdilFAq9VPxP/Fe1wC9Qjd2lw==} + + parseurl@1.3.3: + resolution: {integrity: sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ==} + engines: {node: '>= 0.8'} + + path-exists@4.0.0: + resolution: {integrity: sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==} + engines: {node: '>=8'} + + path-key@3.1.1: + resolution: {integrity: sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==} + engines: {node: '>=8'} + + path-scurry@1.11.1: + resolution: {integrity: sha512-Xa4Nw17FS9ApQFJ9umLiJS4orGjm7ZzwUrwamcGQuHSzDyth9boKDaycYdDcZDuqYATXw4HFXgaqWTctW/v1HA==} + engines: {node: '>=16 || 14 >=14.18'} + + path-scurry@2.0.0: + resolution: {integrity: sha512-ypGJsmGtdXUOeM5u93TyeIEfEhM6s+ljAhrk5vAvSx8uyY/02OvrZnA0YNGUrPXfpJMgI1ODd3nwz8Npx4O4cg==} + engines: {node: 20 || >=22} + + path-to-regexp@0.1.12: + resolution: {integrity: sha512-RA1GjUVMnvYFxuqovrEqZoxxW5NUZqbwKtYz/Tt7nXerk0LbLblQmrsgdeOxV5SFHf0UDggjS/bSeOZwt1pmEQ==} + + path-type@4.0.0: + resolution: {integrity: sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==} + engines: {node: '>=8'} + + pathval@2.0.0: + resolution: {integrity: sha512-vE7JKRyES09KiunauX7nd2Q9/L7lhok4smP9RZTDeD4MVs72Dp2qNFVz39Nz5a0FVEW0BJR6C0DYrq6unoziZA==} + engines: {node: '>= 14.16'} + + peberminta@0.9.0: + resolution: {integrity: sha512-XIxfHpEuSJbITd1H3EeQwpcZbTLHc+VVr8ANI9t5sit565tsI4/xK3KWTUFE2e6QiangUkh3B0jihzmGnNrRsQ==} + + pend@1.2.0: + resolution: {integrity: sha512-F3asv42UuXchdzt+xXqfW1OGlVBe+mxa2mqI0pg5yAHZPvFmY3Y6drSf/GQ1A86WgWEN9Kzh/WrgKa6iGcHXLg==} + + pg-cloudflare@1.2.5: + resolution: {integrity: sha512-OOX22Vt0vOSRrdoUPKJ8Wi2OpE/o/h9T8X1s4qSkCedbNah9ei2W2765be8iMVxQUsvgT7zIAT2eIa9fs5+vtg==} + + pg-connection-string@2.9.0: + resolution: {integrity: sha512-P2DEBKuvh5RClafLngkAuGe9OUlFV7ebu8w1kmaaOgPcpJd1RIFh7otETfI6hAR8YupOLFTY7nuvvIn7PLciUQ==} + + pg-int8@1.0.1: + resolution: {integrity: sha512-WCtabS6t3c8SkpDBUlb1kjOs7l66xsGdKpIPZsg4wR+B3+u9UAum2odSsF9tnvxg80h4ZxLWMy4pRjOsFIqQpw==} + engines: {node: '>=4.0.0'} + + pg-pool@3.10.0: + resolution: {integrity: sha512-DzZ26On4sQ0KmqnO34muPcmKbhrjmyiO4lCCR0VwEd7MjmiKf5NTg/6+apUEu0NF7ESa37CGzFxH513CoUmWnA==} + peerDependencies: + pg: '>=8.0' + + pg-protocol@1.10.0: + resolution: {integrity: sha512-IpdytjudNuLv8nhlHs/UrVBhU0e78J0oIS/0AVdTbWxSOkFUVdsHC/NrorO6nXsQNDTT1kzDSOMJubBQviX18Q==} + + pg-types@2.2.0: + resolution: {integrity: sha512-qTAAlrEsl8s4OiEQY69wDvcMIdQN6wdz5ojQiOy6YRMuynxenON0O5oCpJI6lshc6scgAY8qvJ2On/p+CXY0GA==} + engines: {node: '>=4'} + + pg@8.16.0: + resolution: {integrity: sha512-7SKfdvP8CTNXjMUzfcVTaI+TDzBEeaUnVwiVGZQD1Hh33Kpev7liQba9uLd4CfN8r9mCVsD0JIpq03+Unpz+kg==} + engines: {node: '>= 8.0.0'} + peerDependencies: + pg-native: '>=3.0.1' + peerDependenciesMeta: + pg-native: + optional: true + + pgpass@1.0.5: + resolution: {integrity: sha512-FdW9r/jQZhSeohs1Z3sI1yxFQNFvMcnmfuj4WBMUTxOrAyLMaTcE1aAMBiTlbMNaXvBCQuVi0R7hd8udDSP7ug==} + + picocolors@1.1.1: + resolution: {integrity: sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==} + + picomatch@2.3.1: + resolution: {integrity: sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==} + engines: {node: '>=8.6'} + + picomatch@4.0.2: + resolution: {integrity: sha512-M7BAV6Rlcy5u+m6oPhAPFgJTzAioX/6B0DxyvDlo9l8+T3nLKbrczg2WLUyzd45L8RqfUMyGPzekbMvX2Ldkwg==} + engines: {node: '>=12'} + + pino-abstract-transport@2.0.0: + resolution: {integrity: sha512-F63x5tizV6WCh4R6RHyi2Ml+M70DNRXt/+HANowMflpgGFMAym/VKm6G7ZOQRjqN7XbGxK1Lg9t6ZrtzOaivMw==} + + pino-pretty@13.0.0: + resolution: {integrity: sha512-cQBBIVG3YajgoUjo1FdKVRX6t9XPxwB9lcNJVD5GCnNM4Y6T12YYx8c6zEejxQsU0wrg9TwmDulcE9LR7qcJqA==} + hasBin: true + + pino-std-serializers@7.0.0: + resolution: {integrity: sha512-e906FRY0+tV27iq4juKzSYPbUj2do2X2JX4EzSca1631EB2QJQUqGbDuERal7LCtOpxl6x3+nvo9NPZcmjkiFA==} + + pino@9.7.0: + resolution: {integrity: sha512-vnMCM6xZTb1WDmLvtG2lE/2p+t9hDEIvTWJsu6FejkE62vB7gDhvzrpFR4Cw2to+9JNQxVnkAKVPA1KPB98vWg==} + hasBin: true + + plimit-lit@1.6.1: + resolution: {integrity: sha512-B7+VDyb8Tl6oMJT9oSO2CW8XC/T4UcJGrwOVoNGwOQsQYhlpfajmrMj5xeejqaASq3V/EqThyOeATEOMuSEXiA==} + engines: {node: '>=12'} + + postcss@8.4.31: + resolution: {integrity: sha512-PS08Iboia9mts/2ygV3eLpY5ghnUcfLV/EXTOW1E2qYxJKGGBUtNjN76FYHnMs36RmARn41bC0AZmn+rR0OVpQ==} + engines: {node: ^10 || ^12 || >=14} + + postcss@8.5.5: + resolution: {integrity: sha512-d/jtm+rdNT8tpXuHY5MMtcbJFBkhXE6593XVR9UoGCH8jSFGci7jGvMGH5RYd5PBJW+00NZQt6gf7CbagJCrhg==} + engines: {node: ^10 || ^12 || >=14} + + postgres-array@2.0.0: + resolution: {integrity: sha512-VpZrUqU5A69eQyW2c5CA1jtLecCsN2U/bD6VilrFDWq5+5UIEVO7nazS3TEcHf1zuPYO/sqGvUvW62g86RXZuA==} + engines: {node: '>=4'} + + postgres-bytea@1.0.0: + resolution: {integrity: sha512-xy3pmLuQqRBZBXDULy7KbaitYqLcmxigw14Q5sj8QBVLqEwXfeybIKVWiqAXTlcvdvb0+xkOtDbfQMOf4lST1w==} + engines: {node: '>=0.10.0'} + + postgres-date@1.0.7: + resolution: {integrity: sha512-suDmjLVQg78nMK2UZ454hAG+OAW+HQPZ6n++TNDUX+L0+uUlLywnoxJKDou51Zm+zTCjrCl0Nq6J9C5hP9vK/Q==} + engines: {node: '>=0.10.0'} + + postgres-interval@1.2.0: + resolution: {integrity: sha512-9ZhXKM/rw350N1ovuWHbGxnGh/SNJ4cnxHiM0rxE4VN41wsg8P8zWn9hv/buK00RP4WvlOyr/RBDiptyxVbkZQ==} + engines: {node: '>=0.10.0'} + + postgres@3.4.7: + resolution: {integrity: sha512-Jtc2612XINuBjIl/QTWsV5UvE8UHuNblcO3vVADSrKsrc6RqGX6lOW1cEo3CM2v0XG4Nat8nI+YM7/f26VxXLw==} + engines: {node: '>=12'} + + posthog-js@1.252.1: + resolution: {integrity: sha512-EkUCULWJqonMAvzE6CRX9MQupKG18X+r81+hYp3CBRcvbZG5gkbwR39t6p1347wBZJEsC1cKrjRnklc4w7XAUw==} + peerDependencies: + '@rrweb/types': 2.0.0-alpha.17 + rrweb-snapshot: 2.0.0-alpha.17 + peerDependenciesMeta: + '@rrweb/types': + optional: true + rrweb-snapshot: + optional: true + + posthog-node@4.18.0: + resolution: {integrity: sha512-XROs1h+DNatgKh/AlIlCtDxWzwrKdYDb2mOs58n4yN8BkGN9ewqeQwG5ApS4/IzwCb7HPttUkOVulkYatd2PIw==} + engines: {node: '>=15.0.0'} + + preact@10.26.9: + resolution: {integrity: sha512-SSjF9vcnF27mJK1XyFMNJzFd5u3pQiATFqoaDy03XuN00u4ziveVVEGt5RKJrDR8MHE/wJo9Nnad56RLzS2RMA==} + + prelude-ls@1.2.1: + resolution: {integrity: sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==} + engines: {node: '>= 0.8.0'} + + prettier@3.5.3: + resolution: {integrity: sha512-QQtaxnoDJeAkDvDKWCLiwIXkTgRhwYDEQCghU9Z6q03iyek/rxRh/2lC3HB7P8sWT2xC/y5JDctPLBIGzHKbhw==} + engines: {node: '>=14'} + hasBin: true + + prism-themes@1.9.0: + resolution: {integrity: sha512-tX2AYsehKDw1EORwBps+WhBFKc2kxfoFpQAjxBndbZKr4fRmMkv47XN0BghC/K1qwodB1otbe4oF23vUTFDokw==} + + prismjs@1.30.0: + resolution: {integrity: sha512-DEvV2ZF2r2/63V+tK8hQvrR2ZGn10srHbXviTlcv7Kpzw8jWiNTqbVgjO3IY8RxrrOUF8VPMQQFysYYYv0YZxw==} + engines: {node: '>=6'} + + process-warning@5.0.0: + resolution: {integrity: sha512-a39t9ApHNx2L4+HBnQKqxxHNs1r7KF+Intd8Q/g1bUh6q0WIp9voPXJ/x0j+ZL45KF1pJd9+q2jLIRMfvEshkA==} + + progress@2.0.3: + resolution: {integrity: sha512-7PiHtLll5LdnKIMw100I+8xJXR5gW2QwWYkT6iJva0bXitZKa/XMrSbdmg3r2Xnaidz9Qumd0VPaMrZlF9V9sA==} + engines: {node: '>=0.4.0'} + + prop-types@15.8.1: + resolution: {integrity: sha512-oj87CgZICdulUohogVAR7AjlC0327U4el4L6eAvOqCeudMDVU0NThNaV+b9Df4dXgSP1gXMTnPdhfe/2qDH5cg==} + + property-information@7.1.0: + resolution: {integrity: sha512-TwEZ+X+yCJmYfL7TPUOcvBZ4QfoT5YenQiJuX//0th53DE6w0xxLEtfK3iyryQFddXuvkIk51EEgrJQ0WJkOmQ==} + + proxy-addr@2.0.7: + resolution: {integrity: sha512-llQsMLSUDUPT44jdrU/O37qlnifitDP+ZwrmmZcoSKyLKvtZxpyV0n2/bD/N4tBAAZ/gJEdZU7KMraoK1+XYAg==} + engines: {node: '>= 0.10'} + + proxy-agent@6.5.0: + resolution: {integrity: sha512-TmatMXdr2KlRiA2CyDu8GqR8EjahTG3aY3nXjdzFyoZbmB8hrBsTyMezhULIXKnC0jpfjlmiZ3+EaCzoInSu/A==} + engines: {node: '>= 14'} + + proxy-from-env@1.1.0: + resolution: {integrity: sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg==} + + pstree.remy@1.1.8: + resolution: {integrity: sha512-77DZwxQmxKnu3aR542U+X8FypNzbfJ+C5XQDk3uWjWxn6151aIMGthWYRXTqT1E5oJvg+ljaa2OJi+VfvCOQ8w==} + + pump@3.0.3: + resolution: {integrity: sha512-todwxLMY7/heScKmntwQG8CXVkWUOdYxIvY2s0VWAAMh/nd8SoYiRaKjlr7+iCs984f2P8zvrfWcDDYVb73NfA==} + + punycode@2.3.1: + resolution: {integrity: sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==} + engines: {node: '>=6'} + + puppeteer-core@24.10.1: + resolution: {integrity: sha512-AE6doA9znmEEps/pC5lc9p0zejCdNLR6UBp3EZ49/15Nbvh+uklXxGox7Qh8/lFGqGVwxInl0TXmsOmIuIMwiQ==} + engines: {node: '>=18'} + + puppeteer@24.10.1: + resolution: {integrity: sha512-7T3rfSaaPt5A31VITV5YKQ4wPCCv4aPn8byDaV+9lhDU9v7BWYY4Ncwerw3ZR5mIolrh/PvzGdIDK7yiBth75g==} + engines: {node: '>=18'} + hasBin: true + + pvtsutils@1.3.6: + resolution: {integrity: sha512-PLgQXQ6H2FWCaeRak8vvk1GW462lMxB5s3Jm673N82zI4vqtVUPuZdffdZbPDFRoU8kAhItWFtPCWiPpp4/EDg==} + + pvutils@1.1.3: + resolution: {integrity: sha512-pMpnA0qRdFp32b1sJl1wOJNxZLQ2cbQx+k6tjNtZ8CpvVhNqEPRgivZ2WOUev2YMajecdH7ctUPDvEe87nariQ==} + engines: {node: '>=6.0.0'} + + qs@6.13.0: + resolution: {integrity: sha512-+38qI9SOr8tfZ4QmJNplMUxqjbe7LKvvZgWdExBOmd+egZTtjLB67Gu0HRX3u/XOq7UU2Nx6nsjvS16Z9uwfpg==} + engines: {node: '>=0.6'} + + qs@6.14.0: + resolution: {integrity: sha512-YWWTjgABSKcvs/nWBi9PycY/JiPJqOD4JA6o9Sej2AtvSGarXxKC3OQSk4pAarbdQlKAh5D4FCQkJNkW+GAn3w==} + engines: {node: '>=0.6'} + + querystringify@2.2.0: + resolution: {integrity: sha512-FIqgj2EUvTa7R50u0rGsyTftzjYmv/a3hO345bZNrqabNqjtgiDMgmo4mkUjd+nzU5oF3dClKqFIPUKybUyqoQ==} + + queue-lit@1.5.2: + resolution: {integrity: sha512-tLc36IOPeMAubu8BkW8YDBV+WyIgKlYU7zUNs0J5Vk9skSZ4JfGlPOqplP0aHdfv7HL0B2Pg6nwiq60Qc6M2Hw==} + engines: {node: '>=12'} + + queue-microtask@1.2.3: + resolution: {integrity: sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==} + + quick-format-unescaped@4.0.4: + resolution: {integrity: sha512-tYC1Q1hgyRuHgloV/YXs2w15unPVh8qfu/qCTfhTYamaw7fyhumKa2yGpdSo87vY32rIclj+4fWYQXUMs9EHvg==} + + randombytes@2.1.0: + resolution: {integrity: sha512-vYl3iOX+4CKUWuxGi9Ukhie6fsqXqS9FE2Zaic4tNFD2N2QQaXOMFbuKK4QmDHC0JO6B1Zp41J0LpT0oR68amQ==} + + range-parser@1.2.1: + resolution: {integrity: sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg==} + engines: {node: '>= 0.6'} + + raw-body@2.5.2: + resolution: {integrity: sha512-8zGqypfENjCIqGhgXToC8aB2r7YrBX+AQAfIPs/Mlk+BtPTztOvTS01NRW/3Eh60J+a48lt8qsCzirQ6loCVfA==} + engines: {node: '>= 0.8'} + + react-confetti-explosion@2.1.2: + resolution: {integrity: sha512-4UzDFBajAGXmF9TSJoRMO2QOBCIXc66idTxH8l7Mkul48HLGtk+tMzK9HYDYsy7Zmw5sEGchi2fbn4AJUuLrZw==} + peerDependencies: + react: ^18.x + react-dom: ^18.x + + react-day-picker@8.10.1: + resolution: {integrity: sha512-TMx7fNbhLk15eqcMt+7Z7S2KF7mfTId/XJDjKE8f+IUcFn0l08/kI4FiYTL/0yuOLmEcbR4Fwe3GJf/NiiMnPA==} + peerDependencies: + date-fns: ^2.28.0 || ^3.0.0 + react: ^16.8.0 || ^17.0.0 || ^18.0.0 + + react-display-name@0.2.5: + resolution: {integrity: sha512-I+vcaK9t4+kypiSgaiVWAipqHRXYmZIuAiS8vzFvXHHXVigg/sMKwlRgLy6LH2i3rmP+0Vzfl5lFsFRwF1r3pg==} + + react-dom@18.3.1: + resolution: {integrity: sha512-5m4nQKp+rZRb09LNH59GM4BxTh9251/ylbKIbpe7TpGxfJ+9kv6BLkLBXIjjspbgbnIBNqlI23tRnTWT0snUIw==} + peerDependencies: + react: ^18.3.1 + + react-dropzone@14.3.8: + resolution: {integrity: sha512-sBgODnq+lcA4P296DY4wacOZz3JFpD99fp+hb//iBO2HHnyeZU3FwWyXJ6salNpqQdsZrgMrotuko/BdJMV8Ug==} + engines: {node: '>= 10.13'} + peerDependencies: + react: '>= 16.8 || 18.0.0' + + react-email@4.0.16: + resolution: {integrity: sha512-auhFU+nQxAkKkP6lQhPyGsa9exwfUEzp2BwZnjHokCwphZlg30tu4t1LgdKRwGPYsi7XNGy6asbVLAUhOVpzzg==} + engines: {node: '>=18.0.0'} + hasBin: true + + react-hot-toast@2.5.2: + resolution: {integrity: sha512-Tun3BbCxzmXXM7C+NI4qiv6lT0uwGh4oAfeJyNOjYUejTsm35mK9iCaYLGv8cBz9L5YxZLx/2ii7zsIwPtPUdw==} + engines: {node: '>=10'} + peerDependencies: + react: '>=16' + react-dom: '>=16' + + react-hotkeys-hook@4.6.2: + resolution: {integrity: sha512-FmP+ZriY3EG59Ug/lxNfrObCnW9xQShgk7Nb83+CkpfkcCpfS95ydv+E9JuXA5cp8KtskU7LGlIARpkc92X22Q==} + peerDependencies: + react: '>=16.8.1' + react-dom: '>=16.8.1' + + react-is@16.13.1: + resolution: {integrity: sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==} + + react-jss@10.10.0: + resolution: {integrity: sha512-WLiq84UYWqNBF6579/uprcIUnM1TSywYq6AIjKTTTG5ziJl9Uy+pwuvpN3apuyVwflMbD60PraeTKT7uWH9XEQ==} + peerDependencies: + react: '>=16.8.6' + + react-promise-suspense@0.3.4: + resolution: {integrity: sha512-I42jl7L3Ze6kZaq+7zXWSunBa3b1on5yfvUW6Eo/3fFOj6dZ5Bqmcd264nJbTK/gn1HjjILAjSwnZbV4RpSaNQ==} + + react-refresh@0.17.0: + resolution: {integrity: sha512-z6F7K9bV85EfseRCp2bzrpyQ0Gkw1uLoCel9XBVWPg/TjRj94SkJzUTGfOa4bs7iJvBWtQG0Wq7wnI0syw3EBQ==} + engines: {node: '>=0.10.0'} + + react-remove-scroll-bar@2.3.8: + resolution: {integrity: sha512-9r+yi9+mgU33AKcj6IbT9oRCO78WriSj6t/cF8DWBZJ9aOGPOTEDvdUDz1FwKim7QXWwmHqtdHnRJfhAxEG46Q==} + engines: {node: '>=10'} + peerDependencies: + '@types/react': '*' + react: ^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0 + peerDependenciesMeta: + '@types/react': + optional: true + + react-remove-scroll@2.7.1: + resolution: {integrity: sha512-HpMh8+oahmIdOuS5aFKKY6Pyog+FNaZV/XyJOq7b4YFwsFHe5yYfdbIalI4k3vU2nSDql7YskmUseHsRrJqIPA==} + engines: {node: '>=10'} + peerDependencies: + '@types/react': '*' + react: ^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0 || ^19.0.0-rc + peerDependenciesMeta: + '@types/react': + optional: true + + react-router@7.6.2: + resolution: {integrity: sha512-U7Nv3y+bMimgWjhlT5CRdzHPu2/KVmqPwKUCChW8en5P3znxUqwlYFlbmyj8Rgp1SF6zs5X4+77kBVknkg6a0w==} + engines: {node: '>=20.0.0'} + peerDependencies: + react: '>=18' + react-dom: '>=18' + peerDependenciesMeta: + react-dom: + optional: true + + react-style-singleton@2.2.3: + resolution: {integrity: sha512-b6jSvxvVnyptAiLjbkWLE/lOnR4lfTtDAl+eUC7RZy+QQWc6wRzIV2CE6xBuMmDxc2qIihtDCZD5NPOFl7fRBQ==} + engines: {node: '>=10'} + peerDependencies: + '@types/react': '*' + react: ^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0 || ^19.0.0-rc + peerDependenciesMeta: + '@types/react': + optional: true + + react@18.3.1: + resolution: {integrity: sha512-wS+hAgJShR0KhEvPJArfuPVN1+Hz1t0Y6n5jLrGQbkb4urgPE/0Rve+1kMB1v/oWgHgm4WIcV+i7F2pTVj+2iQ==} + engines: {node: '>=0.10.0'} + + readdirp@3.6.0: + resolution: {integrity: sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==} + engines: {node: '>=8.10.0'} + + readdirp@4.1.2: + resolution: {integrity: sha512-GDhwkLfywWL2s6vEjyhri+eXmfH6j1L7JE27WhqLeYzoh/A3DBaYGEj2H/HFZCn/kMfim73FXxEJTw06WtxQwg==} + engines: {node: '>= 14.18.0'} + + real-require@0.2.0: + resolution: {integrity: sha512-57frrGM/OCTLqLOAh0mhVA9VBMHd+9U7Zb2THMGdBUoZVOtGbJzjxsYGDJ3A9AYYCP4hn6y1TVbaOfzWtm5GFg==} + engines: {node: '>= 12.13.0'} + + recaseai@0.0.37: + resolution: {integrity: sha512-cKVMWTGBnGtm8K+uD2vfMXOzxdHj1U3++vvTePpOoZABI/SY/jjDpW997vM5xeDnzz7Vk/qqVkLQUQ/ZMDXpsQ==} + hasBin: true + + redis-errors@1.2.0: + resolution: {integrity: sha512-1qny3OExCf0UvUV/5wpYKf2YwPcOqXzkwKKSmKHiE6ZMQs5heeE/c8eXK+PNllPvmjgAbfnsbpkGZWy8cBpn9w==} + engines: {node: '>=4'} + + redis-parser@3.0.0: + resolution: {integrity: sha512-DJnGAeenTdpMEH6uAJRK/uiyEIH9WVsUmoLwzudwGJUwZPp80PDBWPHXSAGNPwNvIXAbe7MSUB1zQFugFml66A==} + engines: {node: '>=4'} + + require-directory@2.1.1: + resolution: {integrity: sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q==} + engines: {node: '>=0.10.0'} + + requires-port@1.0.0: + resolution: {integrity: sha512-KigOCHcocU3XODJxsu8i/j8T9tzT4adHiecwORRQ0ZZFcp7ahwXuRU1m+yuO90C5ZUyGeGfocHDI14M3L3yDAQ==} + + resend@4.6.0: + resolution: {integrity: sha512-D5T2I82FvEUYFlrHzaDvVtr5ADHdhuoLaXgLFGABKyNtQgPWIuz0Vp2L2Evx779qjK37aF4kcw1yXJDHhA2JnQ==} + engines: {node: '>=18'} + + resolve-from@4.0.0: + resolution: {integrity: sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==} + engines: {node: '>=4'} + + resolve-pkg-maps@1.0.0: + resolution: {integrity: sha512-seS2Tj26TBVOC2NIc2rOe2y2ZO7efxITtLZcGSOnHHNOQ7CkiUBfw0Iw2ck6xkIhPwLhKNLS8BO+hEpngQlqzw==} + + restore-cursor@5.1.0: + resolution: {integrity: sha512-oMA2dcrw6u0YfxJQXm342bFKX/E4sG9rbTzO9ptUcR/e8A33cHuvStiYOwH7fszkZlZ1z/ta9AAoPk2F4qIOHA==} + engines: {node: '>=18'} + + reusify@1.1.0: + resolution: {integrity: sha512-g6QUff04oZpHs0eG5p83rFLhHeV00ug/Yf9nZM6fLeUrPguBTkTQOdpAWWspMh55TZfVQDPaN3NQJfbVRAxdIw==} + engines: {iojs: '>=1.0.0', node: '>=0.10.0'} + + rollup@4.43.0: + resolution: {integrity: sha512-wdN2Kd3Twh8MAEOEJZsuxuLKCsBEo4PVNLK6tQWAn10VhsVewQLzcucMgLolRlhFybGxfclbPeEYBaP6RvUFGg==} + engines: {node: '>=18.0.0', npm: '>=8.0.0'} + hasBin: true + + rou3@0.5.1: + resolution: {integrity: sha512-OXMmJ3zRk2xeXFGfA3K+EOPHC5u7RDFG7lIOx0X1pdnhUkI8MdVrbV+sNsD80ElpUZ+MRHdyxPnFthq9VHs8uQ==} + + rou3@0.6.3: + resolution: {integrity: sha512-1HSG1ENTj7Kkm5muMnXuzzfdDOf7CFnbSYFA+H3Fp/rB9lOCxCPgy1jlZxTKyFoC5jJay8Mmc+VbPLYRjzYLrA==} + + run-async@3.0.0: + resolution: {integrity: sha512-540WwVDOMxA6dN6We19EcT9sc3hkXPw5mzRNGM3FkdN/vtE9NFvj5lFAPNwUDmJjXidm3v7TC1cTE7t17Ulm1Q==} + engines: {node: '>=0.12.0'} + + run-parallel@1.2.0: + resolution: {integrity: sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==} + + rxjs@7.8.2: + resolution: {integrity: sha512-dhKf903U/PQZY6boNNtAGdWbG85WAbjT/1xYoZIC7FAY0yWapOBQVsVrDl58W86//e1VpMNBtRV4MaXfdMySFA==} + + safe-buffer@5.2.1: + resolution: {integrity: sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==} + + safe-stable-stringify@2.5.0: + resolution: {integrity: sha512-b3rppTKm9T+PsVCBEOUR46GWI7fdOs00VKZ1+9c1EWDaDMvjQc6tUwuFyIprgGgTcWoVHSKrU8H31ZHA2e0RHA==} + engines: {node: '>=10'} + + safer-buffer@2.1.2: + resolution: {integrity: sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==} + + scheduler@0.23.2: + resolution: {integrity: sha512-UOShsPwz7NrMUqhR6t0hWjFduvOzbtv7toDH1/hIrfRNIDBnnBWd0CwJTGvTpngVlmwGCdP9/Zl/tVrDqcuYzQ==} + + secure-json-parse@2.7.0: + resolution: {integrity: sha512-6aU+Rwsezw7VR8/nyvKTx8QpWH9FrcYiXXlqC4z5d5XQBDRqtbfsRjnwGyqbi3gddNtWHuEk9OANUotL26qKUw==} + + selderee@0.11.0: + resolution: {integrity: sha512-5TF+l7p4+OsnP8BCCvSyZiSPc4x4//p5uPwK8TCnVPJYRmU2aYKMpOXvw8zM5a5JvuuCGN1jmsMwuU2W02ukfA==} + + semver@6.3.1: + resolution: {integrity: sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==} + hasBin: true + + semver@7.7.2: + resolution: {integrity: sha512-RF0Fw+rO5AMf9MAyaRXI4AV0Ulj5lMHqVxxdSgiVbixSCXoEmmX/jk0CuJw4+3SqroYO9VoUh+HcuJivvtJemA==} + engines: {node: '>=10'} + hasBin: true + + send@0.19.0: + resolution: {integrity: sha512-dW41u5VfLXu8SJh5bwRmyYUbAoSB3c9uQh6L8h/KtsFREPWpbX1lrljJo186Jc4nmci/sGUZ9a0a0J2zgfq2hw==} + engines: {node: '>= 0.8.0'} + + serialize-error@8.1.0: + resolution: {integrity: sha512-3NnuWfM6vBYoy5gZFvHiYsVbafvI9vZv/+jlIigFn4oP4zjNPK3LhcY0xSCgeb1a5L8jO71Mit9LlNoi2UfDDQ==} + engines: {node: '>=10'} + + serialize-javascript@6.0.2: + resolution: {integrity: sha512-Saa1xPByTTq2gdeFZYLLo+RFE35NHZkAbqZeWNd3BpzppeVisAqpDjcp8dyf6uIvEqJRd46jemmyA4iFIeVk8g==} + + serve-static@1.16.2: + resolution: {integrity: sha512-VqpjJZKadQB/PEbEwvFdO43Ax5dFBZ2UECszz8bQ7pi7wt//PWe1P6MN7eCnjsatYtBT6EuiClbjSWP2WrIoTw==} + engines: {node: '>= 0.8.0'} + + set-cookie-parser@2.7.1: + resolution: {integrity: sha512-IOc8uWeOZgnb3ptbCURJWNjWUPcO3ZnTTdzsurqERrP6nPyv+paC55vJM0LpOlT2ne+Ix+9+CRG1MNLlyZ4GjQ==} + + setprototypeof@1.2.0: + resolution: {integrity: sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw==} + + shallow-equal@1.2.1: + resolution: {integrity: sha512-S4vJDjHHMBaiZuT9NPb616CSmLf618jawtv3sufLl6ivK8WocjAo58cXwbRV1cgqxH0Qbv+iUt6m05eqEa2IRA==} + + sharp@0.34.2: + resolution: {integrity: sha512-lszvBmB9QURERtyKT2bNmsgxXK0ShJrL/fvqlonCo7e6xBF8nT8xU6pW+PMIbLsz0RxQk3rgH9kd8UmvOzlMJg==} + engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0} + + shebang-command@2.0.0: + resolution: {integrity: sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==} + engines: {node: '>=8'} + + shebang-regex@3.0.0: + resolution: {integrity: sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==} + engines: {node: '>=8'} + + side-channel-list@1.0.0: + resolution: {integrity: sha512-FCLHtRD/gnpCiCHEiJLOwdmFP+wzCmDEkc9y7NsYxeF4u7Btsn1ZuwgwJGxImImHicJArLP4R0yX4c2KCrMrTA==} + engines: {node: '>= 0.4'} + + side-channel-map@1.0.1: + resolution: {integrity: sha512-VCjCNfgMsby3tTdo02nbjtM/ewra6jPHmpThenkTYh8pG9ucZ/1P8So4u4FGBek/BjpOVsDCMoLA/iuBKIFXRA==} + engines: {node: '>= 0.4'} + + side-channel-weakmap@1.0.2: + resolution: {integrity: sha512-WPS/HvHQTYnHisLo9McqBHOJk2FkHO/tlpvldyrnem4aeQp4hai3gythswg6p01oSoTl58rcpiFAjF2br2Ak2A==} + engines: {node: '>= 0.4'} + + side-channel@1.1.0: + resolution: {integrity: sha512-ZX99e6tRweoUXqR+VBrslhda51Nh5MTQwou5tnUDgbtyM0dBgmhEDtWGP/xbKn6hqfPRHujUNwz5fy/wbbhnpw==} + engines: {node: '>= 0.4'} + + signal-exit@4.1.0: + resolution: {integrity: sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==} + engines: {node: '>=14'} + + simple-swizzle@0.2.2: + resolution: {integrity: sha512-JA//kQgZtbuY83m+xT+tXJkmJncGMTFT+C+g2h2R9uxkYIrE2yy9sgmcLhCnw57/WSD+Eh3J97FPEDFnbXnDUg==} + + simple-update-notifier@2.0.0: + resolution: {integrity: sha512-a2B9Y0KlNXl9u/vsW6sTIu9vGEpfKu2wRV6l1H3XEas/0gUIzGzBoP/IouTcUQbm9JWZLH3COxyn03TYlFax6w==} + engines: {node: '>=10'} + + slash@3.0.0: + resolution: {integrity: sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==} + engines: {node: '>=8'} + + smart-buffer@4.2.0: + resolution: {integrity: sha512-94hK0Hh8rPqQl2xXc3HsaBoOXKV20MToPkcXvwbISWLEs+64sBq5kFgn2kJDHb1Pry9yrP0dxrCI9RRci7RXKg==} + engines: {node: '>= 6.0.0', npm: '>= 3.0.0'} + + snake-case@3.0.4: + resolution: {integrity: sha512-LAOh4z89bGQvl9pFfNF8V146i7o7/CqFPbqzYgP+yYzDIDeS9HaNFtXABamRW+AQzEVODcvE79ljJ+8a9YSdMg==} + + snakecase-keys@8.0.1: + resolution: {integrity: sha512-Sj51kE1zC7zh6TDlNNz0/Jn1n5HiHdoQErxO8jLtnyrkJW/M5PrI7x05uDgY3BO7OUQYKCvmeMurW6BPUdwEOw==} + engines: {node: '>=18'} + + socket.io-adapter@2.5.5: + resolution: {integrity: sha512-eLDQas5dzPgOWCk9GuuJC2lBqItuhKI4uxGgo9aIV7MYbk2h9Q6uULEh8WBzThoI7l+qU9Ast9fVUmkqPP9wYg==} + + socket.io-parser@4.2.4: + resolution: {integrity: sha512-/GbIKmo8ioc+NIWIhwdecY0ge+qVBSMdgxGygevmdHj24bsfgtCmcUUcQ5ZzcylGFHsN3k4HB4Cgkl96KVnuew==} + engines: {node: '>=10.0.0'} + + socket.io@4.8.1: + resolution: {integrity: sha512-oZ7iUCxph8WYRHHcjBEc9unw3adt5CmSNlppj/5Q4k2RIrhl8Z5yY2Xr4j9zj0+wzVZ0bxmYoGSzKJnRl6A4yg==} + engines: {node: '>=10.2.0'} + + socks-proxy-agent@8.0.5: + resolution: {integrity: sha512-HehCEsotFqbPW9sJ8WVYB6UbmIMv7kUUORIF2Nncq4VQvBfNBLibW9YZR5dlYCSUhwcD628pRllm7n+E+YTzJw==} + engines: {node: '>= 14'} + + socks@2.8.5: + resolution: {integrity: sha512-iF+tNDQla22geJdTyJB1wM/qrX9DMRwWrciEPwWLPRWAUEM8sQiyxgckLxWT1f7+9VabJS0jTGGr4QgBuvi6Ww==} + engines: {node: '>= 10.0.0', npm: '>= 3.0.0'} + + sonic-boom@4.2.0: + resolution: {integrity: sha512-INb7TM37/mAcsGmc9hyyI6+QR3rR1zVRu36B0NeGXKnOOLiZOfER5SA+N7X7k3yUYRzLWafduTDvJAfDswwEww==} + + sonner@2.0.5: + resolution: {integrity: sha512-YwbHQO6cSso3HBXlbCkgrgzDNIhws14r4MO87Ofy+cV2X7ES4pOoAK3+veSmVTvqNx1BWUxlhPmZzP00Crk2aQ==} + peerDependencies: + react: ^18.0.0 || ^19.0.0 || ^19.0.0-rc + react-dom: ^18.0.0 || ^19.0.0 || ^19.0.0-rc + + source-map-js@1.2.1: + resolution: {integrity: sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA==} + engines: {node: '>=0.10.0'} + + source-map-support@0.5.21: + resolution: {integrity: sha512-uBHU3L3czsIyYXKX88fdrGovxdSCoTGDRZ6SYXtSRxLZUzHg5P/66Ht6uoUlHu9EZod+inXhKo3qQgwXUT/y1w==} + + source-map@0.6.1: + resolution: {integrity: sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==} + engines: {node: '>=0.10.0'} + + space-separated-tokens@2.0.2: + resolution: {integrity: sha512-PEGlAwrG8yXGXRjW32fGbg66JAlOAwbObuqVoJpv/mRgoWDQfgH1wDPvtzWyUSNAXBGSk8h755YDbbcEy3SH2Q==} + + split2@4.2.0: + resolution: {integrity: sha512-UcjcJOWknrNkF6PLX83qcHM6KHgVKNkV62Y8a5uYDVv9ydGQVwAHMKqHdJje1VTWpljG0WYpCDhrCdAOYH4TWg==} + engines: {node: '>= 10.x'} + + sprintf-js@1.1.3: + resolution: {integrity: sha512-Oo+0REFV59/rz3gfJNKQiBlwfHaSESl1pcGyABQsnnIfWOFt6JNj5gCog2U6MLZ//IGYD+nA8nI+mTShREReaA==} + + stack-trace@0.0.10: + resolution: {integrity: sha512-KGzahc7puUKkzyMt+IqAep+TVNbKP+k2Lmwhub39m1AsTSkaDutx56aDCo+HLDzf/D26BIHTJWNiTG1KAJiQCg==} + + standard-as-callback@2.1.0: + resolution: {integrity: sha512-qoRRSyROncaz1z0mvYqIE4lCd9p2R90i6GxW3uZv5ucSu8tU7B5HXUP1gG8pVZsYNVaXjk8ClXHPttLyxAL48A==} + + statuses@2.0.1: + resolution: {integrity: sha512-RwNA9Z/7PrK06rYLIzFMlaF+l73iwpzsqRIFgbMLbTcLD6cOao82TaWefPXQvB2fOC4AjuYSEndS7N/mTCbkdQ==} + engines: {node: '>= 0.8'} + + std-env@3.9.0: + resolution: {integrity: sha512-UGvjygr6F6tpH7o2qyqR6QYpwraIjKSdtzyBdyytFOHmPZY917kwdwLG0RbOjWOnKmnm3PeHjaoLLMie7kPLQw==} + + stdin-discarder@0.2.2: + resolution: {integrity: sha512-UhDfHmA92YAlNnCfhmq0VeNL5bDbiZGg7sZ2IvPsXubGkiNa9EC+tUTsjBRsYUAz87btI6/1wf4XoVvQ3uRnmQ==} + engines: {node: '>=18'} + + streamsearch@1.1.0: + resolution: {integrity: sha512-Mcc5wHehp9aXz1ax6bZUyY5afg9u2rv5cqQI3mRrYkGC8rW2hM02jWuwjtL++LS5qinSyhj2QfLyNsuc+VsExg==} + engines: {node: '>=10.0.0'} + + streamx@2.22.1: + resolution: {integrity: sha512-znKXEBxfatz2GBNK02kRnCXjV+AA4kjZIUxeWSr3UGirZMJfTE9uiwKHobnbgxWyL/JWro8tTq+vOqAK1/qbSA==} + + string-width@4.2.3: + resolution: {integrity: sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==} + engines: {node: '>=8'} + + string-width@5.1.2: + resolution: {integrity: sha512-HnLOCR3vjcY8beoNLtcjZ5/nxn2afmME6lhrDrebokqMap+XbeW8n9TXpPDOqdGK5qcI3oT0GKTW6wC7EMiVqA==} + engines: {node: '>=12'} + + string-width@7.2.0: + resolution: {integrity: sha512-tsaTIkKW9b4N+AEj+SVA+WhJzV7/zMhcSu78mLKWSk7cXMOSHsBKFWUs0fWwq8QyK3MgJBQRX6Gbi4kYbdvGkQ==} + engines: {node: '>=18'} + + stringify-entities@4.0.4: + resolution: {integrity: sha512-IwfBptatlO+QCJUo19AqvrPNqlVMpW9YEL2LIVY+Rpv2qsjCGxaDLNRgeGsQWJhfItebuJhsGSLjaBbNSQ+ieg==} + + strip-ansi@6.0.1: + resolution: {integrity: sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==} + engines: {node: '>=8'} + + strip-ansi@7.1.0: + resolution: {integrity: sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ==} + engines: {node: '>=12'} + + strip-bom@3.0.0: + resolution: {integrity: sha512-vavAMRXOgBVNF6nyEEmL3DBK19iRpDcoIwW+swQ+CbGiu7lju6t+JklA1MHweoWtadgt4ISVUsXLyDq34ddcwA==} + engines: {node: '>=4'} + + strip-json-comments@3.1.1: + resolution: {integrity: sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==} + engines: {node: '>=8'} + + stripe@17.7.0: + resolution: {integrity: sha512-aT2BU9KkizY9SATf14WhhYVv2uOapBWX0OFWF4xvcj1mPaNotlSc2CsxpS4DS46ZueSppmCF5BX1sNYBtwBvfw==} + engines: {node: '>=12.*'} + + styled-jsx@5.1.6: + resolution: {integrity: sha512-qSVyDTeMotdvQYoHWLNGwRFJHC+i+ZvdBRYosOFgC+Wg1vx4frN2/RG/NA7SYqqvKNLf39P2LSRA2pu6n0XYZA==} + engines: {node: '>= 12.0.0'} + peerDependencies: + '@babel/core': '*' + babel-plugin-macros: '*' + react: '>= 16.8.0 || 17.x.x || ^18.0.0-0 || ^19.0.0-0' + peerDependenciesMeta: + '@babel/core': + optional: true + babel-plugin-macros: + optional: true + + super-regex@0.2.0: + resolution: {integrity: sha512-WZzIx3rC1CvbMDloLsVw0lkZVKJWbrkJ0k1ghKFmcnPrW1+jWbgTkTEWVtD9lMdmI4jZEz40+naBxl1dCUhXXw==} + engines: {node: '>=14.16'} + + superagent@10.2.1: + resolution: {integrity: sha512-O+PCv11lgTNJUzy49teNAWLjBZfc+A1enOwTpLlH6/rsvKcTwcdTT8m9azGkVqM7HBl5jpyZ7KTPhHweokBcdg==} + engines: {node: '>=14.18.0'} + + supports-color@5.5.0: + resolution: {integrity: sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==} + engines: {node: '>=4'} + + supports-color@7.2.0: + resolution: {integrity: sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==} + engines: {node: '>=8'} + + supports-color@8.1.1: + resolution: {integrity: sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==} + engines: {node: '>=10'} + + svix-fetch@3.0.0: + resolution: {integrity: sha512-rcADxEFhSqHbraZIsjyZNh4TF6V+koloX1OzZ+AQuObX9mZ2LIMhm1buZeuc5BIZPftZpJCMBsSiBaeszo9tRw==} + + svix-react@1.13.4: + resolution: {integrity: sha512-sK34IAyqmbCgiIWbZwwh++bA8n4k2PxcdBl/jxMsmgp+pc5VDuFC5hSuhRHBLdVDmyEmhJoY5oeTBmxoM/2A9Q==} + peerDependencies: + react: '>=16' + react-dom: '>=16' + svix: '>=1.26.0' + + svix@1.67.0: + resolution: {integrity: sha512-VTGUNrf7nvBYuB0n82Igg9PEVOcfriecKLVTGN9l3dY/6yEzV+j4leOppfR1twFzoODA6DJI1+spg/QJ4NKtLg==} + + swr@2.3.3: + resolution: {integrity: sha512-dshNvs3ExOqtZ6kJBaAsabhPdHyeY4P2cKwRCniDVifBMoG/SVI7tfLWqPXriVspf2Rg4tPzXJTnwaihIeFw2A==} + peerDependencies: + react: ^16.11.0 || ^17.0.0 || ^18.0.0 || ^19.0.0 + + symbol-observable@1.2.0: + resolution: {integrity: sha512-e900nM8RRtGhlV36KGEU9k65K3mPb1WV70OdjfxlG2EAuM1noi/E/BaW/uMhL7bPEssK8QV57vN3esixjUvcXQ==} + engines: {node: '>=0.10.0'} + + tailwind-merge@3.3.1: + resolution: {integrity: sha512-gBXpgUm/3rp1lMZZrM/w7D8GKqshif0zAymAhbCyIt8KMe+0v9DQ7cdYLR4FHH/cKpdTXb+A/tKKU3eolfsI+g==} + + tailwindcss-animate@1.0.7: + resolution: {integrity: sha512-bl6mpH3T7I3UFxuvDEXLxy/VuFxBk5bbzplh7tXI68mwMokNYd1t9qPBHlnyTwfa4JGC4zP516I1hYYtQ/vspA==} + peerDependencies: + tailwindcss: '>=3.0.0 || insiders' + + tailwindcss@4.1.10: + resolution: {integrity: sha512-P3nr6WkvKV/ONsTzj6Gb57sWPMX29EPNPopo7+FcpkQaNsrNpZ1pv8QmrYI2RqEKD7mlGqLnGovlcYnBK0IqUA==} + + tapable@2.2.2: + resolution: {integrity: sha512-Re10+NauLTMCudc7T5WLFLAwDhQ0JWdrMK+9B2M8zR5hRExKmsRDCBA7/aV/pNJFltmBFO5BAMlQFi/vq3nKOg==} + engines: {node: '>=6'} + + tar-fs@3.0.9: + resolution: {integrity: sha512-XF4w9Xp+ZQgifKakjZYmFdkLoSWd34VGKcsTCwlNWM7QG3ZbaxnTsaBwnjFZqHRf/rROxaR8rXnbtwdvaDI+lA==} + + tar-stream@3.1.7: + resolution: {integrity: sha512-qJj60CXt7IU1Ffyc3NJMjh6EkuCFej46zUqJ4J7pqYlThyd9bO0XBTmcOIhSzZJVWfsLks0+nle/j538YAW9RQ==} + + tar@7.4.3: + resolution: {integrity: sha512-5S7Va8hKfV7W5U6g3aYxXmlPoZVAwUMy9AOKyF2fVuZa2UD3qZjg578OrLRt8PcNN1PleVaL/5/yYATNL0ICUw==} + engines: {node: '>=18'} + + text-decoder@1.2.3: + resolution: {integrity: sha512-3/o9z3X0X0fTupwsYvR03pJ/DjWuqqrfwBgTQzdWDiQSm9KitAyz/9WqsT2JQW7KV2m+bC2ol/zqpW37NHxLaA==} + + theming@3.3.0: + resolution: {integrity: sha512-u6l4qTJRDaWZsqa8JugaNt7Xd8PPl9+gonZaIe28vAhqgHMIG/DOyFPqiKN/gQLQYj05tHv+YQdNILL4zoiAVA==} + engines: {node: '>=8'} + peerDependencies: + react: '>=16.3' + + thread-stream@3.1.0: + resolution: {integrity: sha512-OqyPZ9u96VohAyMfJykzmivOrY2wfMSf3C5TtFJVgN+Hm6aj+voFhlK+kZEIv2FBh1X6Xp3DlnCOfEQ3B2J86A==} + + throttleit@2.1.0: + resolution: {integrity: sha512-nt6AMGKW1p/70DF/hGBdJB57B8Tspmbp5gfJ8ilhLnt7kkr2ye7hzD6NVG8GGErk2HWF34igrL2CXmNIkzKqKw==} + engines: {node: '>=18'} + + time-span@5.1.0: + resolution: {integrity: sha512-75voc/9G4rDIJleOo4jPvN4/YC4GRZrY8yy1uU4lwrB3XEQbWve8zXoO5No4eFrGcTAMYyoY67p8jRQdtA1HbA==} + engines: {node: '>=12'} + + tiny-warning@1.0.3: + resolution: {integrity: sha512-lBN9zLN/oAf68o3zNXYrdCt1kP8WsiGW8Oo2ka41b2IM5JL/S1CTyX1rW0mb/zSuJun0ZUrDxx4sqvYS2FWzPA==} + + tinyglobby@0.2.14: + resolution: {integrity: sha512-tX5e7OM1HnYr2+a2C/4V0htOcSQcoSTH9KgJnVvNm5zm/cyEWKJ7j7YutsH9CxMdtOkkLFy2AHrMci9IM8IPZQ==} + engines: {node: '>=12.0.0'} + + tmp@0.0.33: + resolution: {integrity: sha512-jRCJlojKnZ3addtTOjdIqoRuPEKBvNXcGYqzO6zWZX8KfKEpnGY5jfggJQ3EjKuu8D4bJRr0y+cYJFmYbImXGw==} + engines: {node: '>=0.6.0'} + + to-regex-range@5.0.1: + resolution: {integrity: sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==} + engines: {node: '>=8.0'} + + toidentifier@1.0.1: + resolution: {integrity: sha512-o5sSPKEkg/DIQNmH43V0/uerLrpzVedkUh8tGNvaeXpfpuwjKenlSox/2O/BTlZUtEe+JG7s5YhEz608PlAHRA==} + engines: {node: '>=0.6'} + + touch@3.1.1: + resolution: {integrity: sha512-r0eojU4bI8MnHr8c5bNo7lJDdI2qXlWWJk6a9EAFG7vbhTjElYhBVS3/miuE0uOuoLdb8Mc/rVfsmm6eo5o9GA==} + hasBin: true + + tr46@0.0.3: + resolution: {integrity: sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw==} + + trim-lines@3.0.1: + resolution: {integrity: sha512-kRj8B+YHZCc9kQYdWfJB2/oUl9rA99qbowYYBtr4ui4mZyAQ2JpvVBd/6U2YloATfqBhBTSMhTpgBHtU0Mf3Rg==} + + ts-api-utils@2.1.0: + resolution: {integrity: sha512-CUgTZL1irw8u29bzrOD/nH85jqyc74D6SshFgujOIA7osm2Rz7dYH77agkx7H4FBNxDq7Cjf+IjaX/8zwFW+ZQ==} + engines: {node: '>=18.12'} + peerDependencies: + typescript: '>=4.8.4' + + ts-node@10.9.2: + resolution: {integrity: sha512-f0FFpIdcHgn8zcPSbf1dRevwt047YMnaiJM3u2w2RewrB+fob/zePZcrOyQoLMMO7aBIddLcQIEK5dYjkLnGrQ==} + hasBin: true + peerDependencies: + '@swc/core': '>=1.2.50' + '@swc/wasm': '>=1.2.50' + '@types/node': '*' + typescript: '>=2.7' + peerDependenciesMeta: + '@swc/core': + optional: true + '@swc/wasm': + optional: true + + tsc-alias@1.8.16: + resolution: {integrity: sha512-QjCyu55NFyRSBAl6+MTFwplpFcnm2Pq01rR/uxfqJoLMm6X3O14KEGtaSDZpJYaE1bJBGDjD0eSuiIWPe2T58g==} + engines: {node: '>=16.20.2'} + hasBin: true + + tsconfig-paths@4.2.0: + resolution: {integrity: sha512-NoZ4roiN7LnbKn9QqE1amc9DJfzvZXxF4xDavcOWt1BPkdx+m+0gJuPM+S0vCe7zTJMYUP0R8pO2XMr+Y8oLIg==} + engines: {node: '>=6'} + + tslib@2.8.1: + resolution: {integrity: sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==} + + tsx@4.20.3: + resolution: {integrity: sha512-qjbnuR9Tr+FJOMBqJCW5ehvIo/buZq7vH7qD7JziU98h6l3qGy0a/yPFjwO+y0/T7GFpNgNAvEcPPVfyT8rrPQ==} + engines: {node: '>=18.0.0'} + hasBin: true + + type-check@0.4.0: + resolution: {integrity: sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==} + engines: {node: '>= 0.8.0'} + + type-fest@0.20.2: + resolution: {integrity: sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ==} + engines: {node: '>=10'} + + type-fest@0.21.3: + resolution: {integrity: sha512-t0rzBq87m3fVcduHDUFhKmyyX+9eo6WQjZvf51Ea/M0Q7+T374Jp1aUiyUl0GKxp8M/OETVHSDvmkyPgvX+X2w==} + engines: {node: '>=10'} + + type-fest@4.41.0: + resolution: {integrity: sha512-TeTSQ6H5YHvpqVwBRcnLDCBnDOHWYu7IvGbHT6N8AOymcr9PJGjc1GTtiWZTYg0NCgYwvnYWEkVChQAr9bjfwA==} + engines: {node: '>=16'} + + type-is@1.6.18: + resolution: {integrity: sha512-TkRKr9sUTxEH8MdfuCSP7VizJyzRNMjj2J2do2Jr3Kym598JVdEksuzPQCnlFPW4ky9Q+iA+ma9BGm06XQBy8g==} + engines: {node: '>= 0.6'} + + typed-query-selector@2.12.0: + resolution: {integrity: sha512-SbklCd1F0EiZOyPiW192rrHZzZ5sBijB6xM+cpmrwDqObvdtunOHHIk9fCGsoK5JVIYXoyEp4iEdE3upFH3PAg==} + + typescript-eslint@8.34.0: + resolution: {integrity: sha512-MRpfN7uYjTrTGigFCt8sRyNqJFhjN0WwZecldaqhWm+wy0gaRt8Edb/3cuUy0zdq2opJWT6iXINKAtewnDOltQ==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + peerDependencies: + eslint: ^8.57.0 || ^9.0.0 + typescript: '>=4.8.4 <5.9.0' + + typescript@5.7.3: + resolution: {integrity: sha512-84MVSjMEHP+FQRPy3pX9sTVV/INIex71s9TL2Gm5FG/WG1SqXeKyZ0k7/blY/4FdOzI12CBy1vGc4og/eus0fw==} + engines: {node: '>=14.17'} + hasBin: true + + typescript@5.8.3: + resolution: {integrity: sha512-p1diW6TqL9L07nNxvRMM7hMMw4c5XOo/1ibL4aAIGmSAt9slTE1Xgw5KWuof2uTOvCg9BY7ZRi+GaF+7sfgPeQ==} + engines: {node: '>=14.17'} + hasBin: true + + uncrypto@0.1.3: + resolution: {integrity: sha512-Ql87qFHB3s/De2ClA9e0gsnS6zXG27SkTiSJwjCc9MebbfapQfuPzumMIUMi38ezPZVNFcHI9sUIepeQfw8J8Q==} + + undefsafe@2.0.5: + resolution: {integrity: sha512-WxONCrssBM8TSPRqN5EmsjVrsv4A8X12J4ArBiiayv3DyyG3ZlIg6yysuuSYdZsVz3TKcTg2fd//Ujd4CHV1iA==} + + undici-types@5.26.5: + resolution: {integrity: sha512-JlCMO+ehdEIKqlFxk6IfVoAUVmgz7cU7zD/h9XZ0qzeosSHmUJVOzSQvvYSYWXkFXC+IfLKSIffhv0sVZup6pA==} + + undici-types@6.21.0: + resolution: {integrity: sha512-iwDZqg0QAGrg9Rav5H4n0M64c3mkR59cJ6wQp+7C4nI0gsmExaedaYLNO44eT4AtBBwjbTiGPMlt2Md0T9H9JQ==} + + undici-types@7.8.0: + resolution: {integrity: sha512-9UJ2xGDvQ43tYyVMpuHlsgApydB8ZKfVYTsLDhXkFL/6gfkp+U8xTGdh8pMJv1SpZna0zxG1DwsKZsreLbXBxw==} + + unist-util-is@6.0.0: + resolution: {integrity: sha512-2qCTHimwdxLfz+YzdGfkqNlH0tLi9xjTnHddPmJwtIG9MGsdbutfTc4P+haPD7l7Cjxf/WZj+we5qfVPvvxfYw==} + + unist-util-position@5.0.0: + resolution: {integrity: sha512-fucsC7HjXvkB5R3kTCO7kUjRdrS0BJt3M/FPxmHMBOm8JQi2BsHAHFsy27E0EolP8rp0NzXsJ+jNPyDWvOJZPA==} + + unist-util-stringify-position@4.0.0: + resolution: {integrity: sha512-0ASV06AAoKCDkS2+xw5RXJywruurpbC4JZSm7nr7MOt1ojAzvyyaO+UxZf18j8FCF6kmzCZKcAgN/yu2gm2XgQ==} + + unist-util-visit-parents@6.0.1: + resolution: {integrity: sha512-L/PqWzfTP9lzzEa6CKs0k2nARxTdZduw3zyh8d2NVBnsyvHjSX4TWse388YrrQKbvI8w20fGjGlhgT96WwKykw==} + + unist-util-visit@5.0.0: + resolution: {integrity: sha512-MR04uvD+07cwl/yhVuVWAtw+3GOR/knlL55Nd/wAdblk27GCVt3lqpTivy/tkJcZoNPzTwS1Y+KMojlLDhoTzg==} + + unpipe@1.0.0: + resolution: {integrity: sha512-pjy2bYhSsufwWlKwPc+l3cN7+wuJlK6uz0YdJEOlQDbl6jo/YlPi4mb8agUkVC8BF7V8NuzeyPNqRksA3hztKQ==} + engines: {node: '>= 0.8'} + + update-browserslist-db@1.1.3: + resolution: {integrity: sha512-UxhIZQ+QInVdunkDAaiazvvT/+fXL5Osr0JZlJulepYu6Jd7qJtDZjlur0emRlT71EN3ScPoE7gvsuIKKNavKw==} + hasBin: true + peerDependencies: + browserslist: '>= 4.21.0' + + uri-js@4.4.1: + resolution: {integrity: sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==} + + url-parse@1.5.10: + resolution: {integrity: sha512-WypcfiRhfeUP9vvF0j6rw0J3hrWrw6iZv3+22h6iRMJ/8z1Tj6XfLP4DsUix5MhMPnXpiHDoKyoZ/bdCkwBCiQ==} + + use-callback-ref@1.3.3: + resolution: {integrity: sha512-jQL3lRnocaFtu3V00JToYz/4QkNWswxijDaCVNZRiRTO3HQDLsdu1ZtmIUvV4yPp+rvWm5j0y0TG/S61cuijTg==} + engines: {node: '>=10'} + peerDependencies: + '@types/react': '*' + react: ^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0 || ^19.0.0-rc + peerDependenciesMeta: + '@types/react': + optional: true + + use-sidecar@1.1.3: + resolution: {integrity: sha512-Fedw0aZvkhynoPYlA5WXrMCAMm+nSWdZt6lzJQ7Ok8S6Q+VsHmHpRWndVRJ8Be0ZbkfPc5LRYH+5XrzXcEeLRQ==} + engines: {node: '>=10'} + peerDependencies: + '@types/react': '*' + react: ^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0 || ^19.0.0-rc + peerDependenciesMeta: + '@types/react': + optional: true + + use-sync-external-store@1.5.0: + resolution: {integrity: sha512-Rb46I4cGGVBmjamjphe8L/UnvJD+uPPtTkNvX5mZgqdbavhI4EbgIWJiIHXJ8bc/i9EQGPRh4DwEURJ552Do0A==} + peerDependencies: + react: ^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0 + + utils-merge@1.0.1: + resolution: {integrity: sha512-pMZTvIkT1d+TFGvDOqodOclx0QWkkgi6Tdoa8gC8ffGAAqz9pzPTZWAybbsHHoED/ztMtkv/VoYTYyShUn81hA==} + engines: {node: '>= 0.4.0'} + + uuid@9.0.1: + resolution: {integrity: sha512-b+1eJOlsR9K8HJpow9Ok3fiWOWSIcIzXodvv0rQjVoOVNpWMpxf1wZNpt4y9h10odCNrqnYp1OBzRktckBe3sA==} + hasBin: true + + v8-compile-cache-lib@3.0.1: + resolution: {integrity: sha512-wa7YjyUGfNZngI/vtK0UHAN+lgDCxBPCylVXGp0zu59Fz5aiGtNXaq3DhIov063MorB+VfufLh3JlF2KdTK3xg==} + + vary@1.1.2: + resolution: {integrity: sha512-BNGbWLfd0eUPabhkXUVm0j8uuvREyTh5ovRa/dyow/BqAbZJyC+5fU+IzQOzmAKzYqYRAISoRhdQr3eIZ/PXqg==} + engines: {node: '>= 0.8'} + + vaul@1.1.2: + resolution: {integrity: sha512-ZFkClGpWyI2WUQjdLJ/BaGuV6AVQiJ3uELGk3OYtP+B6yCO7Cmn9vPFXVJkRaGkOJu3m8bQMgtyzNHixULceQA==} + peerDependencies: + react: ^16.8 || ^17.0 || ^18.0 || ^19.0.0 || ^19.0.0-rc + react-dom: ^16.8 || ^17.0 || ^18.0 || ^19.0.0 || ^19.0.0-rc + + vfile-message@4.0.2: + resolution: {integrity: sha512-jRDZ1IMLttGj41KcZvlrYAaI3CfqpLpfpf+Mfig13viT6NKvRzWZ+lXz0Y5D60w6uJIBAOGq9mSHf0gktF0duw==} + + vfile@6.0.3: + resolution: {integrity: sha512-KzIbH/9tXat2u30jf+smMwFCsno4wHVdNmzFyL+T/L3UGqqk6JKfVqOFOZEpZSHADH1k40ab6NUIXZq422ov3Q==} + + vite@6.3.5: + resolution: {integrity: sha512-cZn6NDFE7wdTpINgs++ZJ4N49W2vRp8LCKrn3Ob1kYNtOo21vfDoaV5GzBfLU4MovSAB8uNRm4jgzVQZ+mBzPQ==} + engines: {node: ^18.0.0 || ^20.0.0 || >=22.0.0} + hasBin: true + peerDependencies: + '@types/node': ^18.0.0 || ^20.0.0 || >=22.0.0 + jiti: '>=1.21.0' + less: '*' + lightningcss: ^1.21.0 + sass: '*' + sass-embedded: '*' + stylus: '*' + sugarss: '*' + terser: ^5.16.0 + tsx: ^4.8.1 + yaml: ^2.4.2 + peerDependenciesMeta: + '@types/node': + optional: true + jiti: + optional: true + less: + optional: true + lightningcss: + optional: true + sass: + optional: true + sass-embedded: + optional: true + stylus: + optional: true + sugarss: + optional: true + terser: + optional: true + tsx: + optional: true + yaml: + optional: true + + vscode-oniguruma@2.0.1: + resolution: {integrity: sha512-poJU8iHIWnC3vgphJnrLZyI3YdqRlR27xzqDmpPXYzA93R4Gk8z7T6oqDzDoHjoikA2aS82crdXFkjELCdJsjQ==} + + vscode-textmate@9.2.0: + resolution: {integrity: sha512-rkvG4SraZQaPSN/5XjwKswdU0OP9MF28QjrYzUBbhb8QyG3ljB1Ky996m++jiI7KdiAP2CkBiQZd9pqEDTClqA==} + + warning@4.0.3: + resolution: {integrity: sha512-rpJyN222KWIvHJ/F53XSZv0Zl/accqHR8et1kpaMTD/fLCRxtV8iX8czMzY7sVZupTI3zcUTg8eycS2kNF9l6w==} + + web-streams-polyfill@4.0.0-beta.3: + resolution: {integrity: sha512-QW95TCTaHmsYfHDybGMwO5IJIM93I/6vTRk+daHTWFPhwh+C8Cg7j7XyKrwrj8Ib6vYXe0ocYNrmzY4xAAN6ug==} + engines: {node: '>= 14'} + + web-vitals@4.2.4: + resolution: {integrity: sha512-r4DIlprAGwJ7YM11VZp4R884m0Vmgr6EAKe3P+kO0PPj3Unqyvv59rczf6UiGcb9Z8QxZVcqKNwv/g0WNdWwsw==} + + webidl-conversions@3.0.1: + resolution: {integrity: sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ==} + + whatwg-fetch@3.6.20: + resolution: {integrity: sha512-EqhiFU6daOA8kpjOWTL0olhVOF3i7OrFzSYiGsEMB8GcXS+RrzauAERX65xMeNWVqxA6HXH2m69Z9LaKKdisfg==} + + whatwg-url@5.0.0: + resolution: {integrity: sha512-saE57nupxk6v3HY35+jzBwYa0rKSy0XR8JSxZPwgLr7ys0IBzhGviA1/TUGJLmSVqs8pb9AnvICXEuOHLprYTw==} + + which@2.0.2: + resolution: {integrity: sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==} + engines: {node: '>= 8'} + hasBin: true + + word-wrap@1.2.5: + resolution: {integrity: sha512-BN22B5eaMMI9UMtjrGd5g5eCYPpCPDUy0FJXbYsaT5zYxjFOckS53SQDE3pWkVoWpHXVb3BrYcEN4Twa55B5cA==} + engines: {node: '>=0.10.0'} + + workerpool@9.3.2: + resolution: {integrity: sha512-Xz4Nm9c+LiBHhDR5bDLnNzmj6+5F+cyEAWPMkbs2awq/dYazR/efelZzUAjB/y3kNHL+uzkHvxVVpaOfGCPV7A==} + + wrap-ansi@6.2.0: + resolution: {integrity: sha512-r6lPcBGxZXlIcymEu7InxDMhdW0KDxpLgoFLcguasxCaJ/SOIZwINatK9KY/tf+ZrlywOKU0UDj3ATXUBfxJXA==} + engines: {node: '>=8'} + + wrap-ansi@7.0.0: + resolution: {integrity: sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==} + engines: {node: '>=10'} + + wrap-ansi@8.1.0: + resolution: {integrity: sha512-si7QWI6zUMq56bESFvagtmzMdGOtoxfR+Sez11Mobfc7tm+VkUckk9bW2UeffTGVUbOksxmSw0AA2gs8g71NCQ==} + engines: {node: '>=12'} + + wrappy@1.0.2: + resolution: {integrity: sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==} + + ws@8.17.1: + resolution: {integrity: sha512-6XQFvXTkbfUOZOKKILFG1PDK2NDQs4azKQl26T0YS5CxqWLgXajbPZ+h4gZekJyRqFU8pvnbAbbs/3TgRPy+GQ==} + engines: {node: '>=10.0.0'} + peerDependencies: + bufferutil: ^4.0.1 + utf-8-validate: '>=5.0.2' + peerDependenciesMeta: + bufferutil: + optional: true + utf-8-validate: + optional: true + + ws@8.18.2: + resolution: {integrity: sha512-DMricUmwGZUVr++AEAe2uiVM7UoO9MAVZMDu05UQOaUII0lp+zOzLLU4Xqh/JvTqklB1T4uELaaPBKyjE1r4fQ==} + engines: {node: '>=10.0.0'} + peerDependencies: + bufferutil: ^4.0.1 + utf-8-validate: '>=5.0.2' + peerDependenciesMeta: + bufferutil: + optional: true + utf-8-validate: + optional: true + + xtend@4.0.2: + resolution: {integrity: sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ==} + engines: {node: '>=0.4'} + + y18n@5.0.8: + resolution: {integrity: sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==} + engines: {node: '>=10'} + + yallist@3.1.1: + resolution: {integrity: sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==} + + yallist@5.0.0: + resolution: {integrity: sha512-YgvUTfwqyc7UXVMrB+SImsVYSmTS8X/tSrtdNZMImM+n7+QTriRXyXim0mBrTXNeqzVF0KWGgHPeiyViFFrNDw==} + engines: {node: '>=18'} + + yargs-parser@21.1.1: + resolution: {integrity: sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw==} + engines: {node: '>=12'} + + yargs-unparser@2.0.0: + resolution: {integrity: sha512-7pRTIA9Qc1caZ0bZ6RYRGbHJthJWuakf+WmHK0rVeLkNrrGhfoabBNdue6kdINI6r4if7ocq9aD/n7xwKOdzOA==} + engines: {node: '>=10'} + + yargs@17.7.2: + resolution: {integrity: sha512-7dSzzRQ++CKnNI/krKnYRV7JKKPUXMEh61soaHKg9mrWEhzFWhFnxPxGl+69cD1Ou63C13NUPCnmIcrvqCuM6w==} + engines: {node: '>=12'} + + yauzl@2.10.0: + resolution: {integrity: sha512-p4a9I6X6nu6IhoGmBqAcbJy1mlC4j27vEPZX9F4L4/vZT3Lyq1VkFHw/V/PUcB9Buo+DG3iHkT0x3Qya58zc3g==} + + yn@3.1.1: + resolution: {integrity: sha512-Ux4ygGWsu2c7isFWe8Yu1YluJmqVhxqK2cLXNQA5AcC3QfbGNpM7fu0Y8b/z16pXLnFxZYvWhd3fhBY9DLmC6Q==} + engines: {node: '>=6'} + + yocto-queue@0.1.0: + resolution: {integrity: sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==} + engines: {node: '>=10'} + + yoctocolors-cjs@2.1.2: + resolution: {integrity: sha512-cYVsTjKl8b+FrnidjibDWskAv7UKOfcwaVZdp/it9n1s9fU3IkgDbhdIRKCW4JDsAlECJY0ytoVPT3sK6kideA==} + engines: {node: '>=18'} + + yoctocolors@2.1.1: + resolution: {integrity: sha512-GQHQqAopRhwU8Kt1DDM8NjibDXHC8eoh1erhGAJPEyveY9qqVeXvVikNKrDz69sHowPMorbPUrH/mx8c50eiBQ==} + engines: {node: '>=18'} + + zod-to-json-schema@3.24.5: + resolution: {integrity: sha512-/AuWwMP+YqiPbsJx5D6TfgRTc4kTLjsh5SOcd4bLsfUg2RcEXrFMJl1DGgdHy2aCfsIA/cr/1JM0xcB2GZji8g==} + peerDependencies: + zod: ^3.24.1 + + zod@3.25.64: + resolution: {integrity: sha512-hbP9FpSZf7pkS7hRVUrOjhwKJNyampPgtXKc3AN6DsWtoHsg2Sb4SQaS4Tcay380zSwd2VPo9G9180emBACp5g==} + + zwitch@2.0.4: + resolution: {integrity: sha512-bXE4cR/kVZhKZX/RjPEflHaKVhUVl85noU3v6b8apfQEc1x4A+zBxjZ4lN8LqGd6WZ3dl98pY4o717VFmoPp+A==} + +snapshots: + + '@ai-sdk/anthropic@1.2.12(zod@3.25.64)': + dependencies: + '@ai-sdk/provider': 1.1.3 + '@ai-sdk/provider-utils': 2.2.8(zod@3.25.64) + zod: 3.25.64 + + '@ai-sdk/provider-utils@2.2.8(zod@3.25.64)': + dependencies: + '@ai-sdk/provider': 1.1.3 + nanoid: 3.3.11 + secure-json-parse: 2.7.0 + zod: 3.25.64 + + '@ai-sdk/provider@1.1.3': + dependencies: + json-schema: 0.4.0 + + '@ai-sdk/react@1.2.12(react@18.3.1)(zod@3.25.64)': + dependencies: + '@ai-sdk/provider-utils': 2.2.8(zod@3.25.64) + '@ai-sdk/ui-utils': 1.2.11(zod@3.25.64) + react: 18.3.1 + swr: 2.3.3(react@18.3.1) + throttleit: 2.1.0 + optionalDependencies: + zod: 3.25.64 + + '@ai-sdk/ui-utils@1.2.11(zod@3.25.64)': + dependencies: + '@ai-sdk/provider': 1.1.3 + '@ai-sdk/provider-utils': 2.2.8(zod@3.25.64) + zod: 3.25.64 + zod-to-json-schema: 3.24.5(zod@3.25.64) + + '@ampproject/remapping@2.3.0': + dependencies: + '@jridgewell/gen-mapping': 0.3.8 + '@jridgewell/trace-mapping': 0.3.25 + + '@anthropic-ai/sdk@0.32.1': + dependencies: + '@types/node': 18.19.111 + '@types/node-fetch': 2.6.12 + abort-controller: 3.0.0 + agentkeepalive: 4.6.0 + form-data-encoder: 1.7.2 + formdata-node: 4.4.1 + node-fetch: 2.7.0 + transitivePeerDependencies: + - encoding + + '@babel/code-frame@7.27.1': + dependencies: + '@babel/helper-validator-identifier': 7.27.1 + js-tokens: 4.0.0 + picocolors: 1.1.1 + + '@babel/compat-data@7.27.5': {} + + '@babel/core@7.27.4': + dependencies: + '@ampproject/remapping': 2.3.0 + '@babel/code-frame': 7.27.1 + '@babel/generator': 7.27.5 + '@babel/helper-compilation-targets': 7.27.2 + '@babel/helper-module-transforms': 7.27.3(@babel/core@7.27.4) + '@babel/helpers': 7.27.6 + '@babel/parser': 7.27.5 + '@babel/template': 7.27.2 + '@babel/traverse': 7.27.4 + '@babel/types': 7.27.6 + convert-source-map: 2.0.0 + debug: 4.4.1 + gensync: 1.0.0-beta.2 + json5: 2.2.3 + semver: 6.3.1 + transitivePeerDependencies: + - supports-color + + '@babel/generator@7.27.5': + dependencies: + '@babel/parser': 7.27.5 + '@babel/types': 7.27.6 + '@jridgewell/gen-mapping': 0.3.8 + '@jridgewell/trace-mapping': 0.3.25 + jsesc: 3.1.0 + + '@babel/helper-annotate-as-pure@7.27.3': + dependencies: + '@babel/types': 7.27.6 + + '@babel/helper-compilation-targets@7.27.2': + dependencies: + '@babel/compat-data': 7.27.5 + '@babel/helper-validator-option': 7.27.1 + browserslist: 4.25.0 + lru-cache: 5.1.1 + semver: 6.3.1 + + '@babel/helper-create-class-features-plugin@7.27.1(@babel/core@7.27.4)': + dependencies: + '@babel/core': 7.27.4 + '@babel/helper-annotate-as-pure': 7.27.3 + '@babel/helper-member-expression-to-functions': 7.27.1 + '@babel/helper-optimise-call-expression': 7.27.1 + '@babel/helper-replace-supers': 7.27.1(@babel/core@7.27.4) + '@babel/helper-skip-transparent-expression-wrappers': 7.27.1 + '@babel/traverse': 7.27.4 + semver: 6.3.1 + transitivePeerDependencies: + - supports-color + + '@babel/helper-member-expression-to-functions@7.27.1': + dependencies: + '@babel/traverse': 7.27.4 + '@babel/types': 7.27.6 + transitivePeerDependencies: + - supports-color + + '@babel/helper-module-imports@7.27.1': + dependencies: + '@babel/traverse': 7.27.4 + '@babel/types': 7.27.6 + transitivePeerDependencies: + - supports-color + + '@babel/helper-module-transforms@7.27.3(@babel/core@7.27.4)': + dependencies: + '@babel/core': 7.27.4 + '@babel/helper-module-imports': 7.27.1 + '@babel/helper-validator-identifier': 7.27.1 + '@babel/traverse': 7.27.4 + transitivePeerDependencies: + - supports-color + + '@babel/helper-optimise-call-expression@7.27.1': + dependencies: + '@babel/types': 7.27.6 + + '@babel/helper-plugin-utils@7.27.1': {} + + '@babel/helper-replace-supers@7.27.1(@babel/core@7.27.4)': + dependencies: + '@babel/core': 7.27.4 + '@babel/helper-member-expression-to-functions': 7.27.1 + '@babel/helper-optimise-call-expression': 7.27.1 + '@babel/traverse': 7.27.4 + transitivePeerDependencies: + - supports-color + + '@babel/helper-skip-transparent-expression-wrappers@7.27.1': + dependencies: + '@babel/traverse': 7.27.4 + '@babel/types': 7.27.6 + transitivePeerDependencies: + - supports-color + + '@babel/helper-string-parser@7.27.1': {} + + '@babel/helper-validator-identifier@7.27.1': {} + + '@babel/helper-validator-option@7.27.1': {} + + '@babel/helpers@7.27.6': + dependencies: + '@babel/template': 7.27.2 + '@babel/types': 7.27.6 + + '@babel/parser@7.27.5': + dependencies: + '@babel/types': 7.27.6 + + '@babel/plugin-proposal-private-property-in-object@7.21.11(@babel/core@7.27.4)': + dependencies: + '@babel/core': 7.27.4 + '@babel/helper-annotate-as-pure': 7.27.3 + '@babel/helper-create-class-features-plugin': 7.27.1(@babel/core@7.27.4) + '@babel/helper-plugin-utils': 7.27.1 + '@babel/plugin-syntax-private-property-in-object': 7.14.5(@babel/core@7.27.4) + transitivePeerDependencies: + - supports-color + + '@babel/plugin-syntax-private-property-in-object@7.14.5(@babel/core@7.27.4)': + dependencies: + '@babel/core': 7.27.4 + '@babel/helper-plugin-utils': 7.27.1 + + '@babel/plugin-transform-react-jsx-self@7.27.1(@babel/core@7.27.4)': + dependencies: + '@babel/core': 7.27.4 + '@babel/helper-plugin-utils': 7.27.1 + + '@babel/plugin-transform-react-jsx-source@7.27.1(@babel/core@7.27.4)': + dependencies: + '@babel/core': 7.27.4 + '@babel/helper-plugin-utils': 7.27.1 + + '@babel/runtime@7.27.6': {} + + '@babel/template@7.27.2': + dependencies: + '@babel/code-frame': 7.27.1 + '@babel/parser': 7.27.5 + '@babel/types': 7.27.6 + + '@babel/traverse@7.27.4': + dependencies: + '@babel/code-frame': 7.27.1 + '@babel/generator': 7.27.5 + '@babel/parser': 7.27.5 + '@babel/template': 7.27.2 + '@babel/types': 7.27.6 + debug: 4.4.1 + globals: 11.12.0 + transitivePeerDependencies: + - supports-color + + '@babel/types@7.27.6': + dependencies: + '@babel/helper-string-parser': 7.27.1 + '@babel/helper-validator-identifier': 7.27.1 + + '@better-auth/utils@0.2.5': + dependencies: + typescript: 5.8.3 + uncrypto: 0.1.3 + + '@better-fetch/fetch@1.1.18': {} + + '@clerk/backend@2.1.0(react-dom@18.3.1(react@18.3.1))(react@18.3.1)': + dependencies: + '@clerk/shared': 3.9.7(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@clerk/types': 4.60.1 + cookie: 1.0.2 + snakecase-keys: 8.0.1 + tslib: 2.8.1 + transitivePeerDependencies: + - react + - react-dom + + '@clerk/clerk-react@5.32.0(react-dom@18.3.1(react@18.3.1))(react@18.3.1)': + dependencies: + '@clerk/shared': 3.9.7(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@clerk/types': 4.60.1 + react: 18.3.1 + react-dom: 18.3.1(react@18.3.1) + tslib: 2.8.1 + + '@clerk/express@1.7.0(express@4.21.2)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)': + dependencies: + '@clerk/backend': 2.1.0(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@clerk/shared': 3.9.7(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@clerk/types': 4.60.1 + express: 4.21.2 + tslib: 2.8.1 + transitivePeerDependencies: + - react + - react-dom + + '@clerk/shared@3.9.7(react-dom@18.3.1(react@18.3.1))(react@18.3.1)': + dependencies: + '@clerk/types': 4.60.1 + dequal: 2.0.3 + glob-to-regexp: 0.4.1 + js-cookie: 3.0.5 + std-env: 3.9.0 + swr: 2.3.3(react@18.3.1) + optionalDependencies: + react: 18.3.1 + react-dom: 18.3.1(react@18.3.1) + + '@clerk/types@4.60.1': + dependencies: + csstype: 3.1.3 + + '@cspotcode/source-map-support@0.8.1': + dependencies: + '@jridgewell/trace-mapping': 0.3.9 + + '@date-fns/tz@1.2.0': {} + + '@date-fns/utc@2.1.0': {} + + '@drizzle-team/brocli@0.10.2': {} + + '@emnapi/runtime@1.4.3': + dependencies: + tslib: 2.8.1 + optional: true + + '@emotion/is-prop-valid@0.7.3': + dependencies: + '@emotion/memoize': 0.7.1 + + '@emotion/memoize@0.7.1': {} + + '@esbuild-kit/core-utils@3.3.2': + dependencies: + esbuild: 0.18.20 + source-map-support: 0.5.21 + + '@esbuild-kit/esm-loader@2.6.5': + dependencies: + '@esbuild-kit/core-utils': 3.3.2 + get-tsconfig: 4.10.1 + + '@esbuild/aix-ppc64@0.25.5': + optional: true + + '@esbuild/android-arm64@0.18.20': + optional: true + + '@esbuild/android-arm64@0.25.5': + optional: true + + '@esbuild/android-arm@0.18.20': + optional: true + + '@esbuild/android-arm@0.25.5': + optional: true + + '@esbuild/android-x64@0.18.20': + optional: true + + '@esbuild/android-x64@0.25.5': + optional: true + + '@esbuild/darwin-arm64@0.18.20': + optional: true + + '@esbuild/darwin-arm64@0.25.5': + optional: true + + '@esbuild/darwin-x64@0.18.20': + optional: true + + '@esbuild/darwin-x64@0.25.5': + optional: true + + '@esbuild/freebsd-arm64@0.18.20': + optional: true + + '@esbuild/freebsd-arm64@0.25.5': + optional: true + + '@esbuild/freebsd-x64@0.18.20': + optional: true + + '@esbuild/freebsd-x64@0.25.5': + optional: true + + '@esbuild/linux-arm64@0.18.20': + optional: true + + '@esbuild/linux-arm64@0.25.5': + optional: true + + '@esbuild/linux-arm@0.18.20': + optional: true + + '@esbuild/linux-arm@0.25.5': + optional: true + + '@esbuild/linux-ia32@0.18.20': + optional: true + + '@esbuild/linux-ia32@0.25.5': + optional: true + + '@esbuild/linux-loong64@0.18.20': + optional: true + + '@esbuild/linux-loong64@0.25.5': + optional: true + + '@esbuild/linux-mips64el@0.18.20': + optional: true + + '@esbuild/linux-mips64el@0.25.5': + optional: true + + '@esbuild/linux-ppc64@0.18.20': + optional: true + + '@esbuild/linux-ppc64@0.25.5': + optional: true + + '@esbuild/linux-riscv64@0.18.20': + optional: true + + '@esbuild/linux-riscv64@0.25.5': + optional: true + + '@esbuild/linux-s390x@0.18.20': + optional: true + + '@esbuild/linux-s390x@0.25.5': + optional: true + + '@esbuild/linux-x64@0.18.20': + optional: true + + '@esbuild/linux-x64@0.25.5': + optional: true + + '@esbuild/netbsd-arm64@0.25.5': + optional: true + + '@esbuild/netbsd-x64@0.18.20': + optional: true + + '@esbuild/netbsd-x64@0.25.5': + optional: true + + '@esbuild/openbsd-arm64@0.25.5': + optional: true + + '@esbuild/openbsd-x64@0.18.20': + optional: true + + '@esbuild/openbsd-x64@0.25.5': + optional: true + + '@esbuild/sunos-x64@0.18.20': + optional: true + + '@esbuild/sunos-x64@0.25.5': + optional: true + + '@esbuild/win32-arm64@0.18.20': + optional: true + + '@esbuild/win32-arm64@0.25.5': + optional: true + + '@esbuild/win32-ia32@0.18.20': + optional: true + + '@esbuild/win32-ia32@0.25.5': + optional: true + + '@esbuild/win32-x64@0.18.20': + optional: true + + '@esbuild/win32-x64@0.25.5': + optional: true + + '@eslint-community/eslint-utils@4.7.0(eslint@9.29.0(jiti@2.4.2))': + dependencies: + eslint: 9.29.0(jiti@2.4.2) + eslint-visitor-keys: 3.4.3 + + '@eslint-community/regexpp@4.12.1': {} + + '@eslint/config-array@0.20.1': + dependencies: + '@eslint/object-schema': 2.1.6 + debug: 4.4.1 + minimatch: 3.1.2 + transitivePeerDependencies: + - supports-color + + '@eslint/config-helpers@0.2.3': {} + + '@eslint/core@0.14.0': + dependencies: + '@types/json-schema': 7.0.15 + + '@eslint/core@0.15.0': + dependencies: + '@types/json-schema': 7.0.15 + + '@eslint/eslintrc@3.3.1': + dependencies: + ajv: 6.12.6 + debug: 4.4.1 + espree: 10.4.0 + globals: 14.0.0 + ignore: 5.3.2 + import-fresh: 3.3.1 + js-yaml: 4.1.0 + minimatch: 3.1.2 + strip-json-comments: 3.1.1 + transitivePeerDependencies: + - supports-color + + '@eslint/js@9.29.0': {} + + '@eslint/object-schema@2.1.6': {} + + '@eslint/plugin-kit@0.3.2': + dependencies: + '@eslint/core': 0.15.0 + levn: 0.4.1 + + '@floating-ui/core@1.7.1': + dependencies: + '@floating-ui/utils': 0.2.9 + + '@floating-ui/dom@1.7.1': + dependencies: + '@floating-ui/core': 1.7.1 + '@floating-ui/utils': 0.2.9 + + '@floating-ui/react-dom@2.1.3(react-dom@18.3.1(react@18.3.1))(react@18.3.1)': + dependencies: + '@floating-ui/dom': 1.7.1 + react: 18.3.1 + react-dom: 18.3.1(react@18.3.1) + + '@floating-ui/utils@0.2.9': {} + + '@fortawesome/fontawesome-common-types@6.7.2': {} + + '@fortawesome/fontawesome-svg-core@6.7.2': + dependencies: + '@fortawesome/fontawesome-common-types': 6.7.2 + + '@fortawesome/free-brands-svg-icons@6.7.2': + dependencies: + '@fortawesome/fontawesome-common-types': 6.7.2 + + '@fortawesome/react-fontawesome@0.2.2(@fortawesome/fontawesome-svg-core@6.7.2)(react@18.3.1)': + dependencies: + '@fortawesome/fontawesome-svg-core': 6.7.2 + prop-types: 15.8.1 + react: 18.3.1 + + '@hexagon/base64@1.1.28': {} + + '@humanfs/core@0.19.1': {} + + '@humanfs/node@0.16.6': + dependencies: + '@humanfs/core': 0.19.1 + '@humanwhocodes/retry': 0.3.1 + + '@humanwhocodes/module-importer@1.0.1': {} + + '@humanwhocodes/retry@0.3.1': {} + + '@humanwhocodes/retry@0.4.3': {} + + '@img/sharp-darwin-arm64@0.34.2': + optionalDependencies: + '@img/sharp-libvips-darwin-arm64': 1.1.0 + optional: true + + '@img/sharp-darwin-x64@0.34.2': + optionalDependencies: + '@img/sharp-libvips-darwin-x64': 1.1.0 + optional: true + + '@img/sharp-libvips-darwin-arm64@1.1.0': + optional: true + + '@img/sharp-libvips-darwin-x64@1.1.0': + optional: true + + '@img/sharp-libvips-linux-arm64@1.1.0': + optional: true + + '@img/sharp-libvips-linux-arm@1.1.0': + optional: true + + '@img/sharp-libvips-linux-ppc64@1.1.0': + optional: true + + '@img/sharp-libvips-linux-s390x@1.1.0': + optional: true + + '@img/sharp-libvips-linux-x64@1.1.0': + optional: true + + '@img/sharp-libvips-linuxmusl-arm64@1.1.0': + optional: true + + '@img/sharp-libvips-linuxmusl-x64@1.1.0': + optional: true + + '@img/sharp-linux-arm64@0.34.2': + optionalDependencies: + '@img/sharp-libvips-linux-arm64': 1.1.0 + optional: true + + '@img/sharp-linux-arm@0.34.2': + optionalDependencies: + '@img/sharp-libvips-linux-arm': 1.1.0 + optional: true + + '@img/sharp-linux-s390x@0.34.2': + optionalDependencies: + '@img/sharp-libvips-linux-s390x': 1.1.0 + optional: true + + '@img/sharp-linux-x64@0.34.2': + optionalDependencies: + '@img/sharp-libvips-linux-x64': 1.1.0 + optional: true + + '@img/sharp-linuxmusl-arm64@0.34.2': + optionalDependencies: + '@img/sharp-libvips-linuxmusl-arm64': 1.1.0 + optional: true + + '@img/sharp-linuxmusl-x64@0.34.2': + optionalDependencies: + '@img/sharp-libvips-linuxmusl-x64': 1.1.0 + optional: true + + '@img/sharp-wasm32@0.34.2': + dependencies: + '@emnapi/runtime': 1.4.3 + optional: true + + '@img/sharp-win32-arm64@0.34.2': + optional: true + + '@img/sharp-win32-ia32@0.34.2': + optional: true + + '@img/sharp-win32-x64@0.34.2': + optional: true + + '@inquirer/checkbox@4.1.8(@types/node@22.15.32)': + dependencies: + '@inquirer/core': 10.1.13(@types/node@22.15.32) + '@inquirer/figures': 1.0.12 + '@inquirer/type': 3.0.7(@types/node@22.15.32) + ansi-escapes: 4.3.2 + yoctocolors-cjs: 2.1.2 + optionalDependencies: + '@types/node': 22.15.32 + + '@inquirer/checkbox@4.1.8(@types/node@24.0.3)': + dependencies: + '@inquirer/core': 10.1.13(@types/node@24.0.3) + '@inquirer/figures': 1.0.12 + '@inquirer/type': 3.0.7(@types/node@24.0.3) + ansi-escapes: 4.3.2 + yoctocolors-cjs: 2.1.2 + optionalDependencies: + '@types/node': 24.0.3 + + '@inquirer/confirm@5.1.12(@types/node@22.15.32)': + dependencies: + '@inquirer/core': 10.1.13(@types/node@22.15.32) + '@inquirer/type': 3.0.7(@types/node@22.15.32) + optionalDependencies: + '@types/node': 22.15.32 + + '@inquirer/confirm@5.1.12(@types/node@24.0.3)': + dependencies: + '@inquirer/core': 10.1.13(@types/node@24.0.3) + '@inquirer/type': 3.0.7(@types/node@24.0.3) + optionalDependencies: + '@types/node': 24.0.3 + + '@inquirer/core@10.1.13(@types/node@22.15.32)': + dependencies: + '@inquirer/figures': 1.0.12 + '@inquirer/type': 3.0.7(@types/node@22.15.32) + ansi-escapes: 4.3.2 + cli-width: 4.1.0 + mute-stream: 2.0.0 + signal-exit: 4.1.0 + wrap-ansi: 6.2.0 + yoctocolors-cjs: 2.1.2 + optionalDependencies: + '@types/node': 22.15.32 + + '@inquirer/core@10.1.13(@types/node@24.0.3)': + dependencies: + '@inquirer/figures': 1.0.12 + '@inquirer/type': 3.0.7(@types/node@24.0.3) + ansi-escapes: 4.3.2 + cli-width: 4.1.0 + mute-stream: 2.0.0 + signal-exit: 4.1.0 + wrap-ansi: 6.2.0 + yoctocolors-cjs: 2.1.2 + optionalDependencies: + '@types/node': 24.0.3 + + '@inquirer/editor@4.2.13(@types/node@22.15.32)': + dependencies: + '@inquirer/core': 10.1.13(@types/node@22.15.32) + '@inquirer/type': 3.0.7(@types/node@22.15.32) + external-editor: 3.1.0 + optionalDependencies: + '@types/node': 22.15.32 + + '@inquirer/editor@4.2.13(@types/node@24.0.3)': + dependencies: + '@inquirer/core': 10.1.13(@types/node@24.0.3) + '@inquirer/type': 3.0.7(@types/node@24.0.3) + external-editor: 3.1.0 + optionalDependencies: + '@types/node': 24.0.3 + + '@inquirer/expand@4.0.15(@types/node@22.15.32)': + dependencies: + '@inquirer/core': 10.1.13(@types/node@22.15.32) + '@inquirer/type': 3.0.7(@types/node@22.15.32) + yoctocolors-cjs: 2.1.2 + optionalDependencies: + '@types/node': 22.15.32 + + '@inquirer/expand@4.0.15(@types/node@24.0.3)': + dependencies: + '@inquirer/core': 10.1.13(@types/node@24.0.3) + '@inquirer/type': 3.0.7(@types/node@24.0.3) + yoctocolors-cjs: 2.1.2 + optionalDependencies: + '@types/node': 24.0.3 + + '@inquirer/figures@1.0.12': {} + + '@inquirer/input@4.1.12(@types/node@22.15.32)': + dependencies: + '@inquirer/core': 10.1.13(@types/node@22.15.32) + '@inquirer/type': 3.0.7(@types/node@22.15.32) + optionalDependencies: + '@types/node': 22.15.32 + + '@inquirer/input@4.1.12(@types/node@24.0.3)': + dependencies: + '@inquirer/core': 10.1.13(@types/node@24.0.3) + '@inquirer/type': 3.0.7(@types/node@24.0.3) + optionalDependencies: + '@types/node': 24.0.3 + + '@inquirer/number@3.0.15(@types/node@22.15.32)': + dependencies: + '@inquirer/core': 10.1.13(@types/node@22.15.32) + '@inquirer/type': 3.0.7(@types/node@22.15.32) + optionalDependencies: + '@types/node': 22.15.32 + + '@inquirer/number@3.0.15(@types/node@24.0.3)': + dependencies: + '@inquirer/core': 10.1.13(@types/node@24.0.3) + '@inquirer/type': 3.0.7(@types/node@24.0.3) + optionalDependencies: + '@types/node': 24.0.3 + + '@inquirer/password@4.0.15(@types/node@22.15.32)': + dependencies: + '@inquirer/core': 10.1.13(@types/node@22.15.32) + '@inquirer/type': 3.0.7(@types/node@22.15.32) + ansi-escapes: 4.3.2 + optionalDependencies: + '@types/node': 22.15.32 + + '@inquirer/password@4.0.15(@types/node@24.0.3)': + dependencies: + '@inquirer/core': 10.1.13(@types/node@24.0.3) + '@inquirer/type': 3.0.7(@types/node@24.0.3) + ansi-escapes: 4.3.2 + optionalDependencies: + '@types/node': 24.0.3 + + '@inquirer/prompts@7.5.3(@types/node@22.15.32)': + dependencies: + '@inquirer/checkbox': 4.1.8(@types/node@22.15.32) + '@inquirer/confirm': 5.1.12(@types/node@22.15.32) + '@inquirer/editor': 4.2.13(@types/node@22.15.32) + '@inquirer/expand': 4.0.15(@types/node@22.15.32) + '@inquirer/input': 4.1.12(@types/node@22.15.32) + '@inquirer/number': 3.0.15(@types/node@22.15.32) + '@inquirer/password': 4.0.15(@types/node@22.15.32) + '@inquirer/rawlist': 4.1.3(@types/node@22.15.32) + '@inquirer/search': 3.0.15(@types/node@22.15.32) + '@inquirer/select': 4.2.3(@types/node@22.15.32) + optionalDependencies: + '@types/node': 22.15.32 + + '@inquirer/prompts@7.5.3(@types/node@24.0.3)': + dependencies: + '@inquirer/checkbox': 4.1.8(@types/node@24.0.3) + '@inquirer/confirm': 5.1.12(@types/node@24.0.3) + '@inquirer/editor': 4.2.13(@types/node@24.0.3) + '@inquirer/expand': 4.0.15(@types/node@24.0.3) + '@inquirer/input': 4.1.12(@types/node@24.0.3) + '@inquirer/number': 3.0.15(@types/node@24.0.3) + '@inquirer/password': 4.0.15(@types/node@24.0.3) + '@inquirer/rawlist': 4.1.3(@types/node@24.0.3) + '@inquirer/search': 3.0.15(@types/node@24.0.3) + '@inquirer/select': 4.2.3(@types/node@24.0.3) + optionalDependencies: + '@types/node': 24.0.3 + + '@inquirer/rawlist@4.1.3(@types/node@22.15.32)': + dependencies: + '@inquirer/core': 10.1.13(@types/node@22.15.32) + '@inquirer/type': 3.0.7(@types/node@22.15.32) + yoctocolors-cjs: 2.1.2 + optionalDependencies: + '@types/node': 22.15.32 + + '@inquirer/rawlist@4.1.3(@types/node@24.0.3)': + dependencies: + '@inquirer/core': 10.1.13(@types/node@24.0.3) + '@inquirer/type': 3.0.7(@types/node@24.0.3) + yoctocolors-cjs: 2.1.2 + optionalDependencies: + '@types/node': 24.0.3 + + '@inquirer/search@3.0.15(@types/node@22.15.32)': + dependencies: + '@inquirer/core': 10.1.13(@types/node@22.15.32) + '@inquirer/figures': 1.0.12 + '@inquirer/type': 3.0.7(@types/node@22.15.32) + yoctocolors-cjs: 2.1.2 + optionalDependencies: + '@types/node': 22.15.32 + + '@inquirer/search@3.0.15(@types/node@24.0.3)': + dependencies: + '@inquirer/core': 10.1.13(@types/node@24.0.3) + '@inquirer/figures': 1.0.12 + '@inquirer/type': 3.0.7(@types/node@24.0.3) + yoctocolors-cjs: 2.1.2 + optionalDependencies: + '@types/node': 24.0.3 + + '@inquirer/select@4.2.3(@types/node@22.15.32)': + dependencies: + '@inquirer/core': 10.1.13(@types/node@22.15.32) + '@inquirer/figures': 1.0.12 + '@inquirer/type': 3.0.7(@types/node@22.15.32) + ansi-escapes: 4.3.2 + yoctocolors-cjs: 2.1.2 + optionalDependencies: + '@types/node': 22.15.32 + + '@inquirer/select@4.2.3(@types/node@24.0.3)': + dependencies: + '@inquirer/core': 10.1.13(@types/node@24.0.3) + '@inquirer/figures': 1.0.12 + '@inquirer/type': 3.0.7(@types/node@24.0.3) + ansi-escapes: 4.3.2 + yoctocolors-cjs: 2.1.2 + optionalDependencies: + '@types/node': 24.0.3 + + '@inquirer/type@3.0.7(@types/node@22.15.32)': + optionalDependencies: + '@types/node': 22.15.32 + + '@inquirer/type@3.0.7(@types/node@24.0.3)': + optionalDependencies: + '@types/node': 24.0.3 + + '@ioredis/commands@1.2.0': {} + + '@isaacs/balanced-match@4.0.1': {} + + '@isaacs/brace-expansion@5.0.0': + dependencies: + '@isaacs/balanced-match': 4.0.1 + + '@isaacs/cliui@8.0.2': + dependencies: + string-width: 5.1.2 + string-width-cjs: string-width@4.2.3 + strip-ansi: 7.1.0 + strip-ansi-cjs: strip-ansi@6.0.1 + wrap-ansi: 8.1.0 + wrap-ansi-cjs: wrap-ansi@7.0.0 + + '@isaacs/fs-minipass@4.0.1': + dependencies: + minipass: 7.1.2 + + '@jridgewell/gen-mapping@0.3.8': + dependencies: + '@jridgewell/set-array': 1.2.1 + '@jridgewell/sourcemap-codec': 1.5.0 + '@jridgewell/trace-mapping': 0.3.25 + + '@jridgewell/resolve-uri@3.1.2': {} + + '@jridgewell/set-array@1.2.1': {} + + '@jridgewell/sourcemap-codec@1.5.0': {} + + '@jridgewell/trace-mapping@0.3.25': + dependencies: + '@jridgewell/resolve-uri': 3.1.2 + '@jridgewell/sourcemap-codec': 1.5.0 + + '@jridgewell/trace-mapping@0.3.9': + dependencies: + '@jridgewell/resolve-uri': 3.1.2 + '@jridgewell/sourcemap-codec': 1.5.0 + + '@levischuck/tiny-cbor@0.2.11': {} + + '@logtail/core@0.5.4': + dependencies: + '@logtail/tools': 0.5.4 + '@logtail/types': 0.5.3 + serialize-error: 8.1.0 + + '@logtail/node@0.5.5': + dependencies: + '@logtail/core': 0.5.4 + '@logtail/types': 0.5.3 + '@msgpack/msgpack': 2.8.0 + '@types/stack-trace': 0.0.33 + minimatch: 9.0.5 + stack-trace: 0.0.10 + + '@logtail/tools@0.5.4': + dependencies: + '@logtail/types': 0.5.3 + + '@logtail/types@0.5.3': {} + + '@msgpack/msgpack@2.8.0': {} + + '@msgpackr-extract/msgpackr-extract-darwin-arm64@3.0.3': + optional: true + + '@msgpackr-extract/msgpackr-extract-darwin-x64@3.0.3': + optional: true + + '@msgpackr-extract/msgpackr-extract-linux-arm64@3.0.3': + optional: true + + '@msgpackr-extract/msgpackr-extract-linux-arm@3.0.3': + optional: true + + '@msgpackr-extract/msgpackr-extract-linux-x64@3.0.3': + optional: true + + '@msgpackr-extract/msgpackr-extract-win32-x64@3.0.3': + optional: true + + '@next/env@15.3.3': {} + + '@next/swc-darwin-arm64@15.3.3': + optional: true + + '@next/swc-darwin-x64@15.3.3': + optional: true + + '@next/swc-linux-arm64-gnu@15.3.3': + optional: true + + '@next/swc-linux-arm64-musl@15.3.3': + optional: true + + '@next/swc-linux-x64-gnu@15.3.3': + optional: true + + '@next/swc-linux-x64-musl@15.3.3': + optional: true + + '@next/swc-win32-arm64-msvc@15.3.3': + optional: true + + '@next/swc-win32-x64-msvc@15.3.3': + optional: true + + '@noble/ciphers@0.6.0': {} + + '@noble/hashes@1.8.0': {} + + '@nodelib/fs.scandir@2.1.5': + dependencies: + '@nodelib/fs.stat': 2.0.5 + run-parallel: 1.2.0 + + '@nodelib/fs.stat@2.0.5': {} + + '@nodelib/fs.walk@1.2.8': + dependencies: + '@nodelib/fs.scandir': 2.1.5 + fastq: 1.19.1 + + '@opentelemetry/api@1.9.0': {} + + '@paralleldrive/cuid2@2.2.2': + dependencies: + '@noble/hashes': 1.8.0 + + '@peculiar/asn1-android@2.3.16': + dependencies: + '@peculiar/asn1-schema': 2.3.15 + asn1js: 3.0.6 + tslib: 2.8.1 + + '@peculiar/asn1-ecc@2.3.15': + dependencies: + '@peculiar/asn1-schema': 2.3.15 + '@peculiar/asn1-x509': 2.3.15 + asn1js: 3.0.6 + tslib: 2.8.1 + + '@peculiar/asn1-rsa@2.3.15': + dependencies: + '@peculiar/asn1-schema': 2.3.15 + '@peculiar/asn1-x509': 2.3.15 + asn1js: 3.0.6 + tslib: 2.8.1 + + '@peculiar/asn1-schema@2.3.15': + dependencies: + asn1js: 3.0.6 + pvtsutils: 1.3.6 + tslib: 2.8.1 + + '@peculiar/asn1-x509@2.3.15': + dependencies: + '@peculiar/asn1-schema': 2.3.15 + asn1js: 3.0.6 + pvtsutils: 1.3.6 + tslib: 2.8.1 + + '@pkgjs/parseargs@0.11.0': + optional: true + + '@puppeteer/browsers@2.10.5': + dependencies: + debug: 4.4.1 + extract-zip: 2.0.1 + progress: 2.0.3 + proxy-agent: 6.5.0 + semver: 7.7.2 + tar-fs: 3.0.9 + yargs: 17.7.2 + transitivePeerDependencies: + - bare-buffer + - supports-color + + '@radix-ui/number@1.1.1': {} + + '@radix-ui/primitive@1.1.2': {} + + '@radix-ui/react-accordion@1.2.11(@types/react-dom@18.3.7(@types/react@18.3.23))(@types/react@18.3.23)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)': + dependencies: + '@radix-ui/primitive': 1.1.2 + '@radix-ui/react-collapsible': 1.1.11(@types/react-dom@18.3.7(@types/react@18.3.23))(@types/react@18.3.23)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@radix-ui/react-collection': 1.1.7(@types/react-dom@18.3.7(@types/react@18.3.23))(@types/react@18.3.23)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@radix-ui/react-compose-refs': 1.1.2(@types/react@18.3.23)(react@18.3.1) + '@radix-ui/react-context': 1.1.2(@types/react@18.3.23)(react@18.3.1) + '@radix-ui/react-direction': 1.1.1(@types/react@18.3.23)(react@18.3.1) + '@radix-ui/react-id': 1.1.1(@types/react@18.3.23)(react@18.3.1) + '@radix-ui/react-primitive': 2.1.3(@types/react-dom@18.3.7(@types/react@18.3.23))(@types/react@18.3.23)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@radix-ui/react-use-controllable-state': 1.2.2(@types/react@18.3.23)(react@18.3.1) + react: 18.3.1 + react-dom: 18.3.1(react@18.3.1) + optionalDependencies: + '@types/react': 18.3.23 + '@types/react-dom': 18.3.7(@types/react@18.3.23) + + '@radix-ui/react-arrow@1.1.7(@types/react-dom@18.3.7(@types/react@18.3.23))(@types/react@18.3.23)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)': + dependencies: + '@radix-ui/react-primitive': 2.1.3(@types/react-dom@18.3.7(@types/react@18.3.23))(@types/react@18.3.23)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + react: 18.3.1 + react-dom: 18.3.1(react@18.3.1) + optionalDependencies: + '@types/react': 18.3.23 + '@types/react-dom': 18.3.7(@types/react@18.3.23) + + '@radix-ui/react-checkbox@1.3.2(@types/react-dom@18.3.7(@types/react@18.3.23))(@types/react@18.3.23)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)': + dependencies: + '@radix-ui/primitive': 1.1.2 + '@radix-ui/react-compose-refs': 1.1.2(@types/react@18.3.23)(react@18.3.1) + '@radix-ui/react-context': 1.1.2(@types/react@18.3.23)(react@18.3.1) + '@radix-ui/react-presence': 1.1.4(@types/react-dom@18.3.7(@types/react@18.3.23))(@types/react@18.3.23)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@radix-ui/react-primitive': 2.1.3(@types/react-dom@18.3.7(@types/react@18.3.23))(@types/react@18.3.23)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@radix-ui/react-use-controllable-state': 1.2.2(@types/react@18.3.23)(react@18.3.1) + '@radix-ui/react-use-previous': 1.1.1(@types/react@18.3.23)(react@18.3.1) + '@radix-ui/react-use-size': 1.1.1(@types/react@18.3.23)(react@18.3.1) + react: 18.3.1 + react-dom: 18.3.1(react@18.3.1) + optionalDependencies: + '@types/react': 18.3.23 + '@types/react-dom': 18.3.7(@types/react@18.3.23) + + '@radix-ui/react-collapsible@1.1.11(@types/react-dom@18.3.7(@types/react@18.3.23))(@types/react@18.3.23)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)': + dependencies: + '@radix-ui/primitive': 1.1.2 + '@radix-ui/react-compose-refs': 1.1.2(@types/react@18.3.23)(react@18.3.1) + '@radix-ui/react-context': 1.1.2(@types/react@18.3.23)(react@18.3.1) + '@radix-ui/react-id': 1.1.1(@types/react@18.3.23)(react@18.3.1) + '@radix-ui/react-presence': 1.1.4(@types/react-dom@18.3.7(@types/react@18.3.23))(@types/react@18.3.23)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@radix-ui/react-primitive': 2.1.3(@types/react-dom@18.3.7(@types/react@18.3.23))(@types/react@18.3.23)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@radix-ui/react-use-controllable-state': 1.2.2(@types/react@18.3.23)(react@18.3.1) + '@radix-ui/react-use-layout-effect': 1.1.1(@types/react@18.3.23)(react@18.3.1) + react: 18.3.1 + react-dom: 18.3.1(react@18.3.1) + optionalDependencies: + '@types/react': 18.3.23 + '@types/react-dom': 18.3.7(@types/react@18.3.23) + + '@radix-ui/react-collection@1.1.7(@types/react-dom@18.3.7(@types/react@18.3.23))(@types/react@18.3.23)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)': + dependencies: + '@radix-ui/react-compose-refs': 1.1.2(@types/react@18.3.23)(react@18.3.1) + '@radix-ui/react-context': 1.1.2(@types/react@18.3.23)(react@18.3.1) + '@radix-ui/react-primitive': 2.1.3(@types/react-dom@18.3.7(@types/react@18.3.23))(@types/react@18.3.23)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@radix-ui/react-slot': 1.2.3(@types/react@18.3.23)(react@18.3.1) + react: 18.3.1 + react-dom: 18.3.1(react@18.3.1) + optionalDependencies: + '@types/react': 18.3.23 + '@types/react-dom': 18.3.7(@types/react@18.3.23) + + '@radix-ui/react-compose-refs@1.1.2(@types/react@18.3.23)(react@18.3.1)': + dependencies: + react: 18.3.1 + optionalDependencies: + '@types/react': 18.3.23 + + '@radix-ui/react-context@1.1.2(@types/react@18.3.23)(react@18.3.1)': + dependencies: + react: 18.3.1 + optionalDependencies: + '@types/react': 18.3.23 + + '@radix-ui/react-dialog@1.1.14(@types/react-dom@18.3.7(@types/react@18.3.23))(@types/react@18.3.23)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)': + dependencies: + '@radix-ui/primitive': 1.1.2 + '@radix-ui/react-compose-refs': 1.1.2(@types/react@18.3.23)(react@18.3.1) + '@radix-ui/react-context': 1.1.2(@types/react@18.3.23)(react@18.3.1) + '@radix-ui/react-dismissable-layer': 1.1.10(@types/react-dom@18.3.7(@types/react@18.3.23))(@types/react@18.3.23)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@radix-ui/react-focus-guards': 1.1.2(@types/react@18.3.23)(react@18.3.1) + '@radix-ui/react-focus-scope': 1.1.7(@types/react-dom@18.3.7(@types/react@18.3.23))(@types/react@18.3.23)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@radix-ui/react-id': 1.1.1(@types/react@18.3.23)(react@18.3.1) + '@radix-ui/react-portal': 1.1.9(@types/react-dom@18.3.7(@types/react@18.3.23))(@types/react@18.3.23)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@radix-ui/react-presence': 1.1.4(@types/react-dom@18.3.7(@types/react@18.3.23))(@types/react@18.3.23)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@radix-ui/react-primitive': 2.1.3(@types/react-dom@18.3.7(@types/react@18.3.23))(@types/react@18.3.23)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@radix-ui/react-slot': 1.2.3(@types/react@18.3.23)(react@18.3.1) + '@radix-ui/react-use-controllable-state': 1.2.2(@types/react@18.3.23)(react@18.3.1) + aria-hidden: 1.2.6 + react: 18.3.1 + react-dom: 18.3.1(react@18.3.1) + react-remove-scroll: 2.7.1(@types/react@18.3.23)(react@18.3.1) + optionalDependencies: + '@types/react': 18.3.23 + '@types/react-dom': 18.3.7(@types/react@18.3.23) + + '@radix-ui/react-direction@1.1.1(@types/react@18.3.23)(react@18.3.1)': + dependencies: + react: 18.3.1 + optionalDependencies: + '@types/react': 18.3.23 + + '@radix-ui/react-dismissable-layer@1.1.10(@types/react-dom@18.3.7(@types/react@18.3.23))(@types/react@18.3.23)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)': + dependencies: + '@radix-ui/primitive': 1.1.2 + '@radix-ui/react-compose-refs': 1.1.2(@types/react@18.3.23)(react@18.3.1) + '@radix-ui/react-primitive': 2.1.3(@types/react-dom@18.3.7(@types/react@18.3.23))(@types/react@18.3.23)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@radix-ui/react-use-callback-ref': 1.1.1(@types/react@18.3.23)(react@18.3.1) + '@radix-ui/react-use-escape-keydown': 1.1.1(@types/react@18.3.23)(react@18.3.1) + react: 18.3.1 + react-dom: 18.3.1(react@18.3.1) + optionalDependencies: + '@types/react': 18.3.23 + '@types/react-dom': 18.3.7(@types/react@18.3.23) + + '@radix-ui/react-dropdown-menu@2.1.15(@types/react-dom@18.3.7(@types/react@18.3.23))(@types/react@18.3.23)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)': + dependencies: + '@radix-ui/primitive': 1.1.2 + '@radix-ui/react-compose-refs': 1.1.2(@types/react@18.3.23)(react@18.3.1) + '@radix-ui/react-context': 1.1.2(@types/react@18.3.23)(react@18.3.1) + '@radix-ui/react-id': 1.1.1(@types/react@18.3.23)(react@18.3.1) + '@radix-ui/react-menu': 2.1.15(@types/react-dom@18.3.7(@types/react@18.3.23))(@types/react@18.3.23)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@radix-ui/react-primitive': 2.1.3(@types/react-dom@18.3.7(@types/react@18.3.23))(@types/react@18.3.23)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@radix-ui/react-use-controllable-state': 1.2.2(@types/react@18.3.23)(react@18.3.1) + react: 18.3.1 + react-dom: 18.3.1(react@18.3.1) + optionalDependencies: + '@types/react': 18.3.23 + '@types/react-dom': 18.3.7(@types/react@18.3.23) + + '@radix-ui/react-focus-guards@1.1.2(@types/react@18.3.23)(react@18.3.1)': + dependencies: + react: 18.3.1 + optionalDependencies: + '@types/react': 18.3.23 + + '@radix-ui/react-focus-scope@1.1.7(@types/react-dom@18.3.7(@types/react@18.3.23))(@types/react@18.3.23)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)': + dependencies: + '@radix-ui/react-compose-refs': 1.1.2(@types/react@18.3.23)(react@18.3.1) + '@radix-ui/react-primitive': 2.1.3(@types/react-dom@18.3.7(@types/react@18.3.23))(@types/react@18.3.23)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@radix-ui/react-use-callback-ref': 1.1.1(@types/react@18.3.23)(react@18.3.1) + react: 18.3.1 + react-dom: 18.3.1(react@18.3.1) + optionalDependencies: + '@types/react': 18.3.23 + '@types/react-dom': 18.3.7(@types/react@18.3.23) + + '@radix-ui/react-id@1.1.1(@types/react@18.3.23)(react@18.3.1)': + dependencies: + '@radix-ui/react-use-layout-effect': 1.1.1(@types/react@18.3.23)(react@18.3.1) + react: 18.3.1 + optionalDependencies: + '@types/react': 18.3.23 + + '@radix-ui/react-menu@2.1.15(@types/react-dom@18.3.7(@types/react@18.3.23))(@types/react@18.3.23)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)': + dependencies: + '@radix-ui/primitive': 1.1.2 + '@radix-ui/react-collection': 1.1.7(@types/react-dom@18.3.7(@types/react@18.3.23))(@types/react@18.3.23)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@radix-ui/react-compose-refs': 1.1.2(@types/react@18.3.23)(react@18.3.1) + '@radix-ui/react-context': 1.1.2(@types/react@18.3.23)(react@18.3.1) + '@radix-ui/react-direction': 1.1.1(@types/react@18.3.23)(react@18.3.1) + '@radix-ui/react-dismissable-layer': 1.1.10(@types/react-dom@18.3.7(@types/react@18.3.23))(@types/react@18.3.23)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@radix-ui/react-focus-guards': 1.1.2(@types/react@18.3.23)(react@18.3.1) + '@radix-ui/react-focus-scope': 1.1.7(@types/react-dom@18.3.7(@types/react@18.3.23))(@types/react@18.3.23)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@radix-ui/react-id': 1.1.1(@types/react@18.3.23)(react@18.3.1) + '@radix-ui/react-popper': 1.2.7(@types/react-dom@18.3.7(@types/react@18.3.23))(@types/react@18.3.23)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@radix-ui/react-portal': 1.1.9(@types/react-dom@18.3.7(@types/react@18.3.23))(@types/react@18.3.23)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@radix-ui/react-presence': 1.1.4(@types/react-dom@18.3.7(@types/react@18.3.23))(@types/react@18.3.23)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@radix-ui/react-primitive': 2.1.3(@types/react-dom@18.3.7(@types/react@18.3.23))(@types/react@18.3.23)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@radix-ui/react-roving-focus': 1.1.10(@types/react-dom@18.3.7(@types/react@18.3.23))(@types/react@18.3.23)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@radix-ui/react-slot': 1.2.3(@types/react@18.3.23)(react@18.3.1) + '@radix-ui/react-use-callback-ref': 1.1.1(@types/react@18.3.23)(react@18.3.1) + aria-hidden: 1.2.6 + react: 18.3.1 + react-dom: 18.3.1(react@18.3.1) + react-remove-scroll: 2.7.1(@types/react@18.3.23)(react@18.3.1) + optionalDependencies: + '@types/react': 18.3.23 + '@types/react-dom': 18.3.7(@types/react@18.3.23) + + '@radix-ui/react-popover@1.1.14(@types/react-dom@18.3.7(@types/react@18.3.23))(@types/react@18.3.23)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)': + dependencies: + '@radix-ui/primitive': 1.1.2 + '@radix-ui/react-compose-refs': 1.1.2(@types/react@18.3.23)(react@18.3.1) + '@radix-ui/react-context': 1.1.2(@types/react@18.3.23)(react@18.3.1) + '@radix-ui/react-dismissable-layer': 1.1.10(@types/react-dom@18.3.7(@types/react@18.3.23))(@types/react@18.3.23)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@radix-ui/react-focus-guards': 1.1.2(@types/react@18.3.23)(react@18.3.1) + '@radix-ui/react-focus-scope': 1.1.7(@types/react-dom@18.3.7(@types/react@18.3.23))(@types/react@18.3.23)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@radix-ui/react-id': 1.1.1(@types/react@18.3.23)(react@18.3.1) + '@radix-ui/react-popper': 1.2.7(@types/react-dom@18.3.7(@types/react@18.3.23))(@types/react@18.3.23)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@radix-ui/react-portal': 1.1.9(@types/react-dom@18.3.7(@types/react@18.3.23))(@types/react@18.3.23)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@radix-ui/react-presence': 1.1.4(@types/react-dom@18.3.7(@types/react@18.3.23))(@types/react@18.3.23)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@radix-ui/react-primitive': 2.1.3(@types/react-dom@18.3.7(@types/react@18.3.23))(@types/react@18.3.23)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@radix-ui/react-slot': 1.2.3(@types/react@18.3.23)(react@18.3.1) + '@radix-ui/react-use-controllable-state': 1.2.2(@types/react@18.3.23)(react@18.3.1) + aria-hidden: 1.2.6 + react: 18.3.1 + react-dom: 18.3.1(react@18.3.1) + react-remove-scroll: 2.7.1(@types/react@18.3.23)(react@18.3.1) + optionalDependencies: + '@types/react': 18.3.23 + '@types/react-dom': 18.3.7(@types/react@18.3.23) + + '@radix-ui/react-popper@1.2.7(@types/react-dom@18.3.7(@types/react@18.3.23))(@types/react@18.3.23)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)': + dependencies: + '@floating-ui/react-dom': 2.1.3(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@radix-ui/react-arrow': 1.1.7(@types/react-dom@18.3.7(@types/react@18.3.23))(@types/react@18.3.23)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@radix-ui/react-compose-refs': 1.1.2(@types/react@18.3.23)(react@18.3.1) + '@radix-ui/react-context': 1.1.2(@types/react@18.3.23)(react@18.3.1) + '@radix-ui/react-primitive': 2.1.3(@types/react-dom@18.3.7(@types/react@18.3.23))(@types/react@18.3.23)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@radix-ui/react-use-callback-ref': 1.1.1(@types/react@18.3.23)(react@18.3.1) + '@radix-ui/react-use-layout-effect': 1.1.1(@types/react@18.3.23)(react@18.3.1) + '@radix-ui/react-use-rect': 1.1.1(@types/react@18.3.23)(react@18.3.1) + '@radix-ui/react-use-size': 1.1.1(@types/react@18.3.23)(react@18.3.1) + '@radix-ui/rect': 1.1.1 + react: 18.3.1 + react-dom: 18.3.1(react@18.3.1) + optionalDependencies: + '@types/react': 18.3.23 + '@types/react-dom': 18.3.7(@types/react@18.3.23) + + '@radix-ui/react-portal@1.1.9(@types/react-dom@18.3.7(@types/react@18.3.23))(@types/react@18.3.23)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)': + dependencies: + '@radix-ui/react-primitive': 2.1.3(@types/react-dom@18.3.7(@types/react@18.3.23))(@types/react@18.3.23)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@radix-ui/react-use-layout-effect': 1.1.1(@types/react@18.3.23)(react@18.3.1) + react: 18.3.1 + react-dom: 18.3.1(react@18.3.1) + optionalDependencies: + '@types/react': 18.3.23 + '@types/react-dom': 18.3.7(@types/react@18.3.23) + + '@radix-ui/react-presence@1.1.4(@types/react-dom@18.3.7(@types/react@18.3.23))(@types/react@18.3.23)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)': + dependencies: + '@radix-ui/react-compose-refs': 1.1.2(@types/react@18.3.23)(react@18.3.1) + '@radix-ui/react-use-layout-effect': 1.1.1(@types/react@18.3.23)(react@18.3.1) + react: 18.3.1 + react-dom: 18.3.1(react@18.3.1) + optionalDependencies: + '@types/react': 18.3.23 + '@types/react-dom': 18.3.7(@types/react@18.3.23) + + '@radix-ui/react-primitive@2.1.3(@types/react-dom@18.3.7(@types/react@18.3.23))(@types/react@18.3.23)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)': + dependencies: + '@radix-ui/react-slot': 1.2.3(@types/react@18.3.23)(react@18.3.1) + react: 18.3.1 + react-dom: 18.3.1(react@18.3.1) + optionalDependencies: + '@types/react': 18.3.23 + '@types/react-dom': 18.3.7(@types/react@18.3.23) + + '@radix-ui/react-roving-focus@1.1.10(@types/react-dom@18.3.7(@types/react@18.3.23))(@types/react@18.3.23)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)': + dependencies: + '@radix-ui/primitive': 1.1.2 + '@radix-ui/react-collection': 1.1.7(@types/react-dom@18.3.7(@types/react@18.3.23))(@types/react@18.3.23)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@radix-ui/react-compose-refs': 1.1.2(@types/react@18.3.23)(react@18.3.1) + '@radix-ui/react-context': 1.1.2(@types/react@18.3.23)(react@18.3.1) + '@radix-ui/react-direction': 1.1.1(@types/react@18.3.23)(react@18.3.1) + '@radix-ui/react-id': 1.1.1(@types/react@18.3.23)(react@18.3.1) + '@radix-ui/react-primitive': 2.1.3(@types/react-dom@18.3.7(@types/react@18.3.23))(@types/react@18.3.23)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@radix-ui/react-use-callback-ref': 1.1.1(@types/react@18.3.23)(react@18.3.1) + '@radix-ui/react-use-controllable-state': 1.2.2(@types/react@18.3.23)(react@18.3.1) + react: 18.3.1 + react-dom: 18.3.1(react@18.3.1) + optionalDependencies: + '@types/react': 18.3.23 + '@types/react-dom': 18.3.7(@types/react@18.3.23) + + '@radix-ui/react-scroll-area@1.2.9(@types/react-dom@18.3.7(@types/react@18.3.23))(@types/react@18.3.23)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)': + dependencies: + '@radix-ui/number': 1.1.1 + '@radix-ui/primitive': 1.1.2 + '@radix-ui/react-compose-refs': 1.1.2(@types/react@18.3.23)(react@18.3.1) + '@radix-ui/react-context': 1.1.2(@types/react@18.3.23)(react@18.3.1) + '@radix-ui/react-direction': 1.1.1(@types/react@18.3.23)(react@18.3.1) + '@radix-ui/react-presence': 1.1.4(@types/react-dom@18.3.7(@types/react@18.3.23))(@types/react@18.3.23)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@radix-ui/react-primitive': 2.1.3(@types/react-dom@18.3.7(@types/react@18.3.23))(@types/react@18.3.23)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@radix-ui/react-use-callback-ref': 1.1.1(@types/react@18.3.23)(react@18.3.1) + '@radix-ui/react-use-layout-effect': 1.1.1(@types/react@18.3.23)(react@18.3.1) + react: 18.3.1 + react-dom: 18.3.1(react@18.3.1) + optionalDependencies: + '@types/react': 18.3.23 + '@types/react-dom': 18.3.7(@types/react@18.3.23) + + '@radix-ui/react-select@2.2.5(@types/react-dom@18.3.7(@types/react@18.3.23))(@types/react@18.3.23)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)': + dependencies: + '@radix-ui/number': 1.1.1 + '@radix-ui/primitive': 1.1.2 + '@radix-ui/react-collection': 1.1.7(@types/react-dom@18.3.7(@types/react@18.3.23))(@types/react@18.3.23)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@radix-ui/react-compose-refs': 1.1.2(@types/react@18.3.23)(react@18.3.1) + '@radix-ui/react-context': 1.1.2(@types/react@18.3.23)(react@18.3.1) + '@radix-ui/react-direction': 1.1.1(@types/react@18.3.23)(react@18.3.1) + '@radix-ui/react-dismissable-layer': 1.1.10(@types/react-dom@18.3.7(@types/react@18.3.23))(@types/react@18.3.23)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@radix-ui/react-focus-guards': 1.1.2(@types/react@18.3.23)(react@18.3.1) + '@radix-ui/react-focus-scope': 1.1.7(@types/react-dom@18.3.7(@types/react@18.3.23))(@types/react@18.3.23)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@radix-ui/react-id': 1.1.1(@types/react@18.3.23)(react@18.3.1) + '@radix-ui/react-popper': 1.2.7(@types/react-dom@18.3.7(@types/react@18.3.23))(@types/react@18.3.23)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@radix-ui/react-portal': 1.1.9(@types/react-dom@18.3.7(@types/react@18.3.23))(@types/react@18.3.23)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@radix-ui/react-primitive': 2.1.3(@types/react-dom@18.3.7(@types/react@18.3.23))(@types/react@18.3.23)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@radix-ui/react-slot': 1.2.3(@types/react@18.3.23)(react@18.3.1) + '@radix-ui/react-use-callback-ref': 1.1.1(@types/react@18.3.23)(react@18.3.1) + '@radix-ui/react-use-controllable-state': 1.2.2(@types/react@18.3.23)(react@18.3.1) + '@radix-ui/react-use-layout-effect': 1.1.1(@types/react@18.3.23)(react@18.3.1) + '@radix-ui/react-use-previous': 1.1.1(@types/react@18.3.23)(react@18.3.1) + '@radix-ui/react-visually-hidden': 1.2.3(@types/react-dom@18.3.7(@types/react@18.3.23))(@types/react@18.3.23)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + aria-hidden: 1.2.6 + react: 18.3.1 + react-dom: 18.3.1(react@18.3.1) + react-remove-scroll: 2.7.1(@types/react@18.3.23)(react@18.3.1) + optionalDependencies: + '@types/react': 18.3.23 + '@types/react-dom': 18.3.7(@types/react@18.3.23) + + '@radix-ui/react-separator@1.1.7(@types/react-dom@18.3.7(@types/react@18.3.23))(@types/react@18.3.23)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)': + dependencies: + '@radix-ui/react-primitive': 2.1.3(@types/react-dom@18.3.7(@types/react@18.3.23))(@types/react@18.3.23)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + react: 18.3.1 + react-dom: 18.3.1(react@18.3.1) + optionalDependencies: + '@types/react': 18.3.23 + '@types/react-dom': 18.3.7(@types/react@18.3.23) + + '@radix-ui/react-slot@1.2.3(@types/react@18.3.23)(react@18.3.1)': + dependencies: + '@radix-ui/react-compose-refs': 1.1.2(@types/react@18.3.23)(react@18.3.1) + react: 18.3.1 + optionalDependencies: + '@types/react': 18.3.23 + + '@radix-ui/react-switch@1.2.5(@types/react-dom@18.3.7(@types/react@18.3.23))(@types/react@18.3.23)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)': + dependencies: + '@radix-ui/primitive': 1.1.2 + '@radix-ui/react-compose-refs': 1.1.2(@types/react@18.3.23)(react@18.3.1) + '@radix-ui/react-context': 1.1.2(@types/react@18.3.23)(react@18.3.1) + '@radix-ui/react-primitive': 2.1.3(@types/react-dom@18.3.7(@types/react@18.3.23))(@types/react@18.3.23)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@radix-ui/react-use-controllable-state': 1.2.2(@types/react@18.3.23)(react@18.3.1) + '@radix-ui/react-use-previous': 1.1.1(@types/react@18.3.23)(react@18.3.1) + '@radix-ui/react-use-size': 1.1.1(@types/react@18.3.23)(react@18.3.1) + react: 18.3.1 + react-dom: 18.3.1(react@18.3.1) + optionalDependencies: + '@types/react': 18.3.23 + '@types/react-dom': 18.3.7(@types/react@18.3.23) + + '@radix-ui/react-tabs@1.1.12(@types/react-dom@18.3.7(@types/react@18.3.23))(@types/react@18.3.23)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)': + dependencies: + '@radix-ui/primitive': 1.1.2 + '@radix-ui/react-context': 1.1.2(@types/react@18.3.23)(react@18.3.1) + '@radix-ui/react-direction': 1.1.1(@types/react@18.3.23)(react@18.3.1) + '@radix-ui/react-id': 1.1.1(@types/react@18.3.23)(react@18.3.1) + '@radix-ui/react-presence': 1.1.4(@types/react-dom@18.3.7(@types/react@18.3.23))(@types/react@18.3.23)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@radix-ui/react-primitive': 2.1.3(@types/react-dom@18.3.7(@types/react@18.3.23))(@types/react@18.3.23)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@radix-ui/react-roving-focus': 1.1.10(@types/react-dom@18.3.7(@types/react@18.3.23))(@types/react@18.3.23)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@radix-ui/react-use-controllable-state': 1.2.2(@types/react@18.3.23)(react@18.3.1) + react: 18.3.1 + react-dom: 18.3.1(react@18.3.1) + optionalDependencies: + '@types/react': 18.3.23 + '@types/react-dom': 18.3.7(@types/react@18.3.23) + + '@radix-ui/react-tooltip@1.2.7(@types/react-dom@18.3.7(@types/react@18.3.23))(@types/react@18.3.23)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)': + dependencies: + '@radix-ui/primitive': 1.1.2 + '@radix-ui/react-compose-refs': 1.1.2(@types/react@18.3.23)(react@18.3.1) + '@radix-ui/react-context': 1.1.2(@types/react@18.3.23)(react@18.3.1) + '@radix-ui/react-dismissable-layer': 1.1.10(@types/react-dom@18.3.7(@types/react@18.3.23))(@types/react@18.3.23)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@radix-ui/react-id': 1.1.1(@types/react@18.3.23)(react@18.3.1) + '@radix-ui/react-popper': 1.2.7(@types/react-dom@18.3.7(@types/react@18.3.23))(@types/react@18.3.23)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@radix-ui/react-portal': 1.1.9(@types/react-dom@18.3.7(@types/react@18.3.23))(@types/react@18.3.23)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@radix-ui/react-presence': 1.1.4(@types/react-dom@18.3.7(@types/react@18.3.23))(@types/react@18.3.23)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@radix-ui/react-primitive': 2.1.3(@types/react-dom@18.3.7(@types/react@18.3.23))(@types/react@18.3.23)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@radix-ui/react-slot': 1.2.3(@types/react@18.3.23)(react@18.3.1) + '@radix-ui/react-use-controllable-state': 1.2.2(@types/react@18.3.23)(react@18.3.1) + '@radix-ui/react-visually-hidden': 1.2.3(@types/react-dom@18.3.7(@types/react@18.3.23))(@types/react@18.3.23)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + react: 18.3.1 + react-dom: 18.3.1(react@18.3.1) + optionalDependencies: + '@types/react': 18.3.23 + '@types/react-dom': 18.3.7(@types/react@18.3.23) + + '@radix-ui/react-use-callback-ref@1.1.1(@types/react@18.3.23)(react@18.3.1)': + dependencies: + react: 18.3.1 + optionalDependencies: + '@types/react': 18.3.23 + + '@radix-ui/react-use-controllable-state@1.2.2(@types/react@18.3.23)(react@18.3.1)': + dependencies: + '@radix-ui/react-use-effect-event': 0.0.2(@types/react@18.3.23)(react@18.3.1) + '@radix-ui/react-use-layout-effect': 1.1.1(@types/react@18.3.23)(react@18.3.1) + react: 18.3.1 + optionalDependencies: + '@types/react': 18.3.23 + + '@radix-ui/react-use-effect-event@0.0.2(@types/react@18.3.23)(react@18.3.1)': + dependencies: + '@radix-ui/react-use-layout-effect': 1.1.1(@types/react@18.3.23)(react@18.3.1) + react: 18.3.1 + optionalDependencies: + '@types/react': 18.3.23 + + '@radix-ui/react-use-escape-keydown@1.1.1(@types/react@18.3.23)(react@18.3.1)': + dependencies: + '@radix-ui/react-use-callback-ref': 1.1.1(@types/react@18.3.23)(react@18.3.1) + react: 18.3.1 + optionalDependencies: + '@types/react': 18.3.23 + + '@radix-ui/react-use-layout-effect@1.1.1(@types/react@18.3.23)(react@18.3.1)': + dependencies: + react: 18.3.1 + optionalDependencies: + '@types/react': 18.3.23 + + '@radix-ui/react-use-previous@1.1.1(@types/react@18.3.23)(react@18.3.1)': + dependencies: + react: 18.3.1 + optionalDependencies: + '@types/react': 18.3.23 + + '@radix-ui/react-use-rect@1.1.1(@types/react@18.3.23)(react@18.3.1)': + dependencies: + '@radix-ui/rect': 1.1.1 + react: 18.3.1 + optionalDependencies: + '@types/react': 18.3.23 + + '@radix-ui/react-use-size@1.1.1(@types/react@18.3.23)(react@18.3.1)': + dependencies: + '@radix-ui/react-use-layout-effect': 1.1.1(@types/react@18.3.23)(react@18.3.1) + react: 18.3.1 + optionalDependencies: + '@types/react': 18.3.23 + + '@radix-ui/react-visually-hidden@1.2.3(@types/react-dom@18.3.7(@types/react@18.3.23))(@types/react@18.3.23)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)': + dependencies: + '@radix-ui/react-primitive': 2.1.3(@types/react-dom@18.3.7(@types/react@18.3.23))(@types/react@18.3.23)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + react: 18.3.1 + react-dom: 18.3.1(react@18.3.1) + optionalDependencies: + '@types/react': 18.3.23 + '@types/react-dom': 18.3.7(@types/react@18.3.23) + + '@radix-ui/rect@1.1.1': {} + + '@react-email/body@0.0.11(react@18.3.1)': + dependencies: + react: 18.3.1 + + '@react-email/button@0.0.19(react@18.3.1)': + dependencies: + react: 18.3.1 + + '@react-email/code-block@0.0.13(react@18.3.1)': + dependencies: + prismjs: 1.30.0 + react: 18.3.1 + + '@react-email/code-inline@0.0.5(react@18.3.1)': + dependencies: + react: 18.3.1 + + '@react-email/column@0.0.13(react@18.3.1)': + dependencies: + react: 18.3.1 + + '@react-email/components@0.0.42(react-dom@18.3.1(react@18.3.1))(react@18.3.1)': + dependencies: + '@react-email/body': 0.0.11(react@18.3.1) + '@react-email/button': 0.0.19(react@18.3.1) + '@react-email/code-block': 0.0.13(react@18.3.1) + '@react-email/code-inline': 0.0.5(react@18.3.1) + '@react-email/column': 0.0.13(react@18.3.1) + '@react-email/container': 0.0.15(react@18.3.1) + '@react-email/font': 0.0.9(react@18.3.1) + '@react-email/head': 0.0.12(react@18.3.1) + '@react-email/heading': 0.0.15(react@18.3.1) + '@react-email/hr': 0.0.11(react@18.3.1) + '@react-email/html': 0.0.11(react@18.3.1) + '@react-email/img': 0.0.11(react@18.3.1) + '@react-email/link': 0.0.12(react@18.3.1) + '@react-email/markdown': 0.0.15(react@18.3.1) + '@react-email/preview': 0.0.13(react@18.3.1) + '@react-email/render': 1.1.2(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@react-email/row': 0.0.12(react@18.3.1) + '@react-email/section': 0.0.16(react@18.3.1) + '@react-email/tailwind': 1.0.5(react@18.3.1) + '@react-email/text': 0.1.5(react@18.3.1) + react: 18.3.1 + transitivePeerDependencies: + - react-dom + + '@react-email/container@0.0.15(react@18.3.1)': + dependencies: + react: 18.3.1 + + '@react-email/font@0.0.9(react@18.3.1)': + dependencies: + react: 18.3.1 + + '@react-email/head@0.0.12(react@18.3.1)': + dependencies: + react: 18.3.1 + + '@react-email/heading@0.0.15(react@18.3.1)': + dependencies: + react: 18.3.1 + + '@react-email/hr@0.0.11(react@18.3.1)': + dependencies: + react: 18.3.1 + + '@react-email/html@0.0.11(react@18.3.1)': + dependencies: + react: 18.3.1 + + '@react-email/img@0.0.11(react@18.3.1)': + dependencies: + react: 18.3.1 + + '@react-email/link@0.0.12(react@18.3.1)': + dependencies: + react: 18.3.1 + + '@react-email/markdown@0.0.15(react@18.3.1)': + dependencies: + md-to-react-email: 5.0.5(react@18.3.1) + react: 18.3.1 + + '@react-email/preview@0.0.13(react@18.3.1)': + dependencies: + react: 18.3.1 + + '@react-email/render@1.1.2(react-dom@18.3.1(react@18.3.1))(react@18.3.1)': + dependencies: + html-to-text: 9.0.5 + prettier: 3.5.3 + react: 18.3.1 + react-dom: 18.3.1(react@18.3.1) + react-promise-suspense: 0.3.4 + + '@react-email/row@0.0.12(react@18.3.1)': + dependencies: + react: 18.3.1 + + '@react-email/section@0.0.16(react@18.3.1)': + dependencies: + react: 18.3.1 + + '@react-email/tailwind@1.0.5(react@18.3.1)': + dependencies: + react: 18.3.1 + + '@react-email/text@0.1.5(react@18.3.1)': + dependencies: + react: 18.3.1 + + '@rolldown/pluginutils@1.0.0-beta.11': {} + + '@rollup/rollup-android-arm-eabi@4.43.0': + optional: true + + '@rollup/rollup-android-arm64@4.43.0': + optional: true + + '@rollup/rollup-darwin-arm64@4.43.0': + optional: true + + '@rollup/rollup-darwin-x64@4.43.0': + optional: true + + '@rollup/rollup-freebsd-arm64@4.43.0': + optional: true + + '@rollup/rollup-freebsd-x64@4.43.0': + optional: true + + '@rollup/rollup-linux-arm-gnueabihf@4.43.0': + optional: true + + '@rollup/rollup-linux-arm-musleabihf@4.43.0': + optional: true + + '@rollup/rollup-linux-arm64-gnu@4.43.0': + optional: true + + '@rollup/rollup-linux-arm64-musl@4.43.0': + optional: true + + '@rollup/rollup-linux-loongarch64-gnu@4.43.0': + optional: true + + '@rollup/rollup-linux-powerpc64le-gnu@4.43.0': + optional: true + + '@rollup/rollup-linux-riscv64-gnu@4.43.0': + optional: true + + '@rollup/rollup-linux-riscv64-musl@4.43.0': + optional: true + + '@rollup/rollup-linux-s390x-gnu@4.43.0': + optional: true + + '@rollup/rollup-linux-x64-gnu@4.43.0': + optional: true + + '@rollup/rollup-linux-x64-musl@4.43.0': + optional: true + + '@rollup/rollup-win32-arm64-msvc@4.43.0': + optional: true + + '@rollup/rollup-win32-ia32-msvc@4.43.0': + optional: true + + '@rollup/rollup-win32-x64-msvc@4.43.0': + optional: true + + '@selderee/plugin-htmlparser2@0.11.0': + dependencies: + domhandler: 5.0.3 + selderee: 0.11.0 + + '@simplewebauthn/browser@13.1.0': {} + + '@simplewebauthn/server@13.1.1': + dependencies: + '@hexagon/base64': 1.1.28 + '@levischuck/tiny-cbor': 0.2.11 + '@peculiar/asn1-android': 2.3.16 + '@peculiar/asn1-ecc': 2.3.15 + '@peculiar/asn1-rsa': 2.3.15 + '@peculiar/asn1-schema': 2.3.15 + '@peculiar/asn1-x509': 2.3.15 + + '@socket.io/component-emitter@3.1.2': {} + + '@stablelib/base64@1.0.1': {} + + '@supabase/auth-js@2.70.0': + dependencies: + '@supabase/node-fetch': 2.6.15 + + '@supabase/functions-js@2.4.4': + dependencies: + '@supabase/node-fetch': 2.6.15 + + '@supabase/node-fetch@2.6.15': + dependencies: + whatwg-url: 5.0.0 + + '@supabase/postgrest-js@1.19.4': + dependencies: + '@supabase/node-fetch': 2.6.15 + + '@supabase/realtime-js@2.11.10': + dependencies: + '@supabase/node-fetch': 2.6.15 + '@types/phoenix': 1.6.6 + '@types/ws': 8.18.1 + ws: 8.18.2 + transitivePeerDependencies: + - bufferutil + - utf-8-validate + + '@supabase/ssr@0.5.2(@supabase/supabase-js@2.50.0)': + dependencies: + '@supabase/supabase-js': 2.50.0 + '@types/cookie': 0.6.0 + cookie: 0.7.2 + + '@supabase/storage-js@2.7.1': + dependencies: + '@supabase/node-fetch': 2.6.15 + + '@supabase/supabase-js@2.50.0': + dependencies: + '@supabase/auth-js': 2.70.0 + '@supabase/functions-js': 2.4.4 + '@supabase/node-fetch': 2.6.15 + '@supabase/postgrest-js': 1.19.4 + '@supabase/realtime-js': 2.11.10 + '@supabase/storage-js': 2.7.1 + transitivePeerDependencies: + - bufferutil + - utf-8-validate + + '@swc/counter@0.1.3': {} + + '@swc/helpers@0.5.15': + dependencies: + tslib: 2.8.1 + + '@tailwindcss/node@4.1.10': + dependencies: + '@ampproject/remapping': 2.3.0 + enhanced-resolve: 5.18.1 + jiti: 2.4.2 + lightningcss: 1.30.1 + magic-string: 0.30.17 + source-map-js: 1.2.1 + tailwindcss: 4.1.10 + + '@tailwindcss/oxide-android-arm64@4.1.10': + optional: true + + '@tailwindcss/oxide-darwin-arm64@4.1.10': + optional: true + + '@tailwindcss/oxide-darwin-x64@4.1.10': + optional: true + + '@tailwindcss/oxide-freebsd-x64@4.1.10': + optional: true + + '@tailwindcss/oxide-linux-arm-gnueabihf@4.1.10': + optional: true + + '@tailwindcss/oxide-linux-arm64-gnu@4.1.10': + optional: true + + '@tailwindcss/oxide-linux-arm64-musl@4.1.10': + optional: true + + '@tailwindcss/oxide-linux-x64-gnu@4.1.10': + optional: true + + '@tailwindcss/oxide-linux-x64-musl@4.1.10': + optional: true + + '@tailwindcss/oxide-wasm32-wasi@4.1.10': + optional: true + + '@tailwindcss/oxide-win32-arm64-msvc@4.1.10': + optional: true + + '@tailwindcss/oxide-win32-x64-msvc@4.1.10': + optional: true + + '@tailwindcss/oxide@4.1.10': + dependencies: + detect-libc: 2.0.4 + tar: 7.4.3 + optionalDependencies: + '@tailwindcss/oxide-android-arm64': 4.1.10 + '@tailwindcss/oxide-darwin-arm64': 4.1.10 + '@tailwindcss/oxide-darwin-x64': 4.1.10 + '@tailwindcss/oxide-freebsd-x64': 4.1.10 + '@tailwindcss/oxide-linux-arm-gnueabihf': 4.1.10 + '@tailwindcss/oxide-linux-arm64-gnu': 4.1.10 + '@tailwindcss/oxide-linux-arm64-musl': 4.1.10 + '@tailwindcss/oxide-linux-x64-gnu': 4.1.10 + '@tailwindcss/oxide-linux-x64-musl': 4.1.10 + '@tailwindcss/oxide-wasm32-wasi': 4.1.10 + '@tailwindcss/oxide-win32-arm64-msvc': 4.1.10 + '@tailwindcss/oxide-win32-x64-msvc': 4.1.10 + + '@tailwindcss/vite@4.1.10(vite@6.3.5(@types/node@22.15.32)(jiti@2.4.2)(lightningcss@1.30.1)(tsx@4.20.3))': + dependencies: + '@tailwindcss/node': 4.1.10 + '@tailwindcss/oxide': 4.1.10 + tailwindcss: 4.1.10 + vite: 6.3.5(@types/node@22.15.32)(jiti@2.4.2)(lightningcss@1.30.1)(tsx@4.20.3) + + '@tanstack/query-core@5.80.7': {} + + '@tanstack/react-query@5.80.7(react@18.3.1)': + dependencies: + '@tanstack/query-core': 5.80.7 + react: 18.3.1 + + '@tanstack/react-table@8.21.3(react-dom@18.3.1(react@18.3.1))(react@18.3.1)': + dependencies: + '@tanstack/table-core': 8.21.3 + react: 18.3.1 + react-dom: 18.3.1(react@18.3.1) + + '@tanstack/table-core@8.21.3': {} + + '@tootallnate/quickjs-emscripten@0.23.0': {} + + '@tsconfig/node10@1.0.11': {} + + '@tsconfig/node12@1.0.11': {} + + '@tsconfig/node14@1.0.3': {} + + '@tsconfig/node16@1.0.4': {} + + '@types/babel__core@7.20.5': + dependencies: + '@babel/parser': 7.27.5 + '@babel/types': 7.27.6 + '@types/babel__generator': 7.27.0 + '@types/babel__template': 7.4.4 + '@types/babel__traverse': 7.20.7 + + '@types/babel__generator@7.27.0': + dependencies: + '@babel/types': 7.27.6 + + '@types/babel__template@7.4.4': + dependencies: + '@babel/parser': 7.27.5 + '@babel/types': 7.27.6 + + '@types/babel__traverse@7.20.7': + dependencies: + '@babel/types': 7.27.6 + + '@types/body-parser@1.19.6': + dependencies: + '@types/connect': 3.4.38 + '@types/node': 22.15.32 + + '@types/chai-http@3.0.5': + dependencies: + '@types/chai': 5.2.2 + '@types/node': 22.15.32 + '@types/superagent': 8.1.9 + + '@types/chai@5.2.2': + dependencies: + '@types/deep-eql': 4.0.2 + + '@types/connect@3.4.38': + dependencies: + '@types/node': 22.15.32 + + '@types/cookie@0.6.0': {} + + '@types/cookiejar@2.1.5': {} + + '@types/cors@2.8.19': + dependencies: + '@types/node': 22.15.32 + + '@types/deep-eql@4.0.2': {} + + '@types/diff-match-patch@1.0.36': {} + + '@types/estree@1.0.7': {} + + '@types/estree@1.0.8': {} + + '@types/express-serve-static-core@5.0.6': + dependencies: + '@types/node': 22.15.32 + '@types/qs': 6.14.0 + '@types/range-parser': 1.2.7 + '@types/send': 0.17.5 + + '@types/express@5.0.3': + dependencies: + '@types/body-parser': 1.19.6 + '@types/express-serve-static-core': 5.0.6 + '@types/serve-static': 1.15.8 + + '@types/hast@3.0.4': + dependencies: + '@types/unist': 3.0.3 + + '@types/http-errors@2.0.5': {} + + '@types/json-schema@7.0.15': {} + + '@types/lodash-es@4.17.12': + dependencies: + '@types/lodash': 4.17.17 + + '@types/lodash@4.17.17': {} + + '@types/luxon@3.4.2': {} + + '@types/mdast@4.0.4': + dependencies: + '@types/unist': 3.0.3 + + '@types/methods@1.1.4': {} + + '@types/mime@1.3.5': {} + + '@types/mocha@10.0.10': {} + + '@types/node-fetch@2.6.12': + dependencies: + '@types/node': 22.15.32 + form-data: 4.0.3 + + '@types/node@18.19.111': + dependencies: + undici-types: 5.26.5 + + '@types/node@22.15.32': + dependencies: + undici-types: 6.21.0 + + '@types/node@24.0.3': + dependencies: + undici-types: 7.8.0 + + '@types/pg@8.15.4': + dependencies: + '@types/node': 22.15.32 + pg-protocol: 1.10.0 + pg-types: 2.2.0 + + '@types/phoenix@1.6.6': {} + + '@types/prismjs@1.26.5': {} + + '@types/prop-types@15.7.15': {} + + '@types/qs@6.14.0': {} + + '@types/range-parser@1.2.7': {} + + '@types/react-dom@18.3.7(@types/react@18.3.23)': + dependencies: + '@types/react': 18.3.23 + + '@types/react@18.3.23': + dependencies: + '@types/prop-types': 15.7.15 + csstype: 3.1.3 + + '@types/send@0.17.5': + dependencies: + '@types/mime': 1.3.5 + '@types/node': 22.15.32 + + '@types/serve-static@1.15.8': + dependencies: + '@types/http-errors': 2.0.5 + '@types/node': 22.15.32 + '@types/send': 0.17.5 + + '@types/stack-trace@0.0.33': {} + + '@types/superagent@8.1.9': + dependencies: + '@types/cookiejar': 2.1.5 + '@types/methods': 1.1.4 + '@types/node': 22.15.32 + form-data: 4.0.3 + + '@types/unist@3.0.3': {} + + '@types/ws@8.18.1': + dependencies: + '@types/node': 22.15.32 + + '@types/yauzl@2.10.3': + dependencies: + '@types/node': 22.15.32 + optional: true + + '@typescript-eslint/eslint-plugin@8.34.0(@typescript-eslint/parser@8.34.0(eslint@9.29.0(jiti@2.4.2))(typescript@5.7.3))(eslint@9.29.0(jiti@2.4.2))(typescript@5.7.3)': + dependencies: + '@eslint-community/regexpp': 4.12.1 + '@typescript-eslint/parser': 8.34.0(eslint@9.29.0(jiti@2.4.2))(typescript@5.7.3) + '@typescript-eslint/scope-manager': 8.34.0 + '@typescript-eslint/type-utils': 8.34.0(eslint@9.29.0(jiti@2.4.2))(typescript@5.7.3) + '@typescript-eslint/utils': 8.34.0(eslint@9.29.0(jiti@2.4.2))(typescript@5.7.3) + '@typescript-eslint/visitor-keys': 8.34.0 + eslint: 9.29.0(jiti@2.4.2) + graphemer: 1.4.0 + ignore: 7.0.5 + natural-compare: 1.4.0 + ts-api-utils: 2.1.0(typescript@5.7.3) + typescript: 5.7.3 + transitivePeerDependencies: + - supports-color + + '@typescript-eslint/parser@8.34.0(eslint@9.29.0(jiti@2.4.2))(typescript@5.7.3)': + dependencies: + '@typescript-eslint/scope-manager': 8.34.0 + '@typescript-eslint/types': 8.34.0 + '@typescript-eslint/typescript-estree': 8.34.0(typescript@5.7.3) + '@typescript-eslint/visitor-keys': 8.34.0 + debug: 4.4.1 + eslint: 9.29.0(jiti@2.4.2) + typescript: 5.7.3 + transitivePeerDependencies: + - supports-color + + '@typescript-eslint/project-service@8.34.0(typescript@5.7.3)': + dependencies: + '@typescript-eslint/tsconfig-utils': 8.34.0(typescript@5.7.3) + '@typescript-eslint/types': 8.34.0 + debug: 4.4.1 + typescript: 5.7.3 + transitivePeerDependencies: + - supports-color + + '@typescript-eslint/scope-manager@8.34.0': + dependencies: + '@typescript-eslint/types': 8.34.0 + '@typescript-eslint/visitor-keys': 8.34.0 + + '@typescript-eslint/tsconfig-utils@8.34.0(typescript@5.7.3)': + dependencies: + typescript: 5.7.3 + + '@typescript-eslint/type-utils@8.34.0(eslint@9.29.0(jiti@2.4.2))(typescript@5.7.3)': + dependencies: + '@typescript-eslint/typescript-estree': 8.34.0(typescript@5.7.3) + '@typescript-eslint/utils': 8.34.0(eslint@9.29.0(jiti@2.4.2))(typescript@5.7.3) + debug: 4.4.1 + eslint: 9.29.0(jiti@2.4.2) + ts-api-utils: 2.1.0(typescript@5.7.3) + typescript: 5.7.3 + transitivePeerDependencies: + - supports-color + + '@typescript-eslint/types@8.34.0': {} + + '@typescript-eslint/typescript-estree@8.34.0(typescript@5.7.3)': + dependencies: + '@typescript-eslint/project-service': 8.34.0(typescript@5.7.3) + '@typescript-eslint/tsconfig-utils': 8.34.0(typescript@5.7.3) + '@typescript-eslint/types': 8.34.0 + '@typescript-eslint/visitor-keys': 8.34.0 + debug: 4.4.1 + fast-glob: 3.3.3 + is-glob: 4.0.3 + minimatch: 9.0.5 + semver: 7.7.2 + ts-api-utils: 2.1.0(typescript@5.7.3) + typescript: 5.7.3 + transitivePeerDependencies: + - supports-color + + '@typescript-eslint/utils@8.34.0(eslint@9.29.0(jiti@2.4.2))(typescript@5.7.3)': + dependencies: + '@eslint-community/eslint-utils': 4.7.0(eslint@9.29.0(jiti@2.4.2)) + '@typescript-eslint/scope-manager': 8.34.0 + '@typescript-eslint/types': 8.34.0 + '@typescript-eslint/typescript-estree': 8.34.0(typescript@5.7.3) + eslint: 9.29.0(jiti@2.4.2) + typescript: 5.7.3 + transitivePeerDependencies: + - supports-color + + '@typescript-eslint/visitor-keys@8.34.0': + dependencies: + '@typescript-eslint/types': 8.34.0 + eslint-visitor-keys: 4.2.1 + + '@ungap/structured-clone@1.3.0': {} + + '@vitejs/plugin-react@4.5.2(vite@6.3.5(@types/node@22.15.32)(jiti@2.4.2)(lightningcss@1.30.1)(tsx@4.20.3))': + dependencies: + '@babel/core': 7.27.4 + '@babel/plugin-transform-react-jsx-self': 7.27.1(@babel/core@7.27.4) + '@babel/plugin-transform-react-jsx-source': 7.27.1(@babel/core@7.27.4) + '@rolldown/pluginutils': 1.0.0-beta.11 + '@types/babel__core': 7.20.5 + react-refresh: 0.17.0 + vite: 6.3.5(@types/node@22.15.32)(jiti@2.4.2)(lightningcss@1.30.1)(tsx@4.20.3) + transitivePeerDependencies: + - supports-color + + '@wooorm/starry-night@3.8.0': + dependencies: + '@types/hast': 3.0.4 + import-meta-resolve: 4.1.0 + vscode-oniguruma: 2.0.1 + vscode-textmate: 9.2.0 + + abort-controller@3.0.0: + dependencies: + event-target-shim: 5.0.1 + + accepts@1.3.8: + dependencies: + mime-types: 2.1.35 + negotiator: 0.6.3 + + acorn-jsx@5.3.2(acorn@8.15.0): + dependencies: + acorn: 8.15.0 + + acorn-walk@8.3.4: + dependencies: + acorn: 8.15.0 + + acorn@8.15.0: {} + + agent-base@7.1.3: {} + + agentkeepalive@4.6.0: + dependencies: + humanize-ms: 1.2.1 + + ai@4.3.16(react@18.3.1)(zod@3.25.64): + dependencies: + '@ai-sdk/provider': 1.1.3 + '@ai-sdk/provider-utils': 2.2.8(zod@3.25.64) + '@ai-sdk/react': 1.2.12(react@18.3.1)(zod@3.25.64) + '@ai-sdk/ui-utils': 1.2.11(zod@3.25.64) + '@opentelemetry/api': 1.9.0 + jsondiffpatch: 0.6.0 + zod: 3.25.64 + optionalDependencies: + react: 18.3.1 + + ajv@6.12.6: + dependencies: + fast-deep-equal: 3.1.3 + fast-json-stable-stringify: 2.1.0 + json-schema-traverse: 0.4.1 + uri-js: 4.4.1 + + ansi-escapes@4.3.2: + dependencies: + type-fest: 0.21.3 + + ansi-regex@5.0.1: {} + + ansi-regex@6.1.0: {} + + ansi-styles@4.3.0: + dependencies: + color-convert: 2.0.1 + + ansi-styles@6.2.1: {} + + anymatch@3.1.3: + dependencies: + normalize-path: 3.0.0 + picomatch: 2.3.1 + + arg@4.1.3: {} + + argparse@2.0.1: {} + + aria-hidden@1.2.6: + dependencies: + tslib: 2.8.1 + + array-flatten@1.1.1: {} + + array-union@2.1.0: {} + + asap@2.0.6: {} + + asn1js@3.0.6: + dependencies: + pvtsutils: 1.3.6 + pvutils: 1.1.3 + tslib: 2.8.1 + + assertion-error@2.0.1: {} + + ast-types@0.13.4: + dependencies: + tslib: 2.8.1 + + async-listen@3.1.0: {} + + asynckit@0.4.0: {} + + atomic-sleep@1.0.0: {} + + attr-accept@2.2.5: {} + + autumn-js@0.0.41(@tanstack/react-query@5.80.7(react@18.3.1))(react@18.3.1): + dependencies: + '@tanstack/react-query': 5.80.7(react@18.3.1) + rou3: 0.6.3 + optionalDependencies: + react: 18.3.1 + + autumn-js@0.0.64(@tanstack/react-query@5.80.7(react@18.3.1))(react@18.3.1): + dependencies: + '@tanstack/react-query': 5.80.7(react@18.3.1) + rou3: 0.6.3 + swr: 2.3.3(react@18.3.1) + optionalDependencies: + react: 18.3.1 + + axios@1.10.0: + dependencies: + follow-redirects: 1.15.9 + form-data: 4.0.3 + proxy-from-env: 1.1.0 + transitivePeerDependencies: + - debug + + b4a@1.6.7: {} + + balanced-match@1.0.2: {} + + bare-events@2.5.4: + optional: true + + bare-fs@4.1.5: + dependencies: + bare-events: 2.5.4 + bare-path: 3.0.0 + bare-stream: 2.6.5(bare-events@2.5.4) + optional: true + + bare-os@3.6.1: + optional: true + + bare-path@3.0.0: + dependencies: + bare-os: 3.6.1 + optional: true + + bare-stream@2.6.5(bare-events@2.5.4): + dependencies: + streamx: 2.22.1 + optionalDependencies: + bare-events: 2.5.4 + optional: true + + base-convert-int-array@1.0.1: {} + + base64id@2.0.0: {} + + basic-ftp@5.0.5: {} + + better-auth@1.2.9: + dependencies: + '@better-auth/utils': 0.2.5 + '@better-fetch/fetch': 1.1.18 + '@noble/ciphers': 0.6.0 + '@noble/hashes': 1.8.0 + '@simplewebauthn/browser': 13.1.0 + '@simplewebauthn/server': 13.1.1 + better-call: 1.0.9 + defu: 6.1.4 + jose: 5.10.0 + kysely: 0.28.2 + nanostores: 0.11.4 + zod: 3.25.64 + + better-call@1.0.9: + dependencies: + '@better-fetch/fetch': 1.1.18 + rou3: 0.5.1 + set-cookie-parser: 2.7.1 + uncrypto: 0.1.3 + + binary-extensions@2.3.0: {} + + body-parser@1.20.3: + dependencies: + bytes: 3.1.2 + content-type: 1.0.5 + debug: 2.6.9 + depd: 2.0.0 + destroy: 1.2.0 + http-errors: 2.0.0 + iconv-lite: 0.4.24 + on-finished: 2.4.1 + qs: 6.13.0 + raw-body: 2.5.2 + type-is: 1.6.18 + unpipe: 1.0.0 + transitivePeerDependencies: + - supports-color + + brace-expansion@1.1.12: + dependencies: + balanced-match: 1.0.2 + concat-map: 0.0.1 + + brace-expansion@2.0.2: + dependencies: + balanced-match: 1.0.2 + + braces@3.0.3: + dependencies: + fill-range: 7.1.1 + + browser-stdout@1.3.1: {} + + browserslist@4.25.0: + dependencies: + caniuse-lite: 1.0.30001723 + electron-to-chromium: 1.5.167 + node-releases: 2.0.19 + update-browserslist-db: 1.1.3(browserslist@4.25.0) + + buffer-crc32@0.2.13: {} + + buffer-from@1.1.2: {} + + bullmq@5.54.0: + dependencies: + cron-parser: 4.9.0 + ioredis: 5.6.1 + msgpackr: 1.11.4 + node-abort-controller: 3.1.1 + semver: 7.7.2 + tslib: 2.8.1 + uuid: 9.0.1 + transitivePeerDependencies: + - supports-color + + busboy@1.6.0: + dependencies: + streamsearch: 1.1.0 + + bytes@3.1.2: {} + + call-bind-apply-helpers@1.0.2: + dependencies: + es-errors: 1.3.0 + function-bind: 1.1.2 + + call-bound@1.0.4: + dependencies: + call-bind-apply-helpers: 1.0.2 + get-intrinsic: 1.3.0 + + callsites@3.1.0: {} + + camelcase@6.3.0: {} + + caniuse-lite@1.0.30001723: {} + + ccount@2.0.1: {} + + chai-http@5.1.2: + dependencies: + '@types/superagent': 8.1.9 + charset: 1.0.1 + cookiejar: 2.1.4 + is-ip: 5.0.1 + methods: 1.1.2 + qs: 6.14.0 + superagent: 10.2.1 + transitivePeerDependencies: + - supports-color + + chai@5.2.0: + dependencies: + assertion-error: 2.0.1 + check-error: 2.1.1 + deep-eql: 5.0.2 + loupe: 3.1.3 + pathval: 2.0.0 + + chalk@4.1.2: + dependencies: + ansi-styles: 4.3.0 + supports-color: 7.2.0 + + chalk@5.4.1: {} + + character-entities-html4@2.1.0: {} + + character-entities-legacy@3.0.0: {} + + chardet@0.7.0: {} + + charset@1.0.1: {} + + check-error@2.1.1: {} + + chokidar@3.6.0: + dependencies: + anymatch: 3.1.3 + braces: 3.0.3 + glob-parent: 5.1.2 + is-binary-path: 2.1.0 + is-glob: 4.0.3 + normalize-path: 3.0.0 + readdirp: 3.6.0 + optionalDependencies: + fsevents: 2.3.3 + + chokidar@4.0.3: + dependencies: + readdirp: 4.1.2 + + chownr@3.0.0: {} + + chromium-bidi@5.1.0(devtools-protocol@0.0.1452169): + dependencies: + devtools-protocol: 0.0.1452169 + mitt: 3.0.1 + zod: 3.25.64 + + class-variance-authority@0.7.1: + dependencies: + clsx: 2.1.1 + + cli-cursor@5.0.0: + dependencies: + restore-cursor: 5.1.0 + + cli-spinners@2.9.2: {} + + cli-width@4.1.0: {} + + client-only@0.0.1: {} + + cliui@8.0.1: + dependencies: + string-width: 4.2.3 + strip-ansi: 6.0.1 + wrap-ansi: 7.0.0 + + clone-regexp@3.0.0: + dependencies: + is-regexp: 3.1.0 + + clsx@2.1.1: {} + + cluster-key-slot@1.1.2: {} + + cmdk@1.1.1(@types/react-dom@18.3.7(@types/react@18.3.23))(@types/react@18.3.23)(react-dom@18.3.1(react@18.3.1))(react@18.3.1): + dependencies: + '@radix-ui/react-compose-refs': 1.1.2(@types/react@18.3.23)(react@18.3.1) + '@radix-ui/react-dialog': 1.1.14(@types/react-dom@18.3.7(@types/react@18.3.23))(@types/react@18.3.23)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@radix-ui/react-id': 1.1.1(@types/react@18.3.23)(react@18.3.1) + '@radix-ui/react-primitive': 2.1.3(@types/react-dom@18.3.7(@types/react@18.3.23))(@types/react@18.3.23)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + react: 18.3.1 + react-dom: 18.3.1(react@18.3.1) + transitivePeerDependencies: + - '@types/react' + - '@types/react-dom' + + color-convert@2.0.1: + dependencies: + color-name: 1.1.4 + + color-name@1.1.4: {} + + color-string@1.9.1: + dependencies: + color-name: 1.1.4 + simple-swizzle: 0.2.2 + optional: true + + color@4.2.3: + dependencies: + color-convert: 2.0.1 + color-string: 1.9.1 + optional: true + + colorette@2.0.20: {} + + combined-stream@1.0.8: + dependencies: + delayed-stream: 1.0.0 + + comma-separated-tokens@2.0.3: {} + + commander@12.1.0: {} + + commander@13.1.0: {} + + commander@9.5.0: {} + + component-emitter@1.3.1: {} + + concat-map@0.0.1: {} + + content-disposition@0.5.4: + dependencies: + safe-buffer: 5.2.1 + + content-type@1.0.5: {} + + convert-hrtime@5.0.0: {} + + convert-source-map@2.0.0: {} + + cookie-signature@1.0.6: {} + + cookie@0.7.1: {} + + cookie@0.7.2: {} + + cookie@1.0.2: {} + + cookiejar@2.1.4: {} + + core-js@3.43.0: {} + + cors@2.8.5: + dependencies: + object-assign: 4.1.1 + vary: 1.1.2 + + cosmiconfig@9.0.0(typescript@5.7.3): + dependencies: + env-paths: 2.2.1 + import-fresh: 3.3.1 + js-yaml: 4.1.0 + parse-json: 5.2.0 + optionalDependencies: + typescript: 5.7.3 + + create-require@1.1.1: {} + + cron-parser@4.9.0: + dependencies: + luxon: 3.6.1 + + cron@3.5.0: + dependencies: + '@types/luxon': 3.4.2 + luxon: 3.5.0 + + cross-spawn@7.0.6: + dependencies: + path-key: 3.1.1 + shebang-command: 2.0.0 + which: 2.0.2 + + css-jss@10.10.0: + dependencies: + '@babel/runtime': 7.27.6 + jss: 10.10.0 + jss-preset-default: 10.10.0 + + css-vendor@2.0.8: + dependencies: + '@babel/runtime': 7.27.6 + is-in-browser: 1.1.3 + + csstype@3.1.3: {} + + csv-parse@5.6.0: {} + + csv-parser@3.2.0: {} + + currency-symbol-map@5.1.0: {} + + data-uri-to-buffer@6.0.2: {} + + date-fns@3.6.0: {} + + date-fns@4.1.0: {} + + dateformat@4.6.3: {} + + debounce@2.2.0: {} + + debug@2.6.9: + dependencies: + ms: 2.0.0 + + debug@4.3.7: + dependencies: + ms: 2.1.3 + + debug@4.4.1: + dependencies: + ms: 2.1.3 + + debug@4.4.1(supports-color@5.5.0): + dependencies: + ms: 2.1.3 + optionalDependencies: + supports-color: 5.5.0 + + debug@4.4.1(supports-color@8.1.1): + dependencies: + ms: 2.1.3 + optionalDependencies: + supports-color: 8.1.1 + + decamelize@4.0.0: {} + + decimal.js@10.5.0: {} + + deep-eql@5.0.2: {} + + deep-is@0.1.4: {} + + deepmerge@4.3.1: {} + + defu@6.1.4: {} + + degenerator@5.0.1: + dependencies: + ast-types: 0.13.4 + escodegen: 2.1.0 + esprima: 4.0.1 + + delayed-stream@1.0.0: {} + + denque@2.1.0: {} + + depd@2.0.0: {} + + dequal@2.0.3: {} + + destroy@1.2.0: {} + + detect-content-type@1.2.0: {} + + detect-libc@2.0.4: {} + + detect-node-es@1.1.0: {} + + devlop@1.1.0: + dependencies: + dequal: 2.0.3 + + devtools-protocol@0.0.1452169: {} + + dezalgo@1.0.4: + dependencies: + asap: 2.0.6 + wrappy: 1.0.2 + + diff-match-patch@1.0.5: {} + + diff@4.0.2: {} + + diff@7.0.0: {} + + dir-glob@3.0.1: + dependencies: + path-type: 4.0.0 + + dom-serializer@2.0.0: + dependencies: + domelementtype: 2.3.0 + domhandler: 5.0.3 + entities: 4.5.0 + + domelementtype@2.3.0: {} + + domhandler@5.0.3: + dependencies: + domelementtype: 2.3.0 + + domutils@3.2.2: + dependencies: + dom-serializer: 2.0.0 + domelementtype: 2.3.0 + domhandler: 5.0.3 + + dot-case@3.0.4: + dependencies: + no-case: 3.0.4 + tslib: 2.8.1 + + dotenv@16.5.0: {} + + drizzle-kit@0.31.1: + dependencies: + '@drizzle-team/brocli': 0.10.2 + '@esbuild-kit/esm-loader': 2.6.5 + esbuild: 0.25.5 + esbuild-register: 3.6.0(esbuild@0.25.5) + transitivePeerDependencies: + - supports-color + + drizzle-orm@0.43.1(@opentelemetry/api@1.9.0)(@types/pg@8.15.4)(kysely@0.28.2)(pg@8.16.0)(postgres@3.4.7): + optionalDependencies: + '@opentelemetry/api': 1.9.0 + '@types/pg': 8.15.4 + kysely: 0.28.2 + pg: 8.16.0 + postgres: 3.4.7 + + drizzle-zod@0.8.2(drizzle-orm@0.43.1(@opentelemetry/api@1.9.0)(@types/pg@8.15.4)(kysely@0.28.2)(pg@8.16.0)(postgres@3.4.7))(zod@3.25.64): + dependencies: + drizzle-orm: 0.43.1(@opentelemetry/api@1.9.0)(@types/pg@8.15.4)(kysely@0.28.2)(pg@8.16.0)(postgres@3.4.7) + zod: 3.25.64 + + dunder-proto@1.0.1: + dependencies: + call-bind-apply-helpers: 1.0.2 + es-errors: 1.3.0 + gopd: 1.2.0 + + eastasianwidth@0.2.0: {} + + ee-first@1.1.1: {} + + electron-to-chromium@1.5.167: {} + + emoji-regex@10.4.0: {} + + emoji-regex@8.0.0: {} + + emoji-regex@9.2.2: {} + + encodeurl@1.0.2: {} + + encodeurl@2.0.0: {} + + end-of-stream@1.4.4: + dependencies: + once: 1.4.0 + + engine.io-parser@5.2.3: {} + + engine.io@6.6.4: + dependencies: + '@types/cors': 2.8.19 + '@types/node': 22.15.32 + accepts: 1.3.8 + base64id: 2.0.0 + cookie: 0.7.2 + cors: 2.8.5 + debug: 4.3.7 + engine.io-parser: 5.2.3 + ws: 8.17.1 + transitivePeerDependencies: + - bufferutil + - supports-color + - utf-8-validate + + enhanced-resolve@5.18.1: + dependencies: + graceful-fs: 4.2.11 + tapable: 2.2.2 + + entities@4.5.0: {} + + env-paths@2.2.1: {} + + error-ex@1.3.2: + dependencies: + is-arrayish: 0.2.1 + + es-define-property@1.0.1: {} + + es-errors@1.3.0: {} + + es-object-atoms@1.1.1: + dependencies: + es-errors: 1.3.0 + + es-set-tostringtag@2.1.0: + dependencies: + es-errors: 1.3.0 + get-intrinsic: 1.3.0 + has-tostringtag: 1.0.2 + hasown: 2.0.2 + + es6-promise@4.2.8: {} + + esbuild-register@3.6.0(esbuild@0.25.5): + dependencies: + debug: 4.4.1 + esbuild: 0.25.5 + transitivePeerDependencies: + - supports-color + + esbuild@0.18.20: + optionalDependencies: + '@esbuild/android-arm': 0.18.20 + '@esbuild/android-arm64': 0.18.20 + '@esbuild/android-x64': 0.18.20 + '@esbuild/darwin-arm64': 0.18.20 + '@esbuild/darwin-x64': 0.18.20 + '@esbuild/freebsd-arm64': 0.18.20 + '@esbuild/freebsd-x64': 0.18.20 + '@esbuild/linux-arm': 0.18.20 + '@esbuild/linux-arm64': 0.18.20 + '@esbuild/linux-ia32': 0.18.20 + '@esbuild/linux-loong64': 0.18.20 + '@esbuild/linux-mips64el': 0.18.20 + '@esbuild/linux-ppc64': 0.18.20 + '@esbuild/linux-riscv64': 0.18.20 + '@esbuild/linux-s390x': 0.18.20 + '@esbuild/linux-x64': 0.18.20 + '@esbuild/netbsd-x64': 0.18.20 + '@esbuild/openbsd-x64': 0.18.20 + '@esbuild/sunos-x64': 0.18.20 + '@esbuild/win32-arm64': 0.18.20 + '@esbuild/win32-ia32': 0.18.20 + '@esbuild/win32-x64': 0.18.20 + + esbuild@0.25.5: + optionalDependencies: + '@esbuild/aix-ppc64': 0.25.5 + '@esbuild/android-arm': 0.25.5 + '@esbuild/android-arm64': 0.25.5 + '@esbuild/android-x64': 0.25.5 + '@esbuild/darwin-arm64': 0.25.5 + '@esbuild/darwin-x64': 0.25.5 + '@esbuild/freebsd-arm64': 0.25.5 + '@esbuild/freebsd-x64': 0.25.5 + '@esbuild/linux-arm': 0.25.5 + '@esbuild/linux-arm64': 0.25.5 + '@esbuild/linux-ia32': 0.25.5 + '@esbuild/linux-loong64': 0.25.5 + '@esbuild/linux-mips64el': 0.25.5 + '@esbuild/linux-ppc64': 0.25.5 + '@esbuild/linux-riscv64': 0.25.5 + '@esbuild/linux-s390x': 0.25.5 + '@esbuild/linux-x64': 0.25.5 + '@esbuild/netbsd-arm64': 0.25.5 + '@esbuild/netbsd-x64': 0.25.5 + '@esbuild/openbsd-arm64': 0.25.5 + '@esbuild/openbsd-x64': 0.25.5 + '@esbuild/sunos-x64': 0.25.5 + '@esbuild/win32-arm64': 0.25.5 + '@esbuild/win32-ia32': 0.25.5 + '@esbuild/win32-x64': 0.25.5 + + escalade@3.2.0: {} + + escape-html@1.0.3: {} + + escape-string-regexp@4.0.0: {} + + escodegen@2.1.0: + dependencies: + esprima: 4.0.1 + estraverse: 5.3.0 + esutils: 2.0.3 + optionalDependencies: + source-map: 0.6.1 + + eslint-plugin-react-hooks@5.2.0(eslint@9.29.0(jiti@2.4.2)): + dependencies: + eslint: 9.29.0(jiti@2.4.2) + + eslint-plugin-react-refresh@0.4.20(eslint@9.29.0(jiti@2.4.2)): + dependencies: + eslint: 9.29.0(jiti@2.4.2) + + eslint-scope@8.4.0: + dependencies: + esrecurse: 4.3.0 + estraverse: 5.3.0 + + eslint-visitor-keys@3.4.3: {} + + eslint-visitor-keys@4.2.1: {} + + eslint@9.29.0(jiti@2.4.2): + dependencies: + '@eslint-community/eslint-utils': 4.7.0(eslint@9.29.0(jiti@2.4.2)) + '@eslint-community/regexpp': 4.12.1 + '@eslint/config-array': 0.20.1 + '@eslint/config-helpers': 0.2.3 + '@eslint/core': 0.14.0 + '@eslint/eslintrc': 3.3.1 + '@eslint/js': 9.29.0 + '@eslint/plugin-kit': 0.3.2 + '@humanfs/node': 0.16.6 + '@humanwhocodes/module-importer': 1.0.1 + '@humanwhocodes/retry': 0.4.3 + '@types/estree': 1.0.8 + '@types/json-schema': 7.0.15 + ajv: 6.12.6 + chalk: 4.1.2 + cross-spawn: 7.0.6 + debug: 4.4.1 + escape-string-regexp: 4.0.0 + eslint-scope: 8.4.0 + eslint-visitor-keys: 4.2.1 + espree: 10.4.0 + esquery: 1.6.0 + esutils: 2.0.3 + fast-deep-equal: 3.1.3 + file-entry-cache: 8.0.0 + find-up: 5.0.0 + glob-parent: 6.0.2 + ignore: 5.3.2 + imurmurhash: 0.1.4 + is-glob: 4.0.3 + json-stable-stringify-without-jsonify: 1.0.1 + lodash.merge: 4.6.2 + minimatch: 3.1.2 + natural-compare: 1.4.0 + optionator: 0.9.4 + optionalDependencies: + jiti: 2.4.2 + transitivePeerDependencies: + - supports-color + + espree@10.4.0: + dependencies: + acorn: 8.15.0 + acorn-jsx: 5.3.2(acorn@8.15.0) + eslint-visitor-keys: 4.2.1 + + esprima@4.0.1: {} + + esquery@1.6.0: + dependencies: + estraverse: 5.3.0 + + esrecurse@4.3.0: + dependencies: + estraverse: 5.3.0 + + estraverse@5.3.0: {} + + esutils@2.0.3: {} + + etag@1.8.1: {} + + event-target-shim@5.0.1: {} + + express@4.21.2: + dependencies: + accepts: 1.3.8 + array-flatten: 1.1.1 + body-parser: 1.20.3 + content-disposition: 0.5.4 + content-type: 1.0.5 + cookie: 0.7.1 + cookie-signature: 1.0.6 + debug: 2.6.9 + depd: 2.0.0 + encodeurl: 2.0.0 + escape-html: 1.0.3 + etag: 1.8.1 + finalhandler: 1.3.1 + fresh: 0.5.2 + http-errors: 2.0.0 + merge-descriptors: 1.0.3 + methods: 1.1.2 + on-finished: 2.4.1 + parseurl: 1.3.3 + path-to-regexp: 0.1.12 + proxy-addr: 2.0.7 + qs: 6.13.0 + range-parser: 1.2.1 + safe-buffer: 5.2.1 + send: 0.19.0 + serve-static: 1.16.2 + setprototypeof: 1.2.0 + statuses: 2.0.1 + type-is: 1.6.18 + utils-merge: 1.0.1 + vary: 1.1.2 + transitivePeerDependencies: + - supports-color + + external-editor@3.1.0: + dependencies: + chardet: 0.7.0 + iconv-lite: 0.4.24 + tmp: 0.0.33 + + extract-zip@2.0.1: + dependencies: + debug: 4.4.1 + get-stream: 5.2.0 + yauzl: 2.10.0 + optionalDependencies: + '@types/yauzl': 2.10.3 + transitivePeerDependencies: + - supports-color + + fast-copy@3.0.2: {} + + fast-deep-equal@2.0.1: {} + + fast-deep-equal@3.1.3: {} + + fast-fifo@1.3.2: {} + + fast-glob@3.3.3: + dependencies: + '@nodelib/fs.stat': 2.0.5 + '@nodelib/fs.walk': 1.2.8 + glob-parent: 5.1.2 + merge2: 1.4.1 + micromatch: 4.0.8 + + fast-json-stable-stringify@2.1.0: {} + + fast-levenshtein@2.0.6: {} + + fast-redact@3.5.0: {} + + fast-safe-stringify@2.1.1: {} + + fast-sha256@1.3.0: {} + + fastq@1.19.1: + dependencies: + reusify: 1.1.0 + + fd-slicer@1.1.0: + dependencies: + pend: 1.2.0 + + fdir@6.4.6(picomatch@4.0.2): + optionalDependencies: + picomatch: 4.0.2 + + fetch-retry@6.0.0: {} + + fflate@0.4.8: {} + + figures@6.1.0: + dependencies: + is-unicode-supported: 2.1.0 + + file-entry-cache@8.0.0: + dependencies: + flat-cache: 4.0.1 + + file-selector@2.1.2: + dependencies: + tslib: 2.8.1 + + fill-range@7.1.1: + dependencies: + to-regex-range: 5.0.1 + + finalhandler@1.3.1: + dependencies: + debug: 2.6.9 + encodeurl: 2.0.0 + escape-html: 1.0.3 + on-finished: 2.4.1 + parseurl: 1.3.3 + statuses: 2.0.1 + unpipe: 1.0.0 + transitivePeerDependencies: + - supports-color + + find-up@5.0.0: + dependencies: + locate-path: 6.0.0 + path-exists: 4.0.0 + + flat-cache@4.0.1: + dependencies: + flatted: 3.3.3 + keyv: 4.5.4 + + flat@5.0.2: {} + + flatted@3.3.3: {} + + follow-redirects@1.15.9: {} + + foreground-child@3.3.1: + dependencies: + cross-spawn: 7.0.6 + signal-exit: 4.1.0 + + form-data-encoder@1.7.2: {} + + form-data@4.0.3: + dependencies: + asynckit: 0.4.0 + combined-stream: 1.0.8 + es-set-tostringtag: 2.1.0 + hasown: 2.0.2 + mime-types: 2.1.35 + + formdata-node@4.4.1: + dependencies: + node-domexception: 1.0.0 + web-streams-polyfill: 4.0.0-beta.3 + + formidable@3.5.4: + dependencies: + '@paralleldrive/cuid2': 2.2.2 + dezalgo: 1.0.4 + once: 1.4.0 + + forwarded@0.2.0: {} + + framer-motion@12.18.1(@emotion/is-prop-valid@0.7.3)(react-dom@18.3.1(react@18.3.1))(react@18.3.1): + dependencies: + motion-dom: 12.18.1 + motion-utils: 12.18.1 + tslib: 2.8.1 + optionalDependencies: + '@emotion/is-prop-valid': 0.7.3 + react: 18.3.1 + react-dom: 18.3.1(react@18.3.1) + + fresh@0.5.2: {} + + fsevents@2.3.3: + optional: true + + function-bind@1.1.2: {} + + function-timeout@0.1.1: {} + + gensync@1.0.0-beta.2: {} + + get-caller-file@2.0.5: {} + + get-east-asian-width@1.3.0: {} + + get-intrinsic@1.3.0: + dependencies: + call-bind-apply-helpers: 1.0.2 + es-define-property: 1.0.1 + es-errors: 1.3.0 + es-object-atoms: 1.1.1 + function-bind: 1.1.2 + get-proto: 1.0.1 + gopd: 1.2.0 + has-symbols: 1.1.0 + hasown: 2.0.2 + math-intrinsics: 1.1.0 + + get-nonce@1.0.1: {} + + get-proto@1.0.1: + dependencies: + dunder-proto: 1.0.1 + es-object-atoms: 1.1.1 + + get-stream@5.2.0: + dependencies: + pump: 3.0.3 + + get-tsconfig@4.10.1: + dependencies: + resolve-pkg-maps: 1.0.0 + + get-uri@6.0.4: + dependencies: + basic-ftp: 5.0.5 + data-uri-to-buffer: 6.0.2 + debug: 4.4.1 + transitivePeerDependencies: + - supports-color + + glob-parent@5.1.2: + dependencies: + is-glob: 4.0.3 + + glob-parent@6.0.2: + dependencies: + is-glob: 4.0.3 + + glob-to-regexp@0.4.1: {} + + glob@10.4.5: + dependencies: + foreground-child: 3.3.1 + jackspeak: 3.4.3 + minimatch: 9.0.5 + minipass: 7.1.2 + package-json-from-dist: 1.0.1 + path-scurry: 1.11.1 + + glob@11.0.3: + dependencies: + foreground-child: 3.3.1 + jackspeak: 4.1.1 + minimatch: 10.0.3 + minipass: 7.1.2 + package-json-from-dist: 1.0.1 + path-scurry: 2.0.0 + + globals@11.12.0: {} + + globals@14.0.0: {} + + globals@15.15.0: {} + + globby@11.1.0: + dependencies: + array-union: 2.1.0 + dir-glob: 3.0.1 + fast-glob: 3.3.3 + ignore: 5.3.2 + merge2: 1.4.1 + slash: 3.0.0 + + goober@2.1.16(csstype@3.1.3): + dependencies: + csstype: 3.1.3 + + gopd@1.2.0: {} + + graceful-fs@4.2.11: {} + + graphemer@1.4.0: {} + + has-flag@3.0.0: {} + + has-flag@4.0.0: {} + + has-symbols@1.1.0: {} + + has-tostringtag@1.0.2: + dependencies: + has-symbols: 1.1.0 + + hasown@2.0.2: + dependencies: + function-bind: 1.1.2 + + hast-util-to-html@9.0.5: + dependencies: + '@types/hast': 3.0.4 + '@types/unist': 3.0.3 + ccount: 2.0.1 + comma-separated-tokens: 2.0.3 + hast-util-whitespace: 3.0.0 + html-void-elements: 3.0.0 + mdast-util-to-hast: 13.2.0 + property-information: 7.1.0 + space-separated-tokens: 2.0.2 + stringify-entities: 4.0.4 + zwitch: 2.0.4 + + hast-util-whitespace@3.0.0: + dependencies: + '@types/hast': 3.0.4 + + he@1.2.0: {} + + help-me@5.0.0: {} + + hoist-non-react-statics@3.3.2: + dependencies: + react-is: 16.13.1 + + html-to-text@9.0.5: + dependencies: + '@selderee/plugin-htmlparser2': 0.11.0 + deepmerge: 4.3.1 + dom-serializer: 2.0.0 + htmlparser2: 8.0.2 + selderee: 0.11.0 + + html-void-elements@3.0.0: {} + + htmlparser2@8.0.2: + dependencies: + domelementtype: 2.3.0 + domhandler: 5.0.3 + domutils: 3.2.2 + entities: 4.5.0 + + http-errors@2.0.0: + dependencies: + depd: 2.0.0 + inherits: 2.0.4 + setprototypeof: 1.2.0 + statuses: 2.0.1 + toidentifier: 1.0.1 + + http-proxy-agent@7.0.2: + dependencies: + agent-base: 7.1.3 + debug: 4.4.1 + transitivePeerDependencies: + - supports-color + + http-status-codes@2.3.0: {} + + https-proxy-agent@7.0.6: + dependencies: + agent-base: 7.1.3 + debug: 4.4.1 + transitivePeerDependencies: + - supports-color + + humanize-ms@1.2.1: + dependencies: + ms: 2.1.3 + + hyphenate-style-name@1.1.0: {} + + iconv-lite@0.4.24: + dependencies: + safer-buffer: 2.1.2 + + iframe-resizer-react@1.1.1(@babel/core@7.27.4)(prop-types@15.8.1)(react-dom@18.3.1(react@18.3.1))(react@18.3.1): + dependencies: + '@babel/plugin-proposal-private-property-in-object': 7.21.11(@babel/core@7.27.4) + iframe-resizer: 4.4.5 + prop-types: 15.8.1 + react: 18.3.1 + react-dom: 18.3.1(react@18.3.1) + warning: 4.0.3 + transitivePeerDependencies: + - '@babel/core' + - supports-color + + iframe-resizer@4.4.5: {} + + ignore-by-default@1.0.1: {} + + ignore@5.3.2: {} + + ignore@7.0.5: {} + + import-fresh@3.3.1: + dependencies: + parent-module: 1.0.1 + resolve-from: 4.0.0 + + import-meta-resolve@4.1.0: {} + + imurmurhash@0.1.4: {} + + inherits@2.0.4: {} + + input-otp@1.4.2(react-dom@18.3.1(react@18.3.1))(react@18.3.1): + dependencies: + react: 18.3.1 + react-dom: 18.3.1(react@18.3.1) + + inquirer@12.6.3(@types/node@22.15.32): + dependencies: + '@inquirer/core': 10.1.13(@types/node@22.15.32) + '@inquirer/prompts': 7.5.3(@types/node@22.15.32) + '@inquirer/type': 3.0.7(@types/node@22.15.32) + ansi-escapes: 4.3.2 + mute-stream: 2.0.0 + run-async: 3.0.0 + rxjs: 7.8.2 + optionalDependencies: + '@types/node': 22.15.32 + + inquirer@12.6.3(@types/node@24.0.3): + dependencies: + '@inquirer/core': 10.1.13(@types/node@24.0.3) + '@inquirer/prompts': 7.5.3(@types/node@24.0.3) + '@inquirer/type': 3.0.7(@types/node@24.0.3) + ansi-escapes: 4.3.2 + mute-stream: 2.0.0 + run-async: 3.0.0 + rxjs: 7.8.2 + optionalDependencies: + '@types/node': 24.0.3 + + ioredis@5.6.1: + dependencies: + '@ioredis/commands': 1.2.0 + cluster-key-slot: 1.1.2 + debug: 4.4.1 + denque: 2.1.0 + lodash.defaults: 4.2.0 + lodash.isarguments: 3.1.0 + redis-errors: 1.2.0 + redis-parser: 3.0.0 + standard-as-callback: 2.1.0 + transitivePeerDependencies: + - supports-color + + ip-address@9.0.5: + dependencies: + jsbn: 1.1.0 + sprintf-js: 1.1.3 + + ip-regex@5.0.0: {} + + ipaddr.js@1.9.1: {} + + is-arrayish@0.2.1: {} + + is-arrayish@0.3.2: + optional: true + + is-binary-path@2.1.0: + dependencies: + binary-extensions: 2.3.0 + + is-extglob@2.1.1: {} + + is-fullwidth-code-point@3.0.0: {} + + is-glob@4.0.3: + dependencies: + is-extglob: 2.1.1 + + is-in-browser@1.1.3: {} + + is-interactive@2.0.0: {} + + is-ip@5.0.1: + dependencies: + ip-regex: 5.0.0 + super-regex: 0.2.0 + + is-number@7.0.0: {} + + is-plain-obj@2.1.0: {} + + is-regexp@3.1.0: {} + + is-unicode-supported@0.1.0: {} + + is-unicode-supported@1.3.0: {} + + is-unicode-supported@2.1.0: {} + + isexe@2.0.0: {} + + jackspeak@3.4.3: + dependencies: + '@isaacs/cliui': 8.0.2 + optionalDependencies: + '@pkgjs/parseargs': 0.11.0 + + jackspeak@4.1.1: + dependencies: + '@isaacs/cliui': 8.0.2 + + jiti@2.4.2: {} + + jose@5.10.0: {} + + joycon@3.1.1: {} + + js-cookie@3.0.5: {} + + js-tokens@4.0.0: {} + + js-yaml@4.1.0: + dependencies: + argparse: 2.0.1 + + jsbn@1.1.0: {} + + jsesc@3.1.0: {} + + json-buffer@3.0.1: {} + + json-parse-even-better-errors@2.3.1: {} + + json-schema-traverse@0.4.1: {} + + json-schema@0.4.0: {} + + json-stable-stringify-without-jsonify@1.0.1: {} + + json5@2.2.3: {} + + jsondiffpatch@0.6.0: + dependencies: + '@types/diff-match-patch': 1.0.36 + chalk: 5.4.1 + diff-match-patch: 1.0.5 + + jss-plugin-camel-case@10.10.0: + dependencies: + '@babel/runtime': 7.27.6 + hyphenate-style-name: 1.1.0 + jss: 10.10.0 + + jss-plugin-compose@10.10.0: + dependencies: + '@babel/runtime': 7.27.6 + jss: 10.10.0 + tiny-warning: 1.0.3 + + jss-plugin-default-unit@10.10.0: + dependencies: + '@babel/runtime': 7.27.6 + jss: 10.10.0 + + jss-plugin-expand@10.10.0: + dependencies: + '@babel/runtime': 7.27.6 + jss: 10.10.0 + + jss-plugin-extend@10.10.0: + dependencies: + '@babel/runtime': 7.27.6 + jss: 10.10.0 + tiny-warning: 1.0.3 + + jss-plugin-global@10.10.0: + dependencies: + '@babel/runtime': 7.27.6 + jss: 10.10.0 + + jss-plugin-nested@10.10.0: + dependencies: + '@babel/runtime': 7.27.6 + jss: 10.10.0 + tiny-warning: 1.0.3 + + jss-plugin-props-sort@10.10.0: + dependencies: + '@babel/runtime': 7.27.6 + jss: 10.10.0 + + jss-plugin-rule-value-function@10.10.0: + dependencies: + '@babel/runtime': 7.27.6 + jss: 10.10.0 + tiny-warning: 1.0.3 + + jss-plugin-rule-value-observable@10.10.0: + dependencies: + '@babel/runtime': 7.27.6 + jss: 10.10.0 + symbol-observable: 1.2.0 + + jss-plugin-template@10.10.0: + dependencies: + '@babel/runtime': 7.27.6 + jss: 10.10.0 + tiny-warning: 1.0.3 + + jss-plugin-vendor-prefixer@10.10.0: + dependencies: + '@babel/runtime': 7.27.6 + css-vendor: 2.0.8 + jss: 10.10.0 + + jss-preset-default@10.10.0: + dependencies: + '@babel/runtime': 7.27.6 + jss: 10.10.0 + jss-plugin-camel-case: 10.10.0 + jss-plugin-compose: 10.10.0 + jss-plugin-default-unit: 10.10.0 + jss-plugin-expand: 10.10.0 + jss-plugin-extend: 10.10.0 + jss-plugin-global: 10.10.0 + jss-plugin-nested: 10.10.0 + jss-plugin-props-sort: 10.10.0 + jss-plugin-rule-value-function: 10.10.0 + jss-plugin-rule-value-observable: 10.10.0 + jss-plugin-template: 10.10.0 + jss-plugin-vendor-prefixer: 10.10.0 + + jss@10.10.0: + dependencies: + '@babel/runtime': 7.27.6 + csstype: 3.1.3 + is-in-browser: 1.1.3 + tiny-warning: 1.0.3 + + keyv@4.5.4: + dependencies: + json-buffer: 3.0.1 + + ksuid@3.0.0: + dependencies: + base-convert-int-array: 1.0.1 + + kysely@0.28.2: {} + + leac@0.6.0: {} + + levn@0.4.1: + dependencies: + prelude-ls: 1.2.1 + type-check: 0.4.0 + + lightningcss-darwin-arm64@1.30.1: + optional: true + + lightningcss-darwin-x64@1.30.1: + optional: true + + lightningcss-freebsd-x64@1.30.1: + optional: true + + lightningcss-linux-arm-gnueabihf@1.30.1: + optional: true + + lightningcss-linux-arm64-gnu@1.30.1: + optional: true + + lightningcss-linux-arm64-musl@1.30.1: + optional: true + + lightningcss-linux-x64-gnu@1.30.1: + optional: true + + lightningcss-linux-x64-musl@1.30.1: + optional: true + + lightningcss-win32-arm64-msvc@1.30.1: + optional: true + + lightningcss-win32-x64-msvc@1.30.1: + optional: true + + lightningcss@1.30.1: + dependencies: + detect-libc: 2.0.4 + optionalDependencies: + lightningcss-darwin-arm64: 1.30.1 + lightningcss-darwin-x64: 1.30.1 + lightningcss-freebsd-x64: 1.30.1 + lightningcss-linux-arm-gnueabihf: 1.30.1 + lightningcss-linux-arm64-gnu: 1.30.1 + lightningcss-linux-arm64-musl: 1.30.1 + lightningcss-linux-x64-gnu: 1.30.1 + lightningcss-linux-x64-musl: 1.30.1 + lightningcss-win32-arm64-msvc: 1.30.1 + lightningcss-win32-x64-msvc: 1.30.1 + + lines-and-columns@1.2.4: {} + + locate-path@6.0.0: + dependencies: + p-locate: 5.0.0 + + lodash-es@4.17.21: {} + + lodash.defaults@4.2.0: {} + + lodash.isarguments@3.1.0: {} + + lodash.merge@4.6.2: {} + + lodash@4.17.21: {} + + log-symbols@4.1.0: + dependencies: + chalk: 4.1.2 + is-unicode-supported: 0.1.0 + + log-symbols@6.0.0: + dependencies: + chalk: 5.4.1 + is-unicode-supported: 1.3.0 + + log-symbols@7.0.1: + dependencies: + is-unicode-supported: 2.1.0 + yoctocolors: 2.1.1 + + loose-envify@1.4.0: + dependencies: + js-tokens: 4.0.0 + + loupe@3.1.3: {} + + lower-case@2.0.2: + dependencies: + tslib: 2.8.1 + + lru-cache@10.4.3: {} + + lru-cache@11.1.0: {} + + lru-cache@5.1.1: + dependencies: + yallist: 3.1.1 + + lru-cache@7.18.3: {} + + lucide-react@0.511.0(react@18.3.1): + dependencies: + react: 18.3.1 + + luxon@3.5.0: {} + + luxon@3.6.1: {} + + magic-string@0.30.17: + dependencies: + '@jridgewell/sourcemap-codec': 1.5.0 + + make-error@1.3.6: {} + + map-obj@4.3.0: {} + + marked@7.0.4: {} + + math-intrinsics@1.1.0: {} + + md-to-react-email@5.0.5(react@18.3.1): + dependencies: + marked: 7.0.4 + react: 18.3.1 + + mdast-util-to-hast@13.2.0: + dependencies: + '@types/hast': 3.0.4 + '@types/mdast': 4.0.4 + '@ungap/structured-clone': 1.3.0 + devlop: 1.1.0 + micromark-util-sanitize-uri: 2.0.1 + trim-lines: 3.0.1 + unist-util-position: 5.0.0 + unist-util-visit: 5.0.0 + vfile: 6.0.3 + + media-typer@0.3.0: {} + + merge-descriptors@1.0.3: {} + + merge2@1.4.1: {} + + methods@1.1.2: {} + + micromark-util-character@2.1.1: + dependencies: + micromark-util-symbol: 2.0.1 + micromark-util-types: 2.0.2 + + micromark-util-encode@2.0.1: {} + + micromark-util-sanitize-uri@2.0.1: + dependencies: + micromark-util-character: 2.1.1 + micromark-util-encode: 2.0.1 + micromark-util-symbol: 2.0.1 + + micromark-util-symbol@2.0.1: {} + + micromark-util-types@2.0.2: {} + + micromatch@4.0.8: + dependencies: + braces: 3.0.3 + picomatch: 2.3.1 + + mime-db@1.52.0: {} + + mime-db@1.54.0: {} + + mime-detect@1.3.0: + dependencies: + mime-db: 1.54.0 + + mime-types@2.1.35: + dependencies: + mime-db: 1.52.0 + + mime-types@3.0.1: + dependencies: + mime-db: 1.54.0 + + mime@1.6.0: {} + + mime@2.6.0: {} + + mimic-function@5.0.1: {} + + minimatch@10.0.3: + dependencies: + '@isaacs/brace-expansion': 5.0.0 + + minimatch@3.1.2: + dependencies: + brace-expansion: 1.1.12 + + minimatch@9.0.5: + dependencies: + brace-expansion: 2.0.2 + + minimist@1.2.8: {} + + minipass@7.1.2: {} + + minizlib@3.0.2: + dependencies: + minipass: 7.1.2 + + mitt@3.0.1: {} + + mkdirp@3.0.1: {} + + mocha@11.6.0: + dependencies: + browser-stdout: 1.3.1 + chokidar: 4.0.3 + debug: 4.4.1(supports-color@8.1.1) + diff: 7.0.0 + escape-string-regexp: 4.0.0 + find-up: 5.0.0 + glob: 10.4.5 + he: 1.2.0 + js-yaml: 4.1.0 + log-symbols: 4.1.0 + minimatch: 9.0.5 + ms: 2.1.3 + picocolors: 1.1.1 + serialize-javascript: 6.0.2 + strip-json-comments: 3.1.1 + supports-color: 8.1.1 + workerpool: 9.3.2 + yargs: 17.7.2 + yargs-parser: 21.1.1 + yargs-unparser: 2.0.0 + + motion-dom@12.18.1: + dependencies: + motion-utils: 12.18.1 + + motion-utils@12.18.1: {} + + motion@12.18.1(@emotion/is-prop-valid@0.7.3)(react-dom@18.3.1(react@18.3.1))(react@18.3.1): + dependencies: + framer-motion: 12.18.1(@emotion/is-prop-valid@0.7.3)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + tslib: 2.8.1 + optionalDependencies: + '@emotion/is-prop-valid': 0.7.3 + react: 18.3.1 + react-dom: 18.3.1(react@18.3.1) + + ms@2.0.0: {} + + ms@2.1.3: {} + + msgpackr-extract@3.0.3: + dependencies: + node-gyp-build-optional-packages: 5.2.2 + optionalDependencies: + '@msgpackr-extract/msgpackr-extract-darwin-arm64': 3.0.3 + '@msgpackr-extract/msgpackr-extract-darwin-x64': 3.0.3 + '@msgpackr-extract/msgpackr-extract-linux-arm': 3.0.3 + '@msgpackr-extract/msgpackr-extract-linux-arm64': 3.0.3 + '@msgpackr-extract/msgpackr-extract-linux-x64': 3.0.3 + '@msgpackr-extract/msgpackr-extract-win32-x64': 3.0.3 + optional: true + + msgpackr@1.11.4: + optionalDependencies: + msgpackr-extract: 3.0.3 + + mute-stream@2.0.0: {} + + mylas@2.1.13: {} + + nanoid@3.3.11: {} + + nanoid@5.1.5: {} + + nanostores@0.11.4: {} + + natural-compare@1.4.0: {} + + negotiator@0.6.3: {} + + netmask@2.0.2: {} + + next-themes@0.4.6(react-dom@18.3.1(react@18.3.1))(react@18.3.1): + dependencies: + react: 18.3.1 + react-dom: 18.3.1(react@18.3.1) + + next@15.3.3(@opentelemetry/api@1.9.0)(react-dom@18.3.1(react@18.3.1))(react@18.3.1): + dependencies: + '@next/env': 15.3.3 + '@swc/counter': 0.1.3 + '@swc/helpers': 0.5.15 + busboy: 1.6.0 + caniuse-lite: 1.0.30001723 + postcss: 8.4.31 + react: 18.3.1 + react-dom: 18.3.1(react@18.3.1) + styled-jsx: 5.1.6(react@18.3.1) + optionalDependencies: + '@next/swc-darwin-arm64': 15.3.3 + '@next/swc-darwin-x64': 15.3.3 + '@next/swc-linux-arm64-gnu': 15.3.3 + '@next/swc-linux-arm64-musl': 15.3.3 + '@next/swc-linux-x64-gnu': 15.3.3 + '@next/swc-linux-x64-musl': 15.3.3 + '@next/swc-win32-arm64-msvc': 15.3.3 + '@next/swc-win32-x64-msvc': 15.3.3 + '@opentelemetry/api': 1.9.0 + sharp: 0.34.2 + transitivePeerDependencies: + - '@babel/core' + - babel-plugin-macros + + no-case@3.0.4: + dependencies: + lower-case: 2.0.2 + tslib: 2.8.1 + + node-abort-controller@3.1.1: {} + + node-domexception@1.0.0: {} + + node-fetch@2.7.0: + dependencies: + whatwg-url: 5.0.0 + + node-gyp-build-optional-packages@5.2.2: + dependencies: + detect-libc: 2.0.4 + optional: true + + node-releases@2.0.19: {} + + nodemon@3.1.10: + dependencies: + chokidar: 3.6.0 + debug: 4.4.1(supports-color@5.5.0) + ignore-by-default: 1.0.1 + minimatch: 3.1.2 + pstree.remy: 1.1.8 + semver: 7.7.2 + simple-update-notifier: 2.0.0 + supports-color: 5.5.0 + touch: 3.1.1 + undefsafe: 2.0.5 + + normalize-path@3.0.0: {} + + object-assign@4.1.1: {} + + object-inspect@1.13.4: {} + + on-exit-leak-free@2.1.2: {} + + on-finished@2.4.1: + dependencies: + ee-first: 1.1.1 + + once@1.4.0: + dependencies: + wrappy: 1.0.2 + + onetime@7.0.0: + dependencies: + mimic-function: 5.0.1 + + openai@4.104.0(ws@8.18.2)(zod@3.25.64): + dependencies: + '@types/node': 18.19.111 + '@types/node-fetch': 2.6.12 + abort-controller: 3.0.0 + agentkeepalive: 4.6.0 + form-data-encoder: 1.7.2 + formdata-node: 4.4.1 + node-fetch: 2.7.0 + optionalDependencies: + ws: 8.18.2 + zod: 3.25.64 + transitivePeerDependencies: + - encoding + + optionator@0.9.4: + dependencies: + deep-is: 0.1.4 + fast-levenshtein: 2.0.6 + levn: 0.4.1 + prelude-ls: 1.2.1 + type-check: 0.4.0 + word-wrap: 1.2.5 + + ora@8.2.0: + dependencies: + chalk: 5.4.1 + cli-cursor: 5.0.0 + cli-spinners: 2.9.2 + is-interactive: 2.0.0 + is-unicode-supported: 2.1.0 + log-symbols: 6.0.0 + stdin-discarder: 0.2.2 + string-width: 7.2.0 + strip-ansi: 7.1.0 + + os-tmpdir@1.0.2: {} + + p-limit@3.1.0: + dependencies: + yocto-queue: 0.1.0 + + p-locate@5.0.0: + dependencies: + p-limit: 3.1.0 + + pac-proxy-agent@7.2.0: + dependencies: + '@tootallnate/quickjs-emscripten': 0.23.0 + agent-base: 7.1.3 + debug: 4.4.1 + get-uri: 6.0.4 + http-proxy-agent: 7.0.2 + https-proxy-agent: 7.0.6 + pac-resolver: 7.0.1 + socks-proxy-agent: 8.0.5 + transitivePeerDependencies: + - supports-color + + pac-resolver@7.0.1: + dependencies: + degenerator: 5.0.1 + netmask: 2.0.2 + + package-json-from-dist@1.0.1: {} + + parent-module@1.0.1: + dependencies: + callsites: 3.1.0 + + parse-json@5.2.0: + dependencies: + '@babel/code-frame': 7.27.1 + error-ex: 1.3.2 + json-parse-even-better-errors: 2.3.1 + lines-and-columns: 1.2.4 + + parseley@0.12.1: + dependencies: + leac: 0.6.0 + peberminta: 0.9.0 + + parseurl@1.3.3: {} + + path-exists@4.0.0: {} + + path-key@3.1.1: {} + + path-scurry@1.11.1: + dependencies: + lru-cache: 10.4.3 + minipass: 7.1.2 + + path-scurry@2.0.0: + dependencies: + lru-cache: 11.1.0 + minipass: 7.1.2 + + path-to-regexp@0.1.12: {} + + path-type@4.0.0: {} + + pathval@2.0.0: {} + + peberminta@0.9.0: {} + + pend@1.2.0: {} + + pg-cloudflare@1.2.5: + optional: true + + pg-connection-string@2.9.0: {} + + pg-int8@1.0.1: {} + + pg-pool@3.10.0(pg@8.16.0): + dependencies: + pg: 8.16.0 + + pg-protocol@1.10.0: {} + + pg-types@2.2.0: + dependencies: + pg-int8: 1.0.1 + postgres-array: 2.0.0 + postgres-bytea: 1.0.0 + postgres-date: 1.0.7 + postgres-interval: 1.2.0 + + pg@8.16.0: + dependencies: + pg-connection-string: 2.9.0 + pg-pool: 3.10.0(pg@8.16.0) + pg-protocol: 1.10.0 + pg-types: 2.2.0 + pgpass: 1.0.5 + optionalDependencies: + pg-cloudflare: 1.2.5 + + pgpass@1.0.5: + dependencies: + split2: 4.2.0 + + picocolors@1.1.1: {} + + picomatch@2.3.1: {} + + picomatch@4.0.2: {} + + pino-abstract-transport@2.0.0: + dependencies: + split2: 4.2.0 + + pino-pretty@13.0.0: + dependencies: + colorette: 2.0.20 + dateformat: 4.6.3 + fast-copy: 3.0.2 + fast-safe-stringify: 2.1.1 + help-me: 5.0.0 + joycon: 3.1.1 + minimist: 1.2.8 + on-exit-leak-free: 2.1.2 + pino-abstract-transport: 2.0.0 + pump: 3.0.3 + secure-json-parse: 2.7.0 + sonic-boom: 4.2.0 + strip-json-comments: 3.1.1 + + pino-std-serializers@7.0.0: {} + + pino@9.7.0: + dependencies: + atomic-sleep: 1.0.0 + fast-redact: 3.5.0 + on-exit-leak-free: 2.1.2 + pino-abstract-transport: 2.0.0 + pino-std-serializers: 7.0.0 + process-warning: 5.0.0 + quick-format-unescaped: 4.0.4 + real-require: 0.2.0 + safe-stable-stringify: 2.5.0 + sonic-boom: 4.2.0 + thread-stream: 3.1.0 + + plimit-lit@1.6.1: + dependencies: + queue-lit: 1.5.2 + + postcss@8.4.31: + dependencies: + nanoid: 3.3.11 + picocolors: 1.1.1 + source-map-js: 1.2.1 + + postcss@8.5.5: + dependencies: + nanoid: 3.3.11 + picocolors: 1.1.1 + source-map-js: 1.2.1 + + postgres-array@2.0.0: {} + + postgres-bytea@1.0.0: {} + + postgres-date@1.0.7: {} + + postgres-interval@1.2.0: + dependencies: + xtend: 4.0.2 + + postgres@3.4.7: {} + + posthog-js@1.252.1: + dependencies: + core-js: 3.43.0 + fflate: 0.4.8 + preact: 10.26.9 + web-vitals: 4.2.4 + + posthog-node@4.18.0: + dependencies: + axios: 1.10.0 + transitivePeerDependencies: + - debug + + preact@10.26.9: {} + + prelude-ls@1.2.1: {} + + prettier@3.5.3: {} + + prism-themes@1.9.0: {} + + prismjs@1.30.0: {} + + process-warning@5.0.0: {} + + progress@2.0.3: {} + + prop-types@15.8.1: + dependencies: + loose-envify: 1.4.0 + object-assign: 4.1.1 + react-is: 16.13.1 + + property-information@7.1.0: {} + + proxy-addr@2.0.7: + dependencies: + forwarded: 0.2.0 + ipaddr.js: 1.9.1 + + proxy-agent@6.5.0: + dependencies: + agent-base: 7.1.3 + debug: 4.4.1 + http-proxy-agent: 7.0.2 + https-proxy-agent: 7.0.6 + lru-cache: 7.18.3 + pac-proxy-agent: 7.2.0 + proxy-from-env: 1.1.0 + socks-proxy-agent: 8.0.5 + transitivePeerDependencies: + - supports-color + + proxy-from-env@1.1.0: {} + + pstree.remy@1.1.8: {} + + pump@3.0.3: + dependencies: + end-of-stream: 1.4.4 + once: 1.4.0 + + punycode@2.3.1: {} + + puppeteer-core@24.10.1: + dependencies: + '@puppeteer/browsers': 2.10.5 + chromium-bidi: 5.1.0(devtools-protocol@0.0.1452169) + debug: 4.4.1 + devtools-protocol: 0.0.1452169 + typed-query-selector: 2.12.0 + ws: 8.18.2 + transitivePeerDependencies: + - bare-buffer + - bufferutil + - supports-color + - utf-8-validate + + puppeteer@24.10.1(typescript@5.7.3): + dependencies: + '@puppeteer/browsers': 2.10.5 + chromium-bidi: 5.1.0(devtools-protocol@0.0.1452169) + cosmiconfig: 9.0.0(typescript@5.7.3) + devtools-protocol: 0.0.1452169 + puppeteer-core: 24.10.1 + typed-query-selector: 2.12.0 + transitivePeerDependencies: + - bare-buffer + - bufferutil + - supports-color + - typescript + - utf-8-validate + + pvtsutils@1.3.6: + dependencies: + tslib: 2.8.1 + + pvutils@1.1.3: {} + + qs@6.13.0: + dependencies: + side-channel: 1.1.0 + + qs@6.14.0: + dependencies: + side-channel: 1.1.0 + + querystringify@2.2.0: {} + + queue-lit@1.5.2: {} + + queue-microtask@1.2.3: {} + + quick-format-unescaped@4.0.4: {} + + randombytes@2.1.0: + dependencies: + safe-buffer: 5.2.1 + + range-parser@1.2.1: {} + + raw-body@2.5.2: + dependencies: + bytes: 3.1.2 + http-errors: 2.0.0 + iconv-lite: 0.4.24 + unpipe: 1.0.0 + + react-confetti-explosion@2.1.2(react-dom@18.3.1(react@18.3.1))(react@18.3.1): + dependencies: + lodash: 4.17.21 + react: 18.3.1 + react-dom: 18.3.1(react@18.3.1) + react-jss: 10.10.0(react@18.3.1) + + react-day-picker@8.10.1(date-fns@3.6.0)(react@18.3.1): + dependencies: + date-fns: 3.6.0 + react: 18.3.1 + + react-display-name@0.2.5: {} + + react-dom@18.3.1(react@18.3.1): + dependencies: + loose-envify: 1.4.0 + react: 18.3.1 + scheduler: 0.23.2 + + react-dropzone@14.3.8(react@18.3.1): + dependencies: + attr-accept: 2.2.5 + file-selector: 2.1.2 + prop-types: 15.8.1 + react: 18.3.1 + + react-email@4.0.16(@opentelemetry/api@1.9.0)(react-dom@18.3.1(react@18.3.1))(react@18.3.1): + dependencies: + '@babel/parser': 7.27.5 + '@babel/traverse': 7.27.4 + chalk: 5.4.1 + chokidar: 4.0.3 + commander: 13.1.0 + debounce: 2.2.0 + esbuild: 0.25.5 + glob: 11.0.3 + log-symbols: 7.0.1 + mime-types: 3.0.1 + next: 15.3.3(@opentelemetry/api@1.9.0)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + normalize-path: 3.0.0 + ora: 8.2.0 + socket.io: 4.8.1 + transitivePeerDependencies: + - '@babel/core' + - '@opentelemetry/api' + - '@playwright/test' + - babel-plugin-macros + - babel-plugin-react-compiler + - bufferutil + - react + - react-dom + - sass + - supports-color + - utf-8-validate + + react-hot-toast@2.5.2(react-dom@18.3.1(react@18.3.1))(react@18.3.1): + dependencies: + csstype: 3.1.3 + goober: 2.1.16(csstype@3.1.3) + react: 18.3.1 + react-dom: 18.3.1(react@18.3.1) + + react-hotkeys-hook@4.6.2(react-dom@18.3.1(react@18.3.1))(react@18.3.1): + dependencies: + react: 18.3.1 + react-dom: 18.3.1(react@18.3.1) + + react-is@16.13.1: {} + + react-jss@10.10.0(react@18.3.1): + dependencies: + '@babel/runtime': 7.27.6 + '@emotion/is-prop-valid': 0.7.3 + css-jss: 10.10.0 + hoist-non-react-statics: 3.3.2 + is-in-browser: 1.1.3 + jss: 10.10.0 + jss-preset-default: 10.10.0 + prop-types: 15.8.1 + react: 18.3.1 + shallow-equal: 1.2.1 + theming: 3.3.0(react@18.3.1) + tiny-warning: 1.0.3 + + react-promise-suspense@0.3.4: + dependencies: + fast-deep-equal: 2.0.1 + + react-refresh@0.17.0: {} + + react-remove-scroll-bar@2.3.8(@types/react@18.3.23)(react@18.3.1): + dependencies: + react: 18.3.1 + react-style-singleton: 2.2.3(@types/react@18.3.23)(react@18.3.1) + tslib: 2.8.1 + optionalDependencies: + '@types/react': 18.3.23 + + react-remove-scroll@2.7.1(@types/react@18.3.23)(react@18.3.1): + dependencies: + react: 18.3.1 + react-remove-scroll-bar: 2.3.8(@types/react@18.3.23)(react@18.3.1) + react-style-singleton: 2.2.3(@types/react@18.3.23)(react@18.3.1) + tslib: 2.8.1 + use-callback-ref: 1.3.3(@types/react@18.3.23)(react@18.3.1) + use-sidecar: 1.1.3(@types/react@18.3.23)(react@18.3.1) + optionalDependencies: + '@types/react': 18.3.23 + + react-router@7.6.2(react-dom@18.3.1(react@18.3.1))(react@18.3.1): + dependencies: + cookie: 1.0.2 + react: 18.3.1 + set-cookie-parser: 2.7.1 + optionalDependencies: + react-dom: 18.3.1(react@18.3.1) + + react-style-singleton@2.2.3(@types/react@18.3.23)(react@18.3.1): + dependencies: + get-nonce: 1.0.1 + react: 18.3.1 + tslib: 2.8.1 + optionalDependencies: + '@types/react': 18.3.23 + + react@18.3.1: + dependencies: + loose-envify: 1.4.0 + + readdirp@3.6.0: + dependencies: + picomatch: 2.3.1 + + readdirp@4.1.2: {} + + real-require@0.2.0: {} + + recaseai@0.0.37(ws@8.18.2)(zod@3.25.64): + dependencies: + '@anthropic-ai/sdk': 0.32.1 + '@supabase/supabase-js': 2.50.0 + '@types/cors': 2.8.19 + '@types/express': 5.0.3 + '@types/node': 22.15.32 + async-listen: 3.1.0 + axios: 1.10.0 + commander: 12.1.0 + cors: 2.8.5 + dotenv: 16.5.0 + express: 4.21.2 + figures: 6.1.0 + inquirer: 12.6.3(@types/node@22.15.32) + ksuid: 3.0.0 + nanoid: 5.1.5 + openai: 4.104.0(ws@8.18.2)(zod@3.25.64) + ora: 8.2.0 + picocolors: 1.1.1 + pino: 9.7.0 + tsx: 4.20.3 + typescript: 5.7.3 + transitivePeerDependencies: + - bufferutil + - debug + - encoding + - supports-color + - utf-8-validate + - ws + - zod + + redis-errors@1.2.0: {} + + redis-parser@3.0.0: + dependencies: + redis-errors: 1.2.0 + + require-directory@2.1.1: {} + + requires-port@1.0.0: {} + + resend@4.6.0(react-dom@18.3.1(react@18.3.1))(react@18.3.1): + dependencies: + '@react-email/render': 1.1.2(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + transitivePeerDependencies: + - react + - react-dom + + resolve-from@4.0.0: {} + + resolve-pkg-maps@1.0.0: {} + + restore-cursor@5.1.0: + dependencies: + onetime: 7.0.0 + signal-exit: 4.1.0 + + reusify@1.1.0: {} + + rollup@4.43.0: + dependencies: + '@types/estree': 1.0.7 + optionalDependencies: + '@rollup/rollup-android-arm-eabi': 4.43.0 + '@rollup/rollup-android-arm64': 4.43.0 + '@rollup/rollup-darwin-arm64': 4.43.0 + '@rollup/rollup-darwin-x64': 4.43.0 + '@rollup/rollup-freebsd-arm64': 4.43.0 + '@rollup/rollup-freebsd-x64': 4.43.0 + '@rollup/rollup-linux-arm-gnueabihf': 4.43.0 + '@rollup/rollup-linux-arm-musleabihf': 4.43.0 + '@rollup/rollup-linux-arm64-gnu': 4.43.0 + '@rollup/rollup-linux-arm64-musl': 4.43.0 + '@rollup/rollup-linux-loongarch64-gnu': 4.43.0 + '@rollup/rollup-linux-powerpc64le-gnu': 4.43.0 + '@rollup/rollup-linux-riscv64-gnu': 4.43.0 + '@rollup/rollup-linux-riscv64-musl': 4.43.0 + '@rollup/rollup-linux-s390x-gnu': 4.43.0 + '@rollup/rollup-linux-x64-gnu': 4.43.0 + '@rollup/rollup-linux-x64-musl': 4.43.0 + '@rollup/rollup-win32-arm64-msvc': 4.43.0 + '@rollup/rollup-win32-ia32-msvc': 4.43.0 + '@rollup/rollup-win32-x64-msvc': 4.43.0 + fsevents: 2.3.3 + + rou3@0.5.1: {} + + rou3@0.6.3: {} + + run-async@3.0.0: {} + + run-parallel@1.2.0: + dependencies: + queue-microtask: 1.2.3 + + rxjs@7.8.2: + dependencies: + tslib: 2.8.1 + + safe-buffer@5.2.1: {} + + safe-stable-stringify@2.5.0: {} + + safer-buffer@2.1.2: {} + + scheduler@0.23.2: + dependencies: + loose-envify: 1.4.0 + + secure-json-parse@2.7.0: {} + + selderee@0.11.0: + dependencies: + parseley: 0.12.1 + + semver@6.3.1: {} + + semver@7.7.2: {} + + send@0.19.0: + dependencies: + debug: 2.6.9 + depd: 2.0.0 + destroy: 1.2.0 + encodeurl: 1.0.2 + escape-html: 1.0.3 + etag: 1.8.1 + fresh: 0.5.2 + http-errors: 2.0.0 + mime: 1.6.0 + ms: 2.1.3 + on-finished: 2.4.1 + range-parser: 1.2.1 + statuses: 2.0.1 + transitivePeerDependencies: + - supports-color + + serialize-error@8.1.0: + dependencies: + type-fest: 0.20.2 + + serialize-javascript@6.0.2: + dependencies: + randombytes: 2.1.0 + + serve-static@1.16.2: + dependencies: + encodeurl: 2.0.0 + escape-html: 1.0.3 + parseurl: 1.3.3 + send: 0.19.0 + transitivePeerDependencies: + - supports-color + + set-cookie-parser@2.7.1: {} + + setprototypeof@1.2.0: {} + + shallow-equal@1.2.1: {} + + sharp@0.34.2: + dependencies: + color: 4.2.3 + detect-libc: 2.0.4 + semver: 7.7.2 + optionalDependencies: + '@img/sharp-darwin-arm64': 0.34.2 + '@img/sharp-darwin-x64': 0.34.2 + '@img/sharp-libvips-darwin-arm64': 1.1.0 + '@img/sharp-libvips-darwin-x64': 1.1.0 + '@img/sharp-libvips-linux-arm': 1.1.0 + '@img/sharp-libvips-linux-arm64': 1.1.0 + '@img/sharp-libvips-linux-ppc64': 1.1.0 + '@img/sharp-libvips-linux-s390x': 1.1.0 + '@img/sharp-libvips-linux-x64': 1.1.0 + '@img/sharp-libvips-linuxmusl-arm64': 1.1.0 + '@img/sharp-libvips-linuxmusl-x64': 1.1.0 + '@img/sharp-linux-arm': 0.34.2 + '@img/sharp-linux-arm64': 0.34.2 + '@img/sharp-linux-s390x': 0.34.2 + '@img/sharp-linux-x64': 0.34.2 + '@img/sharp-linuxmusl-arm64': 0.34.2 + '@img/sharp-linuxmusl-x64': 0.34.2 + '@img/sharp-wasm32': 0.34.2 + '@img/sharp-win32-arm64': 0.34.2 + '@img/sharp-win32-ia32': 0.34.2 + '@img/sharp-win32-x64': 0.34.2 + optional: true + + shebang-command@2.0.0: + dependencies: + shebang-regex: 3.0.0 + + shebang-regex@3.0.0: {} + + side-channel-list@1.0.0: + dependencies: + es-errors: 1.3.0 + object-inspect: 1.13.4 + + side-channel-map@1.0.1: + dependencies: + call-bound: 1.0.4 + es-errors: 1.3.0 + get-intrinsic: 1.3.0 + object-inspect: 1.13.4 + + side-channel-weakmap@1.0.2: + dependencies: + call-bound: 1.0.4 + es-errors: 1.3.0 + get-intrinsic: 1.3.0 + object-inspect: 1.13.4 + side-channel-map: 1.0.1 + + side-channel@1.1.0: + dependencies: + es-errors: 1.3.0 + object-inspect: 1.13.4 + side-channel-list: 1.0.0 + side-channel-map: 1.0.1 + side-channel-weakmap: 1.0.2 + + signal-exit@4.1.0: {} + + simple-swizzle@0.2.2: + dependencies: + is-arrayish: 0.3.2 + optional: true + + simple-update-notifier@2.0.0: + dependencies: + semver: 7.7.2 + + slash@3.0.0: {} + + smart-buffer@4.2.0: {} + + snake-case@3.0.4: + dependencies: + dot-case: 3.0.4 + tslib: 2.8.1 + + snakecase-keys@8.0.1: + dependencies: + map-obj: 4.3.0 + snake-case: 3.0.4 + type-fest: 4.41.0 + + socket.io-adapter@2.5.5: + dependencies: + debug: 4.3.7 + ws: 8.17.1 + transitivePeerDependencies: + - bufferutil + - supports-color + - utf-8-validate + + socket.io-parser@4.2.4: + dependencies: + '@socket.io/component-emitter': 3.1.2 + debug: 4.3.7 + transitivePeerDependencies: + - supports-color + + socket.io@4.8.1: + dependencies: + accepts: 1.3.8 + base64id: 2.0.0 + cors: 2.8.5 + debug: 4.3.7 + engine.io: 6.6.4 + socket.io-adapter: 2.5.5 + socket.io-parser: 4.2.4 + transitivePeerDependencies: + - bufferutil + - supports-color + - utf-8-validate + + socks-proxy-agent@8.0.5: + dependencies: + agent-base: 7.1.3 + debug: 4.4.1 + socks: 2.8.5 + transitivePeerDependencies: + - supports-color + + socks@2.8.5: + dependencies: + ip-address: 9.0.5 + smart-buffer: 4.2.0 + + sonic-boom@4.2.0: + dependencies: + atomic-sleep: 1.0.0 + + sonner@2.0.5(react-dom@18.3.1(react@18.3.1))(react@18.3.1): + dependencies: + react: 18.3.1 + react-dom: 18.3.1(react@18.3.1) + + source-map-js@1.2.1: {} + + source-map-support@0.5.21: + dependencies: + buffer-from: 1.1.2 + source-map: 0.6.1 + + source-map@0.6.1: {} + + space-separated-tokens@2.0.2: {} + + split2@4.2.0: {} + + sprintf-js@1.1.3: {} + + stack-trace@0.0.10: {} + + standard-as-callback@2.1.0: {} + + statuses@2.0.1: {} + + std-env@3.9.0: {} + + stdin-discarder@0.2.2: {} + + streamsearch@1.1.0: {} + + streamx@2.22.1: + dependencies: + fast-fifo: 1.3.2 + text-decoder: 1.2.3 + optionalDependencies: + bare-events: 2.5.4 + + string-width@4.2.3: + dependencies: + emoji-regex: 8.0.0 + is-fullwidth-code-point: 3.0.0 + strip-ansi: 6.0.1 + + string-width@5.1.2: + dependencies: + eastasianwidth: 0.2.0 + emoji-regex: 9.2.2 + strip-ansi: 7.1.0 + + string-width@7.2.0: + dependencies: + emoji-regex: 10.4.0 + get-east-asian-width: 1.3.0 + strip-ansi: 7.1.0 + + stringify-entities@4.0.4: + dependencies: + character-entities-html4: 2.1.0 + character-entities-legacy: 3.0.0 + + strip-ansi@6.0.1: + dependencies: + ansi-regex: 5.0.1 + + strip-ansi@7.1.0: + dependencies: + ansi-regex: 6.1.0 + + strip-bom@3.0.0: {} + + strip-json-comments@3.1.1: {} + + stripe@17.7.0: + dependencies: + '@types/node': 22.15.32 + qs: 6.14.0 + + styled-jsx@5.1.6(react@18.3.1): + dependencies: + client-only: 0.0.1 + react: 18.3.1 + + super-regex@0.2.0: + dependencies: + clone-regexp: 3.0.0 + function-timeout: 0.1.1 + time-span: 5.1.0 + + superagent@10.2.1: + dependencies: + component-emitter: 1.3.1 + cookiejar: 2.1.4 + debug: 4.4.1 + fast-safe-stringify: 2.1.1 + form-data: 4.0.3 + formidable: 3.5.4 + methods: 1.1.2 + mime: 2.6.0 + qs: 6.14.0 + transitivePeerDependencies: + - supports-color + + supports-color@5.5.0: + dependencies: + has-flag: 3.0.0 + + supports-color@7.2.0: + dependencies: + has-flag: 4.0.0 + + supports-color@8.1.1: + dependencies: + has-flag: 4.0.0 + + svix-fetch@3.0.0: + dependencies: + node-fetch: 2.7.0 + whatwg-fetch: 3.6.20 + transitivePeerDependencies: + - encoding + + svix-react@1.13.4(@babel/core@7.27.4)(prop-types@15.8.1)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(svix@1.67.0): + dependencies: + iframe-resizer-react: 1.1.1(@babel/core@7.27.4)(prop-types@15.8.1)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + react: 18.3.1 + react-dom: 18.3.1(react@18.3.1) + svix: 1.67.0 + transitivePeerDependencies: + - '@babel/core' + - prop-types + - supports-color + + svix@1.67.0: + dependencies: + '@stablelib/base64': 1.0.1 + '@types/node': 22.15.32 + es6-promise: 4.2.8 + fast-sha256: 1.3.0 + svix-fetch: 3.0.0 + url-parse: 1.5.10 + transitivePeerDependencies: + - encoding + + swr@2.3.3(react@18.3.1): + dependencies: + dequal: 2.0.3 + react: 18.3.1 + use-sync-external-store: 1.5.0(react@18.3.1) + + symbol-observable@1.2.0: {} + + tailwind-merge@3.3.1: {} + + tailwindcss-animate@1.0.7(tailwindcss@4.1.10): + dependencies: + tailwindcss: 4.1.10 + + tailwindcss@4.1.10: {} + + tapable@2.2.2: {} + + tar-fs@3.0.9: + dependencies: + pump: 3.0.3 + tar-stream: 3.1.7 + optionalDependencies: + bare-fs: 4.1.5 + bare-path: 3.0.0 + transitivePeerDependencies: + - bare-buffer + + tar-stream@3.1.7: + dependencies: + b4a: 1.6.7 + fast-fifo: 1.3.2 + streamx: 2.22.1 + + tar@7.4.3: + dependencies: + '@isaacs/fs-minipass': 4.0.1 + chownr: 3.0.0 + minipass: 7.1.2 + minizlib: 3.0.2 + mkdirp: 3.0.1 + yallist: 5.0.0 + + text-decoder@1.2.3: + dependencies: + b4a: 1.6.7 + + theming@3.3.0(react@18.3.1): + dependencies: + hoist-non-react-statics: 3.3.2 + prop-types: 15.8.1 + react: 18.3.1 + react-display-name: 0.2.5 + tiny-warning: 1.0.3 + + thread-stream@3.1.0: + dependencies: + real-require: 0.2.0 + + throttleit@2.1.0: {} + + time-span@5.1.0: + dependencies: + convert-hrtime: 5.0.0 + + tiny-warning@1.0.3: {} + + tinyglobby@0.2.14: + dependencies: + fdir: 6.4.6(picomatch@4.0.2) + picomatch: 4.0.2 + + tmp@0.0.33: + dependencies: + os-tmpdir: 1.0.2 + + to-regex-range@5.0.1: + dependencies: + is-number: 7.0.0 + + toidentifier@1.0.1: {} + + touch@3.1.1: {} + + tr46@0.0.3: {} + + trim-lines@3.0.1: {} + + ts-api-utils@2.1.0(typescript@5.7.3): + dependencies: + typescript: 5.7.3 + + ts-node@10.9.2(@types/node@22.15.32)(typescript@5.7.3): + dependencies: + '@cspotcode/source-map-support': 0.8.1 + '@tsconfig/node10': 1.0.11 + '@tsconfig/node12': 1.0.11 + '@tsconfig/node14': 1.0.3 + '@tsconfig/node16': 1.0.4 + '@types/node': 22.15.32 + acorn: 8.15.0 + acorn-walk: 8.3.4 + arg: 4.1.3 + create-require: 1.1.1 + diff: 4.0.2 + make-error: 1.3.6 + typescript: 5.7.3 + v8-compile-cache-lib: 3.0.1 + yn: 3.1.1 + + tsc-alias@1.8.16: + dependencies: + chokidar: 3.6.0 + commander: 9.5.0 + get-tsconfig: 4.10.1 + globby: 11.1.0 + mylas: 2.1.13 + normalize-path: 3.0.0 + plimit-lit: 1.6.1 + + tsconfig-paths@4.2.0: + dependencies: + json5: 2.2.3 + minimist: 1.2.8 + strip-bom: 3.0.0 + + tslib@2.8.1: {} + + tsx@4.20.3: + dependencies: + esbuild: 0.25.5 + get-tsconfig: 4.10.1 + optionalDependencies: + fsevents: 2.3.3 + + type-check@0.4.0: + dependencies: + prelude-ls: 1.2.1 + + type-fest@0.20.2: {} + + type-fest@0.21.3: {} + + type-fest@4.41.0: {} + + type-is@1.6.18: + dependencies: + media-typer: 0.3.0 + mime-types: 2.1.35 + + typed-query-selector@2.12.0: {} + + typescript-eslint@8.34.0(eslint@9.29.0(jiti@2.4.2))(typescript@5.7.3): + dependencies: + '@typescript-eslint/eslint-plugin': 8.34.0(@typescript-eslint/parser@8.34.0(eslint@9.29.0(jiti@2.4.2))(typescript@5.7.3))(eslint@9.29.0(jiti@2.4.2))(typescript@5.7.3) + '@typescript-eslint/parser': 8.34.0(eslint@9.29.0(jiti@2.4.2))(typescript@5.7.3) + '@typescript-eslint/utils': 8.34.0(eslint@9.29.0(jiti@2.4.2))(typescript@5.7.3) + eslint: 9.29.0(jiti@2.4.2) + typescript: 5.7.3 + transitivePeerDependencies: + - supports-color + + typescript@5.7.3: {} + + typescript@5.8.3: {} + + uncrypto@0.1.3: {} + + undefsafe@2.0.5: {} + + undici-types@5.26.5: {} + + undici-types@6.21.0: {} + + undici-types@7.8.0: {} + + unist-util-is@6.0.0: + dependencies: + '@types/unist': 3.0.3 + + unist-util-position@5.0.0: + dependencies: + '@types/unist': 3.0.3 + + unist-util-stringify-position@4.0.0: + dependencies: + '@types/unist': 3.0.3 + + unist-util-visit-parents@6.0.1: + dependencies: + '@types/unist': 3.0.3 + unist-util-is: 6.0.0 + + unist-util-visit@5.0.0: + dependencies: + '@types/unist': 3.0.3 + unist-util-is: 6.0.0 + unist-util-visit-parents: 6.0.1 + + unpipe@1.0.0: {} + + update-browserslist-db@1.1.3(browserslist@4.25.0): + dependencies: + browserslist: 4.25.0 + escalade: 3.2.0 + picocolors: 1.1.1 + + uri-js@4.4.1: + dependencies: + punycode: 2.3.1 + + url-parse@1.5.10: + dependencies: + querystringify: 2.2.0 + requires-port: 1.0.0 + + use-callback-ref@1.3.3(@types/react@18.3.23)(react@18.3.1): + dependencies: + react: 18.3.1 + tslib: 2.8.1 + optionalDependencies: + '@types/react': 18.3.23 + + use-sidecar@1.1.3(@types/react@18.3.23)(react@18.3.1): + dependencies: + detect-node-es: 1.1.0 + react: 18.3.1 + tslib: 2.8.1 + optionalDependencies: + '@types/react': 18.3.23 + + use-sync-external-store@1.5.0(react@18.3.1): + dependencies: + react: 18.3.1 + + utils-merge@1.0.1: {} + + uuid@9.0.1: {} + + v8-compile-cache-lib@3.0.1: {} + + vary@1.1.2: {} + + vaul@1.1.2(@types/react-dom@18.3.7(@types/react@18.3.23))(@types/react@18.3.23)(react-dom@18.3.1(react@18.3.1))(react@18.3.1): + dependencies: + '@radix-ui/react-dialog': 1.1.14(@types/react-dom@18.3.7(@types/react@18.3.23))(@types/react@18.3.23)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + react: 18.3.1 + react-dom: 18.3.1(react@18.3.1) + transitivePeerDependencies: + - '@types/react' + - '@types/react-dom' + + vfile-message@4.0.2: + dependencies: + '@types/unist': 3.0.3 + unist-util-stringify-position: 4.0.0 + + vfile@6.0.3: + dependencies: + '@types/unist': 3.0.3 + vfile-message: 4.0.2 + + vite@6.3.5(@types/node@22.15.32)(jiti@2.4.2)(lightningcss@1.30.1)(tsx@4.20.3): + dependencies: + esbuild: 0.25.5 + fdir: 6.4.6(picomatch@4.0.2) + picomatch: 4.0.2 + postcss: 8.5.5 + rollup: 4.43.0 + tinyglobby: 0.2.14 + optionalDependencies: + '@types/node': 22.15.32 + fsevents: 2.3.3 + jiti: 2.4.2 + lightningcss: 1.30.1 + tsx: 4.20.3 + + vscode-oniguruma@2.0.1: {} + + vscode-textmate@9.2.0: {} + + warning@4.0.3: + dependencies: + loose-envify: 1.4.0 + + web-streams-polyfill@4.0.0-beta.3: {} + + web-vitals@4.2.4: {} + + webidl-conversions@3.0.1: {} + + whatwg-fetch@3.6.20: {} + + whatwg-url@5.0.0: + dependencies: + tr46: 0.0.3 + webidl-conversions: 3.0.1 + + which@2.0.2: + dependencies: + isexe: 2.0.0 + + word-wrap@1.2.5: {} + + workerpool@9.3.2: {} + + wrap-ansi@6.2.0: + dependencies: + ansi-styles: 4.3.0 + string-width: 4.2.3 + strip-ansi: 6.0.1 + + wrap-ansi@7.0.0: + dependencies: + ansi-styles: 4.3.0 + string-width: 4.2.3 + strip-ansi: 6.0.1 + + wrap-ansi@8.1.0: + dependencies: + ansi-styles: 6.2.1 + string-width: 5.1.2 + strip-ansi: 7.1.0 + + wrappy@1.0.2: {} + + ws@8.17.1: {} + + ws@8.18.2: {} + + xtend@4.0.2: {} + + y18n@5.0.8: {} + + yallist@3.1.1: {} + + yallist@5.0.0: {} + + yargs-parser@21.1.1: {} + + yargs-unparser@2.0.0: + dependencies: + camelcase: 6.3.0 + decamelize: 4.0.0 + flat: 5.0.2 + is-plain-obj: 2.1.0 + + yargs@17.7.2: + dependencies: + cliui: 8.0.1 + escalade: 3.2.0 + get-caller-file: 2.0.5 + require-directory: 2.1.1 + string-width: 4.2.3 + y18n: 5.0.8 + yargs-parser: 21.1.1 + + yauzl@2.10.0: + dependencies: + buffer-crc32: 0.2.13 + fd-slicer: 1.1.0 + + yn@3.1.1: {} + + yocto-queue@0.1.0: {} + + yoctocolors-cjs@2.1.2: {} + + yoctocolors@2.1.1: {} + + zod-to-json-schema@3.24.5(zod@3.25.64): + dependencies: + zod: 3.25.64 + + zod@3.25.64: {} + + zwitch@2.0.4: {} diff --git a/pnpm-workspace.yaml b/pnpm-workspace.yaml new file mode 100644 index 000000000..52a0f5dc4 --- /dev/null +++ b/pnpm-workspace.yaml @@ -0,0 +1,4 @@ +packages: + - 'shared' + - 'server' + - 'vite' diff --git a/run.sh b/run.sh new file mode 100755 index 000000000..c9f7f6edf --- /dev/null +++ b/run.sh @@ -0,0 +1,3 @@ +if [[ $1 == *"docker-compose"* ]]; then + docker compose -f "$1" up +fi diff --git a/server/.env.example b/server/.env.example new file mode 100644 index 000000000..1ede252c1 --- /dev/null +++ b/server/.env.example @@ -0,0 +1,15 @@ +# AUTH +BETTER_AUTH_SECRET= +BETTER_AUTH_URL=http://localhost:8080 +CLIENT_URL=http://localhost:3000 + +# STRIPE REQUIRED +ENCRYPTION_IV= +ENCRYPTION_PASSWORD= +SERVER_URL= + +# DATABASE +DATABASE_URL= + +# IF using external redis +# REDIS_URL=redis://valkey:6379 \ No newline at end of file diff --git a/server/auth-schema.ts b/server/auth-schema.ts new file mode 100644 index 000000000..52f1c8dbf --- /dev/null +++ b/server/auth-schema.ts @@ -0,0 +1,112 @@ +import { + pgTable, + text, + timestamp, + boolean, + integer, +} from "drizzle-orm/pg-core"; + +export const user = pgTable("user", { + id: text("id").primaryKey(), + name: text("name").notNull(), + email: text("email").notNull().unique(), + emailVerified: boolean("email_verified") + .$defaultFn(() => false) + .notNull(), + image: text("image"), + createdAt: timestamp("created_at", { withTimezone: true }) + .$defaultFn(() => /* @__PURE__ */ new Date()) + .notNull(), + updatedAt: timestamp("updated_at", { withTimezone: true }) + .$defaultFn(() => /* @__PURE__ */ new Date()) + .notNull(), + role: text("role"), + banned: boolean("banned"), + banReason: text("ban_reason"), + banExpires: timestamp("ban_expires"), +}).enableRLS(); + +export const session = pgTable("session", { + id: text("id").primaryKey(), + expiresAt: timestamp("expires_at", { withTimezone: true }).notNull(), + token: text("token").notNull().unique(), + createdAt: timestamp("created_at", { withTimezone: true }).notNull(), + updatedAt: timestamp("updated_at", { withTimezone: true }).notNull(), + ipAddress: text("ip_address"), + userAgent: text("user_agent"), + userId: text("user_id") + .notNull() + .references(() => user.id, { onDelete: "cascade" }), + impersonatedBy: text("impersonated_by"), + activeOrganizationId: text("active_organization_id"), +}).enableRLS(); + +export const account = pgTable("account", { + id: text("id").primaryKey(), + accountId: text("account_id").notNull(), + providerId: text("provider_id").notNull(), + userId: text("user_id") + .notNull() + .references(() => user.id, { onDelete: "cascade" }), + accessToken: text("access_token"), + refreshToken: text("refresh_token"), + idToken: text("id_token"), + accessTokenExpiresAt: timestamp("access_token_expires_at", { + withTimezone: true, + }), + refreshTokenExpiresAt: timestamp("refresh_token_expires_at", { + withTimezone: true, + }), + scope: text("scope"), + password: text("password"), + createdAt: timestamp("created_at").notNull(), + updatedAt: timestamp("updated_at").notNull(), +}).enableRLS(); + +export const verification = pgTable("verification", { + id: text("id").primaryKey(), + identifier: text("identifier").notNull(), + value: text("value").notNull(), + expiresAt: timestamp("expires_at", { withTimezone: true }).notNull(), + createdAt: timestamp("created_at", { withTimezone: true }).$defaultFn( + () => /* @__PURE__ */ new Date(), + ), + updatedAt: timestamp("updated_at", { withTimezone: true }).$defaultFn( + () => /* @__PURE__ */ new Date(), + ), +}).enableRLS(); + +export const organization = pgTable("organization", { + id: text("id").primaryKey(), + name: text("name").notNull(), + slug: text("slug").unique(), + logo: text("logo"), + createdAt: timestamp("created_at", { withTimezone: true }).notNull(), + metadata: text("metadata"), +}).enableRLS(); + +export const member = pgTable("member", { + id: text("id").primaryKey(), + organizationId: text("organization_id") + .notNull() + .references(() => organization.id, { onDelete: "cascade" }), + userId: text("user_id") + .notNull() + .references(() => user.id, { onDelete: "cascade" }), + role: text("role").default("member").notNull(), + createdAt: timestamp("created_at", { withTimezone: true }).notNull(), +}).enableRLS(); + +export const invitation = pgTable("invitation", { + id: text("id").primaryKey(), + organizationId: text("organization_id") + .notNull() + .references(() => organization.id, { onDelete: "cascade" }), + email: text("email").notNull(), + role: text("role"), + status: text("status").default("pending").notNull(), + expiresAt: timestamp("expires_at", { withTimezone: true }).notNull(), + inviterId: text("inviter_id") + .notNull() + .references(() => user.id, { onDelete: "cascade" }), +}).enableRLS(); diff --git a/server/emails/OTPEmail.tsx b/server/emails/OTPEmail.tsx new file mode 100644 index 000000000..152a13afa --- /dev/null +++ b/server/emails/OTPEmail.tsx @@ -0,0 +1,57 @@ +import * as React from "react"; +import { + Html, + Head, + Body, + Container, + Section, + Text, + Heading, + Tailwind, +} from "@react-email/components"; + +const OTPEmail = (props: { otpCode: string }) => { + return ( + + + + + + + Verification code + + + + Enter the following verification code when prompted: + + + + {props.otpCode} + + + + To protect your account, do not share this code. + + + {/* Footer */} +
+ + Autumn +
+ 2261 Market Street STE 22390 +
+ San Francisco, CA, US, 94114 +
+
+
+ +
+ + ); +}; + +OTPEmail.PreviewProps = { + otpCode: "884085", +}; + +export default OTPEmail; diff --git a/server/package.json b/server/package.json index b153e4de8..1ac008645 100644 --- a/server/package.json +++ b/server/package.json @@ -5,6 +5,7 @@ "main": "index.js", "type": "module", "scripts": { + "email": "email dev -p 3001", "dev": "NODE_ENV=development nodemon --no-deprecation --exec tsx src/index.ts --ignore scripts --ignore tests", "start": "tsx src/index.ts", "workers": "tsx watch src/workers.ts", @@ -36,18 +37,20 @@ "dependencies": { "@ai-sdk/anthropic": "^1.2.10", "@anthropic-ai/sdk": "^0.32.1", - "@autumn/shared": "*", + "@autumn/shared": "workspace:*", "@clerk/express": "^1.3.22", "@date-fns/tz": "^1.2.0", "@date-fns/utc": "^2.1.0", "@logtail/node": "^0.5.2", + "@react-email/components": "^0.0.42", "@supabase/supabase-js": "^2.46.2", "@types/cors": "^2.8.17", "@types/express": "^5.0.0", "ai": "^4.3.10", "autumn-js": "^0.0.64", + "better-auth": "^1.2.9", "body-parser": "^1.20.3", - "bullmq": "^5.31.1", + "bullmq": "^5.54.0", "chai": "^5.1.2", "chai-http": "^5.1.1", "chalk": "^5.3.0", @@ -58,6 +61,7 @@ "currency-symbol-map": "^5.1.0", "date-fns": "^4.1.0", "decimal.js": "^10.5.0", + "detect-content-type": "^1.2.0", "dotenv": "^16.5.0", "drizzle-orm": "^0.43.1", "express": "^4.21.1", @@ -66,6 +70,7 @@ "ioredis": "^5.5.0", "ksuid": "^3.0.0", "lodash-es": "^4.17.21", + "mime-detect": "^1.3.0", "nodemon": "^3.1.7", "openai": "^4.85.2", "pg": "^8.13.1", @@ -73,12 +78,14 @@ "pino-pretty": "^13.0.0", "postgres": "^3.4.7", "posthog-node": "^4.17.2", + "react": "^18.2.0", "recaseai": "^0.0.37", "resend": "^4.1.1", "stripe": "^17.5.0", "svix": "^1.45.1", "tsc-alias": "^1.8.16", - "ws": "^8.18.0" + "ws": "^8.18.0", + "zod": "^3.25.23" }, "devDependencies": { "@types/chai": "^5.0.1", @@ -87,9 +94,13 @@ "@types/mocha": "^10.0.10", "@types/node": "^22.13.4", "@types/pg": "^8.11.10", + "@types/react": "^18.3.18", + "@types/react-dom": "^18.3.5", + "@types/ws": "^8.18.1", "drizzle-kit": "^0.31.1", "mocha": "^11.1.0", "puppeteer": "^24.2.0", + "react-email": "4.0.16", "ts-node": "^10.9.2", "tsconfig-paths": "^4.2.0", "tsx": "^4.19.4", diff --git a/server/run.sh b/server/run.sh index 313e0e56d..e9e2d9c6a 100755 --- a/server/run.sh +++ b/server/run.sh @@ -5,6 +5,8 @@ filename=$1 # Check if the file path contains "shell" + + if [[ $filename == *"shell"* ]]; then $filename elif [[ $filename == *"/tests/"* ]]; then @@ -17,6 +19,9 @@ elif [[ $filename == *"/tests/"* ]]; then else ./test.sh custom $path_after_tests fi + +elif [[ $filename == *".sh"* ]]; then + $filename else npx tsx $filename fi diff --git a/server/src/db/initDrizzle.ts b/server/src/db/initDrizzle.ts index 661187126..eaffacf35 100644 --- a/server/src/db/initDrizzle.ts +++ b/server/src/db/initDrizzle.ts @@ -3,7 +3,10 @@ dotenv.config(); import postgres from "postgres"; import { drizzle } from "drizzle-orm/postgres-js"; -import { schemas } from "@autumn/shared"; +import { schemas as schema } from "@autumn/shared"; + +export let client = postgres(process.env.DATABASE_URL!); +export let db = drizzle(client, { schema }); export const initDrizzle = (params?: { maxConnections?: number }) => { let maxConnections = params?.maxConnections || 10; @@ -11,10 +14,7 @@ export const initDrizzle = (params?: { maxConnections?: number }) => { max: maxConnections, }); - const db = drizzle(client, { - schema: schemas, - // logger: true, // Enable SQL logging for debugging - }); + const db = drizzle(client, { schema }); return { db, client }; }; diff --git a/server/src/external/autumn/autumnWebhookRouter.ts b/server/src/external/autumn/autumnWebhookRouter.ts index 553bb2163..ddd1f3226 100644 --- a/server/src/external/autumn/autumnWebhookRouter.ts +++ b/server/src/external/autumn/autumnWebhookRouter.ts @@ -1,7 +1,7 @@ -import express from "express"; +import express, { Router } from "express"; import { Webhook } from "svix"; -export const autumnWebhookRouter = express.Router(); +export const autumnWebhookRouter: Router = express.Router(); const verifyAutumnWebhook = async (req: any, res: any) => { const wh = new Webhook(process.env.AUTUMN_WEBHOOK_SECRET!); @@ -54,5 +54,5 @@ autumnWebhookRouter.post( success: true, message: "Webhook received", }); - } + }, ); diff --git a/server/src/external/caching/CacheManager.ts b/server/src/external/caching/CacheManager.ts index 7e6df2e15..26c06ac38 100644 --- a/server/src/external/caching/CacheManager.ts +++ b/server/src/external/caching/CacheManager.ts @@ -15,10 +15,10 @@ export class CacheManager { console.log("Initializing Cache Manager..."); if (this.initialized) return; - const redisUrl = process.env.REDIS_BACKUP_URL; + const redisUrl = process.env.REDIS_BACKUP_URL || process.env.REDIS_URL; if (!redisUrl) { - throw new Error("Redis URL not configured"); + throw new Error("Cache error: no redis connection string set in env"); } this.client = new Redis(redisUrl, { diff --git a/server/src/external/logtail/logtailUtils.ts b/server/src/external/logtail/logtailUtils.ts index a8306e935..aa2f2c727 100644 --- a/server/src/external/logtail/logtailUtils.ts +++ b/server/src/external/logtail/logtailUtils.ts @@ -1,3 +1,6 @@ +import dotenv from "dotenv"; +dotenv.config(); + import { initLogger } from "@/errors/logger.js"; import { Logtail } from "@logtail/node"; @@ -36,6 +39,10 @@ const createLogMethod = (pinoMethod: any, logtailMethod: any) => { pinoMethod(message); } + if (!logtailMethod) { + return; + } + // Logtail format: message first, then object (if exists) if (Object.keys(mergedObj).length > 0) { logtailMethod(message, mergedObj); @@ -45,34 +52,42 @@ const createLogMethod = (pinoMethod: any, logtailMethod: any) => { }; }; -export const createLogtail = () => { - const logtail = new Logtail(process.env.LOGTAIL_SOURCE_TOKEN!, { - endpoint: process.env.LOGTAIL_INGESTING_HOST!, - }); +export const createLogger = ({ + sourceToken, + ingestingHost, +}: { + sourceToken: string; + ingestingHost: string; +}) => { + let logtail: any; + if (sourceToken && ingestingHost) { + logtail = new Logtail(sourceToken, { + endpoint: ingestingHost, + }); + } // Create a custom logger that logs to both Logtail and console const logger = { debug: createLogMethod( pinoLogger.debug.bind(pinoLogger), - logtail.debug.bind(logtail), + logtail?.debug.bind(logtail), ), info: createLogMethod( pinoLogger.info.bind(pinoLogger), - logtail.info.bind(logtail), + logtail?.info.bind(logtail), ), warn: createLogMethod( pinoLogger.warn.bind(pinoLogger), - logtail.warn.bind(logtail), + logtail?.warn.bind(logtail), ), error: createLogMethod( pinoLogger.error.bind(pinoLogger), - logtail.error.bind(logtail), + logtail?.error.bind(logtail), ), use: (fn: any) => { - logtail.use(fn); + logtail?.use(fn); }, - getLogtail: () => logtail, - flush: () => logtail.flush(), + flush: () => logtail?.flush(), }; return logger; @@ -90,7 +105,21 @@ export const createLogtailWithContext = (context: any) => { return logtail; }; +export const createLogtail = () => { + return createLogger({ + sourceToken: process.env.LOGTAIL_SOURCE_TOKEN!, + ingestingHost: process.env.LOGTAIL_INGESTING_HOST!, + }); +}; + export const createLogtailAll = () => { + if ( + !process.env.LOGTAIL_ALL_SOURCE_TOKEN || + !process.env.LOGTAIL_ALL_INGESTING_HOST + ) { + return null; + } + const logtail = new Logtail(process.env.LOGTAIL_ALL_SOURCE_TOKEN!, { endpoint: process.env.LOGTAIL_ALL_INGESTING_HOST!, }); @@ -98,5 +127,5 @@ export const createLogtailAll = () => { return logtail; }; -// const logtail = createLogtailLogger(); -// export default logtail; +export const logger = createLogtail(); +export const logtailAll = createLogtailAll(); diff --git a/server/src/external/posthog/createPosthogCli.ts b/server/src/external/posthog/createPosthogCli.ts index 471fa7669..c4321a35f 100644 --- a/server/src/external/posthog/createPosthogCli.ts +++ b/server/src/external/posthog/createPosthogCli.ts @@ -2,11 +2,9 @@ import dotenv from "dotenv"; dotenv.config(); import { PostHog } from "posthog-node"; -import { initLogger } from "@/errors/logger.js"; +import { logger } from "../logtail/logtailUtils.js"; export const createPosthogCli = () => { - const logger = initLogger(); - if (!process.env.POSTHOG_API_KEY) { logger.warn("POSTHOG_API_KEY not set, skipping posthog"); return null; diff --git a/server/src/external/resend/resendUtils.ts b/server/src/external/resend/resendUtils.ts index 972704894..fcf202940 100644 --- a/server/src/external/resend/resendUtils.ts +++ b/server/src/external/resend/resendUtils.ts @@ -1,21 +1,23 @@ import { Resend } from "resend"; -export const createCli = () => { +export const createResendCli = () => { return new Resend(process.env.RESEND_API_KEY); }; export const sendTextEmail = async ({ + from, to, subject, body, }: { + from?: string; to: string; subject: string; body: string; }) => { - const resend = createCli(); + const resend = createResendCli(); await resend.emails.send({ - from: `Ayush `, + from: from || `Ayush `, to: to, subject: subject, text: body, @@ -23,17 +25,19 @@ export const sendTextEmail = async ({ }; export const sendHtmlEmail = async ({ + from, to, subject, body, }: { + from?: string; to: string; subject: string; body: string; }) => { - const resend = createCli(); + const resend = createResendCli(); await resend.emails.send({ - from: `Ayush `, + from: from || `Ayush `, to: to, subject: subject, html: body, diff --git a/server/src/external/resend/safeResend.ts b/server/src/external/resend/safeResend.ts new file mode 100644 index 000000000..d48e626d3 --- /dev/null +++ b/server/src/external/resend/safeResend.ts @@ -0,0 +1,23 @@ +import { logger } from "../logtail/logtailUtils.js"; + +export function safeResend any>({ + fn, + action, +}: { + fn: T; + action: string; +}): (...args: Parameters) => Promise | undefined> { + return async (...args: Parameters) => { + if (!process.env.RESEND_API_KEY || !process.env.RESEND_DOMAIN) { + logger.warn( + `RESEND_API_KEY or RESEND_DOMAIN is not set, skipping ${action}`, + ); + return; + } + try { + return await fn(...args); + } catch (error) { + logger.error(`Error ${action}: ${error}`); + } + }; +} diff --git a/server/src/external/stripe/createStripePrice/createStripeArrearProrated.ts b/server/src/external/stripe/createStripePrice/createStripeArrearProrated.ts index 5199ffe7b..05f11556a 100644 --- a/server/src/external/stripe/createStripePrice/createStripeArrearProrated.ts +++ b/server/src/external/stripe/createStripePrice/createStripeArrearProrated.ts @@ -89,7 +89,7 @@ export const createStripeMeteredPrice = async ({ const stripePrice = await stripeCli.prices.create({ ...productData, ...priceAmountData, - currency: org.default_currency, + currency: org.default_currency || "usd", nickname: `Autumn Price (${feature!.name}) [Placeholder]`, recurring: { ...(billingIntervalToStripe(price.config!.interval!) as any), @@ -194,7 +194,7 @@ export const createStripeArrearProrated = async ({ let stripePrice = await stripeCli.prices.create({ ...productData, - currency: org.default_currency, + currency: org.default_currency || "usd", ...priceAmountData, recurring: { ...(recurringData as any), diff --git a/server/src/external/stripe/createStripePrice/createStripeFixedPrice.ts b/server/src/external/stripe/createStripePrice/createStripeFixedPrice.ts index 8c0333a50..dc4fdfd87 100644 --- a/server/src/external/stripe/createStripePrice/createStripeFixedPrice.ts +++ b/server/src/external/stripe/createStripePrice/createStripeFixedPrice.ts @@ -26,7 +26,7 @@ export const createStripeFixedPrice = async ({ const stripePrice = await stripeCli.prices.create({ product: product.processor!.id, unit_amount: amount, - currency: org.default_currency, + currency: org.default_currency!, recurring: { ...(billingIntervalToStripe(config.interval!) as any), }, diff --git a/server/src/external/stripe/createStripePrice/createStripeInArrear.ts b/server/src/external/stripe/createStripePrice/createStripeInArrear.ts index 9de373c56..4e3526230 100644 --- a/server/src/external/stripe/createStripePrice/createStripeInArrear.ts +++ b/server/src/external/stripe/createStripePrice/createStripeInArrear.ts @@ -255,7 +255,7 @@ export const createStripeInArrearPrice = async ({ const stripePrice = await stripeCli.prices.create({ ...productData, ...priceAmountData, - currency: org.default_currency, + currency: org.default_currency!, recurring: { ...(billingIntervalToStripe(price.config!.interval!) as any), meter: meter!.id, diff --git a/server/src/external/stripe/createStripePrice/createStripePrepaid.ts b/server/src/external/stripe/createStripePrice/createStripePrepaid.ts index 72dd4a79a..e57d63c43 100644 --- a/server/src/external/stripe/createStripePrice/createStripePrepaid.ts +++ b/server/src/external/stripe/createStripePrice/createStripePrepaid.ts @@ -110,7 +110,7 @@ export const createStripePrepaid = async ({ ...productData, // unit_amount_decimal: (amount * 100).toString(), unit_amount_decimal: unitAmountDecimalStr, - currency: org.default_currency, + currency: org.default_currency!, }); config.stripe_product_id = stripePrice.product as string; @@ -133,7 +133,7 @@ export const createStripePrepaid = async ({ stripePrice = await stripeCli.prices.create({ ...productData, - currency: org.default_currency, + currency: org.default_currency!, ...priceAmountData, recurring: { ...(recurringData as any), diff --git a/server/src/external/stripe/stripeOnboardingUtils.ts b/server/src/external/stripe/stripeOnboardingUtils.ts index c5cc0465b..4e14dfe1b 100644 --- a/server/src/external/stripe/stripeOnboardingUtils.ts +++ b/server/src/external/stripe/stripeOnboardingUtils.ts @@ -1,4 +1,5 @@ -import { AppEnv } from "@autumn/shared"; +import RecaseError from "@/utils/errorUtils.js"; +import { AppEnv, ErrCode } from "@autumn/shared"; import Stripe from "stripe"; export const checkKeyValid = async (apiKey: string) => { @@ -18,8 +19,19 @@ export const createWebhookEndpoint = async ( ) => { const stripe = new Stripe(apiKey); + const webhookBaseUrl = + process.env.SERVER_URL || process.env.STRIPE_WEBHOOK_URL; + + if (!webhookBaseUrl) { + throw new RecaseError({ + message: "Stripe webhook baseURL not found", + code: ErrCode.StripeKeyInvalid, + statusCode: 500, + }); + } + const endpoint = await stripe.webhookEndpoints.create({ - url: `${process.env.SERVER_URL}/webhooks/stripe/${orgId}/${env}`, + url: `${webhookBaseUrl}/webhooks/stripe/${orgId}/${env}`, enabled_events: [ "customer.subscription.created", "customer.subscription.updated", diff --git a/server/src/external/stripe/stripeWebhooks.ts b/server/src/external/stripe/stripeWebhooks.ts index 18de39c9e..6c8f3c343 100644 --- a/server/src/external/stripe/stripeWebhooks.ts +++ b/server/src/external/stripe/stripeWebhooks.ts @@ -1,7 +1,10 @@ +import express, { Router } from "express"; +import stripe, { Stripe } from "stripe"; +import chalk from "chalk"; + import { OrgService } from "@/internal/orgs/OrgService.js"; import { AuthType, LoggerAction, Organization } from "@autumn/shared"; -import express from "express"; -import stripe, { Stripe } from "stripe"; + import { handleCheckoutSessionCompleted } from "./webhookHandlers/handleCheckoutCompleted.js"; import { handleSubscriptionUpdated } from "./webhookHandlers/handleSubUpdated.js"; import { handleSubDeleted } from "./webhookHandlers/handleSubDeleted.js"; @@ -10,7 +13,6 @@ import { getStripeWebhookSecret } from "@/internal/orgs/orgUtils.js"; import { handleInvoicePaid } from "./webhookHandlers/handleInvoicePaid.js"; import { handleRequestError } from "@/utils/errorUtils.js"; import { handleInvoiceCreated } from "./webhookHandlers/handleInvoiceCreated/handleInvoiceCreated.js"; -import chalk from "chalk"; import { handleInvoiceFinalized } from "./webhookHandlers/handleInvoiceFinalized.js"; import { handleSubscriptionScheduleCanceled } from "./webhookHandlers/handleSubScheduleCanceled.js"; import { createLogtailWithContext } from "../logtail/logtailUtils.js"; @@ -18,7 +20,7 @@ import { handleCusDiscountDeleted } from "./webhookHandlers/handleCusDiscountDel import { ExtendedRequest } from "@/utils/models/Request.js"; import { createStripeCli } from "./utils.js"; -export const stripeWebhookRouter = express.Router(); +export const stripeWebhookRouter: Router = express.Router(); const logStripeWebhook = ({ req, diff --git a/server/src/external/supabase/safeSb.ts b/server/src/external/supabase/safeSb.ts new file mode 100644 index 000000000..682fadec5 --- /dev/null +++ b/server/src/external/supabase/safeSb.ts @@ -0,0 +1,23 @@ +import { logger } from "../logtail/logtailUtils.js"; + +export function safeSb any>({ + fn, + action, +}: { + fn: T; + action: string; +}): (...args: Parameters) => Promise | undefined> { + return async (...args: Parameters) => { + if (!process.env.SUPABASE_URL || !process.env.SUPABASE_SERVICE_KEY) { + logger.warn( + `SUPABASE_URL or SUPABASE_SERVICE_KEY is not set, skipping ${action}`, + ); + return; + } + try { + return await fn(...args); + } catch (error) { + logger.error(`Error ${action}: ${error}`); + } + }; +} diff --git a/server/src/external/supabase/storageUtils.ts b/server/src/external/supabase/storageUtils.ts new file mode 100644 index 000000000..f49c88865 --- /dev/null +++ b/server/src/external/supabase/storageUtils.ts @@ -0,0 +1,42 @@ +import { SupabaseClient } from "@supabase/supabase-js"; +import { createSupabaseClient } from "../supabaseUtils.js"; + +export const uploadFile = async ({ + path, + file, + contentType, +}: { + path: string; + file: Buffer; + contentType?: string; +}) => { + const sb = createSupabaseClient(); + + const { data, error } = await sb.storage.from("autumn").upload(path, file, { + upsert: true, + contentType, + }); + + if (error) { + throw error; + } + + return data; +}; + +export const getUploadUrl = async ({ path }: { path: string }) => { + const sb = createSupabaseClient(); + await sb.storage.from("autumn").remove([path]); + + const { data, error } = await sb.storage + .from("autumn") + .createSignedUploadUrl(path, { + upsert: true, + }); + + if (error) { + throw error; + } + + return data; +}; diff --git a/server/src/external/supabase/subscribeToOrgUpdates.ts b/server/src/external/supabase/subscribeToOrgUpdates.ts index d6fe114e8..8170e4264 100644 --- a/server/src/external/supabase/subscribeToOrgUpdates.ts +++ b/server/src/external/supabase/subscribeToOrgUpdates.ts @@ -1,29 +1,32 @@ import { clearOrgCache } from "@/internal/orgs/orgUtils/clearOrgCache.js"; import { createSupabaseClient } from "../supabaseUtils.js"; import { DrizzleCli } from "@/db/initDrizzle.js"; +import { safeSb } from "./safeSb.js"; -export const subscribeToOrgUpdates = ({ db }: { db: DrizzleCli }) => { - try { - const sb = createSupabaseClient(); - sb.channel("table-db-changes") - .on( - "postgres_changes", - { - event: "UPDATE", - schema: "public", - table: "organizations", - }, - async (payload) => { - // await clearOrgCache(payload.new.id); - try { - await clearOrgCache({ db, orgId: payload.new.id }); - } catch (error) { - console.warn("Error clearing org cache:", error); - } - }, - ) - .subscribe(); - } catch (error) { - console.warn("Error subscribing to org updates:", error); - } -}; +export const subscribeToOrgUpdates = safeSb({ + fn: ({ db }: { db: DrizzleCli }) => { + try { + const sb = createSupabaseClient(); + sb.channel("table-db-changes") + .on( + "postgres_changes", + { + event: "UPDATE", + schema: "public", + table: "organizations", + }, + async (payload) => { + try { + await clearOrgCache({ db, orgId: payload.new.id }); + } catch (error) { + console.warn("Error clearing org cache:", error); + } + }, + ) + .subscribe(); + } catch (error) { + console.warn("Error subscribing to org updates:", error); + } + }, + action: "subscribe to org updates", +}); diff --git a/server/src/external/svix/svixHelpers.ts b/server/src/external/svix/svixHelpers.ts new file mode 100644 index 000000000..45c91c37d --- /dev/null +++ b/server/src/external/svix/svixHelpers.ts @@ -0,0 +1,68 @@ +import { AppEnv, Organization } from "@autumn/shared"; +import { createSvixCli, getSvixAppId, safeSvix } from "./svixUtils.js"; + +export const createSvixApp = safeSvix({ + fn: async ({ + name, + orgId, + env, + }: { + name: string; + orgId: string; + env: AppEnv; + }) => { + const svix = createSvixCli(); + const app = await svix.application.create({ + name, + metadata: { + org_id: orgId, + env, + }, + }); + return app; + }, + action: "createSvixApp", +}); + +export const deleteSvixApp = safeSvix({ + fn: async ({ appId }: { appId: string }) => { + const svix = createSvixCli(); + await svix.application.delete(appId); + }, + action: "deleteSvixApp", +}); + +export const sendSvixEvent = safeSvix({ + fn: async ({ + org, + env, + eventType, + data, + }: { + org: Organization; + env: AppEnv; + eventType: string; + data: any; + }) => { + const svix = createSvixCli(); + return await svix.message.create(getSvixAppId({ org, env }), { + eventType, + payload: { + type: eventType, + data, + }, + }); + }, + action: "sendSvixEvent", +}); + +export const getSvixDashboardUrl = safeSvix({ + fn: async ({ org, env }: { org: Organization; env: AppEnv }) => { + const appId = getSvixAppId({ org, env }); + + const svix = createSvixCli(); + const dashboard = await svix.authentication.appPortalAccess(appId, {}); + return dashboard.url; + }, + action: "getSvixDashboardUrl", +}); diff --git a/server/src/external/svix/svixUtils.ts b/server/src/external/svix/svixUtils.ts index 55f5476d0..2d03d6fb2 100644 --- a/server/src/external/svix/svixUtils.ts +++ b/server/src/external/svix/svixUtils.ts @@ -1,11 +1,32 @@ import { AppEnv } from "@autumn/shared"; import { Organization } from "@autumn/shared"; import { Svix } from "svix"; +import { logger } from "../logtail/logtailUtils.js"; export const createSvixCli = () => { return new Svix(process.env.SVIX_API_KEY as string); }; +export function safeSvix any>({ + fn, + action, +}: { + fn: T; + action: string; +}): (...args: Parameters) => Promise | undefined> { + return async (...args: Parameters) => { + if (!process.env.SVIX_API_KEY) { + logger.warn(`SVIX_API_KEY is not set, skipping ${action}`); + return; + } + try { + return await fn(...args); + } catch (error) { + logger.error(`Error ${action}: ${error}`); + } + }; +} + export const getSvixAppId = ({ org, env, @@ -18,63 +39,3 @@ export const getSvixAppId = ({ ? svixConfig.live_app_id : svixConfig.sandbox_app_id; }; - -export const createSvixApp = async ({ - name, - orgId, - env, -}: { - name: string; - orgId: string; - env: AppEnv; -}) => { - const svix = createSvixCli(); - const app = await svix.application.create({ - name, - metadata: { - org_id: orgId, - env, - }, - }); - return app; -}; - -export const deleteSvixApp = async ({ appId }: { appId: string }) => { - const svix = createSvixCli(); - await svix.application.delete(appId); -}; - -export const sendSvixEvent = async ({ - org, - env, - eventType, - data, -}: { - org: Organization; - env: AppEnv; - eventType: string; - data: any; -}) => { - const svix = createSvixCli(); - return await svix.message.create(getSvixAppId({ org, env }), { - eventType, - payload: { - type: eventType, - data, - }, - }); -}; - -export const getSvixDashboardUrl = async ({ - org, - env, -}: { - org: Organization; - env: AppEnv; -}) => { - const appId = getSvixAppId({ org, env }); - - const svix = createSvixCli(); - const dashboard = await svix.authentication.appPortalAccess(appId, {}); - return dashboard.url; -}; diff --git a/server/src/external/unkeyUtils.ts b/server/src/external/unkeyUtils.ts deleted file mode 100644 index 87d5f4a86..000000000 --- a/server/src/external/unkeyUtils.ts +++ /dev/null @@ -1,59 +0,0 @@ -// import { AppEnv } from "@autumn/shared"; -// import { Unkey } from "@unkey/api"; - -// const UNKEY_API_ID = "api_2fcMv43jiAbBySAgDubovfpVUABP"; -// const createUnkeyCli = () => { -// return new Unkey({ rootKey: process.env.UNKEY_ROOT_KEY! }); -// }; - -// export const createKey = async ({ -// env, -// name, -// ownerId, -// prefix, -// meta, -// }: { -// env: AppEnv; -// name: string; -// ownerId: string; -// prefix: string; -// meta: any; -// }) => { -// const unkey = createUnkeyCli(); -// const key = await unkey.keys.create({ -// apiId: UNKEY_API_ID, -// name, -// prefix, -// ownerId, -// meta, -// environment: env, -// }); -// return key; -// }; - -// export const updateKey = async (keyId: string, meta: any) => { -// const unkey = createUnkeyCli(); -// await unkey.keys.update({ -// keyId, -// meta, -// }); -// }; - -// export const deleteKey = async (keyId: string) => { -// const unkey = createUnkeyCli(); -// await unkey.keys.delete({ keyId }); -// }; - -// export const validateApiKey = async (apiKey: string) => { -// const unkey = createUnkeyCli(); -// const { result, error } = await unkey.keys.verify({ -// apiId: UNKEY_API_ID, -// key: apiKey, -// }); - -// if (error || !result.valid) { -// throw new Error("Invalid API key"); -// } - -// return result; -// }; diff --git a/server/src/external/webhooks/clerkWebhooks.ts b/server/src/external/webhooks/clerkWebhooks.ts index c4def8bd2..8cf6a47f8 100644 --- a/server/src/external/webhooks/clerkWebhooks.ts +++ b/server/src/external/webhooks/clerkWebhooks.ts @@ -2,249 +2,96 @@ import { Request, Response } from "express"; import { Webhook } from "svix"; import { OrgService } from "@/internal/orgs/OrgService.js"; import RecaseError, { handleRequestError } from "@/utils/errorUtils.js"; -import { SupabaseClient } from "@supabase/supabase-js"; -import { createClerkCli } from "../clerkUtils.js"; -import { sendOnboardingEmail } from "./sendOnboardingEmail.js"; + import { AppEnv } from "autumn-js"; -import { deleteSvixApp } from "../svix/svixUtils.js"; -import { - deleteStripeWebhook, - initOrgSvixApps, -} from "@/internal/orgs/orgUtils.js"; +import { deleteSvixApp } from "@/external/svix/svixHelpers.js"; +import { deleteStripeWebhook } from "@/internal/orgs/orgUtils.js"; -import { DrizzleCli } from "@/db/initDrizzle.js"; -import { constructOrg } from "@/internal/orgs/orgUtils.js"; -import { createOnboardingProducts } from "@/internal/orgs/onboarding/createOnboardingProducts.js"; import { eq } from "drizzle-orm"; +import { DrizzleCli } from "@/db/initDrizzle.js"; import { Organization, organizations } from "@autumn/shared"; -const verifyClerkWebhook = async (req: Request, res: Response) => { - const wh = new Webhook(process.env.CLERK_SIGNING_SECRET!); +// const verifyClerkWebhook = async (req: Request, res: Response) => { +// const wh = new Webhook(process.env.CLERK_SIGNING_SECRET!); - const headers = req.headers; - const payload = req.body; +// const headers = req.headers; +// const payload = req.body; - const svix_id = headers["svix-id"]; - const svix_timestamp = headers["svix-timestamp"]; - const svix_signature = headers["svix-signature"]; +// const svix_id = headers["svix-id"]; +// const svix_timestamp = headers["svix-timestamp"]; +// const svix_signature = headers["svix-signature"]; - if (!svix_id || !svix_timestamp || !svix_signature) { - res.status(400).json({ - success: false, - message: "Error: Missing svix headers", - }); - return; - } +// if (!svix_id || !svix_timestamp || !svix_signature) { +// res.status(400).json({ +// success: false, +// message: "Error: Missing svix headers", +// }); +// return; +// } - let evt: any; - try { - evt = wh.verify(payload, { - "svix-id": svix_id as string, - "svix-timestamp": svix_timestamp as string, - "svix-signature": svix_signature as string, - }); - } catch (err) { - console.log("Error: Could not verify webhook"); - res.status(400).json({ - success: false, - message: "Error: Could not verify webhook", - }); - return; - } +// let evt: any; +// try { +// evt = wh.verify(payload, { +// "svix-id": svix_id as string, +// "svix-timestamp": svix_timestamp as string, +// "svix-signature": svix_signature as string, +// }); +// } catch (err) { +// console.log("Error: Could not verify webhook"); +// res.status(400).json({ +// success: false, +// message: "Error: Could not verify webhook", +// }); +// return; +// } - return evt; -}; +// return evt; +// }; -export const handleClerkWebhook = async (req: any, res: any) => { - let event = await verifyClerkWebhook(req, res); +// export const handleClerkWebhook = async (req: any, res: any) => { +// let event = await verifyClerkWebhook(req, res); - if (!event) { - return; - } +// if (!event) { +// return; +// } - const eventType = event.type; - const eventData = event.data; +// const eventType = event.type; +// const eventData = event.data; - try { - switch (eventType) { - case "organization.created": - await saveOrgToDB({ - db: req.db, - id: eventData.id, - slug: eventData.slug, - }); - break; +// try { +// switch (eventType) { +// case "organization.created": +// await saveOrgToDB({ +// db: req.db, +// id: eventData.id, +// slug: eventData.slug, +// createdAt: eventData.created_at, +// }); +// break; - case "organization.deleted": - await handleOrgDeleted({ - db: req.db, - eventData, - }); - break; +// case "organization.deleted": +// await handleOrgDeleted({ +// db: req.db, +// eventData, +// }); +// break; - default: - break; - } - } catch (error) { - handleRequestError({ - req, - error, - res, - action: "Handle Clerk Webhook", - }); - return; - } +// default: +// break; +// } +// } catch (error) { +// handleRequestError({ +// req, +// error, +// res, +// action: "Handle Clerk Webhook", +// }); +// return; +// } - return void res.status(200).json({ - success: true, - message: "Webhook received", - }); -}; - -export const saveOrgToDB = async ({ - db, - id, - slug, -}: { - db: DrizzleCli; - id: string; - slug: string; -}) => { - console.log(`Handling organization.created: ${slug} (${id})`); - - try { - // 2. Insert org - await OrgService.insert({ - db, - org: constructOrg({ - id, - slug, - }), - }); - - // 1. Create svix webhoooks - const { sandboxApp, liveApp } = await initOrgSvixApps({ - slug, - id, - }); - - await OrgService.update({ - db, - orgId: id, - updates: { - svix_config: { sandbox_app_id: sandboxApp.id, live_app_id: liveApp.id }, - }, - }); - - console.log(`Created svix webhooks for org ${id}`); - } catch (error: any) { - if (error?.data && error.data.code == "23505") { - console.error( - `Org ${id} already exists in Supabase -- skipping creationg`, - ); - return; - } - console.error( - `Failed to insert org. Code: ${error.code}, message: ${error.message}`, - ); - return; - } - - const batch = []; - - try { - // batch.push( - // createOnboardingProducts({ - // db, - // orgId: eventData.id, - // }), - // ); - - batch.push( - sendOnboardingEmail({ - orgId: id, - clerkCli: createClerkCli(), - }), - ); - - await Promise.all(batch); - } catch (error) { - console.error( - "Failed to create default products or send onboarding email", - error, - ); - } -}; - -const handleOrgDeleted = async ({ - db, - eventData, -}: { - db: DrizzleCli; - eventData: any; -}) => { - // 1. Delete svix webhooks - - try { - console.log(`Handling organization.deleted: (${eventData.id})`); - - const org = (await db.query.organizations.findFirst({ - where: eq(organizations.id, eventData.id), - })) as unknown as Organization; - - if (!org) { - throw new RecaseError({ - message: `Clerk webhook, tried deleting org ${eventData.slug} but not found`, - code: "org_not_found", - statusCode: 404, - }); - } - - console.log("1. Deleting svix webhooks"); - const batch = []; - if (org.svix_config?.sandbox_app_id) { - batch.push( - deleteSvixApp({ - appId: org.svix_config.sandbox_app_id, - }), - ); - } - - if (org.svix_config?.live_app_id) { - batch.push( - deleteSvixApp({ - appId: org.svix_config.live_app_id, - }), - ); - } - - await Promise.all(batch); - - // 2. Delete stripe webhooks - console.log("2. Deleting stripe webhooks"); - if (org.stripe_config) { - await deleteStripeWebhook({ - org: org, - env: AppEnv.Sandbox, - }); - - await deleteStripeWebhook({ - org: org, - env: AppEnv.Live, - }); - } - - // 3. Delete org - console.log("3. Deleting org"); - await OrgService.delete({ - db, - orgId: eventData.id, - }); - - console.log(`Deleted org ${org.slug} (${org.id})`); - } catch (error) { - console.log("Failed to delete organization", error); - return; - } -}; +// return void res.status(200).json({ +// success: true, +// message: "Webhook received", +// }); +// }; diff --git a/server/src/external/webhooks/sendOnboardingEmail.ts b/server/src/external/webhooks/sendOnboardingEmail.ts deleted file mode 100644 index 38bde6466..000000000 --- a/server/src/external/webhooks/sendOnboardingEmail.ts +++ /dev/null @@ -1,50 +0,0 @@ -import { ClerkClient } from "@clerk/express"; -import { sendHtmlEmail, sendTextEmail } from "../resend/resendUtils.js"; - -const getWelcomeEmailBody = (userFirstName: string) => { - return ` -

Hey ${userFirstName} :)

- -

Just wanted to say thank you for signing up to Autumn!

- -

I'm curious--how did you hear about us? Also are you just looking around or do you have a specific use case I can help you with?

- -

Whatever the reason, anything you need I'm here to help.

- -

Ayush
-Co-founder, Autumn

- -

Oh, and join our Discord community to connect with us and other users

- `; -}; - -export const sendOnboardingEmail = async ({ - orgId, - clerkCli, -}: { - orgId: string; - clerkCli: ClerkClient; -}) => { - const memberships = - await clerkCli.organizations.getOrganizationMembershipList({ - organizationId: orgId, - }); - - for (let membership of memberships.data) { - if (!membership.publicUserData) break; - - const user = await clerkCli.users.getUser(membership.publicUserData.userId); - const email = user.primaryEmailAddress?.emailAddress; - - if (!email) break; - - console.log("Sending onboarding email to", email); - await sendHtmlEmail({ - to: email, - subject: "Anything I can help with?", - body: getWelcomeEmailBody(user.firstName ?? "there"), - }); - - break; - } -}; diff --git a/server/src/external/webhooks/webhooksRouter.ts b/server/src/external/webhooks/webhooksRouter.ts index a6ec2db4e..b9e7ad3e5 100644 --- a/server/src/external/webhooks/webhooksRouter.ts +++ b/server/src/external/webhooks/webhooksRouter.ts @@ -1,19 +1,12 @@ -import express from "express"; -import bodyParser from "body-parser"; -import { handleClerkWebhook } from "./clerkWebhooks.js"; +import express, { Router } from "express"; + import { stripeWebhookRouter } from "../stripe/stripeWebhooks.js"; import { autumnWebhookRouter } from "../autumn/autumnWebhookRouter.js"; -const webhooksRouter = express.Router(); +const webhooksRouter: Router = express.Router(); webhooksRouter.use("/stripe", stripeWebhookRouter); webhooksRouter.use("/autumn", autumnWebhookRouter); -webhooksRouter.post( - "/clerk", - bodyParser.raw({ type: "application/json" }), - handleClerkWebhook -); - export default webhooksRouter; diff --git a/server/src/index.ts b/server/src/index.ts index ca59a907f..e7711b266 100644 --- a/server/src/index.ts +++ b/server/src/index.ts @@ -8,56 +8,75 @@ import mainRouter from "./internal/mainRouter.js"; import express from "express"; import cors from "cors"; import chalk from "chalk"; -import { apiRouter } from "./internal/api/apiRouter.js"; + +import http from "http"; import webhooksRouter from "./external/webhooks/webhooksRouter.js"; -import { initLogger } from "./errors/logger.js"; +import { apiRouter } from "./internal/api/apiRouter.js"; import { QueueManager } from "./queue/QueueManager.js"; import { AppEnv } from "@autumn/shared"; -import { createSupabaseClient } from "./external/supabaseUtils.js"; -import { - createLogtail, - createLogtailAll, -} from "./external/logtail/logtailUtils.js"; +import { createLogtail } from "./external/logtail/logtailUtils.js"; import { CacheManager } from "./external/caching/CacheManager.js"; -import { initDrizzle } from "./db/initDrizzle.js"; -import { createPosthogCli } from "./external/posthog/createPosthogCli.js"; +import { logtailAll, logger } from "./external/logtail/logtailUtils.js"; +import { createPosthogCli } from "./external/posthog/createPosthogCli.js"; import { generateId } from "./utils/genUtils.js"; import { subscribeToOrgUpdates } from "./external/supabase/subscribeToOrgUpdates.js"; +import { client, db } from "./db/initDrizzle.js"; +import { toNodeHandler } from "better-auth/node"; +import { auth } from "./utils/auth.js"; +import { checkEnvVars } from "./utils/initUtils.js"; -if (!process.env.DATABASE_URL) { - console.error(`DATABASE_URL is not set`); - process.exit(1); -} - -const { db, client } = initDrizzle({ maxConnections: 10 }); - +checkEnvVars(); const init = async () => { const app = express(); - const logger = initLogger(); + + // Check if this blocks API calls... + app.use( + cors({ + origin: [ + "http://localhost:3000", + "https://app.useautumn.com", + "https://*.useautumn.com", + process.env.CLIENT_URL || "", + ], + credentials: true, + allowedHeaders: [ + "app_env", + "x-api-version", + "Authorization", + "Content-Type", + "Accept", + "Origin", + "X-API-Version", + "X-Requested-With", + "Access-Control-Request-Method", + "Access-Control-Request-Headers", + "Cache-Control", + "If-Match", + "If-None-Match", + "If-Modified-Since", + "If-Unmodified-Since", + ], + }), + ); + + app.all("/api/auth/*", toNodeHandler(auth)); + const server = http.createServer(app); + const posthog = createPosthogCli(); + server.keepAliveTimeout = 120000; // 120 seconds server.headersTimeout = 120000; // 120 seconds should be >= keepAliveTimeout await QueueManager.getInstance(); // initialize the queue manager await CacheManager.getInstance(); - const supabaseClient = createSupabaseClient(); - - // Optional services - const logtailAll = createLogtailAll(); - const posthog = createPosthogCli(); subscribeToOrgUpdates({ db }); app.use((req: any, res: any, next: any) => { - req.sb = supabaseClient; - req.db = db; - - req.logger = logger; - req.logtailAll = logtailAll; req.env = req.env = req.headers["app_env"] || AppEnv.Sandbox; - + req.db = db; req.logtailAll = logtailAll; req.posthog = posthog; @@ -69,7 +88,7 @@ const init = async () => { headersClone.authorization = undefined; headersClone.Authorization = undefined; - logtailAll.info(`${req.method} ${req.originalUrl}`, { + logtailAll?.info(`${req.method} ${req.originalUrl}`, { url: req.originalUrl, method: req.method, headers: headersClone, @@ -77,9 +96,8 @@ const init = async () => { }); req.logtail = createLogtail(); - req.logger = req.logtail; } catch (error) { - req.logtail = logtailAll; // fallback + req.logtail = logger; // fallback console.error(`Error creating req.logtail`); console.error(error); } @@ -91,8 +109,6 @@ const init = async () => { next(); }); - app.use(cors()); - app.use("/webhooks", webhooksRouter); app.use((req: any, res, next) => { @@ -142,14 +158,7 @@ if (process.env.NODE_ENV === "development") { } cluster.on("exit", (worker, code, signal) => { - try { - let logtail = createLogtail(); - logtail.error(`WORKER DIED: ${worker.process.pid}`); - logtail.flush(); - } catch (error) { - console.log("Error sending log to logtail", error); - } - // LOG in Render + logger.error(`WORKER DIED: ${worker.process.pid}`); cluster.fork(); }); } else { @@ -175,3 +184,21 @@ async function gracefulShutdown() { process.exit(1); } } + +// Close connections gracefully? +const closeConnections = async () => { + console.log("Closing connections"); + await client.end(); +}; + +process.on("SIGTERM", async () => { + console.log("SIGTERM received, shutting down gracefully"); + await closeConnections(); + process.exit(0); +}); + +process.on("SIGINT", async () => { + console.log("SIGINT received, shutting down gracefully"); + await closeConnections(); + process.exit(0); +}); diff --git a/server/src/internal/admin/adminRouter.ts b/server/src/internal/admin/adminRouter.ts new file mode 100644 index 000000000..d35a673ff --- /dev/null +++ b/server/src/internal/admin/adminRouter.ts @@ -0,0 +1,158 @@ +import { handleFrontendReqError } from "@/utils/errorUtils.js"; +import { ExtendedRequest } from "@/utils/models/Request.js"; +import { member, organizations, user } from "@autumn/shared"; +import { and, desc, eq, gt, gte, ilike, inArray, lt, or } from "drizzle-orm"; +import { Router } from "express"; + +export const adminRouter: Router = Router(); + +adminRouter.get("/users", async (req: any, res: any) => { + try { + const { db } = req as ExtendedRequest; + + let { sortKey, search, after, before } = req.query; + + if (after) { + after = { + id: after.split(",")[0], + createdAt: new Date(after.split(",")[1]), + }; + } else if (before) { + before = { + id: before.split(",")[0], + createdAt: new Date(before.split(",")[1]), + }; + } + + const users = await db + .select() + .from(user) + .where( + and( + search + ? or( + ilike(user.email, `%${search as string}%`), + ilike(user.name, `%${search as string}%`), + ilike(user.id, `%${search as string}%`), + ) + : undefined, + after + ? or( + lt(user.createdAt, after.createdAt), + or( + and( + eq(user.createdAt, after.createdAt), + lt(user.id, after.id), + ), + ), + ) + : undefined, + before + ? or( + gte(user.createdAt, before.createdAt), + or( + and( + eq(user.createdAt, before.createdAt), + gt(user.id, before.id), + ), + ), + ) + : undefined, + ), + ) + .orderBy(desc(user.createdAt), desc(user.id)) + .limit(21); + + res.json({ + rows: users.slice(0, 20), + hasNextPage: users.length > 20, + }); + } catch (error) { + handleFrontendReqError({ + res, + req, + error, + action: "admin: search users", + }); + } +}); + +adminRouter.get("/orgs", async (req: any, res: any) => { + try { + const { db } = req as ExtendedRequest; + + let { search, after, before } = req.query; + + if (after) { + after = { + id: after.split(",")[0], + createdAt: new Date(after.split(",")[1]), + }; + } else if (before) { + before = { + id: before.split(",")[0], + createdAt: new Date(before.split(",")[1]), + }; + } + + const orgs = await db + .select() + .from(organizations) + .where( + and( + search + ? or(ilike(organizations.name, `%${search as string}%`)) + : undefined, + after + ? or( + lt(organizations.createdAt, after.createdAt), + or( + and( + eq(organizations.createdAt, after.createdAt), + lt(organizations.id, after.id), + ), + ), + ) + : undefined, + before + ? or( + gte(organizations.createdAt, before.createdAt), + or( + and( + eq(organizations.createdAt, before.createdAt), + gt(organizations.id, before.id), + ), + ), + ) + : undefined, + ), + ) + .orderBy(desc(organizations.createdAt), desc(organizations.id)) + .limit(21); + + let orgIds = orgs.map((org) => org.id); + + let memberships = await db + .select() + .from(member) + .leftJoin(user, eq(member.userId, user.id)) + .where(inArray(member.organizationId, orgIds)); + + res.json({ + rows: orgs.slice(0, 20).map((org) => ({ + ...org, + users: memberships + .filter((membership) => membership.member.organizationId === org.id) + .map((membership) => membership.user?.email), + })), + hasNextPage: orgs.length > 20, + }); + } catch (error) { + handleFrontendReqError({ + res, + req, + error, + action: "admin: search orgs", + }); + } +}); diff --git a/server/src/internal/admin/adminUtils/userAnalytics.ts b/server/src/internal/admin/adminUtils/userAnalytics.ts new file mode 100644 index 000000000..f6a39bff3 --- /dev/null +++ b/server/src/internal/admin/adminUtils/userAnalytics.ts @@ -0,0 +1,14 @@ +import { DrizzleCli } from "@/db/initDrizzle.js"; +import { ExtendedRequest } from "@/utils/models/Request.js"; +import { user } from "@autumn/shared"; +import { count } from "drizzle-orm"; + +// Required stats (by interval): +// 1. User count +// 2. Retained count +// 3. Churned count + +export const getUserCount = async ({ db }: { db: DrizzleCli }) => { + const userCount = await db.select({ count: count() }).from(user); + return userCount[0].count; +}; diff --git a/server/src/internal/admin/withAdminAuth.ts b/server/src/internal/admin/withAdminAuth.ts new file mode 100644 index 000000000..7430180fa --- /dev/null +++ b/server/src/internal/admin/withAdminAuth.ts @@ -0,0 +1,34 @@ +import { ErrCode } from "@/errors/errCodes.js"; +import { auth } from "@/utils/auth.js"; +import { ADMIN_USER_IDs } from "@/utils/constants.js"; +import { ExtendedRequest } from "@/utils/models/Request.js"; +import { NextFunction } from "express"; + +export const withAdminAuth = async (req: any, res: any, next: NextFunction) => { + const { logtail: logger, userId } = req as ExtendedRequest; + + try { + const data = await auth.api.getSession({ + headers: req.headers, + }); + + if ( + !ADMIN_USER_IDs.includes(data?.session?.userId || "") && + !ADMIN_USER_IDs.includes(data?.session?.impersonatedBy || "") + ) { + return res.status(403).json({ + error: { + code: ErrCode.InvalidRequest, + message: "Method not allowed", + }, + }); + } + + console.log("Admin auth passed"); + + next(); + } catch (error: any) { + logger.error(`Admin req failed: ${error.message}`); + return res.status(400).json(); + } +}; diff --git a/server/src/internal/analytics/handlers/handleProductsUpdated.ts b/server/src/internal/analytics/handlers/handleProductsUpdated.ts index 6234c6aac..b9a6b0c73 100644 --- a/server/src/internal/analytics/handlers/handleProductsUpdated.ts +++ b/server/src/internal/analytics/handlers/handleProductsUpdated.ts @@ -8,7 +8,7 @@ import { Organization, } from "@autumn/shared"; -import { sendSvixEvent } from "../../../external/svix/svixUtils.js"; +import { sendSvixEvent } from "@/external/svix/svixHelpers.js"; import { CusService } from "@/internal/customers/CusService.js"; import { getCustomerDetails } from "@/internal/customers/cusUtils/getCustomerDetails.js"; @@ -205,7 +205,7 @@ export const handleProductsUpdated = async ({ } // 2. Send Svix event - const res = await sendSvixEvent({ + await sendSvixEvent({ org, env, eventType: "customer.products.updated", diff --git a/server/src/internal/api/apiRouter.ts b/server/src/internal/api/apiRouter.ts index 790a0ba7e..16ec50e7f 100644 --- a/server/src/internal/api/apiRouter.ts +++ b/server/src/internal/api/apiRouter.ts @@ -21,18 +21,12 @@ import { analyticsMiddleware } from "@/middleware/analyticsMiddleware.js"; import rewardRouter from "./rewards/rewardRouter.js"; import expireRouter from "../customers/expire/expireRouter.js"; -const apiRouter = Router(); +const apiRouter: Router = Router(); apiRouter.use(apiAuthMiddleware); apiRouter.use(pricingMiddleware); apiRouter.use(analyticsMiddleware); -apiRouter.get("/auth", (req: any, res) => { - res.json({ - message: `Authenticated -- Hello ${req.minOrg?.slug}!`, - }); -}); - apiRouter.use("/customers", cusRouter); apiRouter.use("/invoices", invoiceRouter); apiRouter.use("/products", productApiRouter); diff --git a/server/src/internal/api/components/componentRouter.ts b/server/src/internal/api/components/componentRouter.ts index 8d2b03482..9fa0c3570 100644 --- a/server/src/internal/api/components/componentRouter.ts +++ b/server/src/internal/api/components/componentRouter.ts @@ -11,7 +11,7 @@ import { routeHandler } from "@/utils/routerUtils.js"; import { FullCusProduct, CusProductStatus, ProductV2 } from "@autumn/shared"; import { Router } from "express"; -export const componentRouter = Router(); +export const componentRouter: Router = Router(); componentRouter.get("/pricing_table", async (req: any, res) => routeHandler({ diff --git a/server/src/internal/api/cusRouter.ts b/server/src/internal/api/cusRouter.ts index 491b1fac3..75485e07a 100644 --- a/server/src/internal/api/cusRouter.ts +++ b/server/src/internal/api/cusRouter.ts @@ -20,9 +20,8 @@ import { handleUpdateCustomer } from "../customers/handlers/handleUpdateCustomer import { handleCreateBillingPortal } from "../customers/handlers/handleCreateBillingPortal.js"; import { handleGetCustomer } from "../customers/handlers/handleGetCustomer.js"; import { CusSearchService } from "@/internal/customers/CusSearchService.js"; -import assert from "assert"; -export const cusRouter = Router(); +export const cusRouter: Router = Router(); cusRouter.post("/all/search", async (req: any, res: any) => { try { diff --git a/server/src/internal/api/entities/entityRouter.ts b/server/src/internal/api/entities/entityRouter.ts index af6f40d99..e839c47f8 100644 --- a/server/src/internal/api/entities/entityRouter.ts +++ b/server/src/internal/api/entities/entityRouter.ts @@ -1,18 +1,15 @@ import { Router } from "express"; import { routeHandler } from "@/utils/routerUtils.js"; -import { EntityService } from "./EntityService.js"; import { CusService } from "@/internal/customers/CusService.js"; -import RecaseError from "@/utils/errorUtils.js"; -import { ErrCode } from "@autumn/shared"; import { handleGetEntity } from "./handlers/handleGetEntity.js"; import { handlePostEntityRequest } from "../../entities/handlers/handleCreateEntity/handleCreateEntity.js"; import { handleDeleteEntity } from "./handlers/handleDeleteEntity.js"; -export const entityRouter = Router({ mergeParams: true }); +export const entityRouter: Router = Router({ mergeParams: true }); // List entityes -entityRouter.get("", (req, res) => +entityRouter.get("", (req: any, res: any) => routeHandler({ req, res, diff --git a/server/src/internal/api/entitled/entitledRouter.ts b/server/src/internal/api/entitled/entitledRouter.ts index 4f44f4844..3b8c7cccd 100644 --- a/server/src/internal/api/entitled/entitledRouter.ts +++ b/server/src/internal/api/entitled/entitledRouter.ts @@ -30,7 +30,7 @@ import { getOrCreateCustomer } from "@/internal/customers/cusUtils/getOrCreateCu import { getCheckPreview } from "./getCheckPreview.js"; import { orgToVersion } from "@/utils/versionUtils.js"; -export const entitledRouter = Router(); +export const entitledRouter: Router = Router(); const getRequiredAndActualBalance = ({ cusEnts, diff --git a/server/src/internal/api/events/eventRouter.ts b/server/src/internal/api/events/eventRouter.ts index db713779e..987cf5d2c 100644 --- a/server/src/internal/api/events/eventRouter.ts +++ b/server/src/internal/api/events/eventRouter.ts @@ -30,7 +30,7 @@ import { DrizzleCli } from "@/db/initDrizzle.js"; import { ExtendedRequest } from "@/utils/models/Request.js"; import { getEventTimestamp } from "./eventUtils.js"; -export const eventsRouter = Router(); +export const eventsRouter: Router = Router(); const getEventAndCustomer = async ({ req, diff --git a/server/src/internal/api/events/usageRouter.ts b/server/src/internal/api/events/usageRouter.ts index ee17ffb92..9864643f2 100644 --- a/server/src/internal/api/events/usageRouter.ts +++ b/server/src/internal/api/events/usageRouter.ts @@ -3,7 +3,6 @@ import { CusProductStatus, Customer, ErrCode, - Event, EventInsert, FeatureType, FeatureUsageType, @@ -12,22 +11,17 @@ import RecaseError, { handleRequestError } from "@/utils/errorUtils.js"; import { generateId, nullish } from "@/utils/genUtils.js"; import { EventService } from "./EventService.js"; -import { OrgService } from "@/internal/orgs/OrgService.js"; -import { FeatureService } from "@/internal/features/FeatureService.js"; import { StatusCodes } from "http-status-codes"; -import { QueueManager } from "@/queue/QueueManager.js"; - import { JobName } from "@/queue/JobName.js"; import { getOrCreateCustomer } from "@/internal/customers/cusUtils/getOrCreateCustomer.js"; import { creditSystemContainsFeature } from "@/internal/features/creditSystemUtils.js"; import { addTaskToQueue } from "@/queue/queueUtils.js"; -import { getOrgAndFeatures } from "@/internal/orgs/orgUtils.js"; import { getEventTimestamp } from "./eventUtils.js"; import { ExtendedRequest } from "@/utils/models/Request.js"; -import { runUpdateBalanceTask } from "@/trigger/updateBalanceTask.js"; import { runUpdateUsageTask } from "@/trigger/updateUsageTask.js"; -export const eventsRouter = Router(); -export const usageRouter = Router(); + +export const eventsRouter: Router = Router(); +export const usageRouter: Router = Router(); const getCusFeatureAndOrg = async ({ req, diff --git a/server/src/internal/api/features/featureApiRouter.ts b/server/src/internal/api/features/featureApiRouter.ts index 70cd253da..5b7a67013 100644 --- a/server/src/internal/api/features/featureApiRouter.ts +++ b/server/src/internal/api/features/featureApiRouter.ts @@ -6,7 +6,7 @@ import RecaseError, { import { handleUpdateFeature } from "./handlers/handleUpdateFeature.js"; import { Feature, FeatureResponseSchema, FeatureType } from "@autumn/shared"; import { CreateFeatureSchema } from "@autumn/shared"; -import express from "express"; +import express, { Router } from "express"; import { generateId } from "@/utils/genUtils.js"; import { ErrCode } from "@/errors/errCodes.js"; @@ -20,7 +20,7 @@ import { JobName } from "@/queue/JobName.js"; import { OrgService } from "@/internal/orgs/OrgService.js"; import { handleDeleteFeature } from "./handlers/handleDeleteFeature.js"; -export const featureApiRouter = express.Router(); +export const featureApiRouter: Router = express.Router(); export const validateFeature = (data: any) => { let featureType = data.type; diff --git a/server/src/internal/api/invoiceRouter.ts b/server/src/internal/api/invoiceRouter.ts index 8f3f19bf5..73738f70f 100644 --- a/server/src/internal/api/invoiceRouter.ts +++ b/server/src/internal/api/invoiceRouter.ts @@ -4,7 +4,7 @@ import { OrgService } from "@/internal/orgs/OrgService.js"; import { handleRequestError } from "@/utils/errorUtils.js"; import { Router } from "express"; -export const invoiceRouter = Router(); +export const invoiceRouter: Router = Router(); invoiceRouter.get("/:stripe_invoice_id/stripe", async (req: any, res: any) => { try { diff --git a/server/src/internal/api/products/productRouter.ts b/server/src/internal/api/products/productRouter.ts index cf240d3df..f9b98208a 100644 --- a/server/src/internal/api/products/productRouter.ts +++ b/server/src/internal/api/products/productRouter.ts @@ -17,7 +17,7 @@ import { handleCopyProduct } from "./handlers/handleCopyProduct.js"; import { handleCreateProduct } from "./handlers/handleCreateProduct.js"; import { handleListProducts } from "./handlers/handleListProducts.js"; -export const productApiRouter = Router(); +export const productApiRouter: Router = Router(); productApiRouter.get("", handleListProducts); diff --git a/server/src/internal/api/rewards/referralRouter.ts b/server/src/internal/api/rewards/referralRouter.ts index 01832ca90..e94f92cbb 100644 --- a/server/src/internal/api/rewards/referralRouter.ts +++ b/server/src/internal/api/rewards/referralRouter.ts @@ -8,13 +8,13 @@ import { RewardRedemptionService } from "@/internal/rewards/RewardRedemptionServ import RecaseError from "@/utils/errorUtils.js"; import { generateId, notNullish } from "@/utils/genUtils.js"; import { routeHandler } from "@/utils/routerUtils.js"; -import { Customer, ErrCode, RewardTriggerEvent } from "@autumn/shared"; -import express from "express"; -import { ReferralCode, RewardRedemption } from "@autumn/shared"; +import { ErrCode, RewardTriggerEvent } from "@autumn/shared"; +import express, { Router } from "express"; +import { RewardRedemption } from "@autumn/shared"; import { OrgService } from "@/internal/orgs/OrgService.js"; import { RewardProgramService } from "@/internal/rewards/RewardProgramService.js"; -export const referralRouter = express.Router(); +export const referralRouter: Router = express.Router(); // 1. Get referral code referralRouter.post("/code", (req, res) => @@ -238,7 +238,7 @@ referralRouter.post("/redeem", (req, res) => }), ); -export const redemptionRouter = express.Router(); +export const redemptionRouter: Router = express.Router(); redemptionRouter.get("/:redemptionId", (req, res) => routeHandler({ diff --git a/server/src/internal/api/rewards/rewardProgramRouter.ts b/server/src/internal/api/rewards/rewardProgramRouter.ts index aef8b7851..036d2bf5e 100644 --- a/server/src/internal/api/rewards/rewardProgramRouter.ts +++ b/server/src/internal/api/rewards/rewardProgramRouter.ts @@ -8,9 +8,9 @@ import { ErrCode, RewardTriggerEvent, } from "@autumn/shared"; -import express from "express"; +import express, { Router } from "express"; -export const rewardProgramRouter = express.Router(); +export const rewardProgramRouter: Router = express.Router(); rewardProgramRouter.post("", (req, res) => routeHandler({ diff --git a/server/src/internal/api/rewards/rewardRouter.ts b/server/src/internal/api/rewards/rewardRouter.ts index 989c8b0f0..15adf7711 100644 --- a/server/src/internal/api/rewards/rewardRouter.ts +++ b/server/src/internal/api/rewards/rewardRouter.ts @@ -1,4 +1,4 @@ -import express from "express"; +import express, { Router } from "express"; import { CreateRewardSchema, ErrCode, @@ -19,7 +19,7 @@ import { getRewardCat, } from "@/internal/rewards/rewardUtils.js"; -const rewardRouter = express.Router(); +const rewardRouter: Router = express.Router(); rewardRouter.post("", async (req: any, res: any) => { try { diff --git a/server/src/internal/customers/CusService.ts b/server/src/internal/customers/CusService.ts index 11a5d3294..66bd9c41d 100644 --- a/server/src/internal/customers/CusService.ts +++ b/server/src/internal/customers/CusService.ts @@ -189,194 +189,6 @@ export class CusService { return customer as Customer; } - //search customers - - static addPaginationAndSearch = ({ - query, - search, - pageNumber, - pageSize, - lastItem, - customerPrefix = "", - }: { - query: any; - search: string; - pageNumber: number | null; - pageSize: number; - lastItem: any; - customerPrefix: string; - }) => { - if (search && search !== "") { - query.or( - `"name".ilike.%${search}%, ` + - `"email".ilike.%${search}%, ` + - `"id".ilike.%${search}%`, - customerPrefix && { - foreignTable: "customers", - referencedTable: "customers", - }, - ); - } - - if (lastItem) { - query.or( - `"internal_id".lt.${lastItem.internal_id}`, - // `"created_at".lt.${lastItem.created_at},` + - // `and("created_at".eq.${lastItem.created_at},"internal_id".gt.${lastItem.internal_id})`, - customerPrefix && { - foreignTable: "customers", - referencedTable: "customers", - }, - ); - } - - if (customerPrefix) { - query.order(`customer(internal_id)`, { ascending: false }); - } else { - query.order("internal_id", { ascending: false }); - // query - // .order("created_at", { ascending: false }) - // .order("internal_id", { ascending: true }); - } - - query.limit(pageSize); - }; - - static async searchCustomersByProduct({ - sb, - orgId, - env, - search, - filters, - pageSize, - lastItem, - pageNumber, - }: { - sb: SupabaseClient; - orgId: string; - env: AppEnv; - search: string; - filters: any; - pageSize: number; - lastItem: any; - pageNumber: number; - }) { - const query = sb - .from("customer_products") - .select( - `*, - customer:customers!inner(*), product:products!inner(id, name, version)`, - { - count: "exact", - }, - ) - .eq("customer.org_id", orgId) - .eq("customer.env", env) - .in("status", [CusProductStatus.Active, CusProductStatus.PastDue]); - - if (filters.product_id) { - query.eq("product.id", filters.product_id); - } - - if (filters?.status === "canceled") { - console.log("Adding canceled filter"); - query - .eq("status", CusProductStatus.Active) - .not("canceled_at", "is", null); - } else if (filters?.status === "free_trial") { - console.log("Adding free trial filter"); - query - .eq("status", CusProductStatus.Active) - .gt("trial_ends_at", Date.now()); - } - - this.addPaginationAndSearch({ - query, - search, - pageNumber, - pageSize, - lastItem, - customerPrefix: "customers.", - }); - - const { data, count, error } = await query; - - if (error) { - throw error; - } - - // Flip - - const customers = flipProductResults(data); - - return { data: customers, count }; - } - - static async searchCustomers({ - sb, - orgId, - env, - search, - pageSize = 50, - filters, - lastItem, - pageNumber, - }: { - sb: SupabaseClient; - orgId: string; - env: AppEnv; - search: string; - lastItem?: { created_at: string; name: string; internal_id: string } | null; - filters: any; - pageSize?: number; - pageNumber: number; - }) { - if (filters.product_id || filters.status) { - return await this.searchCustomersByProduct({ - sb, - orgId, - env, - search, - filters, - pageSize, - lastItem, - pageNumber, - }); - } - - let select = - "*, customer_products:customer_products(*, product:products(*))"; - - let query = sb - .from("customers") - .select(select, { - count: "exact", - // count: "planned", // use for 1M rows...? - }) - .eq("org_id", orgId) - .eq("env", env); - - this.addPaginationAndSearch({ - query, - search, - pageNumber: null, - pageSize, - lastItem, - customerPrefix: "", - }); - - const { data, count, error } = await query; - - if (error) { - throw error; - } - - const totalCount = count && count + pageSize * (pageNumber - 1); - return { data, count: totalCount }; - } - - // End of search customers - static async insert({ db, data }: { db: DrizzleCli; data: Customer }) { try { const results = await db @@ -469,192 +281,3 @@ export class CusService { return results; } } - -// static async getWithProductsDrizzle({ -// db, -// idOrInternalId, -// orgId, -// env, -// inStatuses = [ -// CusProductStatus.Active, -// CusProductStatus.PastDue, -// CusProductStatus.Scheduled, -// ], -// withEntities = false, -// entityId, -// expand, -// withSubs = false, -// }: { -// db: DrizzleCli; -// idOrInternalId: string; -// orgId: string; -// env: AppEnv; -// inStatuses?: CusProductStatus[]; -// withEntities?: boolean; -// entityId?: string; -// expand?: (CusExpand | EntityExpand)[]; -// withSubs?: boolean; -// }) { -// // 1. Call RPC function -// let data: { -// customer: Customer | null; -// products: FullCusProduct[] | null; -// entities: Entity[] | null; -// entity: Entity | null; -// trials_used: any[] | null; -// subscriptions: any[] | null; -// invoices: any[] | null; -// }; - -// try { -// const result = await db.execute(sql` -// SELECT * FROM get_cus_with_products( -// p_cus_id => ${idOrInternalId}::text, -// p_org_id => ${orgId}::text, -// p_env => ${env}::text, -// p_statuses => ARRAY[${sql.join( -// inStatuses.map((status) => sql`${status}`), -// sql`, `, -// )}]::text[], -// p_with_entities => ${withEntities}::boolean, -// p_entity_id => ${entityId || null}::text, -// p_with_trials_used => ${expand?.includes(CusExpand.TrialsUsed) || false}::boolean, -// p_with_subs => ${withSubs}::boolean, -// p_with_invoices => ${expand?.includes(CusExpand.Invoices) || false}::boolean -// ) -// `); - -// if (!result || result.length == 0 || !result[0].get_cus_with_products) { -// throw new RecaseError({ -// message: "Calling get_cus_with_products RPC returned wrong shape", -// code: ErrCode.GetCusWithProductsFailed, -// statusCode: StatusCodes.INTERNAL_SERVER_ERROR, -// data: result, -// }); -// } - -// data = result[0].get_cus_with_products as any; -// } catch (error) { -// throw error; -// } - -// if (!data || !data.customer) { -// return null; -// } - -// let { customer, products, entities, entity } = data; - -// if (!products) { -// products = []; -// } - -// for (let product of products) { -// if (!product.customer_prices) { -// product.customer_prices = []; -// } - -// if (!product.customer_entitlements) { -// product.customer_entitlements = []; -// } -// } - -// let trialsUsed = data.trials_used; -// if (trialsUsed) { -// trialsUsed = trialsUsed.filter( -// (trial: any, index: number, self: any) => -// index === -// self.findIndex((t: any) => t.product_id === trial.product_id), -// ); -// } - -// return { -// ...customer, -// customer_products: products, -// entities: entities, -// entity: entity, -// trials_used: trialsUsed, -// subscriptions: data.subscriptions, -// invoices: data.invoices, -// } as FullCustomer; -// } - -// static async getWithProducts({ -// sb, -// idOrInternalId, -// orgId, -// env, -// inStatuses = [ -// CusProductStatus.Active, -// CusProductStatus.PastDue, -// CusProductStatus.Scheduled, -// ], -// withEntities = false, -// entityId, -// expand, -// withSubs = false, -// }: { -// sb: SupabaseClient; -// idOrInternalId: string; -// orgId: string; -// env: AppEnv; -// inStatuses?: CusProductStatus[]; -// withEntities?: boolean; -// entityId?: string; -// expand?: (CusExpand | EntityExpand)[]; -// withSubs?: boolean; -// }) { -// const { data, error } = await sb.rpc("get_cus_with_products", { -// p_cus_id: idOrInternalId, -// p_org_id: orgId, -// p_env: env, -// p_statuses: inStatuses, -// p_with_entities: withEntities, -// p_entity_id: entityId, -// p_with_trials_used: expand?.includes(CusExpand.TrialsUsed), -// p_with_subs: withSubs, -// p_with_invoices: expand?.includes(CusExpand.Invoices), -// }); - -// if (error) { -// throw error; -// } - -// if (!data || !data.customer) { -// return null; -// } - -// let { customer, products, entities, entity } = data; - -// if (!products) { -// products = []; -// } - -// for (let product of products) { -// if (!product.customer_prices) { -// product.customer_prices = []; -// } - -// if (!product.customer_entitlements) { -// product.customer_entitlements = []; -// } -// } - -// let trialsUsed = data.trials_used; -// if (trialsUsed) { -// trialsUsed = trialsUsed.filter( -// (trial: any, index: number, self: any) => -// index === -// self.findIndex((t: any) => t.product_id === trial.product_id), -// ); -// } - -// return { -// ...customer, -// customer_products: products, -// entities: entities, -// entity: entity, -// trials_used: trialsUsed, -// subscriptions: data.subscriptions, -// invoices: data.invoices, -// }; -// } diff --git a/server/src/internal/customers/attach/attachFunctions/addProductFlow/handleOneOffFunction.ts b/server/src/internal/customers/attach/attachFunctions/addProductFlow/handleOneOffFunction.ts index c752b6ac0..e4b10669b 100644 --- a/server/src/internal/customers/attach/attachFunctions/addProductFlow/handleOneOffFunction.ts +++ b/server/src/internal/customers/attach/attachFunctions/addProductFlow/handleOneOffFunction.ts @@ -86,18 +86,18 @@ export const handleOneOffFunction = async ({ // Create invoice logger.info("1. Creating invoice"); const stripeInvoice = await stripeCli.invoices.create({ - customer: customer.processor.id, + customer: customer.processor.id!, auto_advance: false, - currency: org.default_currency, + currency: org.default_currency!, }); logger.info("2. Creating invoice items"); for (const invoiceItem of invoiceItems) { await stripeCli.invoiceItems.create({ ...invoiceItem, - customer: customer.processor.id, + customer: customer.processor.id!, invoice: stripeInvoice.id, - }); + } as any); } // Create invoice items diff --git a/server/src/internal/customers/attach/attachRouter.ts b/server/src/internal/customers/attach/attachRouter.ts index 5481f7a57..72f98e562 100644 --- a/server/src/internal/customers/attach/attachRouter.ts +++ b/server/src/internal/customers/attach/attachRouter.ts @@ -42,7 +42,7 @@ import { processAttachBody } from "./attachUtils/attachParams/processAttachBody. import { handleAttachPreview } from "./handleAttachPreview/handleAttachPreview.js"; import { handleAttach } from "./handleAttach.js"; -export const attachRouter = Router(); +export const attachRouter: Router = Router(); export const handlePrepaidErrors = async ({ attachParams, @@ -257,10 +257,6 @@ const handleAttachOld = async (req: any, res: any) => } logger.info("--------------------------------"); - let publicStr = req.isPublic ? "(Public) " : ""; - logger.info( - `${publicStr}ATTACH PRODUCT REQUEST (from ${req.minOrg.slug})`, - ); const { customer, diff --git a/server/src/internal/customers/expire/expireRouter.ts b/server/src/internal/customers/expire/expireRouter.ts index f5568361c..7cf490117 100644 --- a/server/src/internal/customers/expire/expireRouter.ts +++ b/server/src/internal/customers/expire/expireRouter.ts @@ -6,7 +6,7 @@ import { CusProductStatus, ErrCode, FullCusProduct } from "@autumn/shared"; import { Router } from "express"; import { expireCusProduct } from "../handlers/handleCusProductExpired.js"; -const expireRouter = Router(); +const expireRouter: Router = Router(); expireRouter.post("", async (req, res) => routeHandler({ diff --git a/server/src/internal/customers/handlers/handleGetCustomer.ts b/server/src/internal/customers/handlers/handleGetCustomer.ts index b5e434551..adca2a67e 100644 --- a/server/src/internal/customers/handlers/handleGetCustomer.ts +++ b/server/src/internal/customers/handlers/handleGetCustomer.ts @@ -40,7 +40,7 @@ export const handleGetCustomer = async (req: any, res: any) => if (!customer) { req.logtail.warn( - `GET /customers/${customerId}: not found | Org: ${req.minOrg.slug}`, + `GET /customers/${customerId}: not found | Org: ${org.slug}`, ); res.status(StatusCodes.NOT_FOUND).json({ message: `Customer ${customerId} not found`, diff --git a/server/src/internal/customers/handlers/handlePostCustomer.ts b/server/src/internal/customers/handlers/handlePostCustomer.ts index af502ecba..6b12fd1c2 100644 --- a/server/src/internal/customers/handlers/handlePostCustomer.ts +++ b/server/src/internal/customers/handlers/handlePostCustomer.ts @@ -56,9 +56,7 @@ export const handlePostCustomerRequest = async (req: any, res: any) => { error instanceof RecaseError && error.code === ErrCode.DuplicateCustomerId ) { - logger.warn( - `POST /customers: ${error.message} (org: ${req.minOrg.slug})`, - ); + logger.warn(`POST /customers: ${error.message} (org: ${req.org?.slug})`); res.status(error.statusCode).json({ message: error.message, code: error.code, diff --git a/server/src/internal/customers/handlers/handleUpdateBalances.ts b/server/src/internal/customers/handlers/handleUpdateBalances.ts index 5fb45d538..3e8f7122e 100644 --- a/server/src/internal/customers/handlers/handleUpdateBalances.ts +++ b/server/src/internal/customers/handlers/handleUpdateBalances.ts @@ -82,7 +82,7 @@ export const handleUpdateBalances = async (req: any, res: any) => { logger.info("--------------------------------"); logger.info( - `REQUEST: UPDATE BALANCES FOR CUSTOMER ${customer.id}, ORG: ${req.minOrg.slug}`, + `REQUEST: UPDATE BALANCES FOR CUSTOMER ${customer.id}, ORG: ${org.slug}`, ); logger.info( `Features to update: ${balances.map( diff --git a/server/src/internal/customers/internalCusRouter.ts b/server/src/internal/customers/internalCusRouter.ts index 92707fa8b..5a337b645 100644 --- a/server/src/internal/customers/internalCusRouter.ts +++ b/server/src/internal/customers/internalCusRouter.ts @@ -26,7 +26,7 @@ import { StatusCodes } from "http-status-codes"; import { cusProductToProduct } from "./cusProducts/cusProductUtils/convertCusProduct.js"; import { createOrgResponse } from "../orgs/orgUtils.js"; -export const cusRouter = Router(); +export const cusRouter: Router = Router(); cusRouter.get("/:customer_id/data", async (req: any, res: any) => { try { diff --git a/server/src/internal/customers/previews/checkProductUtils.ts b/server/src/internal/customers/previews/checkProductUtils.ts index 7986704e5..027e4d2c3 100644 --- a/server/src/internal/customers/previews/checkProductUtils.ts +++ b/server/src/internal/customers/previews/checkProductUtils.ts @@ -30,7 +30,7 @@ export const getProductChargeText = ({ itemStrs.push( formatCurrency({ amount: total, - defaultCurrency: org.default_currency, + defaultCurrency: org.default_currency!, }), ); } diff --git a/server/src/internal/customers/previews/previewUtils.ts b/server/src/internal/customers/previews/previewUtils.ts index 90a99219a..24dc0c171 100644 --- a/server/src/internal/customers/previews/previewUtils.ts +++ b/server/src/internal/customers/previews/previewUtils.ts @@ -26,17 +26,17 @@ export const formatTiers = ({ if (tiers.length == 1) { return formatCurrency({ amount: tiers[0].amount, - defaultCurrency: org.default_currency, + defaultCurrency: org.default_currency!, }); } let tiersStart = formatCurrency({ amount: tiers[0].amount, - defaultCurrency: org.default_currency, + defaultCurrency: org.default_currency!, }); let tiersEnd = formatCurrency({ amount: tiers[tiers.length - 1].amount, - defaultCurrency: org.default_currency, + defaultCurrency: org.default_currency!, }); return `${tiersStart} - ${tiersEnd}`; @@ -58,13 +58,13 @@ export const getItemsHtml = ({ if (pricedItems.length == 1) { html += `

${formatCurrency({ amount: totalAmount, - defaultCurrency: org.default_currency, + defaultCurrency: org.default_currency!, })}

`; } else { html += `
    ${itemsToHtml({ items: pricedItems })}
`; html += `

Total: ${formatCurrency({ amount: totalAmount, - defaultCurrency: org.default_currency, + defaultCurrency: org.default_currency!, })}

`; } diff --git a/server/src/internal/dev/ApiKeyService.ts b/server/src/internal/dev/ApiKeyService.ts index 437fd4e9d..4c3042106 100644 --- a/server/src/internal/dev/ApiKeyService.ts +++ b/server/src/internal/dev/ApiKeyService.ts @@ -115,32 +115,3 @@ export class CachedKeyService { } } } - -// const { data, error } = await sb.rpc("verify_api_key", { -// p_hashed_key: hashedKey, -// p_env: env, -// }); - -// if (error) { -// throw error; -// } - -// if (!data.success || !data.organization) { -// console.warn(`(warning) failed to verify secret key: ${data.error}`); -// return null; -// } - -// let org = structuredClone(data.organization); -// delete org.features; - -// // Add org config and api version -// org.config = OrgConfigSchema.parse(org.config || {}); -// org.api_version = getApiVersion({ -// createdAt: org.created_at, -// }); - -// return { -// org, -// features: data.organization?.features || [], -// env, -// }; diff --git a/server/src/internal/dev/devRouter.ts b/server/src/internal/dev/devRouter.ts index e7fb9844a..7b5f64622 100644 --- a/server/src/internal/dev/devRouter.ts +++ b/server/src/internal/dev/devRouter.ts @@ -4,13 +4,13 @@ import { Router } from "express"; import { ApiKeyService } from "./ApiKeyService.js"; import { OrgService } from "../orgs/OrgService.js"; import { createKey } from "./api-keys/apiKeyUtils.js"; -import { getSvixDashboardUrl } from "@/external/svix/svixUtils.js"; +import { getSvixDashboardUrl } from "@/external/svix/svixHelpers.js"; import { handleRequestError } from "@/utils/errorUtils.js"; import { CacheManager } from "@/external/caching/CacheManager.js"; import { CacheType } from "@/external/caching/cacheActions.js"; import { routeHandler } from "@/utils/routerUtils.js"; -export const devRouter = Router(); +export const devRouter: Router = Router(); devRouter.get("/data", withOrgAuth, async (req: any, res) => { try { @@ -57,9 +57,7 @@ devRouter.post("/api_key", withOrgAuth, async (req: any, res) => name, orgId, prefix, - meta: { - org_slug: req.minOrg.slug, - }, + meta: {}, }); res.status(200).json({ diff --git a/server/src/internal/emails/sendInvitationEmail.ts b/server/src/internal/emails/sendInvitationEmail.ts new file mode 100644 index 000000000..c4a4dfa17 --- /dev/null +++ b/server/src/internal/emails/sendInvitationEmail.ts @@ -0,0 +1,40 @@ +import { sendTextEmail } from "@/external/resend/resendUtils.js"; +import { safeResend } from "@/external/resend/safeResend.js"; + +const getInvitationEmailBody = ({ + orgName, + inviteLink, +}: { + orgName: string; + inviteLink: string; +}) => { + return `Hey there! You've been invited to join ${orgName} on Autumn. + +Click the link below to create an account / sign in and you'll be automatically added to the organization. + +${process.env.CLIENT_URL}/sign-in + `; +}; + +export const sendInvitationEmail = safeResend({ + fn: async ({ + email, + + orgName, + inviteLink, + }: { + email: string; + + orgName: string; + inviteLink: string; + }) => { + console.log("Sending invitation email to", email); + await sendTextEmail({ + from: `Autumn `, + to: email, + subject: `Join ${orgName} on Autumn`, + body: getInvitationEmailBody({ orgName, inviteLink }), + }); + }, + action: "send org invitation email", +}); diff --git a/server/src/internal/emails/sendMigrationEmail.ts b/server/src/internal/emails/sendMigrationEmail.ts new file mode 100644 index 000000000..8d2354306 --- /dev/null +++ b/server/src/internal/emails/sendMigrationEmail.ts @@ -0,0 +1,49 @@ +import { MigrationService } from "../migrations/MigrationService.js"; +import { sendTextEmail } from "@/external/resend/resendUtils.js"; +import { MigrationJobStep, Organization } from "@autumn/shared"; +import { DrizzleCli } from "@/db/initDrizzle.js"; +import { safeResend } from "@/external/resend/safeResend.js"; + +export const sendMigrationEmail = safeResend({ + fn: async ({ + db, + migrationJobId, + org, + }: { + db: DrizzleCli; + migrationJobId: string; + org: Organization; + }) => { + let migrationJob = await MigrationService.getJob({ + db, + id: migrationJobId, + }); + + // Send email + let getCustomersStep = + migrationJob.step_details[MigrationJobStep.GetCustomers]; + let migrateStep = + migrationJob.step_details[MigrationJobStep.MigrateCustomers]; + + console.log("Sending migration email"); + await sendTextEmail({ + to: "johnyeocx@gmail.com", + subject: `Migration Job Finished -- ${migrationJob.id}`, + body: ` + + ORG: ${org.id}, ${org.slug} + Step: Get migration customers + + 1. Total customers: ${getCustomersStep?.total_customers} + 2. Canceled customers: ${getCustomersStep?.canceled_customers} + + Step: Migrate customers + + 1. Number of errors: ${migrateStep?.num_errors} + 2. Failed customers: + ${migrateStep?.failed_customers} + `, + }); + }, + action: "send migration email", +}); diff --git a/server/src/internal/emails/sendOTPEmail.ts b/server/src/internal/emails/sendOTPEmail.ts new file mode 100644 index 000000000..2b767a4cc --- /dev/null +++ b/server/src/internal/emails/sendOTPEmail.ts @@ -0,0 +1,20 @@ +import { logger } from "@/external/logtail/logtailUtils.js"; +import { createResendCli } from "@/external/resend/resendUtils.js"; +import OTPEmail from "@emails/OTPEmail.js"; + +const sendOTPEmail = async ({ email, otp }: { email: string; otp: string }) => { + if (!process.env.RESEND_API_KEY || !process.env.RESEND_DOMAIN) { + logger.warn(`RESEND NOT SET UP, SIGN IN OTP: ${otp}`); + return; + } + + const resend = createResendCli(); + await resend.emails.send({ + from: `Autumn `, + to: email, + subject: "Your verification code for Autumn", + react: OTPEmail({ otpCode: otp }), + }); +}; + +export default sendOTPEmail; diff --git a/server/src/internal/emails/sendOnboardingEmail.ts b/server/src/internal/emails/sendOnboardingEmail.ts new file mode 100644 index 000000000..73a8585f4 --- /dev/null +++ b/server/src/internal/emails/sendOnboardingEmail.ts @@ -0,0 +1,32 @@ +import { sendHtmlEmail } from "@/external/resend/resendUtils.js"; +import { safeResend } from "@/external/resend/safeResend.js"; + +const getWelcomeEmailBody = (userFirstName: string) => { + return ` +

Hey ${userFirstName} :)

+ +

Just wanted to say thank you for signing up to Autumn!

+ +

I'm curious--how did you hear about us? Also are you just looking around or do you have a specific use case I can help you with?

+ +

Whatever the reason, anything you need I'm here to help.

+ +

Ayush
+Co-founder, Autumn

+ +

Oh, and join our Discord community to connect with us and other users

+ `; +}; + +export const sendOnboardingEmail = safeResend({ + fn: async ({ name, email }: { name: string; email: string }) => { + const firstName = name.split(" ")[0]; + + await sendHtmlEmail({ + to: email, + subject: "Anything I can help with?", + body: getWelcomeEmailBody(firstName), + }); + }, + action: "send onboarding email", +}); diff --git a/server/src/internal/features/featureRouter.ts b/server/src/internal/features/featureRouter.ts index 4823fe450..600b2ab5e 100644 --- a/server/src/internal/features/featureRouter.ts +++ b/server/src/internal/features/featureRouter.ts @@ -1,10 +1,10 @@ -import express from "express"; +import express, { Router } from "express"; import { FeatureService } from "./FeatureService.js"; -export const featureRouter = express.Router(); +export const featureRouter: Router = express.Router(); -featureRouter.get("", async (req: any, res) => { +featureRouter.get("", async (req: any, res: any) => { try { let features = await FeatureService.getFromReq(req); res.status(200).json({ features }); diff --git a/server/src/internal/features/featureUtils.ts b/server/src/internal/features/featureUtils.ts index b7dc53fcb..5c30b42b0 100644 --- a/server/src/internal/features/featureUtils.ts +++ b/server/src/internal/features/featureUtils.ts @@ -159,6 +159,13 @@ export const runSaveFeatureDisplayTask = async ({ }) => { let display; try { + if (!process.env.ANTHROPIC_API_KEY) { + logger.warn( + "ANTHROPIC_API_KEY is not set, skipping feature display generation", + ); + return; + } + logger.info( `Generating feature display for ${feature.id} (org: ${org.slug})`, ); diff --git a/server/src/internal/mainRouter.ts b/server/src/internal/mainRouter.ts index c5ddc4889..b94c68f11 100644 --- a/server/src/internal/mainRouter.ts +++ b/server/src/internal/mainRouter.ts @@ -1,5 +1,4 @@ -import dotenv from "dotenv"; -dotenv.config(); +import "dotenv/config"; import { orgRouter } from "./orgs/orgRouter.js"; import { Router } from "express"; @@ -13,17 +12,18 @@ import { onboardingRouter } from "./orgs/onboarding/onboardingRouter.js"; import { handlePostOrg } from "./orgs/handlers/handlePostOrg.js"; import { Autumn } from "autumn-js"; import { autumnHandler } from "autumn-js/express"; -import { parseAuthHeader } from "@/utils/authUtils.js"; +import { withAdminAuth } from "./admin/withAdminAuth.js"; +import { adminRouter } from "./admin/adminRouter.js"; -const mainRouter = Router(); +const mainRouter: Router = Router(); mainRouter.get("", async (req: any, res) => { res.status(200).json({ message: "Hello World" }); }); mainRouter.post("/organization", withAuth, handlePostOrg); +mainRouter.use("/admin", withAdminAuth, adminRouter); mainRouter.use("/users", withAuth, userRouter); - mainRouter.use("/onboarding", withOrgAuth, onboardingRouter); mainRouter.use("/organization", withOrgAuth, orgRouter); mainRouter.use("/features", withOrgAuth, featureRouter); @@ -31,34 +31,35 @@ mainRouter.use("/products", withOrgAuth, productRouter); mainRouter.use("/dev", devRouter); mainRouter.use("/customers", withOrgAuth, cusRouter); -mainRouter.use( - "/api/autumn", - withOrgAuth, - autumnHandler({ - identify: async (req: any) => { - return { - customerId: req.org?.id, - customerData: { - name: req.org?.slug, - email: req.user?.email, - }, - }; - }, - }), -); +// Optional... +if (process.env.AUTUMN_SECRET_KEY) { + mainRouter.use( + "/api/autumn", + withOrgAuth, + autumnHandler({ + identify: async (req: any) => { + return { + customerId: req.org?.id, + customerData: { + name: req.org?.slug, + email: req.user?.email, + }, + }; + }, + }), + ); +} mainRouter.use( "/demo/api/autumn", withOrgAuth, - autumnHandler({ autumn: (req: any) => { - let bearerToken = parseAuthHeader(req); - - return new Autumn({ - secretKey: bearerToken, + let client = new Autumn({ url: "http://localhost:8080/v1", - }) as any; + headers: req.headers, + }); + return client as any; }, identify: async (req: any) => { return { diff --git a/server/src/internal/migrations/migrationRouter.ts b/server/src/internal/migrations/migrationRouter.ts index 16d4b2ce0..c1d01b25b 100644 --- a/server/src/internal/migrations/migrationRouter.ts +++ b/server/src/internal/migrations/migrationRouter.ts @@ -7,7 +7,7 @@ import { UsagePriceConfig, } from "@autumn/shared"; import { routeHandler } from "@/utils/routerUtils.js"; -import express from "express"; +import express, { Router } from "express"; import { constructMigrationJob } from "@/internal/migrations/migrationUtils.js"; import { MigrationService } from "@/internal/migrations/MigrationService.js"; import { JobName } from "@/queue/JobName.js"; @@ -20,7 +20,7 @@ import { isFreeProduct } from "@/internal/products/productUtils.js"; import { ExtendedRequest, ExtendedResponse } from "@/utils/models/Request.js"; import { findPrepaidPrice } from "../products/prices/priceUtils/findPriceUtils.js"; -export const migrationRouter = express.Router(); +export const migrationRouter: Router = express.Router(); migrationRouter.post("", async (req: any, res: any) => { return routeHandler({ diff --git a/server/src/internal/migrations/migrationSteps/migrateCustomers.ts b/server/src/internal/migrations/migrationSteps/migrateCustomers.ts index cb25297ba..36e0460ba 100644 --- a/server/src/internal/migrations/migrationSteps/migrateCustomers.ts +++ b/server/src/internal/migrations/migrationSteps/migrateCustomers.ts @@ -11,7 +11,7 @@ import { MigrationService } from "../MigrationService.js"; import { OrgService } from "@/internal/orgs/OrgService.js"; import { createStripeCli } from "@/external/stripe/utils.js"; import { migrateCustomer } from "./migrateCustomer.js"; -import { sendMigrationEmail } from "./sendMigrationEmail.js"; +import { sendMigrationEmail } from "../../emails/sendMigrationEmail.js"; import { createStripePriceIFNotExist } from "@/external/stripe/createStripePrice/createStripePrice.js"; import { DrizzleCli } from "@/db/initDrizzle.js"; diff --git a/server/src/internal/migrations/migrationSteps/sendMigrationEmail.ts b/server/src/internal/migrations/migrationSteps/sendMigrationEmail.ts deleted file mode 100644 index 9495c9c59..000000000 --- a/server/src/internal/migrations/migrationSteps/sendMigrationEmail.ts +++ /dev/null @@ -1,45 +0,0 @@ -import { MigrationService } from "../MigrationService.js"; -import { sendTextEmail } from "@/external/resend/resendUtils.js"; -import { MigrationJobStep, Organization } from "@autumn/shared"; -import { DrizzleCli } from "@/db/initDrizzle.js"; - -export const sendMigrationEmail = async ({ - db, - migrationJobId, - org, -}: { - db: DrizzleCli; - migrationJobId: string; - org: Organization; -}) => { - let migrationJob = await MigrationService.getJob({ - db, - id: migrationJobId, - }); - - // Send email - let getCustomersStep = - migrationJob.step_details[MigrationJobStep.GetCustomers]; - let migrateStep = - migrationJob.step_details[MigrationJobStep.MigrateCustomers]; - - console.log("Sending migration email"); - await sendTextEmail({ - to: "johnyeocx@gmail.com", - subject: `Migration Job Finished -- ${migrationJob.id}`, - body: ` - -ORG: ${org.id}, ${org.slug} -Step: Get migration customers - -1. Total customers: ${getCustomersStep?.total_customers} -2. Canceled customers: ${getCustomersStep?.canceled_customers} - -Step: Migrate customers - -1. Number of errors: ${migrateStep?.num_errors} -2. Failed customers: -${migrateStep?.failed_customers} -`, - }); -}; diff --git a/server/src/internal/orgs/AuthService.ts b/server/src/internal/orgs/AuthService.ts new file mode 100644 index 000000000..0fddb7853 --- /dev/null +++ b/server/src/internal/orgs/AuthService.ts @@ -0,0 +1,34 @@ +// import { db } from "@/db/initDrizzle.js"; +// import { OrgService } from "./OrgService.js"; +// import { DrizzleCli } from "@/db/initDrizzle.js"; +// import { member, organizations } from "@autumn/shared"; +// import { generateId } from "@/utils/genUtils.js"; + +// export class AuthService { +// static async createOrg({ +// db, +// name, +// slug, +// userId, +// }: { +// db: DrizzleCli; +// name: string; +// slug: string; +// userId: string; +// }) { +// // 1. Create org +// await db.insert(organizations).values({ +// id: generateId("org"), +// name, +// slug, +// createdAt: new Date(), +// }); + +// await db.insert(member).values({ +// id: generateId("mem"), +// organizationId: org.id, +// userId, +// createdAt: new Date(), +// }); +// } +// } diff --git a/server/src/internal/orgs/OrgService.ts b/server/src/internal/orgs/OrgService.ts index d54c87f18..a949dcdb6 100644 --- a/server/src/internal/orgs/OrgService.ts +++ b/server/src/internal/orgs/OrgService.ts @@ -1,18 +1,21 @@ import RecaseError from "@/utils/errorUtils.js"; +import { and, eq } from "drizzle-orm"; import { AppEnv, ErrCode, Feature, features, + invitation, + member, Organization, OrgConfigSchema, + user, } from "@autumn/shared"; -import { SupabaseClient } from "@supabase/supabase-js"; + import { getApiVersion } from "@/utils/versionUtils.js"; import { clearOrgCache } from "./orgUtils/clearOrgCache.js"; -import { DrizzleCli } from "@/db/initDrizzle.js"; -import { eq } from "drizzle-orm"; import { organizations, apiKeys } from "@autumn/shared"; +import { DrizzleCli } from "@/db/initDrizzle.js"; export class OrgService { static async getFromReq(req: any) { @@ -32,6 +35,30 @@ export class OrgService { return await this.get({ db: req.db, orgId: req.orgId }); } + static async getMembers({ db, orgId }: { db: DrizzleCli; orgId: string }) { + const results = await db + .select() + .from(member) + .where(eq(member.organizationId, orgId)) + .innerJoin(user, eq(member.userId, user.id)); + + return results; + } + + static async getInvites({ db, orgId }: { db: DrizzleCli; orgId: string }) { + const results = await db + .select() + .from(invitation) + .where( + and( + eq(invitation.organizationId, orgId), + eq(invitation.status, "pending"), + ), + ); + + return results; + } + // Drizzle get static async get({ db, orgId }: { db: DrizzleCli; orgId: string }) { const result = await db.query.organizations.findFirst({ diff --git a/server/src/internal/orgs/handlers/handleDeleteOrg.ts b/server/src/internal/orgs/handlers/handleDeleteOrg.ts new file mode 100644 index 000000000..f7ef86112 --- /dev/null +++ b/server/src/internal/orgs/handlers/handleDeleteOrg.ts @@ -0,0 +1,109 @@ +import { deleteSvixApp } from "@/external/svix/svixHelpers.js"; +import RecaseError, { handleFrontendReqError } from "@/utils/errorUtils.js"; +import { ExtendedRequest } from "@/utils/models/Request.js"; +import { AppEnv, customers, ErrCode, Organization } from "@autumn/shared"; +import { and, eq } from "drizzle-orm"; +import { Response } from "express"; +import { deleteStripeWebhook } from "../orgUtils.js"; + +const deleteSvixWebhooks = async ({ + org, + logger, +}: { + org: Organization; + logger: any; +}) => { + const batch = []; + if (org.svix_config?.sandbox_app_id) { + batch.push( + deleteSvixApp({ + appId: org.svix_config.sandbox_app_id, + }), + ); + } + + if (org.svix_config?.live_app_id) { + batch.push( + deleteSvixApp({ + appId: org.svix_config.live_app_id, + }), + ); + } + + try { + await Promise.all(batch); + } catch (error) { + logger.error(`Failed to delete svix webhooks for ${org.id}, ${org.slug}`); + } +}; + +const deleteStripeWebhooks = async ({ + org, + logger, +}: { + org: Organization; + logger: any; +}) => { + if (org.stripe_config) { + try { + await deleteStripeWebhook({ + org: org, + env: AppEnv.Sandbox, + }); + + await deleteStripeWebhook({ + org: org, + env: AppEnv.Live, + }); + } catch (error: any) { + logger.error( + `Failed to delete stripe webhooks for ${org.id}, ${org.slug}. ${error.message})`, + ); + } + } +}; + +export const handleDeleteOrg = async (req: ExtendedRequest, res: Response) => { + try { + const { org, db, logtail: logger } = req; + + // 1. Check if any customers + let hasCustomers = await db.query.customers.findFirst({ + where: eq(customers.org_id, org.id), + }); + + if (hasCustomers) + throw new RecaseError({ + message: "Cannot delete org with production mode customers", + code: ErrCode.OrgHasCustomers, + statusCode: 400, + }); + + // 2. Delete svix webhooks + logger.info("1. Deleting svix webhooks"); + await deleteSvixWebhooks({ org, logger }); + + // 3. Delete stripe webhooks + logger.info("2. Deleting stripe webhooks"); + await deleteStripeWebhooks({ org, logger }); + + // 4. Delete all sandbox customers + logger.info("3. Deleting sandbox customers"); + await db + .delete(customers) + .where( + and(eq(customers.org_id, org.id), eq(customers.env, AppEnv.Sandbox)), + ); + + res.status(200).json({ + message: "Org deleted", + }); + } catch (error) { + handleFrontendReqError({ + res, + error, + req, + action: "delete-org", + }); + } +}; diff --git a/server/src/internal/orgs/handlers/handleGetOrgMembers.ts b/server/src/internal/orgs/handlers/handleGetOrgMembers.ts new file mode 100644 index 000000000..746b6b30b --- /dev/null +++ b/server/src/internal/orgs/handlers/handleGetOrgMembers.ts @@ -0,0 +1,29 @@ +import { handleFrontendReqError } from "@/utils/errorUtils.js"; +import { OrgService } from "../OrgService.js"; +import { auth } from "@/utils/auth.js"; + +export const handleGetOrgMembers = async (req: any, res: any) => { + try { + const { org, db } = req; + const orgId = org.id; + + const memberships = await OrgService.getMembers({ db, orgId }); + const invites = await OrgService.getInvites({ db, orgId }); + + res.status(200).json({ + memberships, + invites, + }); + // res.status(200).json({ + // memberships: Array(10).fill(memberships[0]), + // invites: Array(10).fill(invites[0]), + // }); + } catch (error) { + handleFrontendReqError({ + req, + error, + res, + action: "get org members", + }); + } +}; diff --git a/server/src/internal/orgs/handlers/handleGetUploadUrl.ts b/server/src/internal/orgs/handlers/handleGetUploadUrl.ts new file mode 100644 index 000000000..ad24855ef --- /dev/null +++ b/server/src/internal/orgs/handlers/handleGetUploadUrl.ts @@ -0,0 +1,32 @@ +import { logger } from "@/external/logtail/logtailUtils.js"; +import { getUploadUrl } from "@/external/supabase/storageUtils.js"; +import RecaseError, { handleFrontendReqError } from "@/utils/errorUtils.js"; +import { ErrCode } from "@autumn/shared"; + +export const handleGetUploadUrl = async (req: any, res: any) => { + try { + const { org } = req; + + let path = `logo/${org.id}`; + + if (!process.env.SUPABASE_URL || !process.env.SUPABASE_SERVICE_KEY) { + logger.warn("Supabase storage not set up"); + res.status(400).json({ + message: "Supabase storage not set up", + code: ErrCode.SupabaseNotFound, + }); + return; + } + + const data = await getUploadUrl({ path }); + + res.status(200).json(data); + } catch (error) { + handleFrontendReqError({ + req, + error, + res, + action: "get upload url", + }); + } +}; diff --git a/server/src/internal/orgs/handlers/handleInvite.ts b/server/src/internal/orgs/handlers/handleInvite.ts new file mode 100644 index 000000000..17e4d9fea --- /dev/null +++ b/server/src/internal/orgs/handlers/handleInvite.ts @@ -0,0 +1,48 @@ +import { auth } from "@/utils/auth.js"; +import { + handleFrontendReqError, + handleRequestError, +} from "@/utils/errorUtils.js"; +import { ExtendedRequest, ExtendedResponse } from "@/utils/models/Request.js"; +import { user } from "@autumn/shared"; +import { eq } from "drizzle-orm"; +import { Request, Response } from "express"; + +export const handleInvite = async ( + req: ExtendedRequest, + res: ExtendedResponse, +) => { + try { + const { email, role } = req.body; + const { org, db } = req; + + const emailUser = await db.query.user.findFirst({ + where: eq(user.email, email), + }); + + if (emailUser) { + await auth.api.addMember({ + body: { + organizationId: org.id, + userId: emailUser.id, + role: role, + }, + }); + res.status(200).send({ + message: "User added to organization", + }); + return; + } + + res.status(202).send({ + message: "Send invitation to user", + }); + } catch (error) { + handleFrontendReqError({ + req, + res, + error, + action: "handleInvite", + }); + } +}; diff --git a/server/src/internal/orgs/handlers/handlePostOrg.ts b/server/src/internal/orgs/handlers/handlePostOrg.ts index 2b25401b8..f54e43fc8 100644 --- a/server/src/internal/orgs/handlers/handlePostOrg.ts +++ b/server/src/internal/orgs/handlers/handlePostOrg.ts @@ -1,6 +1,3 @@ -import { createClerkCli } from "@/external/clerkUtils.js"; -import { saveOrgToDB } from "@/external/webhooks/clerkWebhooks.js"; - import { ExtendedRequest, ExtendedResponse } from "@/utils/models/Request.js"; import { routeHandler } from "@/utils/routerUtils.js"; @@ -12,41 +9,51 @@ export const handlePostOrg = async (req: any, res: any) => handler: async (req: ExtendedRequest, res: ExtendedResponse) => { const { userId, db } = req; - const clerk = createClerkCli(); - const user = await clerk.users.getUser(userId!); + console.log("userId", userId); - let userMemberships = await clerk.users.getOrganizationMembershipList({ - userId: userId!, - }); + // const userMemberships = await auth.api.({ + // userId: userId!, + // }); - let org; + // const clerk = createClerkCli(); + // const user = await clerk.users.getUser(userId!); - if (userMemberships.data.length === 0) { - org = await clerk.organizations.createOrganization({ - name: `${user.firstName}'s Org`, - }); + // let userMemberships = await clerk.users.getOrganizationMembershipList({ + // userId: userId!, + // }); - // 2. Create org membership for user - await clerk.organizations.createOrganizationMembership({ - organizationId: org.id, - userId: userId!, - role: "org:admin", - }); + // let org; - await saveOrgToDB({ - db, - id: org.id, - slug: org.slug, - }); + // if (userMemberships.data.length === 0) { + // org = await clerk.organizations.createOrganization({ + // name: `${user.firstName}'s Org`, + // }); - console.log(`Created new org: ${org.id} (${org.slug})`); - } else { - org = userMemberships.data[0].organization; - } + // // 2. Create org membership for user + // await clerk.organizations.createOrganizationMembership({ + // organizationId: org.id, + // userId: userId!, + // role: "org:admin", + // }); + + // await saveOrgToDB({ + // db, + // id: org.id, + // slug: org.slug, + // }); + + // console.log(`Created new org: ${org.id} (${org.slug})`); + // } else { + // org = userMemberships.data[0].organization; + // } res.status(200).json({ - id: org.id, - slug: org.slug, + id: "123", + slug: "123", }); + // res.status(200).json({ + // id: org.id, + // slug: org.slug, + // }); }, }); diff --git a/server/src/internal/orgs/handlers/handleUpdateOrg.ts b/server/src/internal/orgs/handlers/handleUpdateOrg.ts new file mode 100644 index 000000000..a78b77503 --- /dev/null +++ b/server/src/internal/orgs/handlers/handleUpdateOrg.ts @@ -0,0 +1,23 @@ +// import { auth } from "@/utils/auth.js"; +// import { handleFrontendReqError } from "@/utils/errorUtils.js"; + +// export const handleUpdateOrg = async (req: any, res: any) => { +// try { +// await auth.api.updateOrganization({ +// data: { +// name: req.body.name, +// slug: req.body.slug, +// }, +// organizationId: req.org.id, +// }); + +// res.status(200).json({ success: true }); +// } catch (error) { +// handleFrontendReqError({ +// req, +// error, +// res, +// action: "update org", +// }); +// } +// }; diff --git a/server/src/internal/orgs/onboarding/onboardingRouter.ts b/server/src/internal/orgs/onboarding/onboardingRouter.ts index 56602fcdc..10323a758 100644 --- a/server/src/internal/orgs/onboarding/onboardingRouter.ts +++ b/server/src/internal/orgs/onboarding/onboardingRouter.ts @@ -3,7 +3,6 @@ import { Router } from "express"; import { eq } from "drizzle-orm"; import { routeHandler } from "@/utils/routerUtils.js"; import RecaseError from "@/utils/errorUtils.js"; -import { createClerkCli } from "@/external/clerkUtils.js"; import { AppEnv } from "@autumn/shared"; import { parseChatResultFeatures } from "./parseChatFeatures.js"; import { parseChatProducts } from "./parseChatProducts.js"; @@ -14,7 +13,7 @@ import { EntitlementService } from "@/internal/products/entitlements/Entitlement import { PriceService } from "@/internal/products/prices/PriceService.js"; import { ExtendedRequest, ExtendedResponse } from "@/utils/models/Request.js"; -export const onboardingRouter = Router(); +export const onboardingRouter: Router = Router(); onboardingRouter.post("", async (req: Request, res: any) => routeHandler({ diff --git a/server/src/internal/orgs/orgRouter.ts b/server/src/internal/orgs/orgRouter.ts index 1da8c9f79..c50713ec6 100644 --- a/server/src/internal/orgs/orgRouter.ts +++ b/server/src/internal/orgs/orgRouter.ts @@ -1,23 +1,38 @@ +import express, { Router } from "express"; +import Stripe from "stripe"; + +import RecaseError, { handleRequestError } from "@/utils/errorUtils.js"; +import { encryptData } from "@/utils/encryptUtils.js"; + import { ErrCode } from "@/errors/errCodes.js"; import { createClerkCli } from "@/external/clerkUtils.js"; import { checkKeyValid, createWebhookEndpoint, } from "@/external/stripe/stripeOnboardingUtils.js"; -import { encryptData } from "@/utils/encryptUtils.js"; -import RecaseError, { - handleFrontendReqError, - handleRequestError, -} from "@/utils/errorUtils.js"; -import express from "express"; -import Stripe from "stripe"; + import { OrgService } from "./OrgService.js"; import { createStripeCli } from "@/external/stripe/utils.js"; import { AppEnv } from "@autumn/shared"; import { nullish } from "@/utils/genUtils.js"; import { clearOrgCache } from "./orgUtils/clearOrgCache.js"; +import { createOrgResponse } from "./orgUtils.js"; +import { handleGetOrgMembers } from "./handlers/handleGetOrgMembers.js"; +import { handleInvite } from "./handlers/handleInvite.js"; +import { handleGetUploadUrl } from "./handlers/handleGetUploadUrl.js"; +import { handleDeleteOrg } from "./handlers/handleDeleteOrg.js"; -export const orgRouter = express.Router(); +export const orgRouter: Router = express.Router(); +orgRouter.get("/members", handleGetOrgMembers); +orgRouter.get("/upload_url", handleGetUploadUrl); +orgRouter.post("/invite", handleInvite as any); +orgRouter.delete("", handleDeleteOrg as any); + +orgRouter.delete("/delete-user", async (req: any, res) => { + res.status(200).json({ + message: "User deleted", + }); +}); orgRouter.get("", async (req: any, res) => { try { @@ -30,9 +45,7 @@ orgRouter.get("", async (req: any, res) => { const org = await OrgService.getFromReq(req); - res.status(200).json({ - org, - }); + res.status(200).json(createOrgResponse(org)); } catch (error) { handleRequestError({ req, @@ -90,8 +103,6 @@ orgRouter.post("/stripe", async (req: any, res) => { let testWebhook: Stripe.WebhookEndpoint; let liveWebhook: Stripe.WebhookEndpoint; try { - console.log(`Creating stripe webhook for URL: ${process.env.SERVER_URL}`); - testWebhook = await createWebhookEndpoint( testApiKey, AppEnv.Sandbox, @@ -128,15 +139,6 @@ orgRouter.post("/stripe", async (req: any, res) => { }, }); - // 2. Update org in Clerk - const clerkCli = createClerkCli(); - await clerkCli.organizations.updateOrganization(req.orgId, { - publicMetadata: { - stripe_connected: true, - default_currency: defaultCurrency, - }, - }); - res.status(200).json({ message: "Stripe connected", }); diff --git a/server/src/internal/orgs/orgUtils.ts b/server/src/internal/orgs/orgUtils.ts index 4516f1ace..6baba03c1 100644 --- a/server/src/internal/orgs/orgUtils.ts +++ b/server/src/internal/orgs/orgUtils.ts @@ -1,10 +1,10 @@ import { decryptData, generatePublishableKey } from "@/utils/encryptUtils.js"; import RecaseError from "@/utils/errorUtils.js"; -import { AppEnv, ErrCode, Organization } from "@autumn/shared"; -import { createSvixApp } from "@/external/svix/svixUtils.js"; +import { AppEnv, ErrCode, FrontendOrg, Organization } from "@autumn/shared"; import { createStripeCli } from "@/external/stripe/utils.js"; import { OrgService } from "./OrgService.js"; import { FeatureService } from "../features/FeatureService.js"; +import { createSvixApp } from "@/external/svix/svixHelpers.js"; export const constructOrg = ({ id, slug }: { id: string; slug: string }) => { return { @@ -23,33 +23,6 @@ export const constructOrg = ({ id, slug }: { id: string; slug: string }) => { config: {} as any, }; }; -export const initOrgSvixApps = async ({ - id, - slug, -}: { - id: string; - slug: string; -}) => { - const batchCreate = []; - batchCreate.push( - createSvixApp({ - name: `${slug}_${AppEnv.Sandbox}`, - orgId: id, - env: AppEnv.Sandbox, - }), - ); - batchCreate.push( - createSvixApp({ - name: `${slug}_${AppEnv.Live}`, - orgId: id, - env: AppEnv.Live, - }), - ); - - const [sandboxApp, liveApp] = await Promise.all(batchCreate); - - return { sandboxApp, liveApp }; -}; export const deleteStripeWebhook = async ({ org, @@ -104,13 +77,15 @@ export const initDefaultConfig = () => { }; }; -export const createOrgResponse = (org: Organization) => { +export const createOrgResponse = (org: Organization): FrontendOrg => { return { id: org.id, + name: org.name, + logo: org.logo, slug: org.slug, - default_currency: org.default_currency, - stripe_connected: org.stripe_connected, - created_at: org.created_at, + default_currency: org.default_currency || "USD", + stripe_connected: org.stripe_connected || false, + created_at: new Date(org.createdAt).getTime(), test_pkey: org.test_pkey, live_pkey: org.live_pkey, }; diff --git a/server/src/internal/products/internalProductRouter.ts b/server/src/internal/products/internalProductRouter.ts index f1c725028..29200458e 100644 --- a/server/src/internal/products/internalProductRouter.ts +++ b/server/src/internal/products/internalProductRouter.ts @@ -17,7 +17,7 @@ import { isFeaturePriceItem } from "./product-items/productItemUtils/getItemType import RecaseError, { handleFrontendReqError } from "@/utils/errorUtils.js"; import { createOrgResponse } from "../orgs/orgUtils.js"; -export const productRouter = Router({ mergeParams: true }); +export const productRouter: Router = Router({ mergeParams: true }); productRouter.get("/data", async (req: any, res) => { try { diff --git a/server/src/internal/products/pricecn/pricecnUtils.ts b/server/src/internal/products/pricecn/pricecnUtils.ts index cbb004292..b3d5544d9 100644 --- a/server/src/internal/products/pricecn/pricecnUtils.ts +++ b/server/src/internal/products/pricecn/pricecnUtils.ts @@ -1,7 +1,6 @@ import RecaseError from "@/utils/errorUtils.js"; import { nullish } from "@/utils/genUtils.js"; -import { numberWithCommas } from "tests/utils/general/numberUtils.js"; import { getFeatureName } from "@/internal/features/utils/displayUtils.js"; import { @@ -13,6 +12,7 @@ import { ErrCode, Infinite, FullCusProduct, + numberWithCommas, } from "@autumn/shared"; import { isPriceItem } from "../product-items/productItemUtils/getItemType.js"; import { isFeaturePriceItem } from "../product-items/productItemUtils/getItemType.js"; diff --git a/server/src/internal/rewards/RewardProgramService.ts b/server/src/internal/rewards/RewardProgramService.ts index 6d80efdae..67ed56410 100644 --- a/server/src/internal/rewards/RewardProgramService.ts +++ b/server/src/internal/rewards/RewardProgramService.ts @@ -252,17 +252,5 @@ export class RewardProgramService { ); return result[0].count; - - // const { data, error, count } = await sb - // .from("reward_redemptions") - // .select("*, reward_program:reward_programs!inner(*)", { count: "exact" }) - // .eq("referral_code_id", referralCodeId) - // .eq("triggered", true); - - // if (error) { - // throw error; - // } - - // return count; } } diff --git a/server/src/internal/rewards/RewardRedemptionService.ts b/server/src/internal/rewards/RewardRedemptionService.ts index fcb34aba0..184832c9c 100644 --- a/server/src/internal/rewards/RewardRedemptionService.ts +++ b/server/src/internal/rewards/RewardRedemptionService.ts @@ -72,41 +72,6 @@ export class RewardRedemptionService { }); return data as any; - - // let query = sb - // .from("reward_redemptions") - // .select( - // ` - // * - // ${ - // withRewardProgram - // ? ", reward_program:reward_programs!inner(*, reward:rewards!inner(*))" - // : "" - // } - // ${withReferralCode ? ", referral_code:referral_codes!inner(*)" : ""} - // `, - // ) - // .eq("internal_customer_id", internalCustomerId); - - // if (notNullish(internalRewardProgramId)) { - // query = query.eq("internal_reward_program_id", internalRewardProgramId); - // } - - // if (notNullish(triggered)) { - // query = query.eq("triggered", triggered); - // } - - // if (notNullish(limit)) { - // query = query.limit(limit); - // } - - // const { data, error } = await query; - - // if (error) { - // throw error; - // } - - // return data; } static async getByReferrer({ @@ -142,23 +107,6 @@ export class RewardRedemptionService { })); return processed; - - // const { data, error } = await sb - // .from("reward_redemptions") - // .select( - // ` - // *, referral_code:referral_codes!inner(*) - // ${withCustomer ? ", customer:customers!inner(*)" : ""} - // `, - // ) - // .eq("referral_code.internal_customer_id", internalCustomerId) - // .limit(limit); - - // if (error) { - // throw error; - // } - - // return data; } static async insert({ diff --git a/server/src/internal/users/userRouter.ts b/server/src/internal/users/userRouter.ts index 3b0d8c73a..9b06ba60d 100644 --- a/server/src/internal/users/userRouter.ts +++ b/server/src/internal/users/userRouter.ts @@ -1,23 +1,7 @@ -import { createSupabaseClient } from "@/external/supabaseUtils.js"; import { Router } from "express"; -export const userRouter = Router(); +export const userRouter: Router = Router(); userRouter.get("", async (req: any, res) => { - const supabase = createSupabaseClient(); - res.status(200).json({ userId: req.userId }); - // const { data, error } = await supabase - // .from("users") - // .select("id, email, initialized") - // .eq("id", req.userId) - // .single(); - - // if (error) { - // console.error("Error fetching user data:", error); - // res.status(500).json({ error: error.message }); - // return; - // } - - // res.status(200).json(data); }); diff --git a/server/src/middleware/analyticsMiddleware.ts b/server/src/middleware/analyticsMiddleware.ts index c02e9dd63..0c72b8910 100644 --- a/server/src/middleware/analyticsMiddleware.ts +++ b/server/src/middleware/analyticsMiddleware.ts @@ -8,40 +8,44 @@ const handleResFinish = (req: any, res: any, logtailContext: any) => { if (skipUrls.includes(req.originalUrl)) { return; } - req.logtailAll.info( - `[${res.statusCode}] ${req.method} ${req.originalUrl} (${req.org?.slug})`, - { - req: { - ...logtailContext, + + // Only log to logtailAll if it exists + if (req.logtailAll) { + req.logtailAll.info( + `[${res.statusCode}] ${req.method} ${req.originalUrl} (${req.org?.slug})`, + { + req: { + ...logtailContext, + }, + statusCode: res.statusCode, + res: res.locals.responseBody, }, - statusCode: res.statusCode, - res: res.locals.responseBody, - }, - ); - req.logtailAll.flush(); + ); + req.logtailAll.flush(); + } } catch (error) { console.error("Failed to log response to logtailAll"); console.error(error); } - // Post hog - let posthogUrls = ["/v1/attach"]; - if (req.posthog && posthogUrls.includes(req.originalUrl)) { - posthogCapture({ - posthog: req.posthog, - params: { - distinctId: req.org?.id, - event: `${req.method} ${req.originalUrl}`, - properties: { - authType: req.auth, - orgSlug: req.org?.slug, - statusCode: res.statusCode, - res: res.locals.responseBody, - req: req.body, - }, - }, - }); - } + // Save to PostHog + // let posthogUrls = ["/v1/attach"]; + // if (req.posthog && posthogUrls.includes(req.originalUrl)) { + // posthogCapture({ + // posthog: req.posthog, + // params: { + // distinctId: req.org?.id, + // event: `${req.method} ${req.originalUrl}`, + // properties: { + // authType: req.auth, + // orgSlug: req.org?.slug, + // statusCode: res.statusCode, + // res: res.locals.responseBody, + // req: req.body, + // }, + // }, + // }); + // } }; export const analyticsMiddleware = async (req: any, res: any, next: any) => { diff --git a/server/src/middleware/apiMiddleware.ts b/server/src/middleware/apiMiddleware.ts index ed8ac6acd..efc890580 100644 --- a/server/src/middleware/apiMiddleware.ts +++ b/server/src/middleware/apiMiddleware.ts @@ -8,6 +8,7 @@ export const verifySecretKey = async (req: any, res: any, next: any) => { const authHeader = req.headers["authorization"] || req.headers["Authorization"]; + const logger = req.logtail; const version = req.headers["x-api-version"]; if (version) { @@ -56,7 +57,6 @@ export const verifySecretKey = async (req: any, res: any, next: any) => { // Try verify via Autumn - let logger = req.logtail; try { const { valid, data } = await verifyKey({ db: req.db, diff --git a/server/src/middleware/authMiddleware.ts b/server/src/middleware/authMiddleware.ts index 29fa9998d..a0b903851 100644 --- a/server/src/middleware/authMiddleware.ts +++ b/server/src/middleware/authMiddleware.ts @@ -1,6 +1,8 @@ import { OrgService } from "@/internal/orgs/OrgService.js"; -import { AuthType } from "@autumn/shared"; +import { auth } from "@/utils/auth.js"; +import { AuthType, ErrCode } from "@autumn/shared"; import { verifyToken } from "@clerk/express"; +import { fromNodeHeaders } from "better-auth/node"; import { NextFunction } from "express"; const getTokenData = async (req: any, res: any) => { @@ -33,59 +35,73 @@ const getTokenData = async (req: any, res: any) => { }; export const withOrgAuth = async (req: any, res: any, next: NextFunction) => { - try { - let tokenData = await getTokenData(req, res); + const { logtail: logger } = req; - if (!tokenData?.org_id) { - throw new Error("token data has no org_id"); + try { + // let tokenData = await getTokenData(req, res); + const session = await auth.api.getSession({ + headers: fromNodeHeaders(req.headers), + }); + + if (!session) { + logger.info(`Unauthorized - no session found (${req.originalUrl})`); + return res + .status(401) + .json({ message: "Unauthorized - no session found" }); } - let tokenOrg = tokenData!.org as any; + const orgId = session?.session?.activeOrganizationId; + + if (!orgId) { + logger.info(`Unauthorized - no org id found`); + return res + .status(401) + .json({ message: "Unauthorized - no org id found" }); + } + + // let tokenOrg = tokenData!.org as any; let data = await OrgService.getWithFeatures({ db: req.db, - orgId: tokenOrg.id, + orgId: orgId, env: req.env, }); if (!data) { - return res.status(404).json({ message: "Org not found" }); + logger.warn(`Org ${orgId} not found in DB`); + return res + .status(500) + .json({ message: "Org not found", code: ErrCode.OrgNotFound }); } const { org, features } = data; - req.minOrg = { - id: tokenOrg?.id, - slug: tokenOrg?.slug, - }; - - req.orgId = tokenData!.org_id; - req.user = tokenData!.user; + req.user = session?.user; + req.orgId = orgId; req.org = org; req.features = features; req.authType = AuthType.Dashboard; next(); } catch (error: any) { - console.log( - // `withOrgAuth error (${req.headers["authorization"]}):`, - `(warning) clerk auth failed:`, - error?.message || error, - ); + // console.log(`(warning) clerk auth failed:`, error?.message || error); + logger.warn(`(warning) withOrgAuth failed:`, error?.message || error); res.status(401).json({ message: "Unauthorized" }); return; } }; export const withAuth = async (req: any, res: any, next: NextFunction) => { - const tokenData = await getTokenData(req, res); + const session = await auth.api.getSession({ + headers: fromNodeHeaders(req.headers), + }); - if (!tokenData) { + if (!session) { res.status(401).json({ message: "Unauthorized" }); return; } - req.userId = tokenData?.user_id; + req.userId = session?.user.id; next(); }; diff --git a/server/src/queue/QueueManager.ts b/server/src/queue/QueueManager.ts index 4c0825f44..592d866ff 100644 --- a/server/src/queue/QueueManager.ts +++ b/server/src/queue/QueueManager.ts @@ -1,6 +1,11 @@ +import "dotenv/config"; + import { Queue } from "bullmq"; import { Redis } from "ioredis"; +const BACKUP_REDIS_URL = process.env.REDIS_BACKUP_URL || process.env.REDIS_URL; +const MAIN_REDIS_URL = process.env.REDIS_URL; + export class QueueManager { private static instance: QueueManager; private queue: Queue | null = null; @@ -31,16 +36,7 @@ export class QueueManager { useBackup: boolean; keepConnection?: boolean; }) { - // 1. Connect to redis - - if (useBackup && !process.env.REDIS_BACKUP_URL) { - console.warn(`REDIS_BACKUP_URL not set, using main redis`); - useBackup = false; - } - - const redisUrl = useBackup - ? process.env.REDIS_BACKUP_URL - : process.env.REDIS_URL; + const redisUrl = useBackup ? BACKUP_REDIS_URL : MAIN_REDIS_URL; const connection = new Redis(redisUrl!, { retryStrategy: (times) => { @@ -52,7 +48,7 @@ export class QueueManager { console.log( `Redis connection error (${useBackup ? "backup" : "main"}): ${ error.message - }`, + }` ); if (!keepConnection) { @@ -95,7 +91,7 @@ export class QueueManager { console.log("2. Initializing main & backup queues"); const mainQueue = new Queue("autumn", { connection: { - url: process.env.REDIS_URL, + url: MAIN_REDIS_URL, enableOfflineQueue: false, retryStrategy: (times) => { return 5000; @@ -105,7 +101,7 @@ export class QueueManager { const backupQueue = new Queue("autumn", { connection: { - url: process.env.REDIS_BACKUP_URL, + url: BACKUP_REDIS_URL, enableOfflineQueue: false, }, }); diff --git a/server/src/utils/auth.ts b/server/src/utils/auth.ts new file mode 100644 index 000000000..12159187e --- /dev/null +++ b/server/src/utils/auth.ts @@ -0,0 +1,98 @@ +import { db } from "@/db/initDrizzle.js"; + +import { drizzleAdapter } from "better-auth/adapters/drizzle"; +import { sendInvitationEmail } from "@/internal/emails/sendInvitationEmail.js"; +import { beforeSessionCreated } from "./authUtils/beforeSessionCreated.js"; +import { betterAuth } from "better-auth"; +import { emailOTP, admin, organization } from "better-auth/plugins"; + +import sendOTPEmail from "@/internal/emails/sendOTPEmail.js"; +import { sendOnboardingEmail } from "@/internal/emails/sendOnboardingEmail.js"; +import { ADMIN_USER_IDs } from "./constants.js"; +import { afterOrgCreated } from "./authUtils/afterOrgCreated.js"; + +export const auth = betterAuth({ + database: drizzleAdapter(db, { + provider: "pg", // or "mysql", "sqlite" + }), + + databaseHooks: { + user: { + create: { + after: async (user) => { + await sendOnboardingEmail({ + name: user.name, + email: user.email, + }); + }, + }, + }, + session: { + create: { + before: beforeSessionCreated, + }, + }, + }, + user: { + deleteUser: { + enabled: true, + + sendDeleteAccountVerification: async ({ user, url, token }) => { + console.log("Delete account verification", { url, token }); + }, + }, + }, + trustedOrigins: [ + "http://localhost:3000", + "https://app.useautumn.com", + "https://*.useautumn.com", + ], + socialProviders: { + google: { + clientId: process.env.GOOGLE_CLIENT_ID!, + clientSecret: process.env.GOOGLE_CLIENT_SECRET!, + }, + }, + plugins: [ + emailOTP({ + async sendVerificationOTP({ email, otp, type }) { + // Implement the sendVerificationOTP method to send the OTP to the user's email address + + await sendOTPEmail({ + email, + otp, + }); + }, + }), + admin({ + adminUserIds: ADMIN_USER_IDs, + impersonationSessionDuration: 1000 * 60 * 60 * 24, // 1 days + }), + + organization({ + async sendInvitationEmail(data) { + const inviteLink = `${process.env.CLIENT_URL}/accept?id=${data.id}`; + await sendInvitationEmail({ + email: data.email, + orgName: data.organization.name, + inviteLink, + }); + }, + schema: { + organization: { + modelName: "organizations", + fields: { + createdAt: "createdAt", + }, + }, + }, + + organizationCreation: { + disabled: false, + afterCreate: async ({ organization }) => { + await afterOrgCreated({ org: organization as any }); + }, + }, + }), + ], +}); diff --git a/server/src/utils/authUtils/afterOrgCreated.ts b/server/src/utils/authUtils/afterOrgCreated.ts new file mode 100644 index 000000000..bcc251446 --- /dev/null +++ b/server/src/utils/authUtils/afterOrgCreated.ts @@ -0,0 +1,83 @@ +import { db } from "@/db/initDrizzle.js"; +import { OrgService } from "@/internal/orgs/OrgService.js"; +import { AppEnv } from "@autumn/shared"; +import { generatePublishableKey } from "../encryptUtils.js"; +import { createSvixApp } from "@/external/svix/svixHelpers.js"; +import { logger } from "@/external/logtail/logtailUtils.js"; +import { Organization } from "better-auth/plugins"; + +export const initOrgSvixApps = async ({ + id, + slug, +}: { + id: string; + slug: string; +}) => { + const batchCreate = []; + batchCreate.push( + createSvixApp({ + name: `${slug}_${AppEnv.Sandbox}`, + orgId: id, + env: AppEnv.Sandbox, + }), + ); + batchCreate.push( + createSvixApp({ + name: `${slug}_${AppEnv.Live}`, + orgId: id, + env: AppEnv.Live, + }), + ); + + const [sandboxApp, liveApp] = await Promise.all(batchCreate); + + return { sandboxApp, liveApp }; +}; + +export const afterOrgCreated = async ({ org }: { org: Organization }) => { + logger.info(`Org created: ${org.id} (${org.slug})`); + + const { id, slug, createdAt } = org; + + try { + await OrgService.update({ + db, + orgId: id, + updates: { + created_at: createdAt.getTime(), + }, + }); + + // 1. Create svix webhoooks + const { sandboxApp, liveApp } = await initOrgSvixApps({ + slug, + id, + }); + + await OrgService.update({ + db, + orgId: id, + updates: { + svix_config: { + sandbox_app_id: sandboxApp?.id, + live_app_id: liveApp?.id, + }, + test_pkey: generatePublishableKey(AppEnv.Sandbox), + live_pkey: generatePublishableKey(AppEnv.Live), + }, + }); + + logger.info(`Initialized resources for org ${id} (${slug})`); + } catch (error: any) { + if (error?.data && error.data.code == "23505") { + logger.error( + `Org ${id} already exists in Supabase -- skipping creationg`, + ); + return; + } + logger.error( + `Failed to insert org. Code: ${error.code}, message: ${error.message}`, + ); + return; + } +}; diff --git a/server/src/utils/authUtils/beforeSessionCreated.ts b/server/src/utils/authUtils/beforeSessionCreated.ts new file mode 100644 index 000000000..ef6ed19e9 --- /dev/null +++ b/server/src/utils/authUtils/beforeSessionCreated.ts @@ -0,0 +1,37 @@ +import { db } from "@/db/initDrizzle.js"; +import { Session } from "better-auth"; +import { member, session as sessionTable } from "@autumn/shared"; +import { eq, desc } from "drizzle-orm"; +import { createDefaultOrg } from "@/utils/authUtils/createDefaultOrg.js"; + +export const beforeSessionCreated = async (session: Session) => { + try { + console.log(`Running beforeSessionCreated for user ${session.userId}`); + + let membership = await db.query.member.findFirst({ + where: eq(member.userId, session.userId), + }); + + if (membership) { + console.log( + "Returning session with active org ID:", + membership.organizationId, + ); + return { + data: { + ...session, + activeOrganizationId: membership.organizationId, + }, + }; + } + + const orgId = await createDefaultOrg({ session }); + + return { + data: { + ...session, + activeOrganizationId: orgId, + }, + }; + } catch (error) {} +}; diff --git a/server/src/utils/authUtils/createDefaultOrg.ts b/server/src/utils/authUtils/createDefaultOrg.ts new file mode 100644 index 000000000..fbce9697d --- /dev/null +++ b/server/src/utils/authUtils/createDefaultOrg.ts @@ -0,0 +1,64 @@ +import { db } from "@/db/initDrizzle.js"; +import { auth } from "@/utils/auth.js"; +import { Session } from "better-auth"; +import { eq } from "drizzle-orm"; +import { invitation, user as userTable } from "@autumn/shared"; +import { slugify } from "@/utils/genUtils.js"; +import { Organization } from "better-auth/plugins/organization"; +import { and } from "drizzle-orm"; + +export const createDefaultOrg = async ({ + session, +}: { + session: Session; +}): Promise => { + try { + const user = await db.query.user.findFirst({ + where: eq(userTable.id, session.userId), + }); + + const invites = await db + .select() + .from(invitation) + .where( + and( + eq(invitation.email, user?.email || ""), + eq(invitation.status, "pending"), + ), + ); + + if (invites.length > 0) { + await auth.api.addMember({ + body: { + userId: session.userId, + role: invites[0].role as any, + organizationId: invites[0].organizationId, + }, + }); + + await db.update(invitation).set({ + status: "accepted", + }); + + return invites[0].organizationId as any; + } + + let userName = user?.name; + if (!userName) { + userName = user?.email?.split("@")[0] || "org"; + } + + const res = await auth.api.createOrganization({ + body: { + name: `${userName}'s Org`, + slug: `${slugify(userName)}_${Math.floor(10000000 + Math.random() * 90000000)}`, + userId: session.userId, + }, + }); + + return res?.id as any; + } catch (error) { + console.error("Error creating org", error); + return undefined; + } +}; diff --git a/server/src/utils/constants.ts b/server/src/utils/constants.ts index d63c2439c..d0f0e97a1 100644 --- a/server/src/utils/constants.ts +++ b/server/src/utils/constants.ts @@ -1,3 +1,4 @@ +import "dotenv/config"; import { CusProductStatus } from "@autumn/shared"; export const BREAK_API_VERSION = 0.2; @@ -6,3 +7,10 @@ export const getActiveCusProductStatuses = () => [ CusProductStatus.Active, CusProductStatus.PastDue, ]; + +export const ADMIN_USER_IDs = + process.env.ENV == "production" || process.env.NODE_ENV == "production" + ? ["user_2tMgAiPsQzX8JTHjZZh9m0VdvUv", "user_2sB3tBXsnVVLlTKliQIqvvM2xfB"] + : ["user_2rypooIKyMQx81vMS8FFGx24UHU"]; + +// console.log(ADMIN_USER_IDs); diff --git a/server/src/utils/errorUtils.ts b/server/src/utils/errorUtils.ts index a5ba71074..9a81ec6c8 100644 --- a/server/src/utils/errorUtils.ts +++ b/server/src/utils/errorUtils.ts @@ -113,9 +113,7 @@ export const handleRequestError = ({ // logger.warn(`${req.method} ${req.originalUrl}`); logReqUrl(logger, req, "warn"); logger.warn( - `Request from ${ - req.minOrg?.slug || req.org?.slug || req.orgId || "unknown" - } for ${action}`, + `Request from ${req.org?.slug || req.orgId || "unknown"} for ${action}`, ); error.print(logger); if (req.originalUrl.includes("/webhooks/stripe")) { @@ -139,9 +137,7 @@ export const handleRequestError = ({ // logger.error(`${req.method} ${req.originalUrl}`); logReqUrl(logger, req, "error"); logger.error( - `Request from ${ - req.minOrg?.slug || req.org?.slug || req.orgId || "unknown" - } for ${action}`, + `Request from ${req.org?.slug || req.orgId || "unknown"} for ${action}`, ); if (error instanceof Stripe.errors.StripeError) { @@ -221,6 +217,10 @@ export const handleFrontendReqError = ({ }); logger.warn(`${action}`); logger.warn(error); + res.status(400).json({ + message: error.message || "Unknown error", + code: error.code || "unknown_error", + }); } catch (error) { console.log("Failed to log error / warning"); } diff --git a/server/src/utils/genUtils.ts b/server/src/utils/genUtils.ts index c4b9f6eeb..c991b533a 100644 --- a/server/src/utils/genUtils.ts +++ b/server/src/utils/genUtils.ts @@ -101,3 +101,13 @@ export const toSnakeCase = (obj: any): any => { } return obj; }; + +export const slugify = ( + text: string, + type: "underscore" | "dash" = "underscore", +) => { + return text + .toLowerCase() + .replace(/ /g, type == "underscore" ? "_" : "-") + .replace(/[^\w\s-]/g, ""); +}; diff --git a/server/src/utils/initUtils.ts b/server/src/utils/initUtils.ts new file mode 100644 index 000000000..5b9d38ddb --- /dev/null +++ b/server/src/utils/initUtils.ts @@ -0,0 +1,39 @@ +import { logger } from "@/external/logtail/logtailUtils.js"; +import "dotenv/config"; + +export const checkEnvVars = () => { + if (!process.env.DATABASE_URL) { + console.error(`DATABASE_URL is not set`); + process.exit(1); + } + + if (!process.env.ENCRYPTION_IV || !process.env.ENCRYPTION_PASSWORD) { + console.error( + `ENCRYPTION_IV or ENCRYPTION_PASSWORD is not set (used for Stripe key encryption)`, + ); + process.exit(1); + } + + if (!process.env.REDIS_URL) { + console.error(`REDIS_URL is not set`); + process.exit(1); + } + + if (!process.env.BETTER_AUTH_SECRET || !process.env.BETTER_AUTH_URL) { + console.error(`BETTER_AUTH_SECRET or BETTER_AUTH_URL is not set`); + process.exit(1); + } + + if (!process.env.RESEND_API_KEY || !process.env.RESEND_DOMAIN) { + logger.warn( + "RESEND_API_KEY or RESEND_DOMAIN is not set (use terminal for sign in OTP)", + ); + } + + if ( + !process.env.LOGTAIL_SOURCE_TOKEN || + !process.env.LOGTAIL_INGESTING_HOST + ) { + logger.warn("LOGTAIL ENV VARs not found, skipping logtail"); + } +}; diff --git a/server/src/utils/models/Request.ts b/server/src/utils/models/Request.ts index 943c0973a..a389d1a15 100644 --- a/server/src/utils/models/Request.ts +++ b/server/src/utils/models/Request.ts @@ -1,10 +1,4 @@ -import { - AppEnv, - AuthType, - Feature, - MinOrg, - Organization, -} from "@autumn/shared"; +import { AppEnv, AuthType, Feature, Organization } from "@autumn/shared"; import { Logtail } from "@logtail/node"; import type { Request as ExpressRequest, @@ -27,7 +21,6 @@ export interface ExtendedRequest extends ExpressRequest { orgId: string; env: AppEnv; - minOrg: MinOrg; org: Organization; features: Feature[]; diff --git a/server/src/utils/routerUtils.ts b/server/src/utils/routerUtils.ts index 5ba45d798..27de0badc 100644 --- a/server/src/utils/routerUtils.ts +++ b/server/src/utils/routerUtils.ts @@ -24,7 +24,9 @@ export const routeHandler = async ({ try { if (error instanceof RecaseError) { if (error.code === ErrCode.EntityNotFound) { - req.logtail.warn(`${error.message}, org: ${req.minOrg?.slug}`); + req.logtail.warn( + `${error.message}, org: ${req.org?.slug || req.orgId}`, + ); return res.status(404).json({ message: error.message, code: error.code, diff --git a/server/src/utils/scriptUtils/getAll/getAllOrgs.ts b/server/src/utils/scriptUtils/getAll/getAllOrgs.ts new file mode 100644 index 000000000..65535e6c3 --- /dev/null +++ b/server/src/utils/scriptUtils/getAll/getAllOrgs.ts @@ -0,0 +1,25 @@ +import { DrizzleCli } from "@/db/initDrizzle.js"; +import { organizations } from "@autumn/shared"; + +export const getAllOrgs = async (db: DrizzleCli) => { + const orgs = []; + let offset = 0; + const limit = 200; + + while (true) { + const batch = await db + .select() + .from(organizations) + .limit(limit) + .offset(offset); + orgs.push(...batch); + + if (batch.length < limit) { + break; + } + + offset += limit; + console.log(`Fetched ${orgs.length} orgs`); + } + return orgs; +}; diff --git a/server/src/utils/scriptUtils/getAll/getAllUsers.ts b/server/src/utils/scriptUtils/getAll/getAllUsers.ts new file mode 100644 index 000000000..52b02e8b5 --- /dev/null +++ b/server/src/utils/scriptUtils/getAll/getAllUsers.ts @@ -0,0 +1,28 @@ +import { DrizzleCli } from "@/db/initDrizzle.js"; +import { user } from "@autumn/shared"; + +import { desc } from "drizzle-orm"; + +export const getAllUsers = async (db: DrizzleCli) => { + const users = []; + let offset = 0; + const limit = 200; + + while (true) { + const batch = await db + .select() + .from(user) + .limit(limit) + .offset(offset) + .orderBy(desc(user.createdAt)); + users.push(...batch); + + if (batch.length < limit) { + break; + } + + offset += limit; + console.log(`Fetched ${users.length} users`); + } + return users; +}; diff --git a/server/src/websockets/WsManager.ts b/server/src/websockets/WsManager.ts index 62a00d2a0..c49109c76 100644 --- a/server/src/websockets/WsManager.ts +++ b/server/src/websockets/WsManager.ts @@ -1,6 +1,3 @@ -import { WebSocketServer } from "ws"; -import http from "http"; - export class WebsocketManager { public channels: Map>; public subscriptions: WeakMap>; diff --git a/server/src/websockets/initWs.ts b/server/src/websockets/initWs.ts index 09827dd79..b0be1befa 100644 --- a/server/src/websockets/initWs.ts +++ b/server/src/websockets/initWs.ts @@ -1,9 +1,6 @@ -import { WebSocketServer } from "ws"; import http from "http"; - -import { createSupabaseClient } from "@/external/supabaseUtils.js"; import { AppEnv, ErrCode } from "@autumn/shared"; -import { OrgService } from "@/internal/orgs/OrgService.js"; +import { WebSocketServer, WebSocket } from "ws"; export enum SbChannelEvent { BalanceUpdated = "balance_updated", @@ -74,7 +71,7 @@ class WebSocketRouter { constructor(server: http.Server) { this.wss = new WebSocketServer({ server }); - this.wss.on("connection", (ws, req) => + this.wss.on("connection", (ws: WebSocket, req: http.IncomingMessage) => this.handleConnection(ws as any, req as any), ); } diff --git a/server/tests/advanced/usage/usage4.ts b/server/tests/advanced/usage/usage4.ts index 06dd0e215..e1ac734e3 100644 --- a/server/tests/advanced/usage/usage4.ts +++ b/server/tests/advanced/usage/usage4.ts @@ -144,7 +144,6 @@ describe(`${chalk.yellowBright("usage4: GPU starter annual")}`, () => { // let usagePrice = await getUsageInArrearPrice({ // org: this.org, -// sb: this.sb, // env: this.env, // productId: advanceProducts.gpuStarterAnnual.id, // }); diff --git a/server/tests/alex/00_setup.ts b/server/tests/alex/00_setup.ts index 246cfb766..73cd737ac 100644 --- a/server/tests/alex/00_setup.ts +++ b/server/tests/alex/00_setup.ts @@ -12,7 +12,6 @@ describe("Initialize org for tests", () => { this.org = await clearOrg({ orgSlug: ORG_SLUG, env: DEFAULT_ENV }); this.env = DEFAULT_ENV; - this.sb = createSupabaseClient(); await setupOrg({ orgId: this.org.id, env: DEFAULT_ENV, diff --git a/server/tests/alex/init.ts b/server/tests/alex/init.ts index 9a1bd22b2..d3338a1d9 100644 --- a/server/tests/alex/init.ts +++ b/server/tests/alex/init.ts @@ -422,7 +422,6 @@ let orgSlug = "unit-test-org"; before(async function () { try { this.env = AppEnv.Sandbox; - this.sb = createSupabaseClient(); const { db, client } = initDrizzle(); this.db = db; this.client = client; diff --git a/server/tests/archives/arrear_prorated/arrear_prorated2.ts b/server/tests/archives/arrear_prorated/arrear_prorated2.ts index c4b1d23a5..3aae3b373 100644 --- a/server/tests/archives/arrear_prorated/arrear_prorated2.ts +++ b/server/tests/archives/arrear_prorated/arrear_prorated2.ts @@ -1,298 +1,298 @@ -import chalk from "chalk"; -import Stripe from "stripe"; +// import chalk from "chalk"; +// import Stripe from "stripe"; -import { expect } from "chai"; -import { AutumnCli } from "tests/cli/AutumnCli.js"; -import { advanceProducts, features } from "tests/global.js"; -import { compareMainProduct } from "tests/utils/compare.js"; -import { advanceTestClock } from "tests/utils/stripeUtils.js"; -import { timeout } from "tests/utils/genUtils.js"; -import { createStripeCli } from "@/external/stripe/utils.js"; -import { addDays, addMonths, format } from "date-fns"; +// import { expect } from "chai"; +// import { AutumnCli } from "tests/cli/AutumnCli.js"; +// import { advanceProducts, features } from "tests/global.js"; +// import { compareMainProduct } from "tests/utils/compare.js"; +// import { advanceTestClock } from "tests/utils/stripeUtils.js"; +// import { timeout } from "tests/utils/genUtils.js"; +// import { createStripeCli } from "@/external/stripe/utils.js"; +// import { addDays, addMonths, format } from "date-fns"; -import { initCustomerWithTestClock } from "tests/utils/testInitUtils.js"; -import { checkSubscriptionContainsProducts } from "tests/utils/scheduleCheckUtils.js"; -import { CacheManager } from "@/external/caching/CacheManager.js"; -import { CacheType } from "@/external/caching/cacheActions.js"; -import { hashApiKey } from "@/internal/dev/api-keys/apiKeyUtils.js"; +// import { initCustomerWithTestClock } from "tests/utils/testInitUtils.js"; +// import { checkSubscriptionContainsProducts } from "tests/utils/scheduleCheckUtils.js"; +// import { CacheManager } from "@/external/caching/CacheManager.js"; +// import { CacheType } from "@/external/caching/cacheActions.js"; +// import { hashApiKey } from "@/internal/dev/api-keys/apiKeyUtils.js"; -const advanceAPThroughBalances = async ({ - stripeSub, - stripeCli, - testClockId, - customerId, - billingUnits, - startingFrom, - startingBalance, -}: { - stripeSub: Stripe.Subscription; - stripeCli: Stripe; - testClockId: string; - customerId: string; - billingUnits: number; - startingFrom?: number; - startingBalance?: number; -}) => { - // 1. Get total period - let totalPeriod = - (stripeSub.current_period_end - stripeSub.current_period_start) * 1000; +// const advanceAPThroughBalances = async ({ +// stripeSub, +// stripeCli, +// testClockId, +// customerId, +// billingUnits, +// startingFrom, +// startingBalance, +// }: { +// stripeSub: Stripe.Subscription; +// stripeCli: Stripe; +// testClockId: string; +// customerId: string; +// billingUnits: number; +// startingFrom?: number; +// startingBalance?: number; +// }) => { +// // 1. Get total period +// let totalPeriod = +// (stripeSub.current_period_end - stripeSub.current_period_start) * 1000; - // 2. Get allowance - let allowance = - advanceProducts.proratedArrearSeats.entitlements.seats.allowance!; +// // 2. Get allowance +// let allowance = +// advanceProducts.proratedArrearSeats.entitlements.seats.allowance!; - // 3. Get starting balance - let balance = startingBalance || allowance; +// // 3. Get starting balance +// let balance = startingBalance || allowance; - // 4. Get price per seat - let pricePerSeat = - advanceProducts.proratedArrearSeats.prices[1].config.usage_tiers[0].amount; +// // 4. Get price per seat +// let pricePerSeat = +// advanceProducts.proratedArrearSeats.prices[1].config.usage_tiers[0].amount; - let skipDays = 2; - // 5. Get accrued price - let accruedPrice = 0; - if (startingBalance) { - let proratedPrice = - (-startingBalance * - pricePerSeat * - (startingFrom! - stripeSub.current_period_start * 1000)) / - totalPeriod; +// let skipDays = 2; +// // 5. Get accrued price +// let accruedPrice = 0; +// if (startingBalance) { +// let proratedPrice = +// (-startingBalance * +// pricePerSeat * +// (startingFrom! - stripeSub.current_period_start * 1000)) / +// totalPeriod; - let previouslyPaid = pricePerSeat * -startingBalance; - let priceToPay = proratedPrice - previouslyPaid; +// let previouslyPaid = pricePerSeat * -startingBalance; +// let priceToPay = proratedPrice - previouslyPaid; - accruedPrice = priceToPay; - // accruedPrice = Math.max(accruedPrice, 0); - console.log(" 🔍 Starting balance: ", startingBalance); - console.log(" 🔍 Starting price: ", accruedPrice); - } +// accruedPrice = priceToPay; +// // accruedPrice = Math.max(accruedPrice, 0); +// console.log(" 🔍 Starting balance: ", startingBalance); +// console.log(" 🔍 Starting price: ", accruedPrice); +// } - let curTime = startingFrom || stripeSub.current_period_start * 1000; - let numberOfEvents = 2; +// let curTime = startingFrom || stripeSub.current_period_start * 1000; +// let numberOfEvents = 2; - console.group(); - console.group(); - for (let i = 0; i < numberOfEvents; i++) { - let sign = balance > 0 ? 1 : Math.random() > 0.7 ? 1 : -1; +// console.group(); +// console.group(); +// for (let i = 0; i < numberOfEvents; i++) { +// let sign = balance > 0 ? 1 : Math.random() > 0.7 ? 1 : -1; - let currentUsage = allowance - balance; +// let currentUsage = allowance - balance; - let nextBoundary = - Math.ceil((currentUsage + 1) / billingUnits) * billingUnits; +// let nextBoundary = +// Math.ceil((currentUsage + 1) / billingUnits) * billingUnits; - let prevBoundary = nextBoundary - billingUnits; +// let prevBoundary = nextBoundary - billingUnits; - let valueNeeded = 0; - if (sign > 0) { - // Add random amount to push above next boundary - const valueToGetToNegative = balance + 1; - valueNeeded = - Math.floor(Math.random() * 10) + (nextBoundary - currentUsage + 1); +// let valueNeeded = 0; +// if (sign > 0) { +// // Add random amount to push above next boundary +// const valueToGetToNegative = balance + 1; +// valueNeeded = +// Math.floor(Math.random() * 10) + (nextBoundary - currentUsage + 1); - valueNeeded = Math.max(valueNeeded, valueToGetToNegative); - } else { - valueNeeded = -( - Math.floor(Math.random() * 10) + - (currentUsage - prevBoundary + 1) - ); - } +// valueNeeded = Math.max(valueNeeded, valueToGetToNegative); +// } else { +// valueNeeded = -( +// Math.floor(Math.random() * 10) + +// (currentUsage - prevBoundary + 1) +// ); +// } - let newBalance = balance - valueNeeded; +// let newBalance = balance - valueNeeded; - await AutumnCli.updateBalances({ - customerId, - balances: [ - { - feature_id: features.seats.id, - balance: newBalance, - }, - ], - }); +// await AutumnCli.updateBalances({ +// customerId, +// balances: [ +// { +// feature_id: features.seats.id, +// balance: newBalance, +// }, +// ], +// }); - await timeout(2000); +// await timeout(2000); - let prevBalance = balance; - balance = newBalance; +// let prevBalance = balance; +// balance = newBalance; - // Calculate prorated price only when crossing boundary - let newPrice = Math.max(0, -balance * pricePerSeat); - let prevCurTime = curTime; - curTime = addDays(curTime, 2).getTime(); +// // Calculate prorated price only when crossing boundary +// let newPrice = Math.max(0, -balance * pricePerSeat); +// let prevCurTime = curTime; +// curTime = addDays(curTime, 2).getTime(); - if (i === numberOfEvents - 1) { - curTime = stripeSub.current_period_end * 1000; - } +// if (i === numberOfEvents - 1) { +// curTime = stripeSub.current_period_end * 1000; +// } - let proratedPrice = (newPrice * (curTime - prevCurTime)) / totalPeriod; - accruedPrice += Number(proratedPrice.toFixed(2)); +// let proratedPrice = (newPrice * (curTime - prevCurTime)) / totalPeriod; +// accruedPrice += Number(proratedPrice.toFixed(2)); - console.log(`Event ${i + 1}:`); - console.log(` - Value added: ${valueNeeded}`); - console.log(` - Balance: ${prevBalance} -> ${balance}`); - console.log(` - Prorated price: ${proratedPrice.toFixed(2)}`); - console.log(` - Accrued price: ${accruedPrice.toFixed(2)}`); +// console.log(`Event ${i + 1}:`); +// console.log(` - Value added: ${valueNeeded}`); +// console.log(` - Balance: ${prevBalance} -> ${balance}`); +// console.log(` - Prorated price: ${proratedPrice.toFixed(2)}`); +// console.log(` - Accrued price: ${accruedPrice.toFixed(2)}`); - await advanceTestClock({ - stripeCli, - testClockId, - numberOfDays: 2, - startingFrom: new Date(prevCurTime), - }); - } +// await advanceTestClock({ +// stripeCli, +// testClockId, +// numberOfDays: 2, +// startingFrom: new Date(prevCurTime), +// }); +// } - console.groupEnd(); - console.groupEnd(); +// console.groupEnd(); +// console.groupEnd(); - // Advance test clock to end of period +// // Advance test clock to end of period - let advanceTo = addDays(addMonths(new Date(), 1), 2); - let advanceToStart = startingFrom ? new Date(startingFrom) : new Date(); - await advanceTestClock({ - stripeCli, - testClockId, - numberOfDays: 2, - startingFrom: addMonths(advanceToStart, 1), - }); +// let advanceTo = addDays(addMonths(new Date(), 1), 2); +// let advanceToStart = startingFrom ? new Date(startingFrom) : new Date(); +// await advanceTestClock({ +// stripeCli, +// testClockId, +// numberOfDays: 2, +// startingFrom: addMonths(advanceToStart, 1), +// }); - // Check invoice amount - const res = await AutumnCli.getCustomer(customerId); - let invoice = res.invoices[0]; +// // Check invoice amount +// const res = await AutumnCli.getCustomer(customerId); +// let invoice = res.invoices[0]; - let basePrice = advanceProducts.proratedArrearSeats.prices[0].config.amount; - let nextMonthUsagePrice = Math.max(-balance * pricePerSeat, 0); - console.log(" 🔍 Next month usage price: ", nextMonthUsagePrice); +// let basePrice = advanceProducts.proratedArrearSeats.prices[0].config.amount; +// let nextMonthUsagePrice = Math.max(-balance * pricePerSeat, 0); +// console.log(" 🔍 Next month usage price: ", nextMonthUsagePrice); - let expectedTotal = invoice.total; - expect(Number(expectedTotal.toFixed(2))).to.lessThan(invoice.total + 0.1); - expect(Number(expectedTotal.toFixed(2))).to.greaterThan(invoice.total - 0.1); +// let expectedTotal = invoice.total; +// expect(Number(expectedTotal.toFixed(2))).to.lessThan(invoice.total + 0.1); +// expect(Number(expectedTotal.toFixed(2))).to.greaterThan(invoice.total - 0.1); - return { - balance, - advancedTo: advanceTo.getTime(), - }; -}; +// return { +// balance, +// advancedTo: advanceTo.getTime(), +// }; +// }; -describe(`${chalk.yellowBright( - "arrear_prorated2: testing update in arrear prorated through /balances", -)}`, () => { - const customerId = "arrear-prorated-balances"; +// describe(`${chalk.yellowBright( +// "arrear_prorated2: testing update in arrear prorated through /balances", +// )}`, () => { +// const customerId = "arrear-prorated-balances"; - let testClockId = ""; - let stripeCli: Stripe; - let subId = ""; - let stripeSub: Stripe.Subscription; - let billingUnits = - advanceProducts.proratedArrearSeats.prices[1].config.billing_units || 1; +// let testClockId = ""; +// let stripeCli: Stripe; +// let subId = ""; +// let stripeSub: Stripe.Subscription; +// let billingUnits = +// advanceProducts.proratedArrearSeats.prices[1].config.billing_units || 1; - before(async function () { - const { testClockId: createdTestClockId } = await initCustomerWithTestClock( - { - customerId, - org: this.org, - env: this.env, - db: this.db, - }, - ); +// before(async function () { +// const { testClockId: createdTestClockId } = await initCustomerWithTestClock( +// { +// customerId, +// org: this.org, +// env: this.env, +// db: this.db, +// }, +// ); - stripeCli = createStripeCli({ - org: this.org, - env: this.env, - }); +// stripeCli = createStripeCli({ +// org: this.org, +// env: this.env, +// }); - testClockId = createdTestClockId; +// testClockId = createdTestClockId; - await this.sb - .from("organizations") - .update({ - config: { - ...this.org.config, - bill_upgrade_immediately: false, - }, - }) - .eq("id", this.org.id); +// await this.sb +// .from("organizations") +// .update({ +// config: { +// ...this.org.config, +// bill_upgrade_immediately: false, +// }, +// }) +// .eq("id", this.org.id); - await CacheManager.invalidate({ - action: CacheType.SecretKey, - value: hashApiKey(process.env.UNIT_TEST_AUTUMN_SECRET_KEY!), - }); - await CacheManager.disconnect(); - }); +// await CacheManager.invalidate({ +// action: CacheType.SecretKey, +// value: hashApiKey(process.env.UNIT_TEST_AUTUMN_SECRET_KEY!), +// }); +// await CacheManager.disconnect(); +// }); - it("should attach in arrear prorated seats", async () => { - await timeout(5000); - await AutumnCli.attach({ - customerId, - productId: advanceProducts.proratedArrearSeats.id, - }); - }); +// it("should attach in arrear prorated seats", async () => { +// await timeout(5000); +// await AutumnCli.attach({ +// customerId, +// productId: advanceProducts.proratedArrearSeats.id, +// }); +// }); - it("should have correct product", async function () { - const res = await AutumnCli.getCustomer(customerId); - compareMainProduct({ - sent: advanceProducts.proratedArrearSeats, - cusRes: res, - }); +// it("should have correct product", async function () { +// const res = await AutumnCli.getCustomer(customerId); +// compareMainProduct({ +// sent: advanceProducts.proratedArrearSeats, +// cusRes: res, +// }); - // 2. Get subscription period start and period end - subId = res.products[0].subscription_ids[0]; - stripeSub = await stripeCli.subscriptions.retrieve(subId); +// // 2. Get subscription period start and period end +// subId = res.products[0].subscription_ids[0]; +// stripeSub = await stripeCli.subscriptions.retrieve(subId); - await checkSubscriptionContainsProducts({ - db: this.db, - org: this.org, - env: this.env, - subscriptionId: subId, - productIds: [advanceProducts.proratedArrearSeats.id], - }); - }); +// await checkSubscriptionContainsProducts({ +// db: this.db, +// org: this.org, +// env: this.env, +// subscriptionId: subId, +// productIds: [advanceProducts.proratedArrearSeats.id], +// }); +// }); - let advancedTo: number; - let balance: number; - it("should run first cycles and have correct invoice / balance", async () => { - // Do it again - let { advancedTo: advancedTo1, balance: balance1 } = - await advanceAPThroughBalances({ - stripeSub, - stripeCli, - testClockId, - customerId, - billingUnits, - }); +// let advancedTo: number; +// let balance: number; +// it("should run first cycles and have correct invoice / balance", async () => { +// // Do it again +// let { advancedTo: advancedTo1, balance: balance1 } = +// await advanceAPThroughBalances({ +// stripeSub, +// stripeCli, +// testClockId, +// customerId, +// billingUnits, +// }); - advancedTo = advancedTo1; - balance = balance1; - }); +// advancedTo = advancedTo1; +// balance = balance1; +// }); - it("should run second cycle and have correct invoice / balance", async () => { - console.log(` Advanced to ${format(new Date(advancedTo), "yyyy-MM-dd")}`); +// it("should run second cycle and have correct invoice / balance", async () => { +// console.log(` Advanced to ${format(new Date(advancedTo), "yyyy-MM-dd")}`); - let newStripeSub = await stripeCli.subscriptions.retrieve(subId); - await advanceAPThroughBalances({ - stripeSub: newStripeSub, - stripeCli, - testClockId, - customerId, - billingUnits, - startingFrom: advancedTo, - startingBalance: balance, - }); - }); +// let newStripeSub = await stripeCli.subscriptions.retrieve(subId); +// await advanceAPThroughBalances({ +// stripeSub: newStripeSub, +// stripeCli, +// testClockId, +// customerId, +// billingUnits, +// startingFrom: advancedTo, +// startingBalance: balance, +// }); +// }); - after(async function () { - await this.sb - .from("organizations") - .update({ - config: { - ...this.org.config, - bill_upgrade_immediately: true, - }, - }) - .eq("id", this.org.id); - void CacheManager.invalidate({ - action: CacheType.SecretKey, - value: hashApiKey(process.env.UNIT_TEST_AUTUMN_SECRET_KEY!), - }); - }); - // TODO: Test reset at for in arrear prorated with Ent Interval = Lifetime - // TODO: Test in arrear prorated for entitlements with billing units > 1 -}); +// after(async function () { +// await this.sb +// .from("organizations") +// .update({ +// config: { +// ...this.org.config, +// bill_upgrade_immediately: true, +// }, +// }) +// .eq("id", this.org.id); +// void CacheManager.invalidate({ +// action: CacheType.SecretKey, +// value: hashApiKey(process.env.UNIT_TEST_AUTUMN_SECRET_KEY!), +// }); +// }); +// // TODO: Test reset at for in arrear prorated with Ent Interval = Lifetime +// // TODO: Test in arrear prorated for entitlements with billing units > 1 +// }); diff --git a/server/tests/archives/multi_interval2.ts b/server/tests/archives/multi_interval2.ts deleted file mode 100644 index 4243588c4..000000000 --- a/server/tests/archives/multi_interval2.ts +++ /dev/null @@ -1,199 +0,0 @@ -// THIS TEST CASE IS COVERED UNDER UPGRADE2.TS - -// import { Customer } from "@autumn/shared"; -// import chalk from "chalk"; -// import { compareMainProduct } from "../../utils/compare.js"; -// import { AutumnCli } from "../../cli/AutumnCli.js"; -// import { advanceProducts, creditSystems } from "../../global.js"; -// import { timeout } from "../../utils/genUtils.js"; -// import { assert, expect } from "chai"; -// import { createStripeCli } from "@/external/stripe/utils.js"; -// import { -// advanceClockForInvoice, -// advanceMonths, -// advanceTestClock, -// checkBillingMeterEventSummary, -// getUsageInArrearPrice, -// } from "../../utils/stripeUtils.js"; -// import { addMonths } from "date-fns"; -// import { -// sendGPUEvents, -// checkUsageInvoiceAmount, -// } from "../../utils/advancedUsageUtils.js"; -// import { Decimal } from "decimal.js"; -// import { initCustomer } from "@/utils/scriptUtils/initCustomer.js"; -// import { setupBefore } from "tests/before.js"; -// import Stripe from "stripe"; - -// // FOURTH, TEST GPU STARTER ANNUAL UPGRADE TO GPU PRO - -// const testCase = "usage5"; -// describe(`${chalk.yellowBright("usage5: multi interval upgrade, GPU starter annual -> GPU pro annual")}`, () => { -// const customerId = testCase; -// let testClockId = ""; -// let totalCreditsUsed = 0; -// let customer: Customer; -// let stripeCli: Stripe; - -// let curTime = new Date(); -// before(async function () { -// await setupBefore(this); -// let res = await initCustomer({ -// customerId, -// org: this.org, -// env: this.env, -// db: this.db, -// autumn: this.autumnJs, -// attachPm: "success", -// }); - -// testClockId = res.testClockId; -// customer = res.customer; -// stripeCli = this.stripeCli; -// }); - -// it("should attach GPU starter annual", async function () { -// await AutumnCli.attach({ -// customerId: customerId, -// productId: advanceProducts.gpuStarterAnnual.id, -// }); - -// const res = await AutumnCli.getCustomer(customerId); -// compareMainProduct({ -// sent: advanceProducts.gpuStarterAnnual, -// cusRes: res, -// }); -// }); - -// it(`should advance 1 month and upgrade to GPU pro monthly`, async function () { -// let numberOfMonths = 1; -// await advanceMonths({ -// stripeCli, -// testClockId, -// numberOfMonths, -// }); - -// curTime = addMonths(curTime, numberOfMonths); - -// // Send 20 events -// let eventCount = 20; -// const { creditsUsed } = await sendGPUEvents({ -// customerId, -// eventCount, -// }); - -// totalCreditsUsed = creditsUsed; - -// await AutumnCli.attach({ -// customerId: customerId, -// productId: advanceProducts.gpuProAnnual.id, -// }); - -// await advanceTestClock({ -// stripeCli, -// testClockId, -// numberOfDays: 10, -// startingFrom: curTime, -// }); -// }); - -// it("should have GPU pro annual product and 2 Stripe subscriptions", async function () { -// const res = await AutumnCli.getCustomer(customerId); -// compareMainProduct({ -// sent: advanceProducts.gpuProAnnual, -// cusRes: res, -// }); - -// // Should have 2 subscriptions -// const subs = await stripeCli.subscriptions.list({ -// customer: customer.processor.id, -// }); - -// expect(subs.data.length).to.equal(2); -// }); - -// it("should have correct invoice for GPU starter annual (bill for remaining usages)", async function () { -// const res = await AutumnCli.getCustomer(customerId); -// const invoices = res!.invoices; - -// let invoiceIndex = invoices.findIndex((invoice: any) => -// invoice.product_ids.includes(advanceProducts.gpuStarterAnnual.id), -// ); - -// await checkUsageInvoiceAmount({ -// invoices, -// totalUsage: totalCreditsUsed, -// product: advanceProducts.gpuStarterAnnual, -// featureId: creditSystems.gpuCredits.id, -// invoiceIndex, -// includeBase: false, -// }); -// }); - -// it("should send 20 events (on GPU pro annual)", async function () { -// const stripeCli = createStripeCli({ org: this.org, env: this.env }); -// // Send 20 events -// let eventCount = 20; -// const { creditsUsed } = await sendGPUEvents({ -// customerId, -// eventCount, -// }); - -// totalCreditsUsed = creditsUsed; - -// await advanceClockForInvoice({ -// stripeCli, -// testClockId, -// waitForMeterUpdate: true, -// startingFrom: curTime, -// }); -// }); - -// it("should have correct billing meter event summary for GPU pro annual", async function () { -// const res = await AutumnCli.getCustomer(customerId); -// const invoices = res!.invoices; - -// // Think I have to use Stripe metered event summary to check this -// let usagePrice = await getUsageInArrearPrice({ -// org: this.org, -// sb: this.sb, -// env: this.env, -// productId: advanceProducts.gpuProAnnual.id, -// }); - -// let eventSummary = await checkBillingMeterEventSummary({ -// stripeCli, -// startTime: curTime, // Wrong date? -// stripeMeterId: usagePrice?.config?.stripe_meter_id, -// stripeCustomerId: customer.processor.id, -// }); - -// let roundedFirst = Math.ceil( -// new Decimal(totalCreditsUsed) -// .div(usagePrice?.config?.billing_units!) -// .toNumber(), -// ); -// let roundedTotalCreditsUsed = new Decimal(roundedFirst) -// .mul(usagePrice?.config?.billing_units!) -// .toNumber(); -// try { -// assert.exists(eventSummary); -// assert.equal(eventSummary?.aggregated_value, roundedTotalCreditsUsed); -// } catch (error) { -// console.group(); -// console.log(" - Event summary: ", eventSummary); -// console.log(" - Total credits used: ", totalCreditsUsed); -// console.groupEnd(); -// throw error; -// } - -// // await checkUsageInvoiceAmount({ -// // invoices, -// // totalUsage: totalCreditsUsed, -// // product: advanceProducts.gpuProAnnual, -// // featureId: creditSystems.gpuCredits.id, -// // invoiceIndex: 0, -// // includeBase: false, -// // }); -// }); -// }); diff --git a/server/tests/before.ts b/server/tests/before.ts index 36d2897d0..2250ebab8 100644 --- a/server/tests/before.ts +++ b/server/tests/before.ts @@ -14,7 +14,6 @@ const ORG_SLUG = "unit-test-org"; const DEFAULT_ENV = AppEnv.Sandbox; export const setupBefore = async (instance: any) => { - const sb = createSupabaseClient(); const { db, client } = initDrizzle(); const org = await OrgService.getBySlug({ db, slug: ORG_SLUG }); @@ -31,7 +30,6 @@ export const setupBefore = async (instance: any) => { }); const stripeCli = createStripeCli({ org, env }); - instance.sb = sb; instance.org = org; instance.env = env; instance.autumn = autumn; diff --git a/server/tests/global.ts b/server/tests/global.ts index 809840853..2aca93eb3 100644 --- a/server/tests/global.ts +++ b/server/tests/global.ts @@ -854,7 +854,6 @@ const DEFAULT_ENV = AppEnv.Sandbox; before(async function () { try { this.env = AppEnv.Sandbox; - this.sb = createSupabaseClient(); let { db, client } = initDrizzle(); this.db = db; this.client = client; diff --git a/server/tests/utils/setup.ts b/server/tests/utils/setup.ts index 59e7a0dc7..c732c95bf 100644 --- a/server/tests/utils/setup.ts +++ b/server/tests/utils/setup.ts @@ -5,6 +5,7 @@ import { Feature, FeatureType, FullProduct, + Organization, Price, PriceType, RewardProgram, @@ -218,7 +219,6 @@ export const setupOrg = async ({ rewardTriggers: Record; }) => { const axiosInstance = getAxiosInstance(); - const sb = createSupabaseClient(); const { client, db } = initDrizzle(); const autumn = new AutumnInt(); @@ -235,21 +235,27 @@ export const setupOrg = async ({ logger: console, }); - const org = await OrgService.get({ db, orgId }); - await OrgService.update({ - db, - orgId, - updates: { - config: { - ...org.config, - bill_upgrade_immediately: true, + let org: Organization | null = null; + let newFeatures: Feature[] = []; + try { + org = await OrgService.get({ db, orgId }); + await OrgService.update({ + db, + orgId, + updates: { + config: { + ...org.config, + bill_upgrade_immediately: true, + }, }, - }, - }); + }); - const newFeatures = (await FeatureService.list({ db, orgId, env })).filter( - (f) => Object.keys(features).includes(f.id), - ); + newFeatures = (await FeatureService.list({ db, orgId, env })).filter((f) => + Object.keys(features).includes(f.id), + ); + } catch (error) { + console.error("Error updating org", error); + } await client.end(); for (const feature of newFeatures!) { diff --git a/server/tests/utils/stripeUtils.ts b/server/tests/utils/stripeUtils.ts index 28b97a4dd..7c2084127 100644 --- a/server/tests/utils/stripeUtils.ts +++ b/server/tests/utils/stripeUtils.ts @@ -391,37 +391,6 @@ export const checkBillingMeterEventSummary = async ({ } }; -export const getUsageInArrearPrice = async ({ - org, - sb, - env, - productId, -}: { - org: Organization; - sb: SupabaseClient; - env: AppEnv; - productId: string; -}) => { - const { data, error } = await sb - .from("prices") - .select("*, product:products!inner(*)") - .eq("product.org_id", org.id) - .eq("product.env", env) - .eq("product.id", productId); - - if (error) { - throw new Error(error.message); - } - - for (const price of data) { - if (getBillingType(price.config as any) === BillingType.UsageInArrear) { - return price; - } - } - - return null; -}; - export const getDiscount = async ({ stripeCli, customer, diff --git a/server/tsconfig.build.json b/server/tsconfig.build.json index c6ca30cb0..2197394fa 100644 --- a/server/tsconfig.build.json +++ b/server/tsconfig.build.json @@ -7,7 +7,8 @@ "target": "ES2020", "moduleResolution": "NodeNext", "module": "NodeNext", - "declaration": true, + "jsx": "react-jsx", + "rootDir": ".", "baseUrl": ".", "outDir": "./dist", @@ -17,9 +18,10 @@ "skipLibCheck": true, "forceConsistentCasingInFileNames": true, "paths": { - "@/*": ["src/*"] + "@/*": ["src/*"], + "@emails/*": ["emails/*"] } }, - "include": ["src"], + "include": ["src", "emails"], "exclude": ["node_modules", "dist"] } diff --git a/server/tsconfig.json b/server/tsconfig.json index c8456d24f..82edec939 100644 --- a/server/tsconfig.json +++ b/server/tsconfig.json @@ -5,10 +5,11 @@ }, "compilerOptions": { "target": "ES2020", - "moduleResolution": "NodeNext", // or "node16"/"nodenext" - "module": "NodeNext", // or "node16"/"nodenext" + "moduleResolution": "NodeNext", + "module": "NodeNext", - "declaration": true, + // "declaration": true, + "jsx": "react-jsx", "rootDir": ".", "baseUrl": ".", "outDir": "./dist", @@ -20,10 +21,11 @@ "paths": { "@/*": ["src/*"], "@shared/*": ["../shared/*"], - "@scripts/*": ["scripts/*"] + "@scripts/*": ["scripts/*"], + "@emails/*": ["emails/*"] } }, - "include": ["src", "tests", "scripts"], + "include": ["src", "tests", "scripts", "emails"], "references": [ { "path": "../shared" diff --git a/setup.js b/setup.js new file mode 100644 index 000000000..b141ab92d --- /dev/null +++ b/setup.js @@ -0,0 +1,327 @@ +#!/usr/bin/env node +import { randomBytes } from 'crypto'; +import { writeFileSync, copyFileSync } from 'fs'; +import inquirer from 'inquirer'; +import { spawnSync } from 'child_process'; +import chalk from 'chalk'; + +const genUrlSafeBase64 = (bytes) => { + return randomBytes(bytes) + .toString('base64') + .replace(/\+/g, '-') + .replace(/\//g, '_') + .replace(/=+$/g, ''); +} + + +const genRandomSubdomain = (length = 10) => { + const chars = 'abcdefghijklmnopqrstuvwxyz'; + let result = ''; + for (let i = 0; i < length; i++) { + result += chars.charAt(Math.floor(Math.random() * chars.length)); + } + return result; +} + +const genAlphanumericPassword = (length = 24) => { + const chars = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789'; + let result = ''; + for (let i = 0; i < length; i++) { + result += chars.charAt(Math.floor(Math.random() * chars.length)); + } + return result; +} + +// Helper to get or create a Supabase org +const getOrCreateSupabaseOrg = async () => { + + // List orgs (table output) + const orgListResult = spawnSync( + 'npx', + ['supabase', 'orgs', 'list'], + { encoding: 'utf-8' } + ); + if (orgListResult.status !== 0) { + console.error(chalk.red('❌ Failed to list Supabase orgs.')); + process.exit(1); + } + const lines = orgListResult.stdout.split('\n').map(l => l.trim()).filter(Boolean); + + // Find separator line (e.g., "------|------") + const sepIdx = lines.findIndex(line => line.includes('|') && line.includes('-')); + + // If only header and separator, no orgs exist + if (lines.length <= sepIdx + 1) { + console.log(chalk.yellowBright('No Supabase organizations found.')); + const { createOrg } = await inquirer.prompt([ + { + type: 'confirm', + name: 'createOrg', + message: chalk.cyan('Would you like to create a new Supabase organization now?'), + default: true, + }, + ]); + if (!createOrg) { + console.log(chalk.red('❌ Cannot continue without a Supabase organization. Exiting.')); + process.exit(1); + } + const { orgName } = await inquirer.prompt([ + { + type: 'input', + name: 'orgName', + message: chalk.cyan('Enter a name for your new Supabase organization:'), + validate: (input) => input && input.length > 2, + }, + ]); + console.log(chalk.blueBright(`\nCreating Supabase organization '${orgName}'...`)); + const createOrgResult = spawnSync( + 'npx', + ['supabase', 'orgs', 'create', orgName], + { stdio: 'inherit', encoding: 'utf-8' } + ); + if (createOrgResult.status !== 0) { + console.error(chalk.red('❌ Failed to create Supabase organization.')); + process.exit(1); + } + // Done! Org created, return + return; + } + + // At least one org exists, just proceed + return; +}; + +const generateSupabaseDatabaseUrl = async () => { + // Step 3: Run supabase login + console.log(chalk.magentaBright('\n================ Supabase Setup ================\n')); + + console.log(chalk.blueBright('\nLaunching Supabase login...')); + spawnSync('npx', ['supabase', 'login'], { stdio: 'inherit' }); + + // Step 3.5: Ensure org exists and select one + await getOrCreateSupabaseOrg(); + + // Step 4: Prompt for project name and region + const projectName = "autumn-oss-db"; + + // Step 5: Generate DB password (alphanumeric only) + const dbPassword = genAlphanumericPassword(24); // 24 chars, alphanumeric + + // Step 6: Create Supabase project + console.log(chalk.blueBright(`\nCreating Supabase project '${projectName}'...`)); + const createResult = spawnSync( + 'npx', + ['supabase', 'projects', 'create', projectName, '--db-password', dbPassword], + { stdio: 'inherit', encoding: 'utf-8' } + ); + + if (createResult.status !== 0) { + console.error('❌ Failed to create Supabase project.'); + process.exit(1); + } + + // List supabase projects + const listResult = spawnSync( + 'npx', + ['supabase', 'projects', 'list', '--output', 'json'], + { encoding: 'utf-8' } + ); + + if (listResult.status !== 0) { + console.error('❌ Failed to list Supabase projects.'); + process.exit(1); + } + + const projects = JSON.parse(listResult.stdout); + const found = projects.find(p => p.name === projectName); + if (!found) { + console.error(chalk.red('❌ Failed to find new Supabase project.')); + process.exit(1); + } + const projectId = found.id; + const region = found.region; + + // Step 8: Construct DATABASE_URL + const databaseUrl = `postgresql://postgres.${projectId}:${dbPassword}@aws-0-${region}.pooler.supabase.com:5432/postgres`; + console.log(chalk.greenBright(`\nGenerated DB password: ${dbPassword}\n`)); + console.log(chalk.greenBright(`\nYour DATABASE_URL is:\n${databaseUrl}\n`)); + console.log(chalk.yellow('--------------------------------')); + + // Step 9: Prompt to run docker compose up + console.log(chalk.magentaBright('\nNext steps:')); + console.log(chalk.yellow('Run "docker compose -f docker-compose.dev.yml up" to start Autumn')); + + + return databaseUrl; +} + +const handleDatabaseSetup = async () => { + // Step 2: Ask user what to do for DB + console.log(chalk.magentaBright('\n================ Autumn Database Setup ================\n')); + const { dbOption } = await inquirer.prompt([ + { + type: 'list', + name: 'dbOption', + message: chalk.cyan('How do you want to set up your database?'), + choices: [ + { name: 'Set up Supabase (Cloud) for Autumn', value: 'supabase' }, + { name: 'Paste in your own DATABASE_URL', value: 'paste' }, + { name: 'Paste in your own DATABASE_URL later', value: 'later' }, + ], + default: 'supabase', + }, +]); + +let databaseUrl = ''; + +if (dbOption === 'supabase') { + databaseUrl = await generateSupabaseDatabaseUrl(); +} else if (dbOption === 'paste') { + databaseUrl = await inquirer.prompt([ + { + type: 'input', + name: 'databaseUrl', + message: 'Paste in your DATABASE_URL:', + validate: (input) => input && input.length > 5, + }, + ]); +} else if (dbOption === 'later') { + databaseUrl = ''; +} + +return databaseUrl; +} + +const handleLocalRunSetup = async () => { + // Step 10: Stripe webhook URL setup + console.log(chalk.magentaBright('\n================ Stripe Webhook Setup ================\n')); + const { webhookOption } = await inquirer.prompt([ + { + type: 'list', + name: 'webhookOption', + message: + chalk.cyan('Stripe requires a public URL to send webhook events to your app.\nThis is read from the STRIPE_WEBHOOK_URL environment variable.\n\nWould you like to:'), + choices: [ + { name: '1. Generate a localtunnel URL (recommended for local development)', value: 'localtunnel' }, + { name: '2. Skip for now and paste in your own URL later', value: 'skip' }, + ], + default: 'localtunnel', + }, + ]); + + let stripeWebhookVars = []; + + if (webhookOption === 'localtunnel') { + const subdomain = genRandomSubdomain(32); + const webhookUrl = `https://${subdomain}.loca.lt`; + stripeWebhookVars.push(`STRIPE_WEBHOOK_URL=${webhookUrl}`); + stripeWebhookVars.push(`LOCALHOST_RUN_SUBDOMAIN=${subdomain}`); + console.log(chalk.greenBright(`\nTo start your webhook tunnel, run this in another terminal:\n`)); + console.log(chalk.yellowBright(` npx localtunnel --port 8080 --subdomain ${subdomain}\n`)); + console.log(chalk.greenBright(`\nTest your webhook URL with:\n`)); + console.log(chalk.yellowBright(` curl ${webhookUrl}\n`)); + console.log(chalk.cyan('If you need to restart the tunnel in the future, use the same command.')); + } else if (webhookOption === 'paste') { + const { stripeWebhookUrl } = await inquirer.prompt([ + { + type: 'input', + name: 'stripeWebhookUrl', + message: chalk.cyan('Paste in your STRIPE_WEBHOOK_URL:'), + validate: (input) => input && input.length > 5, + }, + ]); + stripeWebhookVars.push(`STRIPE_WEBHOOK_URL=${stripeWebhookUrl}`); + } else { + // skip + } + + console.log(chalk.yellow('--------------------------------')); + + return stripeWebhookVars; +} + +async function main() { + // Step 1: Generate secrets + console.log(chalk.magentaBright('\n================ Autumn Setup ================\n')); + const secrets = { + BETTER_AUTH_SECRET: genUrlSafeBase64(64), + ENCRYPTION_IV: genUrlSafeBase64(16), + ENCRYPTION_PASSWORD: genUrlSafeBase64(64), + BETTER_AUTH_URL: 'http://localhost:8080', + CLIENT_URL: 'http://localhost:3000', + }; + + let databaseUrl = ""; + let stripeWebhookVars = []; + + databaseUrl = await handleDatabaseSetup(); + stripeWebhookVars = await handleLocalRunSetup(); + + // Step 11: Write to server/.env + console.log(chalk.magentaBright('\n================ Writing .env ================\n')); + const envSections = []; + + // Autumn Auth section + envSections.push( + '# Autumn Auth', + `BETTER_AUTH_SECRET=${secrets.BETTER_AUTH_SECRET}`, + `ENCRYPTION_IV=${secrets.ENCRYPTION_IV}`, + `ENCRYPTION_PASSWORD=${secrets.ENCRYPTION_PASSWORD}`, + `BETTER_AUTH_URL=${secrets.BETTER_AUTH_URL}`, + `CLIENT_URL=${secrets.CLIENT_URL}`, + '' + ); + + // Database section + if (databaseUrl) { + envSections.push( + '# Database', + `DATABASE_URL=${databaseUrl}`, + '' + ); + } + + // Stripe Webhooks section + if (stripeWebhookVars.length > 0) { + envSections.push('# Stripe Webhooks'); + envSections.push(...stripeWebhookVars); + envSections.push(''); + } + + const envVars = envSections.join('\n'); + + + writeFileSync('server/.env', envVars); + try { + copyFileSync('vite/.env.example', 'vite/.env'); + } catch (error) { + console.log(chalk.red('❌ Failed to copy vite/.env.example to vite/.env')); + console.log(chalk.red('❌ Please copy the file manually')); + } + + console.log(chalk.greenBright('🎉 Setup complete! 🎉')); + console.log(chalk.cyan('You can find your env variables in server/.env')); + + + // Prompt to run pnpm run db:push at the end + const { runDbPush } = await inquirer.prompt([ + { + type: 'confirm', + name: 'runDbPush', + message: chalk.cyan('Would you like to run "pnpm run db:push" to set up your tables now?'), + default: true, + }, + ]); + + if (runDbPush) { + console.log(chalk.blueBright('\nRunning "pnpm run db:push"...')); + const dbPushResult = spawnSync('pnpm', ['run', 'db:push'], { stdio: 'inherit', encoding: 'utf-8' }); + if (dbPushResult.status !== 0) { + console.error(chalk.red('❌ Failed to run "pnpm run db:push". Please check the error above.')); + process.exit(1); + } + console.log(chalk.greenBright('✅ Successfully ran "pnpm run db:push".')); + } +} + +main(); \ No newline at end of file diff --git a/shared/archives/orgModels_old.ts b/shared/archives/orgModels_old.ts index 56532a3d5..a82709468 100644 --- a/shared/archives/orgModels_old.ts +++ b/shared/archives/orgModels_old.ts @@ -3,11 +3,6 @@ import { z } from "zod"; import { OrgConfigSchema } from "../models/orgModels/orgConfig.js"; -export const MinOrgSchema = z.object({ - id: z.string(), - slug: z.string(), -}); - export const StripeConfigSchema = z.object({ test_api_key: z.string(), live_api_key: z.string(), @@ -41,7 +36,6 @@ export const OrganizationSchema = z.object({ api_version: z.number().nullish(), }); -export type MinOrg = z.infer; export type Organization = z.infer; export type StripeConfig = z.infer; export type SvixConfig = z.infer; diff --git a/shared/db/auth-relations.ts b/shared/db/auth-relations.ts new file mode 100644 index 000000000..d5048222a --- /dev/null +++ b/shared/db/auth-relations.ts @@ -0,0 +1,5 @@ +import { relations } from "drizzle-orm"; +import { user } from "./auth-schema.js"; +import { organizations } from "../models/orgModels/orgTable.js"; + +export const userRelations = relations(user, ({ many }) => ({})); diff --git a/shared/db/auth-schema.ts b/shared/db/auth-schema.ts new file mode 100644 index 000000000..bc6dbe3a8 --- /dev/null +++ b/shared/db/auth-schema.ts @@ -0,0 +1,123 @@ +import { + pgTable, + text, + timestamp, + boolean, + integer, +} from "drizzle-orm/pg-core"; +import { organizations } from "./schema.js"; + +export const user = pgTable("user", { + id: text("id").primaryKey(), + name: text("name").notNull(), + email: text("email").notNull().unique(), + emailVerified: boolean("email_verified") + .$defaultFn(() => false) + .notNull(), + image: text("image"), + createdAt: timestamp("created_at", { withTimezone: true }) + .$defaultFn(() => /* @__PURE__ */ new Date()) + .notNull(), + updatedAt: timestamp("updated_at", { withTimezone: true }) + .$defaultFn(() => /* @__PURE__ */ new Date()) + .notNull(), + role: text("role"), + banned: boolean("banned"), + banReason: text("ban_reason"), + banExpires: timestamp("ban_expires"), +}); + +export const session = pgTable("session", { + id: text("id").primaryKey(), + expiresAt: timestamp("expires_at", { withTimezone: true }).notNull(), + token: text("token").notNull().unique(), + createdAt: timestamp("created_at", { withTimezone: true }).notNull(), + updatedAt: timestamp("updated_at", { withTimezone: true }).notNull(), + ipAddress: text("ip_address"), + userAgent: text("user_agent"), + userId: text("user_id") + .notNull() + .references(() => user.id, { onDelete: "cascade" }), + impersonatedBy: text("impersonated_by"), + activeOrganizationId: text("active_organization_id"), +}).enableRLS(); + +export const account = pgTable("account", { + id: text("id").primaryKey(), + accountId: text("account_id").notNull(), + providerId: text("provider_id").notNull(), + userId: text("user_id") + .notNull() + .references(() => user.id, { onDelete: "cascade" }), + accessToken: text("access_token"), + refreshToken: text("refresh_token"), + idToken: text("id_token"), + accessTokenExpiresAt: timestamp("access_token_expires_at"), + refreshTokenExpiresAt: timestamp("refresh_token_expires_at"), + scope: text("scope"), + password: text("password"), + createdAt: timestamp("created_at", { withTimezone: true }).notNull(), + updatedAt: timestamp("updated_at", { withTimezone: true }).notNull(), +}).enableRLS(); + +export const verification = pgTable("verification", { + id: text("id").primaryKey(), + identifier: text("identifier").notNull(), + value: text("value").notNull(), + expiresAt: timestamp("expires_at", { withTimezone: true }).notNull(), + createdAt: timestamp("created_at", { withTimezone: true }).$defaultFn( + () => /* @__PURE__ */ new Date(), + ), + updatedAt: timestamp("updated_at", { withTimezone: true }).$defaultFn( + () => /* @__PURE__ */ new Date(), + ), +}).enableRLS(); + +// export const organization = pgTable("organization", { +// id: text("id").primaryKey(), +// name: text("name").notNull(), +// slug: text("slug").unique(), +// logo: text("logo"), +// createdAt: timestamp("created_at").notNull(), +// metadata: text("metadata"), +// }); + +export const member = pgTable("member", { + id: text("id").primaryKey(), + organizationId: text("organization_id") + .notNull() + .references(() => organizations.id, { onDelete: "cascade" }), + userId: text("user_id") + .notNull() + .references(() => user.id, { onDelete: "cascade" }), + role: text("role").default("member").notNull(), + createdAt: timestamp("created_at", { withTimezone: true }).notNull(), +}).enableRLS(); + +export const invitation = pgTable("invitation", { + id: text("id").primaryKey(), + organizationId: text("organization_id") + .notNull() + .references(() => organizations.id, { onDelete: "cascade" }), + email: text("email").notNull(), + role: text("role"), + status: text("status").default("pending").notNull(), + expiresAt: timestamp("expires_at").notNull(), + inviterId: text("inviter_id") + .notNull() + .references(() => user.id, { onDelete: "cascade" }), +}).enableRLS(); + +export const authSchema = { + user, + session, + account, + verification, + member, + invitation, + organizations, +}; + +export type User = typeof user.$inferSelect; +export type Member = typeof member.$inferSelect; +export type Invite = typeof invitation.$inferSelect; diff --git a/shared/db/schema.ts b/shared/db/schema.ts index 7bc4f3130..f8027fad6 100644 --- a/shared/db/schema.ts +++ b/shared/db/schema.ts @@ -68,6 +68,16 @@ import { actions } from "../models/analyticsModels/actionTable.js"; import { events } from "../models/eventModels/eventTable.js"; import { replaceables } from "../models/cusProductModels/cusEntModels/replaceableTable.js"; +import { + user, + session, + account, + verification, + member, + invitation, +} from "./auth-schema.js"; +import { userRelations } from "./auth-relations.js"; + export { // Tables organizations, @@ -96,6 +106,14 @@ export { events, replaceables, + // Auth + user, + session, + account, + verification, + member, + invitation, + // Relations organizationsRelations, entitlementsRelations, @@ -114,4 +132,7 @@ export { rewardRedemptionRelations, migrationErrorRelations, replaceableRelations, + + // Auth Relations + userRelations, }; diff --git a/shared/drizzle.config.ts b/shared/drizzle.config.ts index 6c2c3ee78..6c759e188 100644 --- a/shared/drizzle.config.ts +++ b/shared/drizzle.config.ts @@ -1,11 +1,14 @@ -import "dotenv/config"; +import { config } from "dotenv"; +config({ path: "../server/.env" }); import { defineConfig } from "drizzle-kit"; +console.log("DATABASE_URL", process.env.DATABASE_URL); + export default defineConfig({ dialect: "postgresql", out: "./drizzle", schema: "./db/schema.ts", dbCredentials: { - url: process.env.DEV_DATABASE_URL!, + url: process.env.DATABASE_URL!, }, }); diff --git a/shared/drizzle/0000_minor_gunslinger.sql b/shared/drizzle/0000_minor_gunslinger.sql deleted file mode 100644 index 3150d7d57..000000000 --- a/shared/drizzle/0000_minor_gunslinger.sql +++ /dev/null @@ -1,25 +0,0 @@ -CREATE TABLE "actions" ( - "id" text COLLATE "C" PRIMARY KEY NOT NULL, - "request_id" text NOT NULL, - "org_id" text NOT NULL, - "org_slug" text NOT NULL, - "env" text NOT NULL, - "customer_id" text, - "internal_customer_id" text, - "entity_id" text, - "internal_entity_id" text, - "type" text NOT NULL, - "auth_type" text NOT NULL, - "method" text NOT NULL, - "path" text NOT NULL, - "timestamp" timestamp with time zone DEFAULT now() NOT NULL, - "properties" jsonb, - CONSTRAINT "actions_request_id_unique" UNIQUE("request_id") -); ---> statement-breakpoint -ALTER TABLE "actions" ENABLE ROW LEVEL SECURITY;--> statement-breakpoint - ---> statement-breakpoint -ALTER TABLE "actions" ADD CONSTRAINT "actions_org_id_fkey" FOREIGN KEY ("org_id") REFERENCES "public"."organizations"("id") ON DELETE set null ON UPDATE no action;--> statement-breakpoint -ALTER TABLE "actions" ADD CONSTRAINT "actions_customer_id_fkey" FOREIGN KEY ("internal_customer_id") REFERENCES "public"."customers"("internal_id") ON DELETE set null ON UPDATE no action;--> statement-breakpoint -ALTER TABLE "actions" ADD CONSTRAINT "actions_entity_id_fkey" FOREIGN KEY ("internal_entity_id") REFERENCES "public"."entities"("internal_id") ON DELETE set null ON UPDATE no action;--> statement-breakpoint diff --git a/shared/drizzle/0001_complete_forgotten_one.sql b/shared/drizzle/0001_complete_forgotten_one.sql deleted file mode 100644 index 4f514e755..000000000 --- a/shared/drizzle/0001_complete_forgotten_one.sql +++ /dev/null @@ -1 +0,0 @@ -ALTER TABLE "actions" DROP CONSTRAINT "actions_request_id_unique"; \ No newline at end of file diff --git a/shared/drizzle/0002_foamy_tombstone.sql b/shared/drizzle/0002_foamy_tombstone.sql deleted file mode 100644 index c6e19effb..000000000 --- a/shared/drizzle/0002_foamy_tombstone.sql +++ /dev/null @@ -1,20 +0,0 @@ --- CREATE TABLE "events" ( --- "id" text PRIMARY KEY NOT NULL, --- "org_id" text NOT NULL, --- "internal_customer_id" text, --- "env" text NOT NULL, --- "created_at" bigint, --- "timestamp" numeric, --- "event_name" text NOT NULL, --- "idempotency_key" text DEFAULT null, --- "value" numeric, --- "set_usage" boolean DEFAULT false, --- "entity_id" text, --- "customer_id" text NOT NULL, --- "properties" jsonb, --- CONSTRAINT "unique_event_constraint" UNIQUE("org_id","env","customer_id","event_name","idempotency_key") --- ); --- --> statement-breakpoint --- ALTER TABLE "events" ADD CONSTRAINT "events_internal_customer_id_fkey" FOREIGN KEY ("internal_customer_id") REFERENCES "public"."customers"("internal_id") ON DELETE cascade ON UPDATE no action; - -ALTER TABLE "events" ADD COLUMN "created_at" bigint; diff --git a/shared/drizzle/0003_yummy_la_nuit.sql b/shared/drizzle/0003_yummy_la_nuit.sql deleted file mode 100644 index 22ed59c39..000000000 --- a/shared/drizzle/0003_yummy_la_nuit.sql +++ /dev/null @@ -1,4 +0,0 @@ -ALTER TABLE "events" ALTER COLUMN "timestamp" SET DATA TYPE timestamp with time zone;--> statement-breakpoint -ALTER TABLE "customer_products" ADD COLUMN "api_version" numeric;--> statement-breakpoint -ALTER TABLE "events" ADD COLUMN "org_slug" text NOT NULL;--> statement-breakpoint -ALTER TABLE "prices" ADD COLUMN "proration_config" jsonb DEFAULT null; \ No newline at end of file diff --git a/shared/drizzle/0004_broad_shocker.sql b/shared/drizzle/0004_broad_shocker.sql deleted file mode 100644 index e6c1ba06d..000000000 --- a/shared/drizzle/0004_broad_shocker.sql +++ /dev/null @@ -1,9 +0,0 @@ -CREATE TABLE "replaceables" ( - "id" text COLLATE "C" PRIMARY KEY NOT NULL, - "cus_ent_id" text NOT NULL, - "created_at" bigint NOT NULL, - "from_entity_id" text, - "delete_next_cycle" boolean DEFAULT false NOT NULL -); ---> statement-breakpoint -ALTER TABLE "replaceables" ADD CONSTRAINT "replaceables_cus_ent_id_fkey" FOREIGN KEY ("cus_ent_id") REFERENCES "public"."customer_entitlements"("id") ON DELETE cascade ON UPDATE no action; \ No newline at end of file diff --git a/shared/drizzle/meta/0000_snapshot.json b/shared/drizzle/meta/0000_snapshot.json deleted file mode 100644 index 33c9ddc72..000000000 --- a/shared/drizzle/meta/0000_snapshot.json +++ /dev/null @@ -1,2395 +0,0 @@ -{ - "id": "b89d5375-4ef4-4cf1-b58b-540024d404a2", - "prevId": "00000000-0000-0000-0000-000000000000", - "version": "7", - "dialect": "postgresql", - "tables": { - "public.actions": { - "name": "actions", - "schema": "", - "columns": { - "id": { - "name": "id", - "type": "text COLLATE \"C\"", - "primaryKey": true, - "notNull": true - }, - "request_id": { - "name": "request_id", - "type": "text", - "primaryKey": false, - "notNull": true - }, - "org_id": { - "name": "org_id", - "type": "text", - "primaryKey": false, - "notNull": true - }, - "org_slug": { - "name": "org_slug", - "type": "text", - "primaryKey": false, - "notNull": true - }, - "env": { - "name": "env", - "type": "text", - "primaryKey": false, - "notNull": true - }, - "customer_id": { - "name": "customer_id", - "type": "text", - "primaryKey": false, - "notNull": false - }, - "internal_customer_id": { - "name": "internal_customer_id", - "type": "text", - "primaryKey": false, - "notNull": false - }, - "entity_id": { - "name": "entity_id", - "type": "text", - "primaryKey": false, - "notNull": false - }, - "internal_entity_id": { - "name": "internal_entity_id", - "type": "text", - "primaryKey": false, - "notNull": false - }, - "type": { - "name": "type", - "type": "text", - "primaryKey": false, - "notNull": true - }, - "auth_type": { - "name": "auth_type", - "type": "text", - "primaryKey": false, - "notNull": true - }, - "method": { - "name": "method", - "type": "text", - "primaryKey": false, - "notNull": true - }, - "path": { - "name": "path", - "type": "text", - "primaryKey": false, - "notNull": true - }, - "timestamp": { - "name": "timestamp", - "type": "timestamp with time zone", - "primaryKey": false, - "notNull": true, - "default": "now()" - }, - "properties": { - "name": "properties", - "type": "jsonb", - "primaryKey": false, - "notNull": false - } - }, - "indexes": {}, - "foreignKeys": { - "actions_org_id_fkey": { - "name": "actions_org_id_fkey", - "tableFrom": "actions", - "tableTo": "organizations", - "columnsFrom": [ - "org_id" - ], - "columnsTo": [ - "id" - ], - "onDelete": "set null", - "onUpdate": "no action" - }, - "actions_customer_id_fkey": { - "name": "actions_customer_id_fkey", - "tableFrom": "actions", - "tableTo": "customers", - "columnsFrom": [ - "internal_customer_id" - ], - "columnsTo": [ - "internal_id" - ], - "onDelete": "set null", - "onUpdate": "no action" - }, - "actions_entity_id_fkey": { - "name": "actions_entity_id_fkey", - "tableFrom": "actions", - "tableTo": "entities", - "columnsFrom": [ - "internal_entity_id" - ], - "columnsTo": [ - "internal_id" - ], - "onDelete": "set null", - "onUpdate": "no action" - } - }, - "compositePrimaryKeys": {}, - "uniqueConstraints": { - "actions_request_id_unique": { - "name": "actions_request_id_unique", - "nullsNotDistinct": false, - "columns": [ - "request_id" - ] - } - }, - "policies": {}, - "checkConstraints": {}, - "isRLSEnabled": true - }, - "public.api_keys": { - "name": "api_keys", - "schema": "", - "columns": { - "id": { - "name": "id", - "type": "text COLLATE \"C\"", - "primaryKey": true, - "notNull": true - }, - "created_at": { - "name": "created_at", - "type": "numeric", - "primaryKey": false, - "notNull": true, - "default": "ROUND(date_part('epoch', NOW()) * 1000)::BIGINT" - }, - "name": { - "name": "name", - "type": "text", - "primaryKey": false, - "notNull": false - }, - "prefix": { - "name": "prefix", - "type": "text", - "primaryKey": false, - "notNull": false - }, - "org_id": { - "name": "org_id", - "type": "text", - "primaryKey": false, - "notNull": false - }, - "user_id": { - "name": "user_id", - "type": "text", - "primaryKey": false, - "notNull": false - }, - "env": { - "name": "env", - "type": "text", - "primaryKey": false, - "notNull": false - }, - "hashed_key": { - "name": "hashed_key", - "type": "text", - "primaryKey": false, - "notNull": false - }, - "meta": { - "name": "meta", - "type": "jsonb", - "primaryKey": false, - "notNull": false - } - }, - "indexes": {}, - "foreignKeys": { - "api_keys_org_id_fkey": { - "name": "api_keys_org_id_fkey", - "tableFrom": "api_keys", - "tableTo": "organizations", - "columnsFrom": [ - "org_id" - ], - "columnsTo": [ - "id" - ], - "onDelete": "cascade", - "onUpdate": "no action" - } - }, - "compositePrimaryKeys": {}, - "uniqueConstraints": { - "api_keys_hashed_key_key": { - "name": "api_keys_hashed_key_key", - "nullsNotDistinct": false, - "columns": [ - "hashed_key" - ] - } - }, - "policies": {}, - "checkConstraints": {}, - "isRLSEnabled": false - }, - "public.chat_results": { - "name": "chat_results", - "schema": "", - "columns": { - "id": { - "name": "id", - "type": "text COLLATE \"C\"", - "primaryKey": true, - "notNull": true - }, - "created_at": { - "name": "created_at", - "type": "numeric", - "primaryKey": false, - "notNull": false - }, - "data": { - "name": "data", - "type": "jsonb", - "primaryKey": false, - "notNull": true - } - }, - "indexes": {}, - "foreignKeys": {}, - "compositePrimaryKeys": {}, - "uniqueConstraints": {}, - "policies": {}, - "checkConstraints": {}, - "isRLSEnabled": true - }, - "public.customer_entitlements": { - "name": "customer_entitlements", - "schema": "", - "columns": { - "id": { - "name": "id", - "type": "text COLLATE \"C\"", - "primaryKey": true, - "notNull": true - }, - "customer_product_id": { - "name": "customer_product_id", - "type": "text", - "primaryKey": false, - "notNull": true - }, - "entitlement_id": { - "name": "entitlement_id", - "type": "text", - "primaryKey": false, - "notNull": true - }, - "internal_customer_id": { - "name": "internal_customer_id", - "type": "text", - "primaryKey": false, - "notNull": true - }, - "internal_feature_id": { - "name": "internal_feature_id", - "type": "text", - "primaryKey": false, - "notNull": true - }, - "unlimited": { - "name": "unlimited", - "type": "boolean", - "primaryKey": false, - "notNull": false, - "default": false - }, - "balance": { - "name": "balance", - "type": "numeric", - "primaryKey": false, - "notNull": true, - "default": 0 - }, - "created_at": { - "name": "created_at", - "type": "numeric", - "primaryKey": false, - "notNull": true - }, - "next_reset_at": { - "name": "next_reset_at", - "type": "numeric", - "primaryKey": false, - "notNull": false - }, - "usage_allowed": { - "name": "usage_allowed", - "type": "boolean", - "primaryKey": false, - "notNull": false, - "default": false - }, - "adjustment": { - "name": "adjustment", - "type": "numeric", - "primaryKey": false, - "notNull": false - }, - "entities": { - "name": "entities", - "type": "jsonb", - "primaryKey": false, - "notNull": false - }, - "customer_id": { - "name": "customer_id", - "type": "text", - "primaryKey": false, - "notNull": false - }, - "feature_id": { - "name": "feature_id", - "type": "text", - "primaryKey": false, - "notNull": false - } - }, - "indexes": {}, - "foreignKeys": { - "entitlements_internal_feature_id_fkey": { - "name": "entitlements_internal_feature_id_fkey", - "tableFrom": "customer_entitlements", - "tableTo": "features", - "columnsFrom": [ - "internal_feature_id" - ], - "columnsTo": [ - "internal_id" - ], - "onDelete": "cascade", - "onUpdate": "no action" - }, - "customer_entitlements_customer_product_id_fkey": { - "name": "customer_entitlements_customer_product_id_fkey", - "tableFrom": "customer_entitlements", - "tableTo": "customer_products", - "columnsFrom": [ - "customer_product_id" - ], - "columnsTo": [ - "id" - ], - "onDelete": "cascade", - "onUpdate": "cascade" - } - }, - "compositePrimaryKeys": {}, - "uniqueConstraints": { - "entitlements_id_key": { - "name": "entitlements_id_key", - "nullsNotDistinct": false, - "columns": [ - "id" - ] - } - }, - "policies": {}, - "checkConstraints": {}, - "isRLSEnabled": false - }, - "public.customer_prices": { - "name": "customer_prices", - "schema": "", - "columns": { - "id": { - "name": "id", - "type": "text", - "primaryKey": true, - "notNull": true - }, - "created_at": { - "name": "created_at", - "type": "numeric", - "primaryKey": false, - "notNull": true - }, - "price_id": { - "name": "price_id", - "type": "text", - "primaryKey": false, - "notNull": false - }, - "options": { - "name": "options", - "type": "jsonb", - "primaryKey": false, - "notNull": false - }, - "internal_customer_id": { - "name": "internal_customer_id", - "type": "text", - "primaryKey": false, - "notNull": false - }, - "customer_product_id": { - "name": "customer_product_id", - "type": "text", - "primaryKey": false, - "notNull": false - } - }, - "indexes": {}, - "foreignKeys": { - "customer_prices_customer_product_id_fkey": { - "name": "customer_prices_customer_product_id_fkey", - "tableFrom": "customer_prices", - "tableTo": "customer_products", - "columnsFrom": [ - "customer_product_id" - ], - "columnsTo": [ - "id" - ], - "onDelete": "cascade", - "onUpdate": "no action" - }, - "customer_prices_internal_customer_id_fkey": { - "name": "customer_prices_internal_customer_id_fkey", - "tableFrom": "customer_prices", - "tableTo": "customers", - "columnsFrom": [ - "internal_customer_id" - ], - "columnsTo": [ - "internal_id" - ], - "onDelete": "cascade", - "onUpdate": "no action" - }, - "customer_prices_price_id_fkey": { - "name": "customer_prices_price_id_fkey", - "tableFrom": "customer_prices", - "tableTo": "prices", - "columnsFrom": [ - "price_id" - ], - "columnsTo": [ - "id" - ], - "onDelete": "no action", - "onUpdate": "no action" - } - }, - "compositePrimaryKeys": {}, - "uniqueConstraints": {}, - "policies": {}, - "checkConstraints": {}, - "isRLSEnabled": false - }, - "public.customer_products": { - "name": "customer_products", - "schema": "", - "columns": { - "id": { - "name": "id", - "type": "text COLLATE \"C\"", - "primaryKey": true, - "notNull": true - }, - "internal_customer_id": { - "name": "internal_customer_id", - "type": "text", - "primaryKey": false, - "notNull": true - }, - "internal_product_id": { - "name": "internal_product_id", - "type": "text", - "primaryKey": false, - "notNull": true - }, - "internal_entity_id": { - "name": "internal_entity_id", - "type": "text", - "primaryKey": false, - "notNull": false - }, - "created_at": { - "name": "created_at", - "type": "numeric", - "primaryKey": false, - "notNull": false - }, - "status": { - "name": "status", - "type": "text", - "primaryKey": false, - "notNull": false - }, - "processor": { - "name": "processor", - "type": "jsonb", - "primaryKey": false, - "notNull": false - }, - "canceled_at": { - "name": "canceled_at", - "type": "numeric", - "primaryKey": false, - "notNull": false - }, - "ended_at": { - "name": "ended_at", - "type": "numeric", - "primaryKey": false, - "notNull": false - }, - "starts_at": { - "name": "starts_at", - "type": "numeric", - "primaryKey": false, - "notNull": false - }, - "options": { - "name": "options", - "type": "jsonb[]", - "primaryKey": false, - "notNull": false - }, - "product_id": { - "name": "product_id", - "type": "text", - "primaryKey": false, - "notNull": false - }, - "free_trial_id": { - "name": "free_trial_id", - "type": "text", - "primaryKey": false, - "notNull": false - }, - "trial_ends_at": { - "name": "trial_ends_at", - "type": "numeric", - "primaryKey": false, - "notNull": false - }, - "collection_method": { - "name": "collection_method", - "type": "text", - "primaryKey": false, - "notNull": false, - "default": "'charge_automatically'" - }, - "subscription_ids": { - "name": "subscription_ids", - "type": "text[]", - "primaryKey": false, - "notNull": false - }, - "scheduled_ids": { - "name": "scheduled_ids", - "type": "text[]", - "primaryKey": false, - "notNull": false - }, - "quantity": { - "name": "quantity", - "type": "numeric", - "primaryKey": false, - "notNull": false, - "default": 1 - }, - "is_custom": { - "name": "is_custom", - "type": "boolean", - "primaryKey": false, - "notNull": true, - "default": false - }, - "customer_id": { - "name": "customer_id", - "type": "text", - "primaryKey": false, - "notNull": false - }, - "entity_id": { - "name": "entity_id", - "type": "text", - "primaryKey": false, - "notNull": false - } - }, - "indexes": {}, - "foreignKeys": { - "customer_products_free_trial_id_fkey": { - "name": "customer_products_free_trial_id_fkey", - "tableFrom": "customer_products", - "tableTo": "free_trials", - "columnsFrom": [ - "free_trial_id" - ], - "columnsTo": [ - "id" - ], - "onDelete": "no action", - "onUpdate": "no action" - }, - "customer_products_internal_customer_id_fkey": { - "name": "customer_products_internal_customer_id_fkey", - "tableFrom": "customer_products", - "tableTo": "customers", - "columnsFrom": [ - "internal_customer_id" - ], - "columnsTo": [ - "internal_id" - ], - "onDelete": "cascade", - "onUpdate": "cascade" - }, - "customer_products_internal_product_id_fkey": { - "name": "customer_products_internal_product_id_fkey", - "tableFrom": "customer_products", - "tableTo": "products", - "columnsFrom": [ - "internal_product_id" - ], - "columnsTo": [ - "internal_id" - ], - "onDelete": "no action", - "onUpdate": "no action" - }, - "customer_products_internal_entity_id_fkey": { - "name": "customer_products_internal_entity_id_fkey", - "tableFrom": "customer_products", - "tableTo": "entities", - "columnsFrom": [ - "internal_entity_id" - ], - "columnsTo": [ - "internal_id" - ], - "onDelete": "set null", - "onUpdate": "no action" - } - }, - "compositePrimaryKeys": {}, - "uniqueConstraints": {}, - "policies": {}, - "checkConstraints": {}, - "isRLSEnabled": false - }, - "public.customers": { - "name": "customers", - "schema": "", - "columns": { - "internal_id": { - "name": "internal_id", - "type": "text COLLATE \"C\"", - "primaryKey": true, - "notNull": true - }, - "org_id": { - "name": "org_id", - "type": "text", - "primaryKey": false, - "notNull": true - }, - "created_at": { - "name": "created_at", - "type": "numeric", - "primaryKey": false, - "notNull": true - }, - "name": { - "name": "name", - "type": "text", - "primaryKey": false, - "notNull": false - }, - "id": { - "name": "id", - "type": "text", - "primaryKey": false, - "notNull": false - }, - "email": { - "name": "email", - "type": "text", - "primaryKey": false, - "notNull": false - }, - "fingerprint": { - "name": "fingerprint", - "type": "text", - "primaryKey": false, - "notNull": false, - "default": "null" - }, - "metadata": { - "name": "metadata", - "type": "jsonb", - "primaryKey": false, - "notNull": false - }, - "env": { - "name": "env", - "type": "text", - "primaryKey": false, - "notNull": true - }, - "processor": { - "name": "processor", - "type": "jsonb", - "primaryKey": false, - "notNull": false - } - }, - "indexes": {}, - "foreignKeys": { - "customers_org_id_fkey": { - "name": "customers_org_id_fkey", - "tableFrom": "customers", - "tableTo": "organizations", - "columnsFrom": [ - "org_id" - ], - "columnsTo": [ - "id" - ], - "onDelete": "cascade", - "onUpdate": "no action" - } - }, - "compositePrimaryKeys": {}, - "uniqueConstraints": { - "cus_id_constraint": { - "name": "cus_id_constraint", - "nullsNotDistinct": false, - "columns": [ - "org_id", - "id", - "env" - ] - } - }, - "policies": {}, - "checkConstraints": {}, - "isRLSEnabled": true - }, - "public.entities": { - "name": "entities", - "schema": "", - "columns": { - "id": { - "name": "id", - "type": "text", - "primaryKey": false, - "notNull": false - }, - "org_id": { - "name": "org_id", - "type": "text", - "primaryKey": false, - "notNull": false - }, - "created_at": { - "name": "created_at", - "type": "numeric", - "primaryKey": false, - "notNull": true - }, - "internal_id": { - "name": "internal_id", - "type": "text", - "primaryKey": true, - "notNull": true - }, - "internal_customer_id": { - "name": "internal_customer_id", - "type": "text", - "primaryKey": false, - "notNull": true - }, - "env": { - "name": "env", - "type": "text", - "primaryKey": false, - "notNull": false - }, - "name": { - "name": "name", - "type": "text", - "primaryKey": false, - "notNull": false - }, - "deleted": { - "name": "deleted", - "type": "boolean", - "primaryKey": false, - "notNull": true, - "default": false - }, - "internal_feature_id": { - "name": "internal_feature_id", - "type": "text", - "primaryKey": false, - "notNull": false - }, - "feature_id": { - "name": "feature_id", - "type": "text", - "primaryKey": false, - "notNull": false - } - }, - "indexes": {}, - "foreignKeys": { - "entities_internal_customer_id_fkey": { - "name": "entities_internal_customer_id_fkey", - "tableFrom": "entities", - "tableTo": "customers", - "columnsFrom": [ - "internal_customer_id" - ], - "columnsTo": [ - "internal_id" - ], - "onDelete": "cascade", - "onUpdate": "no action" - }, - "entities_internal_feature_id_fkey": { - "name": "entities_internal_feature_id_fkey", - "tableFrom": "entities", - "tableTo": "features", - "columnsFrom": [ - "internal_feature_id" - ], - "columnsTo": [ - "internal_id" - ], - "onDelete": "cascade", - "onUpdate": "no action" - }, - "entities_org_id_fkey": { - "name": "entities_org_id_fkey", - "tableFrom": "entities", - "tableTo": "organizations", - "columnsFrom": [ - "org_id" - ], - "columnsTo": [ - "id" - ], - "onDelete": "cascade", - "onUpdate": "no action" - } - }, - "compositePrimaryKeys": {}, - "uniqueConstraints": { - "entity_id_constraint": { - "name": "entity_id_constraint", - "nullsNotDistinct": false, - "columns": [ - "org_id", - "env", - "internal_customer_id", - "id" - ] - } - }, - "policies": {}, - "checkConstraints": {}, - "isRLSEnabled": false - }, - "public.entitlements": { - "name": "entitlements", - "schema": "", - "columns": { - "id": { - "name": "id", - "type": "text COLLATE \"C\"", - "primaryKey": true, - "notNull": true - }, - "created_at": { - "name": "created_at", - "type": "numeric", - "primaryKey": false, - "notNull": true - }, - "internal_feature_id": { - "name": "internal_feature_id", - "type": "text", - "primaryKey": false, - "notNull": true - }, - "internal_product_id": { - "name": "internal_product_id", - "type": "text", - "primaryKey": false, - "notNull": true - }, - "is_custom": { - "name": "is_custom", - "type": "boolean", - "primaryKey": false, - "notNull": false, - "default": false - }, - "allowance_type": { - "name": "allowance_type", - "type": "text", - "primaryKey": false, - "notNull": false - }, - "allowance": { - "name": "allowance", - "type": "numeric", - "primaryKey": false, - "notNull": false - }, - "interval": { - "name": "interval", - "type": "text", - "primaryKey": false, - "notNull": false - }, - "carry_from_previous": { - "name": "carry_from_previous", - "type": "boolean", - "primaryKey": false, - "notNull": false, - "default": false - }, - "entity_feature_id": { - "name": "entity_feature_id", - "type": "text", - "primaryKey": false, - "notNull": false, - "default": "null" - }, - "org_id": { - "name": "org_id", - "type": "text", - "primaryKey": false, - "notNull": false - }, - "feature_id": { - "name": "feature_id", - "type": "text", - "primaryKey": false, - "notNull": false - } - }, - "indexes": {}, - "foreignKeys": { - "entitlements_internal_feature_id_fkey": { - "name": "entitlements_internal_feature_id_fkey", - "tableFrom": "entitlements", - "tableTo": "features", - "columnsFrom": [ - "internal_feature_id" - ], - "columnsTo": [ - "internal_id" - ], - "onDelete": "cascade", - "onUpdate": "no action" - }, - "entitlements_internal_product_id_fkey": { - "name": "entitlements_internal_product_id_fkey", - "tableFrom": "entitlements", - "tableTo": "products", - "columnsFrom": [ - "internal_product_id" - ], - "columnsTo": [ - "internal_id" - ], - "onDelete": "cascade", - "onUpdate": "cascade" - } - }, - "compositePrimaryKeys": {}, - "uniqueConstraints": { - "entitlements_id_key": { - "name": "entitlements_id_key", - "nullsNotDistinct": false, - "columns": [ - "id" - ] - } - }, - "policies": {}, - "checkConstraints": {}, - "isRLSEnabled": false - }, - "public.features": { - "name": "features", - "schema": "", - "columns": { - "internal_id": { - "name": "internal_id", - "type": "text COLLATE \"C\"", - "primaryKey": true, - "notNull": true - }, - "org_id": { - "name": "org_id", - "type": "text", - "primaryKey": false, - "notNull": true - }, - "created_at": { - "name": "created_at", - "type": "numeric", - "primaryKey": false, - "notNull": false - }, - "env": { - "name": "env", - "type": "text", - "primaryKey": false, - "notNull": false - }, - "id": { - "name": "id", - "type": "text", - "primaryKey": false, - "notNull": true - }, - "name": { - "name": "name", - "type": "text", - "primaryKey": false, - "notNull": false - }, - "type": { - "name": "type", - "type": "text", - "primaryKey": false, - "notNull": true - }, - "config": { - "name": "config", - "type": "jsonb", - "primaryKey": false, - "notNull": false - }, - "display": { - "name": "display", - "type": "jsonb", - "primaryKey": false, - "notNull": false, - "default": "null" - } - }, - "indexes": {}, - "foreignKeys": { - "features_org_id_fkey": { - "name": "features_org_id_fkey", - "tableFrom": "features", - "tableTo": "organizations", - "columnsFrom": [ - "org_id" - ], - "columnsTo": [ - "id" - ], - "onDelete": "cascade", - "onUpdate": "no action" - } - }, - "compositePrimaryKeys": {}, - "uniqueConstraints": { - "feature_id_constraint": { - "name": "feature_id_constraint", - "nullsNotDistinct": false, - "columns": [ - "org_id", - "id", - "env" - ] - } - }, - "policies": {}, - "checkConstraints": {}, - "isRLSEnabled": false - }, - "public.free_trials": { - "name": "free_trials", - "schema": "", - "columns": { - "id": { - "name": "id", - "type": "text", - "primaryKey": true, - "notNull": true - }, - "created_at": { - "name": "created_at", - "type": "numeric", - "primaryKey": false, - "notNull": true - }, - "internal_product_id": { - "name": "internal_product_id", - "type": "text", - "primaryKey": false, - "notNull": false - }, - "duration": { - "name": "duration", - "type": "text", - "primaryKey": false, - "notNull": false, - "default": "'day'" - }, - "length": { - "name": "length", - "type": "numeric", - "primaryKey": false, - "notNull": false - }, - "unique_fingerprint": { - "name": "unique_fingerprint", - "type": "boolean", - "primaryKey": false, - "notNull": false - }, - "is_custom": { - "name": "is_custom", - "type": "boolean", - "primaryKey": false, - "notNull": false, - "default": false - } - }, - "indexes": {}, - "foreignKeys": { - "free_trials_internal_product_id_fkey": { - "name": "free_trials_internal_product_id_fkey", - "tableFrom": "free_trials", - "tableTo": "products", - "columnsFrom": [ - "internal_product_id" - ], - "columnsTo": [ - "internal_id" - ], - "onDelete": "cascade", - "onUpdate": "no action" - } - }, - "compositePrimaryKeys": {}, - "uniqueConstraints": {}, - "policies": {}, - "checkConstraints": {}, - "isRLSEnabled": false - }, - "public.invoices": { - "name": "invoices", - "schema": "", - "columns": { - "id": { - "name": "id", - "type": "text COLLATE \"C\"", - "primaryKey": true, - "notNull": true - }, - "created_at": { - "name": "created_at", - "type": "numeric", - "primaryKey": false, - "notNull": true, - "default": "ROUND(date_part('epoch', NOW()) * 1000)::BIGINT" - }, - "product_ids": { - "name": "product_ids", - "type": "text[]", - "primaryKey": false, - "notNull": false, - "default": "'{}'" - }, - "internal_product_ids": { - "name": "internal_product_ids", - "type": "text[]", - "primaryKey": false, - "notNull": false, - "default": "'{}'" - }, - "internal_customer_id": { - "name": "internal_customer_id", - "type": "text", - "primaryKey": false, - "notNull": true - }, - "internal_entity_id": { - "name": "internal_entity_id", - "type": "text", - "primaryKey": false, - "notNull": false - }, - "stripe_id": { - "name": "stripe_id", - "type": "text", - "primaryKey": false, - "notNull": true - }, - "status": { - "name": "status", - "type": "text", - "primaryKey": false, - "notNull": true, - "default": "'draft'" - }, - "hosted_invoice_url": { - "name": "hosted_invoice_url", - "type": "text", - "primaryKey": false, - "notNull": false - }, - "total": { - "name": "total", - "type": "numeric", - "primaryKey": false, - "notNull": true, - "default": 0 - }, - "currency": { - "name": "currency", - "type": "text", - "primaryKey": false, - "notNull": true, - "default": "'usd'" - }, - "discounts": { - "name": "discounts", - "type": "jsonb[]", - "primaryKey": false, - "notNull": false, - "default": "'{}'" - }, - "items": { - "name": "items", - "type": "jsonb[]", - "primaryKey": false, - "notNull": false, - "default": "'{}'" - } - }, - "indexes": {}, - "foreignKeys": { - "invoices_internal_customer_id_fkey": { - "name": "invoices_internal_customer_id_fkey", - "tableFrom": "invoices", - "tableTo": "customers", - "columnsFrom": [ - "internal_customer_id" - ], - "columnsTo": [ - "id" - ], - "onDelete": "no action", - "onUpdate": "no action" - }, - "invoices_internal_entity_id_fkey": { - "name": "invoices_internal_entity_id_fkey", - "tableFrom": "invoices", - "tableTo": "entities", - "columnsFrom": [ - "internal_entity_id" - ], - "columnsTo": [ - "id" - ], - "onDelete": "no action", - "onUpdate": "no action" - } - }, - "compositePrimaryKeys": {}, - "uniqueConstraints": {}, - "policies": {}, - "checkConstraints": {}, - "isRLSEnabled": false - }, - "public.metadata": { - "name": "metadata", - "schema": "", - "columns": { - "id": { - "name": "id", - "type": "text", - "primaryKey": true, - "notNull": true - }, - "created_at": { - "name": "created_at", - "type": "numeric", - "primaryKey": false, - "notNull": true, - "default": "ROUND(date_part('epoch', NOW()) * 1000)::BIGINT" - }, - "expires_at": { - "name": "expires_at", - "type": "numeric", - "primaryKey": false, - "notNull": false - }, - "data": { - "name": "data", - "type": "jsonb", - "primaryKey": false, - "notNull": false - } - }, - "indexes": {}, - "foreignKeys": {}, - "compositePrimaryKeys": {}, - "uniqueConstraints": {}, - "policies": {}, - "checkConstraints": {}, - "isRLSEnabled": false - }, - "public.migration_errors": { - "name": "migration_errors", - "schema": "", - "columns": { - "internal_customer_id": { - "name": "internal_customer_id", - "type": "text", - "primaryKey": false, - "notNull": true - }, - "migration_job_id": { - "name": "migration_job_id", - "type": "text", - "primaryKey": false, - "notNull": true - }, - "created_at": { - "name": "created_at", - "type": "numeric", - "primaryKey": false, - "notNull": false - }, - "updated_at": { - "name": "updated_at", - "type": "numeric", - "primaryKey": false, - "notNull": false - }, - "data": { - "name": "data", - "type": "jsonb", - "primaryKey": false, - "notNull": false - }, - "message": { - "name": "message", - "type": "text", - "primaryKey": false, - "notNull": false - }, - "code": { - "name": "code", - "type": "text", - "primaryKey": false, - "notNull": false - } - }, - "indexes": {}, - "foreignKeys": { - "migration_customers_internal_customer_id_fkey": { - "name": "migration_customers_internal_customer_id_fkey", - "tableFrom": "migration_errors", - "tableTo": "customers", - "columnsFrom": [ - "internal_customer_id" - ], - "columnsTo": [ - "internal_id" - ], - "onDelete": "cascade", - "onUpdate": "no action" - }, - "migration_customers_migration_job_id_fkey": { - "name": "migration_customers_migration_job_id_fkey", - "tableFrom": "migration_errors", - "tableTo": "migration_jobs", - "columnsFrom": [ - "migration_job_id" - ], - "columnsTo": [ - "id" - ], - "onDelete": "cascade", - "onUpdate": "no action" - } - }, - "compositePrimaryKeys": { - "migration_errors_pkey": { - "name": "migration_errors_pkey", - "columns": [ - "internal_customer_id", - "migration_job_id" - ] - } - }, - "uniqueConstraints": {}, - "policies": {}, - "checkConstraints": {}, - "isRLSEnabled": false - }, - "public.migration_jobs": { - "name": "migration_jobs", - "schema": "", - "columns": { - "id": { - "name": "id", - "type": "text", - "primaryKey": true, - "notNull": true - }, - "org_id": { - "name": "org_id", - "type": "text", - "primaryKey": false, - "notNull": true - }, - "env": { - "name": "env", - "type": "text", - "primaryKey": false, - "notNull": true - }, - "created_at": { - "name": "created_at", - "type": "numeric", - "primaryKey": false, - "notNull": true - }, - "updated_at": { - "name": "updated_at", - "type": "numeric", - "primaryKey": false, - "notNull": false - }, - "current_step": { - "name": "current_step", - "type": "text", - "primaryKey": false, - "notNull": false - }, - "from_internal_product_id": { - "name": "from_internal_product_id", - "type": "text", - "primaryKey": false, - "notNull": false - }, - "to_internal_product_id": { - "name": "to_internal_product_id", - "type": "text", - "primaryKey": false, - "notNull": false - }, - "step_details": { - "name": "step_details", - "type": "jsonb", - "primaryKey": false, - "notNull": false - } - }, - "indexes": {}, - "foreignKeys": { - "migration_jobs_from_internal_product_id_fkey": { - "name": "migration_jobs_from_internal_product_id_fkey", - "tableFrom": "migration_jobs", - "tableTo": "products", - "columnsFrom": [ - "from_internal_product_id" - ], - "columnsTo": [ - "internal_id" - ], - "onDelete": "cascade", - "onUpdate": "no action" - }, - "migration_jobs_org_id_fkey": { - "name": "migration_jobs_org_id_fkey", - "tableFrom": "migration_jobs", - "tableTo": "organizations", - "columnsFrom": [ - "org_id" - ], - "columnsTo": [ - "id" - ], - "onDelete": "cascade", - "onUpdate": "no action" - }, - "migration_jobs_to_internal_product_id_fkey": { - "name": "migration_jobs_to_internal_product_id_fkey", - "tableFrom": "migration_jobs", - "tableTo": "products", - "columnsFrom": [ - "to_internal_product_id" - ], - "columnsTo": [ - "internal_id" - ], - "onDelete": "cascade", - "onUpdate": "no action" - } - }, - "compositePrimaryKeys": {}, - "uniqueConstraints": {}, - "policies": {}, - "checkConstraints": {}, - "isRLSEnabled": false - }, - "public.organizations": { - "name": "organizations", - "schema": "", - "columns": { - "id": { - "name": "id", - "type": "text", - "primaryKey": true, - "notNull": true - }, - "slug": { - "name": "slug", - "type": "text", - "primaryKey": false, - "notNull": true - }, - "default_currency": { - "name": "default_currency", - "type": "text", - "primaryKey": false, - "notNull": true, - "default": "'usd'" - }, - "stripe_connected": { - "name": "stripe_connected", - "type": "boolean", - "primaryKey": false, - "notNull": false, - "default": false - }, - "stripe_config": { - "name": "stripe_config", - "type": "jsonb", - "primaryKey": false, - "notNull": false - }, - "test_pkey": { - "name": "test_pkey", - "type": "text", - "primaryKey": false, - "notNull": false - }, - "live_pkey": { - "name": "live_pkey", - "type": "text", - "primaryKey": false, - "notNull": false - }, - "svix_config": { - "name": "svix_config", - "type": "jsonb", - "primaryKey": false, - "notNull": true - }, - "created_at": { - "name": "created_at", - "type": "numeric", - "primaryKey": false, - "notNull": false - }, - "config": { - "name": "config", - "type": "jsonb", - "primaryKey": false, - "notNull": true, - "default": "'{}'::jsonb" - } - }, - "indexes": {}, - "foreignKeys": {}, - "compositePrimaryKeys": {}, - "uniqueConstraints": { - "organizations_test_pkey_key": { - "name": "organizations_test_pkey_key", - "nullsNotDistinct": false, - "columns": [ - "test_pkey" - ] - }, - "organizations_live_pkey_key": { - "name": "organizations_live_pkey_key", - "nullsNotDistinct": false, - "columns": [ - "live_pkey" - ] - } - }, - "policies": {}, - "checkConstraints": {}, - "isRLSEnabled": false - }, - "public.prices": { - "name": "prices", - "schema": "", - "columns": { - "id": { - "name": "id", - "type": "text COLLATE \"C\"", - "primaryKey": true, - "notNull": true - }, - "org_id": { - "name": "org_id", - "type": "text", - "primaryKey": false, - "notNull": true - }, - "internal_product_id": { - "name": "internal_product_id", - "type": "text", - "primaryKey": false, - "notNull": true - }, - "config": { - "name": "config", - "type": "jsonb", - "primaryKey": false, - "notNull": false - }, - "created_at": { - "name": "created_at", - "type": "numeric", - "primaryKey": false, - "notNull": true - }, - "billing_type": { - "name": "billing_type", - "type": "text", - "primaryKey": false, - "notNull": false - }, - "is_custom": { - "name": "is_custom", - "type": "boolean", - "primaryKey": false, - "notNull": false, - "default": false - }, - "entitlement_id": { - "name": "entitlement_id", - "type": "text", - "primaryKey": false, - "notNull": false, - "default": "null" - } - }, - "indexes": {}, - "foreignKeys": { - "prices_entitlement_id_fkey": { - "name": "prices_entitlement_id_fkey", - "tableFrom": "prices", - "tableTo": "entitlements", - "columnsFrom": [ - "entitlement_id" - ], - "columnsTo": [ - "id" - ], - "onDelete": "no action", - "onUpdate": "no action" - }, - "prices_internal_product_id_fkey": { - "name": "prices_internal_product_id_fkey", - "tableFrom": "prices", - "tableTo": "products", - "columnsFrom": [ - "internal_product_id" - ], - "columnsTo": [ - "internal_id" - ], - "onDelete": "cascade", - "onUpdate": "cascade" - } - }, - "compositePrimaryKeys": {}, - "uniqueConstraints": { - "prices_id_key": { - "name": "prices_id_key", - "nullsNotDistinct": false, - "columns": [ - "id" - ] - } - }, - "policies": {}, - "checkConstraints": {}, - "isRLSEnabled": false - }, - "public.products": { - "name": "products", - "schema": "", - "columns": { - "internal_id": { - "name": "internal_id", - "type": "text COLLATE \"C\"", - "primaryKey": true, - "notNull": true - }, - "id": { - "name": "id", - "type": "text", - "primaryKey": false, - "notNull": true - }, - "name": { - "name": "name", - "type": "text", - "primaryKey": false, - "notNull": false - }, - "org_id": { - "name": "org_id", - "type": "text", - "primaryKey": false, - "notNull": true - }, - "created_at": { - "name": "created_at", - "type": "numeric", - "primaryKey": false, - "notNull": true, - "default": "ROUND(date_part('epoch', NOW()) * 1000)::BIGINT" - }, - "env": { - "name": "env", - "type": "text", - "primaryKey": false, - "notNull": true - }, - "is_add_on": { - "name": "is_add_on", - "type": "boolean", - "primaryKey": false, - "notNull": true, - "default": false - }, - "is_default": { - "name": "is_default", - "type": "boolean", - "primaryKey": false, - "notNull": true, - "default": false - }, - "group": { - "name": "group", - "type": "text", - "primaryKey": false, - "notNull": false, - "default": "''" - }, - "version": { - "name": "version", - "type": "numeric", - "primaryKey": false, - "notNull": true, - "default": 1 - }, - "processor": { - "name": "processor", - "type": "jsonb", - "primaryKey": false, - "notNull": false, - "default": "null" - } - }, - "indexes": {}, - "foreignKeys": { - "products_org_id_fkey": { - "name": "products_org_id_fkey", - "tableFrom": "products", - "tableTo": "organizations", - "columnsFrom": [ - "org_id" - ], - "columnsTo": [ - "id" - ], - "onDelete": "cascade", - "onUpdate": "no action" - } - }, - "compositePrimaryKeys": {}, - "uniqueConstraints": { - "unique_product": { - "name": "unique_product", - "nullsNotDistinct": false, - "columns": [ - "org_id", - "id", - "env", - "version" - ] - } - }, - "policies": {}, - "checkConstraints": {}, - "isRLSEnabled": false - }, - "public.referral_codes": { - "name": "referral_codes", - "schema": "", - "columns": { - "code": { - "name": "code", - "type": "text", - "primaryKey": false, - "notNull": true - }, - "org_id": { - "name": "org_id", - "type": "text", - "primaryKey": false, - "notNull": true - }, - "env": { - "name": "env", - "type": "text", - "primaryKey": false, - "notNull": true - }, - "internal_customer_id": { - "name": "internal_customer_id", - "type": "text", - "primaryKey": false, - "notNull": false - }, - "internal_reward_program_id": { - "name": "internal_reward_program_id", - "type": "text", - "primaryKey": false, - "notNull": false - }, - "id": { - "name": "id", - "type": "text", - "primaryKey": false, - "notNull": true - }, - "created_at": { - "name": "created_at", - "type": "numeric", - "primaryKey": false, - "notNull": false - } - }, - "indexes": {}, - "foreignKeys": { - "referral_codes_internal_customer_id_fkey": { - "name": "referral_codes_internal_customer_id_fkey", - "tableFrom": "referral_codes", - "tableTo": "customers", - "columnsFrom": [ - "internal_customer_id" - ], - "columnsTo": [ - "internal_id" - ], - "onDelete": "cascade", - "onUpdate": "no action" - }, - "referral_codes_internal_reward_program_id_fkey": { - "name": "referral_codes_internal_reward_program_id_fkey", - "tableFrom": "referral_codes", - "tableTo": "reward_programs", - "columnsFrom": [ - "internal_reward_program_id" - ], - "columnsTo": [ - "internal_id" - ], - "onDelete": "cascade", - "onUpdate": "no action" - }, - "referral_codes_org_id_fkey": { - "name": "referral_codes_org_id_fkey", - "tableFrom": "referral_codes", - "tableTo": "organizations", - "columnsFrom": [ - "org_id" - ], - "columnsTo": [ - "id" - ], - "onDelete": "cascade", - "onUpdate": "no action" - } - }, - "compositePrimaryKeys": { - "referral_codes_pkey": { - "name": "referral_codes_pkey", - "columns": [ - "code", - "org_id", - "env" - ] - } - }, - "uniqueConstraints": { - "referral_codes_id_key": { - "name": "referral_codes_id_key", - "nullsNotDistinct": false, - "columns": [ - "id" - ] - } - }, - "policies": {}, - "checkConstraints": {}, - "isRLSEnabled": false - }, - "public.reward_programs": { - "name": "reward_programs", - "schema": "", - "columns": { - "internal_id": { - "name": "internal_id", - "type": "text", - "primaryKey": true, - "notNull": true - }, - "id": { - "name": "id", - "type": "text", - "primaryKey": false, - "notNull": false - }, - "created_at": { - "name": "created_at", - "type": "numeric", - "primaryKey": false, - "notNull": false - }, - "internal_reward_id": { - "name": "internal_reward_id", - "type": "text", - "primaryKey": false, - "notNull": false - }, - "max_redemptions": { - "name": "max_redemptions", - "type": "numeric", - "primaryKey": false, - "notNull": false - }, - "unlimited_redemptions": { - "name": "unlimited_redemptions", - "type": "boolean", - "primaryKey": false, - "notNull": false, - "default": false - }, - "org_id": { - "name": "org_id", - "type": "text", - "primaryKey": false, - "notNull": false - }, - "env": { - "name": "env", - "type": "text", - "primaryKey": false, - "notNull": false - }, - "when": { - "name": "when", - "type": "text", - "primaryKey": false, - "notNull": false, - "default": "'immediately'" - }, - "product_ids": { - "name": "product_ids", - "type": "text[]", - "primaryKey": false, - "notNull": false, - "default": "'{\"\"}'" - }, - "exclude_trial": { - "name": "exclude_trial", - "type": "boolean", - "primaryKey": false, - "notNull": false, - "default": false - }, - "received_by": { - "name": "received_by", - "type": "text", - "primaryKey": false, - "notNull": false - } - }, - "indexes": {}, - "foreignKeys": { - "reward_triggers_internal_reward_id_fkey": { - "name": "reward_triggers_internal_reward_id_fkey", - "tableFrom": "reward_programs", - "tableTo": "rewards", - "columnsFrom": [ - "internal_reward_id" - ], - "columnsTo": [ - "internal_id" - ], - "onDelete": "cascade", - "onUpdate": "no action" - }, - "reward_triggers_org_id_fkey": { - "name": "reward_triggers_org_id_fkey", - "tableFrom": "reward_programs", - "tableTo": "organizations", - "columnsFrom": [ - "org_id" - ], - "columnsTo": [ - "id" - ], - "onDelete": "cascade", - "onUpdate": "no action" - } - }, - "compositePrimaryKeys": {}, - "uniqueConstraints": {}, - "policies": {}, - "checkConstraints": {}, - "isRLSEnabled": false - }, - "public.reward_redemptions": { - "name": "reward_redemptions", - "schema": "", - "columns": { - "id": { - "name": "id", - "type": "text", - "primaryKey": true, - "notNull": true - }, - "created_at": { - "name": "created_at", - "type": "numeric", - "primaryKey": false, - "notNull": false - }, - "updated_at": { - "name": "updated_at", - "type": "numeric", - "primaryKey": false, - "notNull": false - }, - "internal_customer_id": { - "name": "internal_customer_id", - "type": "text", - "primaryKey": false, - "notNull": false - }, - "triggered": { - "name": "triggered", - "type": "boolean", - "primaryKey": false, - "notNull": false - }, - "internal_reward_program_id": { - "name": "internal_reward_program_id", - "type": "text", - "primaryKey": false, - "notNull": false - }, - "applied": { - "name": "applied", - "type": "boolean", - "primaryKey": false, - "notNull": false, - "default": false - }, - "referral_code_id": { - "name": "referral_code_id", - "type": "text", - "primaryKey": false, - "notNull": false - } - }, - "indexes": {}, - "foreignKeys": { - "reward_redemptions_internal_customer_id_fkey": { - "name": "reward_redemptions_internal_customer_id_fkey", - "tableFrom": "reward_redemptions", - "tableTo": "customers", - "columnsFrom": [ - "internal_customer_id" - ], - "columnsTo": [ - "internal_id" - ], - "onDelete": "cascade", - "onUpdate": "no action" - }, - "reward_redemptions_internal_reward_program_id_fkey": { - "name": "reward_redemptions_internal_reward_program_id_fkey", - "tableFrom": "reward_redemptions", - "tableTo": "reward_programs", - "columnsFrom": [ - "internal_reward_program_id" - ], - "columnsTo": [ - "internal_id" - ], - "onDelete": "cascade", - "onUpdate": "no action" - }, - "reward_redemptions_referral_code_id_fkey": { - "name": "reward_redemptions_referral_code_id_fkey", - "tableFrom": "reward_redemptions", - "tableTo": "referral_codes", - "columnsFrom": [ - "referral_code_id" - ], - "columnsTo": [ - "id" - ], - "onDelete": "cascade", - "onUpdate": "no action" - } - }, - "compositePrimaryKeys": {}, - "uniqueConstraints": {}, - "policies": {}, - "checkConstraints": {}, - "isRLSEnabled": false - }, - "public.rewards": { - "name": "rewards", - "schema": "", - "columns": { - "internal_id": { - "name": "internal_id", - "type": "text", - "primaryKey": true, - "notNull": true - }, - "id": { - "name": "id", - "type": "text", - "primaryKey": false, - "notNull": false - }, - "org_id": { - "name": "org_id", - "type": "text", - "primaryKey": false, - "notNull": false - }, - "env": { - "name": "env", - "type": "text", - "primaryKey": false, - "notNull": false - }, - "created_at": { - "name": "created_at", - "type": "numeric", - "primaryKey": false, - "notNull": false - }, - "name": { - "name": "name", - "type": "text", - "primaryKey": false, - "notNull": false - }, - "discount_config": { - "name": "discount_config", - "type": "jsonb", - "primaryKey": false, - "notNull": false - }, - "free_product_id": { - "name": "free_product_id", - "type": "text", - "primaryKey": false, - "notNull": false - }, - "promo_codes": { - "name": "promo_codes", - "type": "jsonb[]", - "primaryKey": false, - "notNull": false - }, - "type": { - "name": "type", - "type": "text", - "primaryKey": false, - "notNull": false - } - }, - "indexes": {}, - "foreignKeys": { - "coupons_org_id_fkey": { - "name": "coupons_org_id_fkey", - "tableFrom": "rewards", - "tableTo": "organizations", - "columnsFrom": [ - "org_id" - ], - "columnsTo": [ - "id" - ], - "onDelete": "cascade", - "onUpdate": "no action" - } - }, - "compositePrimaryKeys": {}, - "uniqueConstraints": {}, - "policies": {}, - "checkConstraints": {}, - "isRLSEnabled": false - }, - "public.subscriptions": { - "name": "subscriptions", - "schema": "", - "columns": { - "id": { - "name": "id", - "type": "text", - "primaryKey": true, - "notNull": true - }, - "org_id": { - "name": "org_id", - "type": "text", - "primaryKey": false, - "notNull": true - }, - "stripe_id": { - "name": "stripe_id", - "type": "text", - "primaryKey": false, - "notNull": false - }, - "stripe_schedule_id": { - "name": "stripe_schedule_id", - "type": "text", - "primaryKey": false, - "notNull": false - }, - "created_at": { - "name": "created_at", - "type": "numeric", - "primaryKey": false, - "notNull": true, - "default": "ROUND(date_part('epoch', NOW()) * 1000)::BIGINT" - }, - "metadata": { - "name": "metadata", - "type": "jsonb", - "primaryKey": false, - "notNull": false, - "default": "'{}'::jsonb" - }, - "usage_features": { - "name": "usage_features", - "type": "text[]", - "primaryKey": false, - "notNull": false, - "default": "'{}'" - }, - "env": { - "name": "env", - "type": "text", - "primaryKey": false, - "notNull": false - }, - "current_period_start": { - "name": "current_period_start", - "type": "numeric", - "primaryKey": false, - "notNull": false - }, - "current_period_end": { - "name": "current_period_end", - "type": "numeric", - "primaryKey": false, - "notNull": false - } - }, - "indexes": {}, - "foreignKeys": { - "subscriptions_org_id_fkey": { - "name": "subscriptions_org_id_fkey", - "tableFrom": "subscriptions", - "tableTo": "organizations", - "columnsFrom": [ - "org_id" - ], - "columnsTo": [ - "id" - ], - "onDelete": "cascade", - "onUpdate": "no action" - } - }, - "compositePrimaryKeys": {}, - "uniqueConstraints": { - "subscriptions_stripe_id_key": { - "name": "subscriptions_stripe_id_key", - "nullsNotDistinct": false, - "columns": [ - "stripe_id" - ] - } - }, - "policies": {}, - "checkConstraints": {}, - "isRLSEnabled": false - } - }, - "enums": {}, - "schemas": {}, - "sequences": {}, - "roles": {}, - "policies": {}, - "views": {}, - "_meta": { - "columns": {}, - "schemas": {}, - "tables": {} - } -} \ No newline at end of file diff --git a/shared/drizzle/meta/0001_snapshot.json b/shared/drizzle/meta/0001_snapshot.json deleted file mode 100644 index b443ed4f4..000000000 --- a/shared/drizzle/meta/0001_snapshot.json +++ /dev/null @@ -1,2387 +0,0 @@ -{ - "id": "f1f27d42-50b5-4ec1-8b42-8a2607dc15ed", - "prevId": "b89d5375-4ef4-4cf1-b58b-540024d404a2", - "version": "7", - "dialect": "postgresql", - "tables": { - "public.actions": { - "name": "actions", - "schema": "", - "columns": { - "id": { - "name": "id", - "type": "text COLLATE \"C\"", - "primaryKey": true, - "notNull": true - }, - "request_id": { - "name": "request_id", - "type": "text", - "primaryKey": false, - "notNull": true - }, - "org_id": { - "name": "org_id", - "type": "text", - "primaryKey": false, - "notNull": true - }, - "org_slug": { - "name": "org_slug", - "type": "text", - "primaryKey": false, - "notNull": true - }, - "env": { - "name": "env", - "type": "text", - "primaryKey": false, - "notNull": true - }, - "customer_id": { - "name": "customer_id", - "type": "text", - "primaryKey": false, - "notNull": false - }, - "internal_customer_id": { - "name": "internal_customer_id", - "type": "text", - "primaryKey": false, - "notNull": false - }, - "entity_id": { - "name": "entity_id", - "type": "text", - "primaryKey": false, - "notNull": false - }, - "internal_entity_id": { - "name": "internal_entity_id", - "type": "text", - "primaryKey": false, - "notNull": false - }, - "type": { - "name": "type", - "type": "text", - "primaryKey": false, - "notNull": true - }, - "auth_type": { - "name": "auth_type", - "type": "text", - "primaryKey": false, - "notNull": true - }, - "method": { - "name": "method", - "type": "text", - "primaryKey": false, - "notNull": true - }, - "path": { - "name": "path", - "type": "text", - "primaryKey": false, - "notNull": true - }, - "timestamp": { - "name": "timestamp", - "type": "timestamp with time zone", - "primaryKey": false, - "notNull": true, - "default": "now()" - }, - "properties": { - "name": "properties", - "type": "jsonb", - "primaryKey": false, - "notNull": false - } - }, - "indexes": {}, - "foreignKeys": { - "actions_org_id_fkey": { - "name": "actions_org_id_fkey", - "tableFrom": "actions", - "tableTo": "organizations", - "columnsFrom": [ - "org_id" - ], - "columnsTo": [ - "id" - ], - "onDelete": "set null", - "onUpdate": "no action" - }, - "actions_customer_id_fkey": { - "name": "actions_customer_id_fkey", - "tableFrom": "actions", - "tableTo": "customers", - "columnsFrom": [ - "internal_customer_id" - ], - "columnsTo": [ - "internal_id" - ], - "onDelete": "set null", - "onUpdate": "no action" - }, - "actions_entity_id_fkey": { - "name": "actions_entity_id_fkey", - "tableFrom": "actions", - "tableTo": "entities", - "columnsFrom": [ - "internal_entity_id" - ], - "columnsTo": [ - "internal_id" - ], - "onDelete": "set null", - "onUpdate": "no action" - } - }, - "compositePrimaryKeys": {}, - "uniqueConstraints": {}, - "policies": {}, - "checkConstraints": {}, - "isRLSEnabled": true - }, - "public.api_keys": { - "name": "api_keys", - "schema": "", - "columns": { - "id": { - "name": "id", - "type": "text COLLATE \"C\"", - "primaryKey": true, - "notNull": true - }, - "created_at": { - "name": "created_at", - "type": "numeric", - "primaryKey": false, - "notNull": true, - "default": "ROUND(date_part('epoch', NOW()) * 1000)::BIGINT" - }, - "name": { - "name": "name", - "type": "text", - "primaryKey": false, - "notNull": false - }, - "prefix": { - "name": "prefix", - "type": "text", - "primaryKey": false, - "notNull": false - }, - "org_id": { - "name": "org_id", - "type": "text", - "primaryKey": false, - "notNull": false - }, - "user_id": { - "name": "user_id", - "type": "text", - "primaryKey": false, - "notNull": false - }, - "env": { - "name": "env", - "type": "text", - "primaryKey": false, - "notNull": false - }, - "hashed_key": { - "name": "hashed_key", - "type": "text", - "primaryKey": false, - "notNull": false - }, - "meta": { - "name": "meta", - "type": "jsonb", - "primaryKey": false, - "notNull": false - } - }, - "indexes": {}, - "foreignKeys": { - "api_keys_org_id_fkey": { - "name": "api_keys_org_id_fkey", - "tableFrom": "api_keys", - "tableTo": "organizations", - "columnsFrom": [ - "org_id" - ], - "columnsTo": [ - "id" - ], - "onDelete": "cascade", - "onUpdate": "no action" - } - }, - "compositePrimaryKeys": {}, - "uniqueConstraints": { - "api_keys_hashed_key_key": { - "name": "api_keys_hashed_key_key", - "nullsNotDistinct": false, - "columns": [ - "hashed_key" - ] - } - }, - "policies": {}, - "checkConstraints": {}, - "isRLSEnabled": false - }, - "public.chat_results": { - "name": "chat_results", - "schema": "", - "columns": { - "id": { - "name": "id", - "type": "text COLLATE \"C\"", - "primaryKey": true, - "notNull": true - }, - "created_at": { - "name": "created_at", - "type": "numeric", - "primaryKey": false, - "notNull": false - }, - "data": { - "name": "data", - "type": "jsonb", - "primaryKey": false, - "notNull": true - } - }, - "indexes": {}, - "foreignKeys": {}, - "compositePrimaryKeys": {}, - "uniqueConstraints": {}, - "policies": {}, - "checkConstraints": {}, - "isRLSEnabled": true - }, - "public.customer_entitlements": { - "name": "customer_entitlements", - "schema": "", - "columns": { - "id": { - "name": "id", - "type": "text COLLATE \"C\"", - "primaryKey": true, - "notNull": true - }, - "customer_product_id": { - "name": "customer_product_id", - "type": "text", - "primaryKey": false, - "notNull": true - }, - "entitlement_id": { - "name": "entitlement_id", - "type": "text", - "primaryKey": false, - "notNull": true - }, - "internal_customer_id": { - "name": "internal_customer_id", - "type": "text", - "primaryKey": false, - "notNull": true - }, - "internal_feature_id": { - "name": "internal_feature_id", - "type": "text", - "primaryKey": false, - "notNull": true - }, - "unlimited": { - "name": "unlimited", - "type": "boolean", - "primaryKey": false, - "notNull": false, - "default": false - }, - "balance": { - "name": "balance", - "type": "numeric", - "primaryKey": false, - "notNull": true, - "default": 0 - }, - "created_at": { - "name": "created_at", - "type": "numeric", - "primaryKey": false, - "notNull": true - }, - "next_reset_at": { - "name": "next_reset_at", - "type": "numeric", - "primaryKey": false, - "notNull": false - }, - "usage_allowed": { - "name": "usage_allowed", - "type": "boolean", - "primaryKey": false, - "notNull": false, - "default": false - }, - "adjustment": { - "name": "adjustment", - "type": "numeric", - "primaryKey": false, - "notNull": false - }, - "entities": { - "name": "entities", - "type": "jsonb", - "primaryKey": false, - "notNull": false - }, - "customer_id": { - "name": "customer_id", - "type": "text", - "primaryKey": false, - "notNull": false - }, - "feature_id": { - "name": "feature_id", - "type": "text", - "primaryKey": false, - "notNull": false - } - }, - "indexes": {}, - "foreignKeys": { - "entitlements_internal_feature_id_fkey": { - "name": "entitlements_internal_feature_id_fkey", - "tableFrom": "customer_entitlements", - "tableTo": "features", - "columnsFrom": [ - "internal_feature_id" - ], - "columnsTo": [ - "internal_id" - ], - "onDelete": "cascade", - "onUpdate": "no action" - }, - "customer_entitlements_customer_product_id_fkey": { - "name": "customer_entitlements_customer_product_id_fkey", - "tableFrom": "customer_entitlements", - "tableTo": "customer_products", - "columnsFrom": [ - "customer_product_id" - ], - "columnsTo": [ - "id" - ], - "onDelete": "cascade", - "onUpdate": "cascade" - } - }, - "compositePrimaryKeys": {}, - "uniqueConstraints": { - "entitlements_id_key": { - "name": "entitlements_id_key", - "nullsNotDistinct": false, - "columns": [ - "id" - ] - } - }, - "policies": {}, - "checkConstraints": {}, - "isRLSEnabled": false - }, - "public.customer_prices": { - "name": "customer_prices", - "schema": "", - "columns": { - "id": { - "name": "id", - "type": "text", - "primaryKey": true, - "notNull": true - }, - "created_at": { - "name": "created_at", - "type": "numeric", - "primaryKey": false, - "notNull": true - }, - "price_id": { - "name": "price_id", - "type": "text", - "primaryKey": false, - "notNull": false - }, - "options": { - "name": "options", - "type": "jsonb", - "primaryKey": false, - "notNull": false - }, - "internal_customer_id": { - "name": "internal_customer_id", - "type": "text", - "primaryKey": false, - "notNull": false - }, - "customer_product_id": { - "name": "customer_product_id", - "type": "text", - "primaryKey": false, - "notNull": false - } - }, - "indexes": {}, - "foreignKeys": { - "customer_prices_customer_product_id_fkey": { - "name": "customer_prices_customer_product_id_fkey", - "tableFrom": "customer_prices", - "tableTo": "customer_products", - "columnsFrom": [ - "customer_product_id" - ], - "columnsTo": [ - "id" - ], - "onDelete": "cascade", - "onUpdate": "no action" - }, - "customer_prices_internal_customer_id_fkey": { - "name": "customer_prices_internal_customer_id_fkey", - "tableFrom": "customer_prices", - "tableTo": "customers", - "columnsFrom": [ - "internal_customer_id" - ], - "columnsTo": [ - "internal_id" - ], - "onDelete": "cascade", - "onUpdate": "no action" - }, - "customer_prices_price_id_fkey": { - "name": "customer_prices_price_id_fkey", - "tableFrom": "customer_prices", - "tableTo": "prices", - "columnsFrom": [ - "price_id" - ], - "columnsTo": [ - "id" - ], - "onDelete": "no action", - "onUpdate": "no action" - } - }, - "compositePrimaryKeys": {}, - "uniqueConstraints": {}, - "policies": {}, - "checkConstraints": {}, - "isRLSEnabled": false - }, - "public.customer_products": { - "name": "customer_products", - "schema": "", - "columns": { - "id": { - "name": "id", - "type": "text COLLATE \"C\"", - "primaryKey": true, - "notNull": true - }, - "internal_customer_id": { - "name": "internal_customer_id", - "type": "text", - "primaryKey": false, - "notNull": true - }, - "internal_product_id": { - "name": "internal_product_id", - "type": "text", - "primaryKey": false, - "notNull": true - }, - "internal_entity_id": { - "name": "internal_entity_id", - "type": "text", - "primaryKey": false, - "notNull": false - }, - "created_at": { - "name": "created_at", - "type": "numeric", - "primaryKey": false, - "notNull": false - }, - "status": { - "name": "status", - "type": "text", - "primaryKey": false, - "notNull": false - }, - "processor": { - "name": "processor", - "type": "jsonb", - "primaryKey": false, - "notNull": false - }, - "canceled_at": { - "name": "canceled_at", - "type": "numeric", - "primaryKey": false, - "notNull": false - }, - "ended_at": { - "name": "ended_at", - "type": "numeric", - "primaryKey": false, - "notNull": false - }, - "starts_at": { - "name": "starts_at", - "type": "numeric", - "primaryKey": false, - "notNull": false - }, - "options": { - "name": "options", - "type": "jsonb[]", - "primaryKey": false, - "notNull": false - }, - "product_id": { - "name": "product_id", - "type": "text", - "primaryKey": false, - "notNull": false - }, - "free_trial_id": { - "name": "free_trial_id", - "type": "text", - "primaryKey": false, - "notNull": false - }, - "trial_ends_at": { - "name": "trial_ends_at", - "type": "numeric", - "primaryKey": false, - "notNull": false - }, - "collection_method": { - "name": "collection_method", - "type": "text", - "primaryKey": false, - "notNull": false, - "default": "'charge_automatically'" - }, - "subscription_ids": { - "name": "subscription_ids", - "type": "text[]", - "primaryKey": false, - "notNull": false - }, - "scheduled_ids": { - "name": "scheduled_ids", - "type": "text[]", - "primaryKey": false, - "notNull": false - }, - "quantity": { - "name": "quantity", - "type": "numeric", - "primaryKey": false, - "notNull": false, - "default": 1 - }, - "is_custom": { - "name": "is_custom", - "type": "boolean", - "primaryKey": false, - "notNull": true, - "default": false - }, - "customer_id": { - "name": "customer_id", - "type": "text", - "primaryKey": false, - "notNull": false - }, - "entity_id": { - "name": "entity_id", - "type": "text", - "primaryKey": false, - "notNull": false - } - }, - "indexes": {}, - "foreignKeys": { - "customer_products_free_trial_id_fkey": { - "name": "customer_products_free_trial_id_fkey", - "tableFrom": "customer_products", - "tableTo": "free_trials", - "columnsFrom": [ - "free_trial_id" - ], - "columnsTo": [ - "id" - ], - "onDelete": "no action", - "onUpdate": "no action" - }, - "customer_products_internal_customer_id_fkey": { - "name": "customer_products_internal_customer_id_fkey", - "tableFrom": "customer_products", - "tableTo": "customers", - "columnsFrom": [ - "internal_customer_id" - ], - "columnsTo": [ - "internal_id" - ], - "onDelete": "cascade", - "onUpdate": "cascade" - }, - "customer_products_internal_product_id_fkey": { - "name": "customer_products_internal_product_id_fkey", - "tableFrom": "customer_products", - "tableTo": "products", - "columnsFrom": [ - "internal_product_id" - ], - "columnsTo": [ - "internal_id" - ], - "onDelete": "no action", - "onUpdate": "no action" - }, - "customer_products_internal_entity_id_fkey": { - "name": "customer_products_internal_entity_id_fkey", - "tableFrom": "customer_products", - "tableTo": "entities", - "columnsFrom": [ - "internal_entity_id" - ], - "columnsTo": [ - "internal_id" - ], - "onDelete": "set null", - "onUpdate": "no action" - } - }, - "compositePrimaryKeys": {}, - "uniqueConstraints": {}, - "policies": {}, - "checkConstraints": {}, - "isRLSEnabled": false - }, - "public.customers": { - "name": "customers", - "schema": "", - "columns": { - "internal_id": { - "name": "internal_id", - "type": "text COLLATE \"C\"", - "primaryKey": true, - "notNull": true - }, - "org_id": { - "name": "org_id", - "type": "text", - "primaryKey": false, - "notNull": true - }, - "created_at": { - "name": "created_at", - "type": "numeric", - "primaryKey": false, - "notNull": true - }, - "name": { - "name": "name", - "type": "text", - "primaryKey": false, - "notNull": false - }, - "id": { - "name": "id", - "type": "text", - "primaryKey": false, - "notNull": false - }, - "email": { - "name": "email", - "type": "text", - "primaryKey": false, - "notNull": false - }, - "fingerprint": { - "name": "fingerprint", - "type": "text", - "primaryKey": false, - "notNull": false, - "default": "null" - }, - "metadata": { - "name": "metadata", - "type": "jsonb", - "primaryKey": false, - "notNull": false - }, - "env": { - "name": "env", - "type": "text", - "primaryKey": false, - "notNull": true - }, - "processor": { - "name": "processor", - "type": "jsonb", - "primaryKey": false, - "notNull": false - } - }, - "indexes": {}, - "foreignKeys": { - "customers_org_id_fkey": { - "name": "customers_org_id_fkey", - "tableFrom": "customers", - "tableTo": "organizations", - "columnsFrom": [ - "org_id" - ], - "columnsTo": [ - "id" - ], - "onDelete": "cascade", - "onUpdate": "no action" - } - }, - "compositePrimaryKeys": {}, - "uniqueConstraints": { - "cus_id_constraint": { - "name": "cus_id_constraint", - "nullsNotDistinct": false, - "columns": [ - "org_id", - "id", - "env" - ] - } - }, - "policies": {}, - "checkConstraints": {}, - "isRLSEnabled": true - }, - "public.entities": { - "name": "entities", - "schema": "", - "columns": { - "id": { - "name": "id", - "type": "text", - "primaryKey": false, - "notNull": false - }, - "org_id": { - "name": "org_id", - "type": "text", - "primaryKey": false, - "notNull": false - }, - "created_at": { - "name": "created_at", - "type": "numeric", - "primaryKey": false, - "notNull": true - }, - "internal_id": { - "name": "internal_id", - "type": "text", - "primaryKey": true, - "notNull": true - }, - "internal_customer_id": { - "name": "internal_customer_id", - "type": "text", - "primaryKey": false, - "notNull": true - }, - "env": { - "name": "env", - "type": "text", - "primaryKey": false, - "notNull": false - }, - "name": { - "name": "name", - "type": "text", - "primaryKey": false, - "notNull": false - }, - "deleted": { - "name": "deleted", - "type": "boolean", - "primaryKey": false, - "notNull": true, - "default": false - }, - "internal_feature_id": { - "name": "internal_feature_id", - "type": "text", - "primaryKey": false, - "notNull": false - }, - "feature_id": { - "name": "feature_id", - "type": "text", - "primaryKey": false, - "notNull": false - } - }, - "indexes": {}, - "foreignKeys": { - "entities_internal_customer_id_fkey": { - "name": "entities_internal_customer_id_fkey", - "tableFrom": "entities", - "tableTo": "customers", - "columnsFrom": [ - "internal_customer_id" - ], - "columnsTo": [ - "internal_id" - ], - "onDelete": "cascade", - "onUpdate": "no action" - }, - "entities_internal_feature_id_fkey": { - "name": "entities_internal_feature_id_fkey", - "tableFrom": "entities", - "tableTo": "features", - "columnsFrom": [ - "internal_feature_id" - ], - "columnsTo": [ - "internal_id" - ], - "onDelete": "cascade", - "onUpdate": "no action" - }, - "entities_org_id_fkey": { - "name": "entities_org_id_fkey", - "tableFrom": "entities", - "tableTo": "organizations", - "columnsFrom": [ - "org_id" - ], - "columnsTo": [ - "id" - ], - "onDelete": "cascade", - "onUpdate": "no action" - } - }, - "compositePrimaryKeys": {}, - "uniqueConstraints": { - "entity_id_constraint": { - "name": "entity_id_constraint", - "nullsNotDistinct": false, - "columns": [ - "org_id", - "env", - "internal_customer_id", - "id" - ] - } - }, - "policies": {}, - "checkConstraints": {}, - "isRLSEnabled": false - }, - "public.entitlements": { - "name": "entitlements", - "schema": "", - "columns": { - "id": { - "name": "id", - "type": "text COLLATE \"C\"", - "primaryKey": true, - "notNull": true - }, - "created_at": { - "name": "created_at", - "type": "numeric", - "primaryKey": false, - "notNull": true - }, - "internal_feature_id": { - "name": "internal_feature_id", - "type": "text", - "primaryKey": false, - "notNull": true - }, - "internal_product_id": { - "name": "internal_product_id", - "type": "text", - "primaryKey": false, - "notNull": true - }, - "is_custom": { - "name": "is_custom", - "type": "boolean", - "primaryKey": false, - "notNull": false, - "default": false - }, - "allowance_type": { - "name": "allowance_type", - "type": "text", - "primaryKey": false, - "notNull": false - }, - "allowance": { - "name": "allowance", - "type": "numeric", - "primaryKey": false, - "notNull": false - }, - "interval": { - "name": "interval", - "type": "text", - "primaryKey": false, - "notNull": false - }, - "carry_from_previous": { - "name": "carry_from_previous", - "type": "boolean", - "primaryKey": false, - "notNull": false, - "default": false - }, - "entity_feature_id": { - "name": "entity_feature_id", - "type": "text", - "primaryKey": false, - "notNull": false, - "default": "null" - }, - "org_id": { - "name": "org_id", - "type": "text", - "primaryKey": false, - "notNull": false - }, - "feature_id": { - "name": "feature_id", - "type": "text", - "primaryKey": false, - "notNull": false - } - }, - "indexes": {}, - "foreignKeys": { - "entitlements_internal_feature_id_fkey": { - "name": "entitlements_internal_feature_id_fkey", - "tableFrom": "entitlements", - "tableTo": "features", - "columnsFrom": [ - "internal_feature_id" - ], - "columnsTo": [ - "internal_id" - ], - "onDelete": "cascade", - "onUpdate": "no action" - }, - "entitlements_internal_product_id_fkey": { - "name": "entitlements_internal_product_id_fkey", - "tableFrom": "entitlements", - "tableTo": "products", - "columnsFrom": [ - "internal_product_id" - ], - "columnsTo": [ - "internal_id" - ], - "onDelete": "cascade", - "onUpdate": "cascade" - } - }, - "compositePrimaryKeys": {}, - "uniqueConstraints": { - "entitlements_id_key": { - "name": "entitlements_id_key", - "nullsNotDistinct": false, - "columns": [ - "id" - ] - } - }, - "policies": {}, - "checkConstraints": {}, - "isRLSEnabled": false - }, - "public.features": { - "name": "features", - "schema": "", - "columns": { - "internal_id": { - "name": "internal_id", - "type": "text COLLATE \"C\"", - "primaryKey": true, - "notNull": true - }, - "org_id": { - "name": "org_id", - "type": "text", - "primaryKey": false, - "notNull": true - }, - "created_at": { - "name": "created_at", - "type": "numeric", - "primaryKey": false, - "notNull": false - }, - "env": { - "name": "env", - "type": "text", - "primaryKey": false, - "notNull": false - }, - "id": { - "name": "id", - "type": "text", - "primaryKey": false, - "notNull": true - }, - "name": { - "name": "name", - "type": "text", - "primaryKey": false, - "notNull": false - }, - "type": { - "name": "type", - "type": "text", - "primaryKey": false, - "notNull": true - }, - "config": { - "name": "config", - "type": "jsonb", - "primaryKey": false, - "notNull": false - }, - "display": { - "name": "display", - "type": "jsonb", - "primaryKey": false, - "notNull": false, - "default": "null" - } - }, - "indexes": {}, - "foreignKeys": { - "features_org_id_fkey": { - "name": "features_org_id_fkey", - "tableFrom": "features", - "tableTo": "organizations", - "columnsFrom": [ - "org_id" - ], - "columnsTo": [ - "id" - ], - "onDelete": "cascade", - "onUpdate": "no action" - } - }, - "compositePrimaryKeys": {}, - "uniqueConstraints": { - "feature_id_constraint": { - "name": "feature_id_constraint", - "nullsNotDistinct": false, - "columns": [ - "org_id", - "id", - "env" - ] - } - }, - "policies": {}, - "checkConstraints": {}, - "isRLSEnabled": false - }, - "public.free_trials": { - "name": "free_trials", - "schema": "", - "columns": { - "id": { - "name": "id", - "type": "text", - "primaryKey": true, - "notNull": true - }, - "created_at": { - "name": "created_at", - "type": "numeric", - "primaryKey": false, - "notNull": true - }, - "internal_product_id": { - "name": "internal_product_id", - "type": "text", - "primaryKey": false, - "notNull": false - }, - "duration": { - "name": "duration", - "type": "text", - "primaryKey": false, - "notNull": false, - "default": "'day'" - }, - "length": { - "name": "length", - "type": "numeric", - "primaryKey": false, - "notNull": false - }, - "unique_fingerprint": { - "name": "unique_fingerprint", - "type": "boolean", - "primaryKey": false, - "notNull": false - }, - "is_custom": { - "name": "is_custom", - "type": "boolean", - "primaryKey": false, - "notNull": false, - "default": false - } - }, - "indexes": {}, - "foreignKeys": { - "free_trials_internal_product_id_fkey": { - "name": "free_trials_internal_product_id_fkey", - "tableFrom": "free_trials", - "tableTo": "products", - "columnsFrom": [ - "internal_product_id" - ], - "columnsTo": [ - "internal_id" - ], - "onDelete": "cascade", - "onUpdate": "no action" - } - }, - "compositePrimaryKeys": {}, - "uniqueConstraints": {}, - "policies": {}, - "checkConstraints": {}, - "isRLSEnabled": false - }, - "public.invoices": { - "name": "invoices", - "schema": "", - "columns": { - "id": { - "name": "id", - "type": "text COLLATE \"C\"", - "primaryKey": true, - "notNull": true - }, - "created_at": { - "name": "created_at", - "type": "numeric", - "primaryKey": false, - "notNull": true, - "default": "ROUND(date_part('epoch', NOW()) * 1000)::BIGINT" - }, - "product_ids": { - "name": "product_ids", - "type": "text[]", - "primaryKey": false, - "notNull": false, - "default": "'{}'" - }, - "internal_product_ids": { - "name": "internal_product_ids", - "type": "text[]", - "primaryKey": false, - "notNull": false, - "default": "'{}'" - }, - "internal_customer_id": { - "name": "internal_customer_id", - "type": "text", - "primaryKey": false, - "notNull": true - }, - "internal_entity_id": { - "name": "internal_entity_id", - "type": "text", - "primaryKey": false, - "notNull": false - }, - "stripe_id": { - "name": "stripe_id", - "type": "text", - "primaryKey": false, - "notNull": true - }, - "status": { - "name": "status", - "type": "text", - "primaryKey": false, - "notNull": true, - "default": "'draft'" - }, - "hosted_invoice_url": { - "name": "hosted_invoice_url", - "type": "text", - "primaryKey": false, - "notNull": false - }, - "total": { - "name": "total", - "type": "numeric", - "primaryKey": false, - "notNull": true, - "default": 0 - }, - "currency": { - "name": "currency", - "type": "text", - "primaryKey": false, - "notNull": true, - "default": "'usd'" - }, - "discounts": { - "name": "discounts", - "type": "jsonb[]", - "primaryKey": false, - "notNull": false, - "default": "'{}'" - }, - "items": { - "name": "items", - "type": "jsonb[]", - "primaryKey": false, - "notNull": false, - "default": "'{}'" - } - }, - "indexes": {}, - "foreignKeys": { - "invoices_internal_customer_id_fkey": { - "name": "invoices_internal_customer_id_fkey", - "tableFrom": "invoices", - "tableTo": "customers", - "columnsFrom": [ - "internal_customer_id" - ], - "columnsTo": [ - "id" - ], - "onDelete": "no action", - "onUpdate": "no action" - }, - "invoices_internal_entity_id_fkey": { - "name": "invoices_internal_entity_id_fkey", - "tableFrom": "invoices", - "tableTo": "entities", - "columnsFrom": [ - "internal_entity_id" - ], - "columnsTo": [ - "id" - ], - "onDelete": "no action", - "onUpdate": "no action" - } - }, - "compositePrimaryKeys": {}, - "uniqueConstraints": {}, - "policies": {}, - "checkConstraints": {}, - "isRLSEnabled": false - }, - "public.metadata": { - "name": "metadata", - "schema": "", - "columns": { - "id": { - "name": "id", - "type": "text", - "primaryKey": true, - "notNull": true - }, - "created_at": { - "name": "created_at", - "type": "numeric", - "primaryKey": false, - "notNull": true, - "default": "ROUND(date_part('epoch', NOW()) * 1000)::BIGINT" - }, - "expires_at": { - "name": "expires_at", - "type": "numeric", - "primaryKey": false, - "notNull": false - }, - "data": { - "name": "data", - "type": "jsonb", - "primaryKey": false, - "notNull": false - } - }, - "indexes": {}, - "foreignKeys": {}, - "compositePrimaryKeys": {}, - "uniqueConstraints": {}, - "policies": {}, - "checkConstraints": {}, - "isRLSEnabled": false - }, - "public.migration_errors": { - "name": "migration_errors", - "schema": "", - "columns": { - "internal_customer_id": { - "name": "internal_customer_id", - "type": "text", - "primaryKey": false, - "notNull": true - }, - "migration_job_id": { - "name": "migration_job_id", - "type": "text", - "primaryKey": false, - "notNull": true - }, - "created_at": { - "name": "created_at", - "type": "numeric", - "primaryKey": false, - "notNull": false - }, - "updated_at": { - "name": "updated_at", - "type": "numeric", - "primaryKey": false, - "notNull": false - }, - "data": { - "name": "data", - "type": "jsonb", - "primaryKey": false, - "notNull": false - }, - "message": { - "name": "message", - "type": "text", - "primaryKey": false, - "notNull": false - }, - "code": { - "name": "code", - "type": "text", - "primaryKey": false, - "notNull": false - } - }, - "indexes": {}, - "foreignKeys": { - "migration_customers_internal_customer_id_fkey": { - "name": "migration_customers_internal_customer_id_fkey", - "tableFrom": "migration_errors", - "tableTo": "customers", - "columnsFrom": [ - "internal_customer_id" - ], - "columnsTo": [ - "internal_id" - ], - "onDelete": "cascade", - "onUpdate": "no action" - }, - "migration_customers_migration_job_id_fkey": { - "name": "migration_customers_migration_job_id_fkey", - "tableFrom": "migration_errors", - "tableTo": "migration_jobs", - "columnsFrom": [ - "migration_job_id" - ], - "columnsTo": [ - "id" - ], - "onDelete": "cascade", - "onUpdate": "no action" - } - }, - "compositePrimaryKeys": { - "migration_errors_pkey": { - "name": "migration_errors_pkey", - "columns": [ - "internal_customer_id", - "migration_job_id" - ] - } - }, - "uniqueConstraints": {}, - "policies": {}, - "checkConstraints": {}, - "isRLSEnabled": false - }, - "public.migration_jobs": { - "name": "migration_jobs", - "schema": "", - "columns": { - "id": { - "name": "id", - "type": "text", - "primaryKey": true, - "notNull": true - }, - "org_id": { - "name": "org_id", - "type": "text", - "primaryKey": false, - "notNull": true - }, - "env": { - "name": "env", - "type": "text", - "primaryKey": false, - "notNull": true - }, - "created_at": { - "name": "created_at", - "type": "numeric", - "primaryKey": false, - "notNull": true - }, - "updated_at": { - "name": "updated_at", - "type": "numeric", - "primaryKey": false, - "notNull": false - }, - "current_step": { - "name": "current_step", - "type": "text", - "primaryKey": false, - "notNull": false - }, - "from_internal_product_id": { - "name": "from_internal_product_id", - "type": "text", - "primaryKey": false, - "notNull": false - }, - "to_internal_product_id": { - "name": "to_internal_product_id", - "type": "text", - "primaryKey": false, - "notNull": false - }, - "step_details": { - "name": "step_details", - "type": "jsonb", - "primaryKey": false, - "notNull": false - } - }, - "indexes": {}, - "foreignKeys": { - "migration_jobs_from_internal_product_id_fkey": { - "name": "migration_jobs_from_internal_product_id_fkey", - "tableFrom": "migration_jobs", - "tableTo": "products", - "columnsFrom": [ - "from_internal_product_id" - ], - "columnsTo": [ - "internal_id" - ], - "onDelete": "cascade", - "onUpdate": "no action" - }, - "migration_jobs_org_id_fkey": { - "name": "migration_jobs_org_id_fkey", - "tableFrom": "migration_jobs", - "tableTo": "organizations", - "columnsFrom": [ - "org_id" - ], - "columnsTo": [ - "id" - ], - "onDelete": "cascade", - "onUpdate": "no action" - }, - "migration_jobs_to_internal_product_id_fkey": { - "name": "migration_jobs_to_internal_product_id_fkey", - "tableFrom": "migration_jobs", - "tableTo": "products", - "columnsFrom": [ - "to_internal_product_id" - ], - "columnsTo": [ - "internal_id" - ], - "onDelete": "cascade", - "onUpdate": "no action" - } - }, - "compositePrimaryKeys": {}, - "uniqueConstraints": {}, - "policies": {}, - "checkConstraints": {}, - "isRLSEnabled": false - }, - "public.organizations": { - "name": "organizations", - "schema": "", - "columns": { - "id": { - "name": "id", - "type": "text", - "primaryKey": true, - "notNull": true - }, - "slug": { - "name": "slug", - "type": "text", - "primaryKey": false, - "notNull": true - }, - "default_currency": { - "name": "default_currency", - "type": "text", - "primaryKey": false, - "notNull": true, - "default": "'usd'" - }, - "stripe_connected": { - "name": "stripe_connected", - "type": "boolean", - "primaryKey": false, - "notNull": false, - "default": false - }, - "stripe_config": { - "name": "stripe_config", - "type": "jsonb", - "primaryKey": false, - "notNull": false - }, - "test_pkey": { - "name": "test_pkey", - "type": "text", - "primaryKey": false, - "notNull": false - }, - "live_pkey": { - "name": "live_pkey", - "type": "text", - "primaryKey": false, - "notNull": false - }, - "svix_config": { - "name": "svix_config", - "type": "jsonb", - "primaryKey": false, - "notNull": true - }, - "created_at": { - "name": "created_at", - "type": "numeric", - "primaryKey": false, - "notNull": false - }, - "config": { - "name": "config", - "type": "jsonb", - "primaryKey": false, - "notNull": true, - "default": "'{}'::jsonb" - } - }, - "indexes": {}, - "foreignKeys": {}, - "compositePrimaryKeys": {}, - "uniqueConstraints": { - "organizations_test_pkey_key": { - "name": "organizations_test_pkey_key", - "nullsNotDistinct": false, - "columns": [ - "test_pkey" - ] - }, - "organizations_live_pkey_key": { - "name": "organizations_live_pkey_key", - "nullsNotDistinct": false, - "columns": [ - "live_pkey" - ] - } - }, - "policies": {}, - "checkConstraints": {}, - "isRLSEnabled": false - }, - "public.prices": { - "name": "prices", - "schema": "", - "columns": { - "id": { - "name": "id", - "type": "text COLLATE \"C\"", - "primaryKey": true, - "notNull": true - }, - "org_id": { - "name": "org_id", - "type": "text", - "primaryKey": false, - "notNull": true - }, - "internal_product_id": { - "name": "internal_product_id", - "type": "text", - "primaryKey": false, - "notNull": true - }, - "config": { - "name": "config", - "type": "jsonb", - "primaryKey": false, - "notNull": false - }, - "created_at": { - "name": "created_at", - "type": "numeric", - "primaryKey": false, - "notNull": true - }, - "billing_type": { - "name": "billing_type", - "type": "text", - "primaryKey": false, - "notNull": false - }, - "is_custom": { - "name": "is_custom", - "type": "boolean", - "primaryKey": false, - "notNull": false, - "default": false - }, - "entitlement_id": { - "name": "entitlement_id", - "type": "text", - "primaryKey": false, - "notNull": false, - "default": "null" - } - }, - "indexes": {}, - "foreignKeys": { - "prices_entitlement_id_fkey": { - "name": "prices_entitlement_id_fkey", - "tableFrom": "prices", - "tableTo": "entitlements", - "columnsFrom": [ - "entitlement_id" - ], - "columnsTo": [ - "id" - ], - "onDelete": "no action", - "onUpdate": "no action" - }, - "prices_internal_product_id_fkey": { - "name": "prices_internal_product_id_fkey", - "tableFrom": "prices", - "tableTo": "products", - "columnsFrom": [ - "internal_product_id" - ], - "columnsTo": [ - "internal_id" - ], - "onDelete": "cascade", - "onUpdate": "cascade" - } - }, - "compositePrimaryKeys": {}, - "uniqueConstraints": { - "prices_id_key": { - "name": "prices_id_key", - "nullsNotDistinct": false, - "columns": [ - "id" - ] - } - }, - "policies": {}, - "checkConstraints": {}, - "isRLSEnabled": false - }, - "public.products": { - "name": "products", - "schema": "", - "columns": { - "internal_id": { - "name": "internal_id", - "type": "text COLLATE \"C\"", - "primaryKey": true, - "notNull": true - }, - "id": { - "name": "id", - "type": "text", - "primaryKey": false, - "notNull": true - }, - "name": { - "name": "name", - "type": "text", - "primaryKey": false, - "notNull": false - }, - "org_id": { - "name": "org_id", - "type": "text", - "primaryKey": false, - "notNull": true - }, - "created_at": { - "name": "created_at", - "type": "numeric", - "primaryKey": false, - "notNull": true, - "default": "ROUND(date_part('epoch', NOW()) * 1000)::BIGINT" - }, - "env": { - "name": "env", - "type": "text", - "primaryKey": false, - "notNull": true - }, - "is_add_on": { - "name": "is_add_on", - "type": "boolean", - "primaryKey": false, - "notNull": true, - "default": false - }, - "is_default": { - "name": "is_default", - "type": "boolean", - "primaryKey": false, - "notNull": true, - "default": false - }, - "group": { - "name": "group", - "type": "text", - "primaryKey": false, - "notNull": false, - "default": "''" - }, - "version": { - "name": "version", - "type": "numeric", - "primaryKey": false, - "notNull": true, - "default": 1 - }, - "processor": { - "name": "processor", - "type": "jsonb", - "primaryKey": false, - "notNull": false, - "default": "null" - } - }, - "indexes": {}, - "foreignKeys": { - "products_org_id_fkey": { - "name": "products_org_id_fkey", - "tableFrom": "products", - "tableTo": "organizations", - "columnsFrom": [ - "org_id" - ], - "columnsTo": [ - "id" - ], - "onDelete": "cascade", - "onUpdate": "no action" - } - }, - "compositePrimaryKeys": {}, - "uniqueConstraints": { - "unique_product": { - "name": "unique_product", - "nullsNotDistinct": false, - "columns": [ - "org_id", - "id", - "env", - "version" - ] - } - }, - "policies": {}, - "checkConstraints": {}, - "isRLSEnabled": false - }, - "public.referral_codes": { - "name": "referral_codes", - "schema": "", - "columns": { - "code": { - "name": "code", - "type": "text", - "primaryKey": false, - "notNull": true - }, - "org_id": { - "name": "org_id", - "type": "text", - "primaryKey": false, - "notNull": true - }, - "env": { - "name": "env", - "type": "text", - "primaryKey": false, - "notNull": true - }, - "internal_customer_id": { - "name": "internal_customer_id", - "type": "text", - "primaryKey": false, - "notNull": false - }, - "internal_reward_program_id": { - "name": "internal_reward_program_id", - "type": "text", - "primaryKey": false, - "notNull": false - }, - "id": { - "name": "id", - "type": "text", - "primaryKey": false, - "notNull": true - }, - "created_at": { - "name": "created_at", - "type": "numeric", - "primaryKey": false, - "notNull": false - } - }, - "indexes": {}, - "foreignKeys": { - "referral_codes_internal_customer_id_fkey": { - "name": "referral_codes_internal_customer_id_fkey", - "tableFrom": "referral_codes", - "tableTo": "customers", - "columnsFrom": [ - "internal_customer_id" - ], - "columnsTo": [ - "internal_id" - ], - "onDelete": "cascade", - "onUpdate": "no action" - }, - "referral_codes_internal_reward_program_id_fkey": { - "name": "referral_codes_internal_reward_program_id_fkey", - "tableFrom": "referral_codes", - "tableTo": "reward_programs", - "columnsFrom": [ - "internal_reward_program_id" - ], - "columnsTo": [ - "internal_id" - ], - "onDelete": "cascade", - "onUpdate": "no action" - }, - "referral_codes_org_id_fkey": { - "name": "referral_codes_org_id_fkey", - "tableFrom": "referral_codes", - "tableTo": "organizations", - "columnsFrom": [ - "org_id" - ], - "columnsTo": [ - "id" - ], - "onDelete": "cascade", - "onUpdate": "no action" - } - }, - "compositePrimaryKeys": { - "referral_codes_pkey": { - "name": "referral_codes_pkey", - "columns": [ - "code", - "org_id", - "env" - ] - } - }, - "uniqueConstraints": { - "referral_codes_id_key": { - "name": "referral_codes_id_key", - "nullsNotDistinct": false, - "columns": [ - "id" - ] - } - }, - "policies": {}, - "checkConstraints": {}, - "isRLSEnabled": false - }, - "public.reward_programs": { - "name": "reward_programs", - "schema": "", - "columns": { - "internal_id": { - "name": "internal_id", - "type": "text", - "primaryKey": true, - "notNull": true - }, - "id": { - "name": "id", - "type": "text", - "primaryKey": false, - "notNull": false - }, - "created_at": { - "name": "created_at", - "type": "numeric", - "primaryKey": false, - "notNull": false - }, - "internal_reward_id": { - "name": "internal_reward_id", - "type": "text", - "primaryKey": false, - "notNull": false - }, - "max_redemptions": { - "name": "max_redemptions", - "type": "numeric", - "primaryKey": false, - "notNull": false - }, - "unlimited_redemptions": { - "name": "unlimited_redemptions", - "type": "boolean", - "primaryKey": false, - "notNull": false, - "default": false - }, - "org_id": { - "name": "org_id", - "type": "text", - "primaryKey": false, - "notNull": false - }, - "env": { - "name": "env", - "type": "text", - "primaryKey": false, - "notNull": false - }, - "when": { - "name": "when", - "type": "text", - "primaryKey": false, - "notNull": false, - "default": "'immediately'" - }, - "product_ids": { - "name": "product_ids", - "type": "text[]", - "primaryKey": false, - "notNull": false, - "default": "'{\"\"}'" - }, - "exclude_trial": { - "name": "exclude_trial", - "type": "boolean", - "primaryKey": false, - "notNull": false, - "default": false - }, - "received_by": { - "name": "received_by", - "type": "text", - "primaryKey": false, - "notNull": false - } - }, - "indexes": {}, - "foreignKeys": { - "reward_triggers_internal_reward_id_fkey": { - "name": "reward_triggers_internal_reward_id_fkey", - "tableFrom": "reward_programs", - "tableTo": "rewards", - "columnsFrom": [ - "internal_reward_id" - ], - "columnsTo": [ - "internal_id" - ], - "onDelete": "cascade", - "onUpdate": "no action" - }, - "reward_triggers_org_id_fkey": { - "name": "reward_triggers_org_id_fkey", - "tableFrom": "reward_programs", - "tableTo": "organizations", - "columnsFrom": [ - "org_id" - ], - "columnsTo": [ - "id" - ], - "onDelete": "cascade", - "onUpdate": "no action" - } - }, - "compositePrimaryKeys": {}, - "uniqueConstraints": {}, - "policies": {}, - "checkConstraints": {}, - "isRLSEnabled": false - }, - "public.reward_redemptions": { - "name": "reward_redemptions", - "schema": "", - "columns": { - "id": { - "name": "id", - "type": "text", - "primaryKey": true, - "notNull": true - }, - "created_at": { - "name": "created_at", - "type": "numeric", - "primaryKey": false, - "notNull": false - }, - "updated_at": { - "name": "updated_at", - "type": "numeric", - "primaryKey": false, - "notNull": false - }, - "internal_customer_id": { - "name": "internal_customer_id", - "type": "text", - "primaryKey": false, - "notNull": false - }, - "triggered": { - "name": "triggered", - "type": "boolean", - "primaryKey": false, - "notNull": false - }, - "internal_reward_program_id": { - "name": "internal_reward_program_id", - "type": "text", - "primaryKey": false, - "notNull": false - }, - "applied": { - "name": "applied", - "type": "boolean", - "primaryKey": false, - "notNull": false, - "default": false - }, - "referral_code_id": { - "name": "referral_code_id", - "type": "text", - "primaryKey": false, - "notNull": false - } - }, - "indexes": {}, - "foreignKeys": { - "reward_redemptions_internal_customer_id_fkey": { - "name": "reward_redemptions_internal_customer_id_fkey", - "tableFrom": "reward_redemptions", - "tableTo": "customers", - "columnsFrom": [ - "internal_customer_id" - ], - "columnsTo": [ - "internal_id" - ], - "onDelete": "cascade", - "onUpdate": "no action" - }, - "reward_redemptions_internal_reward_program_id_fkey": { - "name": "reward_redemptions_internal_reward_program_id_fkey", - "tableFrom": "reward_redemptions", - "tableTo": "reward_programs", - "columnsFrom": [ - "internal_reward_program_id" - ], - "columnsTo": [ - "internal_id" - ], - "onDelete": "cascade", - "onUpdate": "no action" - }, - "reward_redemptions_referral_code_id_fkey": { - "name": "reward_redemptions_referral_code_id_fkey", - "tableFrom": "reward_redemptions", - "tableTo": "referral_codes", - "columnsFrom": [ - "referral_code_id" - ], - "columnsTo": [ - "id" - ], - "onDelete": "cascade", - "onUpdate": "no action" - } - }, - "compositePrimaryKeys": {}, - "uniqueConstraints": {}, - "policies": {}, - "checkConstraints": {}, - "isRLSEnabled": false - }, - "public.rewards": { - "name": "rewards", - "schema": "", - "columns": { - "internal_id": { - "name": "internal_id", - "type": "text", - "primaryKey": true, - "notNull": true - }, - "id": { - "name": "id", - "type": "text", - "primaryKey": false, - "notNull": false - }, - "org_id": { - "name": "org_id", - "type": "text", - "primaryKey": false, - "notNull": false - }, - "env": { - "name": "env", - "type": "text", - "primaryKey": false, - "notNull": false - }, - "created_at": { - "name": "created_at", - "type": "numeric", - "primaryKey": false, - "notNull": false - }, - "name": { - "name": "name", - "type": "text", - "primaryKey": false, - "notNull": false - }, - "discount_config": { - "name": "discount_config", - "type": "jsonb", - "primaryKey": false, - "notNull": false - }, - "free_product_id": { - "name": "free_product_id", - "type": "text", - "primaryKey": false, - "notNull": false - }, - "promo_codes": { - "name": "promo_codes", - "type": "jsonb[]", - "primaryKey": false, - "notNull": false - }, - "type": { - "name": "type", - "type": "text", - "primaryKey": false, - "notNull": false - } - }, - "indexes": {}, - "foreignKeys": { - "coupons_org_id_fkey": { - "name": "coupons_org_id_fkey", - "tableFrom": "rewards", - "tableTo": "organizations", - "columnsFrom": [ - "org_id" - ], - "columnsTo": [ - "id" - ], - "onDelete": "cascade", - "onUpdate": "no action" - } - }, - "compositePrimaryKeys": {}, - "uniqueConstraints": {}, - "policies": {}, - "checkConstraints": {}, - "isRLSEnabled": false - }, - "public.subscriptions": { - "name": "subscriptions", - "schema": "", - "columns": { - "id": { - "name": "id", - "type": "text", - "primaryKey": true, - "notNull": true - }, - "org_id": { - "name": "org_id", - "type": "text", - "primaryKey": false, - "notNull": true - }, - "stripe_id": { - "name": "stripe_id", - "type": "text", - "primaryKey": false, - "notNull": false - }, - "stripe_schedule_id": { - "name": "stripe_schedule_id", - "type": "text", - "primaryKey": false, - "notNull": false - }, - "created_at": { - "name": "created_at", - "type": "numeric", - "primaryKey": false, - "notNull": true, - "default": "ROUND(date_part('epoch', NOW()) * 1000)::BIGINT" - }, - "metadata": { - "name": "metadata", - "type": "jsonb", - "primaryKey": false, - "notNull": false, - "default": "'{}'::jsonb" - }, - "usage_features": { - "name": "usage_features", - "type": "text[]", - "primaryKey": false, - "notNull": false, - "default": "'{}'" - }, - "env": { - "name": "env", - "type": "text", - "primaryKey": false, - "notNull": false - }, - "current_period_start": { - "name": "current_period_start", - "type": "numeric", - "primaryKey": false, - "notNull": false - }, - "current_period_end": { - "name": "current_period_end", - "type": "numeric", - "primaryKey": false, - "notNull": false - } - }, - "indexes": {}, - "foreignKeys": { - "subscriptions_org_id_fkey": { - "name": "subscriptions_org_id_fkey", - "tableFrom": "subscriptions", - "tableTo": "organizations", - "columnsFrom": [ - "org_id" - ], - "columnsTo": [ - "id" - ], - "onDelete": "cascade", - "onUpdate": "no action" - } - }, - "compositePrimaryKeys": {}, - "uniqueConstraints": { - "subscriptions_stripe_id_key": { - "name": "subscriptions_stripe_id_key", - "nullsNotDistinct": false, - "columns": [ - "stripe_id" - ] - } - }, - "policies": {}, - "checkConstraints": {}, - "isRLSEnabled": false - } - }, - "enums": {}, - "schemas": {}, - "sequences": {}, - "roles": {}, - "policies": {}, - "views": {}, - "_meta": { - "columns": {}, - "schemas": {}, - "tables": {} - } -} \ No newline at end of file diff --git a/shared/drizzle/meta/0002_snapshot.json b/shared/drizzle/meta/0002_snapshot.json deleted file mode 100644 index c45b21882..000000000 --- a/shared/drizzle/meta/0002_snapshot.json +++ /dev/null @@ -1,2506 +0,0 @@ -{ - "id": "bd68ad51-9560-4872-aa55-3fe710632cb2", - "prevId": "f1f27d42-50b5-4ec1-8b42-8a2607dc15ed", - "version": "7", - "dialect": "postgresql", - "tables": { - "public.actions": { - "name": "actions", - "schema": "", - "columns": { - "id": { - "name": "id", - "type": "text COLLATE \"C\"", - "primaryKey": true, - "notNull": true - }, - "request_id": { - "name": "request_id", - "type": "text", - "primaryKey": false, - "notNull": true - }, - "org_id": { - "name": "org_id", - "type": "text", - "primaryKey": false, - "notNull": true - }, - "org_slug": { - "name": "org_slug", - "type": "text", - "primaryKey": false, - "notNull": true - }, - "env": { - "name": "env", - "type": "text", - "primaryKey": false, - "notNull": true - }, - "customer_id": { - "name": "customer_id", - "type": "text", - "primaryKey": false, - "notNull": false - }, - "internal_customer_id": { - "name": "internal_customer_id", - "type": "text", - "primaryKey": false, - "notNull": false - }, - "entity_id": { - "name": "entity_id", - "type": "text", - "primaryKey": false, - "notNull": false - }, - "internal_entity_id": { - "name": "internal_entity_id", - "type": "text", - "primaryKey": false, - "notNull": false - }, - "type": { - "name": "type", - "type": "text", - "primaryKey": false, - "notNull": true - }, - "auth_type": { - "name": "auth_type", - "type": "text", - "primaryKey": false, - "notNull": true - }, - "method": { - "name": "method", - "type": "text", - "primaryKey": false, - "notNull": true - }, - "path": { - "name": "path", - "type": "text", - "primaryKey": false, - "notNull": true - }, - "timestamp": { - "name": "timestamp", - "type": "timestamp with time zone", - "primaryKey": false, - "notNull": true, - "default": "now()" - }, - "properties": { - "name": "properties", - "type": "jsonb", - "primaryKey": false, - "notNull": false - } - }, - "indexes": {}, - "foreignKeys": { - "actions_org_id_fkey": { - "name": "actions_org_id_fkey", - "tableFrom": "actions", - "tableTo": "organizations", - "columnsFrom": [ - "org_id" - ], - "columnsTo": [ - "id" - ], - "onDelete": "set null", - "onUpdate": "no action" - }, - "actions_customer_id_fkey": { - "name": "actions_customer_id_fkey", - "tableFrom": "actions", - "tableTo": "customers", - "columnsFrom": [ - "internal_customer_id" - ], - "columnsTo": [ - "internal_id" - ], - "onDelete": "set null", - "onUpdate": "no action" - }, - "actions_entity_id_fkey": { - "name": "actions_entity_id_fkey", - "tableFrom": "actions", - "tableTo": "entities", - "columnsFrom": [ - "internal_entity_id" - ], - "columnsTo": [ - "internal_id" - ], - "onDelete": "set null", - "onUpdate": "no action" - } - }, - "compositePrimaryKeys": {}, - "uniqueConstraints": {}, - "policies": {}, - "checkConstraints": {}, - "isRLSEnabled": true - }, - "public.api_keys": { - "name": "api_keys", - "schema": "", - "columns": { - "id": { - "name": "id", - "type": "text COLLATE \"C\"", - "primaryKey": true, - "notNull": true - }, - "created_at": { - "name": "created_at", - "type": "numeric", - "primaryKey": false, - "notNull": true, - "default": "ROUND(date_part('epoch', NOW()) * 1000)::BIGINT" - }, - "name": { - "name": "name", - "type": "text", - "primaryKey": false, - "notNull": false - }, - "prefix": { - "name": "prefix", - "type": "text", - "primaryKey": false, - "notNull": false - }, - "org_id": { - "name": "org_id", - "type": "text", - "primaryKey": false, - "notNull": false - }, - "user_id": { - "name": "user_id", - "type": "text", - "primaryKey": false, - "notNull": false - }, - "env": { - "name": "env", - "type": "text", - "primaryKey": false, - "notNull": false - }, - "hashed_key": { - "name": "hashed_key", - "type": "text", - "primaryKey": false, - "notNull": false - }, - "meta": { - "name": "meta", - "type": "jsonb", - "primaryKey": false, - "notNull": false - } - }, - "indexes": {}, - "foreignKeys": { - "api_keys_org_id_fkey": { - "name": "api_keys_org_id_fkey", - "tableFrom": "api_keys", - "tableTo": "organizations", - "columnsFrom": [ - "org_id" - ], - "columnsTo": [ - "id" - ], - "onDelete": "cascade", - "onUpdate": "no action" - } - }, - "compositePrimaryKeys": {}, - "uniqueConstraints": { - "api_keys_hashed_key_key": { - "name": "api_keys_hashed_key_key", - "nullsNotDistinct": false, - "columns": [ - "hashed_key" - ] - } - }, - "policies": {}, - "checkConstraints": {}, - "isRLSEnabled": false - }, - "public.chat_results": { - "name": "chat_results", - "schema": "", - "columns": { - "id": { - "name": "id", - "type": "text COLLATE \"C\"", - "primaryKey": true, - "notNull": true - }, - "created_at": { - "name": "created_at", - "type": "numeric", - "primaryKey": false, - "notNull": false - }, - "data": { - "name": "data", - "type": "jsonb", - "primaryKey": false, - "notNull": true - } - }, - "indexes": {}, - "foreignKeys": {}, - "compositePrimaryKeys": {}, - "uniqueConstraints": {}, - "policies": {}, - "checkConstraints": {}, - "isRLSEnabled": true - }, - "public.customer_entitlements": { - "name": "customer_entitlements", - "schema": "", - "columns": { - "id": { - "name": "id", - "type": "text COLLATE \"C\"", - "primaryKey": true, - "notNull": true - }, - "customer_product_id": { - "name": "customer_product_id", - "type": "text", - "primaryKey": false, - "notNull": true - }, - "entitlement_id": { - "name": "entitlement_id", - "type": "text", - "primaryKey": false, - "notNull": true - }, - "internal_customer_id": { - "name": "internal_customer_id", - "type": "text", - "primaryKey": false, - "notNull": true - }, - "internal_feature_id": { - "name": "internal_feature_id", - "type": "text", - "primaryKey": false, - "notNull": true - }, - "unlimited": { - "name": "unlimited", - "type": "boolean", - "primaryKey": false, - "notNull": false, - "default": false - }, - "balance": { - "name": "balance", - "type": "numeric", - "primaryKey": false, - "notNull": true, - "default": 0 - }, - "created_at": { - "name": "created_at", - "type": "numeric", - "primaryKey": false, - "notNull": true - }, - "next_reset_at": { - "name": "next_reset_at", - "type": "numeric", - "primaryKey": false, - "notNull": false - }, - "usage_allowed": { - "name": "usage_allowed", - "type": "boolean", - "primaryKey": false, - "notNull": false, - "default": false - }, - "adjustment": { - "name": "adjustment", - "type": "numeric", - "primaryKey": false, - "notNull": false - }, - "entities": { - "name": "entities", - "type": "jsonb", - "primaryKey": false, - "notNull": false - }, - "customer_id": { - "name": "customer_id", - "type": "text", - "primaryKey": false, - "notNull": false - }, - "feature_id": { - "name": "feature_id", - "type": "text", - "primaryKey": false, - "notNull": false - } - }, - "indexes": {}, - "foreignKeys": { - "entitlements_internal_feature_id_fkey": { - "name": "entitlements_internal_feature_id_fkey", - "tableFrom": "customer_entitlements", - "tableTo": "features", - "columnsFrom": [ - "internal_feature_id" - ], - "columnsTo": [ - "internal_id" - ], - "onDelete": "cascade", - "onUpdate": "no action" - }, - "customer_entitlements_customer_product_id_fkey": { - "name": "customer_entitlements_customer_product_id_fkey", - "tableFrom": "customer_entitlements", - "tableTo": "customer_products", - "columnsFrom": [ - "customer_product_id" - ], - "columnsTo": [ - "id" - ], - "onDelete": "cascade", - "onUpdate": "cascade" - } - }, - "compositePrimaryKeys": {}, - "uniqueConstraints": { - "entitlements_id_key": { - "name": "entitlements_id_key", - "nullsNotDistinct": false, - "columns": [ - "id" - ] - } - }, - "policies": {}, - "checkConstraints": {}, - "isRLSEnabled": false - }, - "public.customer_prices": { - "name": "customer_prices", - "schema": "", - "columns": { - "id": { - "name": "id", - "type": "text", - "primaryKey": true, - "notNull": true - }, - "created_at": { - "name": "created_at", - "type": "numeric", - "primaryKey": false, - "notNull": true - }, - "price_id": { - "name": "price_id", - "type": "text", - "primaryKey": false, - "notNull": false - }, - "options": { - "name": "options", - "type": "jsonb", - "primaryKey": false, - "notNull": false - }, - "internal_customer_id": { - "name": "internal_customer_id", - "type": "text", - "primaryKey": false, - "notNull": false - }, - "customer_product_id": { - "name": "customer_product_id", - "type": "text", - "primaryKey": false, - "notNull": false - } - }, - "indexes": {}, - "foreignKeys": { - "customer_prices_customer_product_id_fkey": { - "name": "customer_prices_customer_product_id_fkey", - "tableFrom": "customer_prices", - "tableTo": "customer_products", - "columnsFrom": [ - "customer_product_id" - ], - "columnsTo": [ - "id" - ], - "onDelete": "cascade", - "onUpdate": "no action" - }, - "customer_prices_internal_customer_id_fkey": { - "name": "customer_prices_internal_customer_id_fkey", - "tableFrom": "customer_prices", - "tableTo": "customers", - "columnsFrom": [ - "internal_customer_id" - ], - "columnsTo": [ - "internal_id" - ], - "onDelete": "cascade", - "onUpdate": "no action" - }, - "customer_prices_price_id_fkey": { - "name": "customer_prices_price_id_fkey", - "tableFrom": "customer_prices", - "tableTo": "prices", - "columnsFrom": [ - "price_id" - ], - "columnsTo": [ - "id" - ], - "onDelete": "no action", - "onUpdate": "no action" - } - }, - "compositePrimaryKeys": {}, - "uniqueConstraints": {}, - "policies": {}, - "checkConstraints": {}, - "isRLSEnabled": false - }, - "public.customer_products": { - "name": "customer_products", - "schema": "", - "columns": { - "id": { - "name": "id", - "type": "text COLLATE \"C\"", - "primaryKey": true, - "notNull": true - }, - "internal_customer_id": { - "name": "internal_customer_id", - "type": "text", - "primaryKey": false, - "notNull": true - }, - "internal_product_id": { - "name": "internal_product_id", - "type": "text", - "primaryKey": false, - "notNull": true - }, - "internal_entity_id": { - "name": "internal_entity_id", - "type": "text", - "primaryKey": false, - "notNull": false - }, - "created_at": { - "name": "created_at", - "type": "numeric", - "primaryKey": false, - "notNull": false - }, - "status": { - "name": "status", - "type": "text", - "primaryKey": false, - "notNull": false - }, - "processor": { - "name": "processor", - "type": "jsonb", - "primaryKey": false, - "notNull": false - }, - "canceled_at": { - "name": "canceled_at", - "type": "numeric", - "primaryKey": false, - "notNull": false - }, - "ended_at": { - "name": "ended_at", - "type": "numeric", - "primaryKey": false, - "notNull": false - }, - "starts_at": { - "name": "starts_at", - "type": "numeric", - "primaryKey": false, - "notNull": false - }, - "options": { - "name": "options", - "type": "jsonb[]", - "primaryKey": false, - "notNull": false - }, - "product_id": { - "name": "product_id", - "type": "text", - "primaryKey": false, - "notNull": false - }, - "free_trial_id": { - "name": "free_trial_id", - "type": "text", - "primaryKey": false, - "notNull": false - }, - "trial_ends_at": { - "name": "trial_ends_at", - "type": "numeric", - "primaryKey": false, - "notNull": false - }, - "collection_method": { - "name": "collection_method", - "type": "text", - "primaryKey": false, - "notNull": false, - "default": "'charge_automatically'" - }, - "subscription_ids": { - "name": "subscription_ids", - "type": "text[]", - "primaryKey": false, - "notNull": false - }, - "scheduled_ids": { - "name": "scheduled_ids", - "type": "text[]", - "primaryKey": false, - "notNull": false - }, - "quantity": { - "name": "quantity", - "type": "numeric", - "primaryKey": false, - "notNull": false, - "default": 1 - }, - "is_custom": { - "name": "is_custom", - "type": "boolean", - "primaryKey": false, - "notNull": true, - "default": false - }, - "customer_id": { - "name": "customer_id", - "type": "text", - "primaryKey": false, - "notNull": false - }, - "entity_id": { - "name": "entity_id", - "type": "text", - "primaryKey": false, - "notNull": false - } - }, - "indexes": {}, - "foreignKeys": { - "customer_products_free_trial_id_fkey": { - "name": "customer_products_free_trial_id_fkey", - "tableFrom": "customer_products", - "tableTo": "free_trials", - "columnsFrom": [ - "free_trial_id" - ], - "columnsTo": [ - "id" - ], - "onDelete": "no action", - "onUpdate": "no action" - }, - "customer_products_internal_customer_id_fkey": { - "name": "customer_products_internal_customer_id_fkey", - "tableFrom": "customer_products", - "tableTo": "customers", - "columnsFrom": [ - "internal_customer_id" - ], - "columnsTo": [ - "internal_id" - ], - "onDelete": "cascade", - "onUpdate": "cascade" - }, - "customer_products_internal_product_id_fkey": { - "name": "customer_products_internal_product_id_fkey", - "tableFrom": "customer_products", - "tableTo": "products", - "columnsFrom": [ - "internal_product_id" - ], - "columnsTo": [ - "internal_id" - ], - "onDelete": "no action", - "onUpdate": "no action" - }, - "customer_products_internal_entity_id_fkey": { - "name": "customer_products_internal_entity_id_fkey", - "tableFrom": "customer_products", - "tableTo": "entities", - "columnsFrom": [ - "internal_entity_id" - ], - "columnsTo": [ - "internal_id" - ], - "onDelete": "set null", - "onUpdate": "no action" - } - }, - "compositePrimaryKeys": {}, - "uniqueConstraints": {}, - "policies": {}, - "checkConstraints": {}, - "isRLSEnabled": false - }, - "public.customers": { - "name": "customers", - "schema": "", - "columns": { - "internal_id": { - "name": "internal_id", - "type": "text COLLATE \"C\"", - "primaryKey": true, - "notNull": true - }, - "org_id": { - "name": "org_id", - "type": "text", - "primaryKey": false, - "notNull": true - }, - "created_at": { - "name": "created_at", - "type": "numeric", - "primaryKey": false, - "notNull": true - }, - "name": { - "name": "name", - "type": "text", - "primaryKey": false, - "notNull": false - }, - "id": { - "name": "id", - "type": "text", - "primaryKey": false, - "notNull": false - }, - "email": { - "name": "email", - "type": "text", - "primaryKey": false, - "notNull": false - }, - "fingerprint": { - "name": "fingerprint", - "type": "text", - "primaryKey": false, - "notNull": false, - "default": "null" - }, - "metadata": { - "name": "metadata", - "type": "jsonb", - "primaryKey": false, - "notNull": false - }, - "env": { - "name": "env", - "type": "text", - "primaryKey": false, - "notNull": true - }, - "processor": { - "name": "processor", - "type": "jsonb", - "primaryKey": false, - "notNull": false - } - }, - "indexes": {}, - "foreignKeys": { - "customers_org_id_fkey": { - "name": "customers_org_id_fkey", - "tableFrom": "customers", - "tableTo": "organizations", - "columnsFrom": [ - "org_id" - ], - "columnsTo": [ - "id" - ], - "onDelete": "cascade", - "onUpdate": "no action" - } - }, - "compositePrimaryKeys": {}, - "uniqueConstraints": { - "cus_id_constraint": { - "name": "cus_id_constraint", - "nullsNotDistinct": false, - "columns": [ - "org_id", - "id", - "env" - ] - } - }, - "policies": {}, - "checkConstraints": {}, - "isRLSEnabled": true - }, - "public.entities": { - "name": "entities", - "schema": "", - "columns": { - "id": { - "name": "id", - "type": "text", - "primaryKey": false, - "notNull": false - }, - "org_id": { - "name": "org_id", - "type": "text", - "primaryKey": false, - "notNull": false - }, - "created_at": { - "name": "created_at", - "type": "numeric", - "primaryKey": false, - "notNull": true - }, - "internal_id": { - "name": "internal_id", - "type": "text", - "primaryKey": true, - "notNull": true - }, - "internal_customer_id": { - "name": "internal_customer_id", - "type": "text", - "primaryKey": false, - "notNull": true - }, - "env": { - "name": "env", - "type": "text", - "primaryKey": false, - "notNull": false - }, - "name": { - "name": "name", - "type": "text", - "primaryKey": false, - "notNull": false - }, - "deleted": { - "name": "deleted", - "type": "boolean", - "primaryKey": false, - "notNull": true, - "default": false - }, - "internal_feature_id": { - "name": "internal_feature_id", - "type": "text", - "primaryKey": false, - "notNull": false - }, - "feature_id": { - "name": "feature_id", - "type": "text", - "primaryKey": false, - "notNull": false - } - }, - "indexes": {}, - "foreignKeys": { - "entities_internal_customer_id_fkey": { - "name": "entities_internal_customer_id_fkey", - "tableFrom": "entities", - "tableTo": "customers", - "columnsFrom": [ - "internal_customer_id" - ], - "columnsTo": [ - "internal_id" - ], - "onDelete": "cascade", - "onUpdate": "no action" - }, - "entities_internal_feature_id_fkey": { - "name": "entities_internal_feature_id_fkey", - "tableFrom": "entities", - "tableTo": "features", - "columnsFrom": [ - "internal_feature_id" - ], - "columnsTo": [ - "internal_id" - ], - "onDelete": "cascade", - "onUpdate": "no action" - }, - "entities_org_id_fkey": { - "name": "entities_org_id_fkey", - "tableFrom": "entities", - "tableTo": "organizations", - "columnsFrom": [ - "org_id" - ], - "columnsTo": [ - "id" - ], - "onDelete": "cascade", - "onUpdate": "no action" - } - }, - "compositePrimaryKeys": {}, - "uniqueConstraints": { - "entity_id_constraint": { - "name": "entity_id_constraint", - "nullsNotDistinct": false, - "columns": [ - "org_id", - "env", - "internal_customer_id", - "id" - ] - } - }, - "policies": {}, - "checkConstraints": {}, - "isRLSEnabled": false - }, - "public.entitlements": { - "name": "entitlements", - "schema": "", - "columns": { - "id": { - "name": "id", - "type": "text COLLATE \"C\"", - "primaryKey": true, - "notNull": true - }, - "created_at": { - "name": "created_at", - "type": "numeric", - "primaryKey": false, - "notNull": true - }, - "internal_feature_id": { - "name": "internal_feature_id", - "type": "text", - "primaryKey": false, - "notNull": true - }, - "internal_product_id": { - "name": "internal_product_id", - "type": "text", - "primaryKey": false, - "notNull": true - }, - "is_custom": { - "name": "is_custom", - "type": "boolean", - "primaryKey": false, - "notNull": false, - "default": false - }, - "allowance_type": { - "name": "allowance_type", - "type": "text", - "primaryKey": false, - "notNull": false - }, - "allowance": { - "name": "allowance", - "type": "numeric", - "primaryKey": false, - "notNull": false - }, - "interval": { - "name": "interval", - "type": "text", - "primaryKey": false, - "notNull": false - }, - "carry_from_previous": { - "name": "carry_from_previous", - "type": "boolean", - "primaryKey": false, - "notNull": false, - "default": false - }, - "entity_feature_id": { - "name": "entity_feature_id", - "type": "text", - "primaryKey": false, - "notNull": false, - "default": "null" - }, - "org_id": { - "name": "org_id", - "type": "text", - "primaryKey": false, - "notNull": false - }, - "feature_id": { - "name": "feature_id", - "type": "text", - "primaryKey": false, - "notNull": false - } - }, - "indexes": {}, - "foreignKeys": { - "entitlements_internal_feature_id_fkey": { - "name": "entitlements_internal_feature_id_fkey", - "tableFrom": "entitlements", - "tableTo": "features", - "columnsFrom": [ - "internal_feature_id" - ], - "columnsTo": [ - "internal_id" - ], - "onDelete": "cascade", - "onUpdate": "no action" - }, - "entitlements_internal_product_id_fkey": { - "name": "entitlements_internal_product_id_fkey", - "tableFrom": "entitlements", - "tableTo": "products", - "columnsFrom": [ - "internal_product_id" - ], - "columnsTo": [ - "internal_id" - ], - "onDelete": "cascade", - "onUpdate": "cascade" - } - }, - "compositePrimaryKeys": {}, - "uniqueConstraints": { - "entitlements_id_key": { - "name": "entitlements_id_key", - "nullsNotDistinct": false, - "columns": [ - "id" - ] - } - }, - "policies": {}, - "checkConstraints": {}, - "isRLSEnabled": false - }, - "public.events": { - "name": "events", - "schema": "", - "columns": { - "id": { - "name": "id", - "type": "text", - "primaryKey": true, - "notNull": true - }, - "org_id": { - "name": "org_id", - "type": "text", - "primaryKey": false, - "notNull": true - }, - "internal_customer_id": { - "name": "internal_customer_id", - "type": "text", - "primaryKey": false, - "notNull": false - }, - "env": { - "name": "env", - "type": "text", - "primaryKey": false, - "notNull": true - }, - "created_at": { - "name": "created_at", - "type": "bigint", - "primaryKey": false, - "notNull": false - }, - "timestamp": { - "name": "timestamp", - "type": "numeric", - "primaryKey": false, - "notNull": false - }, - "event_name": { - "name": "event_name", - "type": "text", - "primaryKey": false, - "notNull": true - }, - "idempotency_key": { - "name": "idempotency_key", - "type": "text", - "primaryKey": false, - "notNull": false, - "default": "null" - }, - "value": { - "name": "value", - "type": "numeric", - "primaryKey": false, - "notNull": false - }, - "set_usage": { - "name": "set_usage", - "type": "boolean", - "primaryKey": false, - "notNull": false, - "default": false - }, - "entity_id": { - "name": "entity_id", - "type": "text", - "primaryKey": false, - "notNull": false - }, - "customer_id": { - "name": "customer_id", - "type": "text", - "primaryKey": false, - "notNull": true - }, - "properties": { - "name": "properties", - "type": "jsonb", - "primaryKey": false, - "notNull": false - } - }, - "indexes": {}, - "foreignKeys": { - "events_internal_customer_id_fkey": { - "name": "events_internal_customer_id_fkey", - "tableFrom": "events", - "tableTo": "customers", - "columnsFrom": [ - "internal_customer_id" - ], - "columnsTo": [ - "internal_id" - ], - "onDelete": "cascade", - "onUpdate": "no action" - } - }, - "compositePrimaryKeys": {}, - "uniqueConstraints": { - "unique_event_constraint": { - "name": "unique_event_constraint", - "nullsNotDistinct": false, - "columns": [ - "org_id", - "env", - "customer_id", - "event_name", - "idempotency_key" - ] - } - }, - "policies": {}, - "checkConstraints": {}, - "isRLSEnabled": false - }, - "public.features": { - "name": "features", - "schema": "", - "columns": { - "internal_id": { - "name": "internal_id", - "type": "text COLLATE \"C\"", - "primaryKey": true, - "notNull": true - }, - "org_id": { - "name": "org_id", - "type": "text", - "primaryKey": false, - "notNull": true - }, - "created_at": { - "name": "created_at", - "type": "numeric", - "primaryKey": false, - "notNull": false - }, - "env": { - "name": "env", - "type": "text", - "primaryKey": false, - "notNull": false - }, - "id": { - "name": "id", - "type": "text", - "primaryKey": false, - "notNull": true - }, - "name": { - "name": "name", - "type": "text", - "primaryKey": false, - "notNull": false - }, - "type": { - "name": "type", - "type": "text", - "primaryKey": false, - "notNull": true - }, - "config": { - "name": "config", - "type": "jsonb", - "primaryKey": false, - "notNull": false - }, - "display": { - "name": "display", - "type": "jsonb", - "primaryKey": false, - "notNull": false, - "default": "null" - } - }, - "indexes": {}, - "foreignKeys": { - "features_org_id_fkey": { - "name": "features_org_id_fkey", - "tableFrom": "features", - "tableTo": "organizations", - "columnsFrom": [ - "org_id" - ], - "columnsTo": [ - "id" - ], - "onDelete": "cascade", - "onUpdate": "no action" - } - }, - "compositePrimaryKeys": {}, - "uniqueConstraints": { - "feature_id_constraint": { - "name": "feature_id_constraint", - "nullsNotDistinct": false, - "columns": [ - "org_id", - "id", - "env" - ] - } - }, - "policies": {}, - "checkConstraints": {}, - "isRLSEnabled": false - }, - "public.free_trials": { - "name": "free_trials", - "schema": "", - "columns": { - "id": { - "name": "id", - "type": "text", - "primaryKey": true, - "notNull": true - }, - "created_at": { - "name": "created_at", - "type": "numeric", - "primaryKey": false, - "notNull": true - }, - "internal_product_id": { - "name": "internal_product_id", - "type": "text", - "primaryKey": false, - "notNull": false - }, - "duration": { - "name": "duration", - "type": "text", - "primaryKey": false, - "notNull": false, - "default": "'day'" - }, - "length": { - "name": "length", - "type": "numeric", - "primaryKey": false, - "notNull": false - }, - "unique_fingerprint": { - "name": "unique_fingerprint", - "type": "boolean", - "primaryKey": false, - "notNull": false - }, - "is_custom": { - "name": "is_custom", - "type": "boolean", - "primaryKey": false, - "notNull": false, - "default": false - } - }, - "indexes": {}, - "foreignKeys": { - "free_trials_internal_product_id_fkey": { - "name": "free_trials_internal_product_id_fkey", - "tableFrom": "free_trials", - "tableTo": "products", - "columnsFrom": [ - "internal_product_id" - ], - "columnsTo": [ - "internal_id" - ], - "onDelete": "cascade", - "onUpdate": "no action" - } - }, - "compositePrimaryKeys": {}, - "uniqueConstraints": {}, - "policies": {}, - "checkConstraints": {}, - "isRLSEnabled": false - }, - "public.invoices": { - "name": "invoices", - "schema": "", - "columns": { - "id": { - "name": "id", - "type": "text COLLATE \"C\"", - "primaryKey": true, - "notNull": true - }, - "created_at": { - "name": "created_at", - "type": "numeric", - "primaryKey": false, - "notNull": true, - "default": "ROUND(date_part('epoch', NOW()) * 1000)::BIGINT" - }, - "product_ids": { - "name": "product_ids", - "type": "text[]", - "primaryKey": false, - "notNull": false, - "default": "'{}'" - }, - "internal_product_ids": { - "name": "internal_product_ids", - "type": "text[]", - "primaryKey": false, - "notNull": false, - "default": "'{}'" - }, - "internal_customer_id": { - "name": "internal_customer_id", - "type": "text", - "primaryKey": false, - "notNull": true - }, - "internal_entity_id": { - "name": "internal_entity_id", - "type": "text", - "primaryKey": false, - "notNull": false - }, - "stripe_id": { - "name": "stripe_id", - "type": "text", - "primaryKey": false, - "notNull": true - }, - "status": { - "name": "status", - "type": "text", - "primaryKey": false, - "notNull": true, - "default": "'draft'" - }, - "hosted_invoice_url": { - "name": "hosted_invoice_url", - "type": "text", - "primaryKey": false, - "notNull": false - }, - "total": { - "name": "total", - "type": "numeric", - "primaryKey": false, - "notNull": true, - "default": 0 - }, - "currency": { - "name": "currency", - "type": "text", - "primaryKey": false, - "notNull": true, - "default": "'usd'" - }, - "discounts": { - "name": "discounts", - "type": "jsonb[]", - "primaryKey": false, - "notNull": false, - "default": "'{}'" - }, - "items": { - "name": "items", - "type": "jsonb[]", - "primaryKey": false, - "notNull": false, - "default": "'{}'" - } - }, - "indexes": {}, - "foreignKeys": { - "invoices_internal_customer_id_fkey": { - "name": "invoices_internal_customer_id_fkey", - "tableFrom": "invoices", - "tableTo": "customers", - "columnsFrom": [ - "internal_customer_id" - ], - "columnsTo": [ - "id" - ], - "onDelete": "no action", - "onUpdate": "no action" - }, - "invoices_internal_entity_id_fkey": { - "name": "invoices_internal_entity_id_fkey", - "tableFrom": "invoices", - "tableTo": "entities", - "columnsFrom": [ - "internal_entity_id" - ], - "columnsTo": [ - "id" - ], - "onDelete": "no action", - "onUpdate": "no action" - } - }, - "compositePrimaryKeys": {}, - "uniqueConstraints": {}, - "policies": {}, - "checkConstraints": {}, - "isRLSEnabled": false - }, - "public.metadata": { - "name": "metadata", - "schema": "", - "columns": { - "id": { - "name": "id", - "type": "text", - "primaryKey": true, - "notNull": true - }, - "created_at": { - "name": "created_at", - "type": "numeric", - "primaryKey": false, - "notNull": true, - "default": "ROUND(date_part('epoch', NOW()) * 1000)::BIGINT" - }, - "expires_at": { - "name": "expires_at", - "type": "numeric", - "primaryKey": false, - "notNull": false - }, - "data": { - "name": "data", - "type": "jsonb", - "primaryKey": false, - "notNull": false - } - }, - "indexes": {}, - "foreignKeys": {}, - "compositePrimaryKeys": {}, - "uniqueConstraints": {}, - "policies": {}, - "checkConstraints": {}, - "isRLSEnabled": false - }, - "public.migration_errors": { - "name": "migration_errors", - "schema": "", - "columns": { - "internal_customer_id": { - "name": "internal_customer_id", - "type": "text", - "primaryKey": false, - "notNull": true - }, - "migration_job_id": { - "name": "migration_job_id", - "type": "text", - "primaryKey": false, - "notNull": true - }, - "created_at": { - "name": "created_at", - "type": "numeric", - "primaryKey": false, - "notNull": false - }, - "updated_at": { - "name": "updated_at", - "type": "numeric", - "primaryKey": false, - "notNull": false - }, - "data": { - "name": "data", - "type": "jsonb", - "primaryKey": false, - "notNull": false - }, - "message": { - "name": "message", - "type": "text", - "primaryKey": false, - "notNull": false - }, - "code": { - "name": "code", - "type": "text", - "primaryKey": false, - "notNull": false - } - }, - "indexes": {}, - "foreignKeys": { - "migration_customers_internal_customer_id_fkey": { - "name": "migration_customers_internal_customer_id_fkey", - "tableFrom": "migration_errors", - "tableTo": "customers", - "columnsFrom": [ - "internal_customer_id" - ], - "columnsTo": [ - "internal_id" - ], - "onDelete": "cascade", - "onUpdate": "no action" - }, - "migration_customers_migration_job_id_fkey": { - "name": "migration_customers_migration_job_id_fkey", - "tableFrom": "migration_errors", - "tableTo": "migration_jobs", - "columnsFrom": [ - "migration_job_id" - ], - "columnsTo": [ - "id" - ], - "onDelete": "cascade", - "onUpdate": "no action" - } - }, - "compositePrimaryKeys": { - "migration_errors_pkey": { - "name": "migration_errors_pkey", - "columns": [ - "internal_customer_id", - "migration_job_id" - ] - } - }, - "uniqueConstraints": {}, - "policies": {}, - "checkConstraints": {}, - "isRLSEnabled": false - }, - "public.migration_jobs": { - "name": "migration_jobs", - "schema": "", - "columns": { - "id": { - "name": "id", - "type": "text", - "primaryKey": true, - "notNull": true - }, - "org_id": { - "name": "org_id", - "type": "text", - "primaryKey": false, - "notNull": true - }, - "env": { - "name": "env", - "type": "text", - "primaryKey": false, - "notNull": true - }, - "created_at": { - "name": "created_at", - "type": "numeric", - "primaryKey": false, - "notNull": true - }, - "updated_at": { - "name": "updated_at", - "type": "numeric", - "primaryKey": false, - "notNull": false - }, - "current_step": { - "name": "current_step", - "type": "text", - "primaryKey": false, - "notNull": false - }, - "from_internal_product_id": { - "name": "from_internal_product_id", - "type": "text", - "primaryKey": false, - "notNull": false - }, - "to_internal_product_id": { - "name": "to_internal_product_id", - "type": "text", - "primaryKey": false, - "notNull": false - }, - "step_details": { - "name": "step_details", - "type": "jsonb", - "primaryKey": false, - "notNull": false - } - }, - "indexes": {}, - "foreignKeys": { - "migration_jobs_from_internal_product_id_fkey": { - "name": "migration_jobs_from_internal_product_id_fkey", - "tableFrom": "migration_jobs", - "tableTo": "products", - "columnsFrom": [ - "from_internal_product_id" - ], - "columnsTo": [ - "internal_id" - ], - "onDelete": "cascade", - "onUpdate": "no action" - }, - "migration_jobs_org_id_fkey": { - "name": "migration_jobs_org_id_fkey", - "tableFrom": "migration_jobs", - "tableTo": "organizations", - "columnsFrom": [ - "org_id" - ], - "columnsTo": [ - "id" - ], - "onDelete": "cascade", - "onUpdate": "no action" - }, - "migration_jobs_to_internal_product_id_fkey": { - "name": "migration_jobs_to_internal_product_id_fkey", - "tableFrom": "migration_jobs", - "tableTo": "products", - "columnsFrom": [ - "to_internal_product_id" - ], - "columnsTo": [ - "internal_id" - ], - "onDelete": "cascade", - "onUpdate": "no action" - } - }, - "compositePrimaryKeys": {}, - "uniqueConstraints": {}, - "policies": {}, - "checkConstraints": {}, - "isRLSEnabled": false - }, - "public.organizations": { - "name": "organizations", - "schema": "", - "columns": { - "id": { - "name": "id", - "type": "text", - "primaryKey": true, - "notNull": true - }, - "slug": { - "name": "slug", - "type": "text", - "primaryKey": false, - "notNull": true - }, - "default_currency": { - "name": "default_currency", - "type": "text", - "primaryKey": false, - "notNull": true, - "default": "'usd'" - }, - "stripe_connected": { - "name": "stripe_connected", - "type": "boolean", - "primaryKey": false, - "notNull": false, - "default": false - }, - "stripe_config": { - "name": "stripe_config", - "type": "jsonb", - "primaryKey": false, - "notNull": false - }, - "test_pkey": { - "name": "test_pkey", - "type": "text", - "primaryKey": false, - "notNull": false - }, - "live_pkey": { - "name": "live_pkey", - "type": "text", - "primaryKey": false, - "notNull": false - }, - "svix_config": { - "name": "svix_config", - "type": "jsonb", - "primaryKey": false, - "notNull": true - }, - "created_at": { - "name": "created_at", - "type": "numeric", - "primaryKey": false, - "notNull": false - }, - "config": { - "name": "config", - "type": "jsonb", - "primaryKey": false, - "notNull": true, - "default": "'{}'::jsonb" - } - }, - "indexes": {}, - "foreignKeys": {}, - "compositePrimaryKeys": {}, - "uniqueConstraints": { - "organizations_test_pkey_key": { - "name": "organizations_test_pkey_key", - "nullsNotDistinct": false, - "columns": [ - "test_pkey" - ] - }, - "organizations_live_pkey_key": { - "name": "organizations_live_pkey_key", - "nullsNotDistinct": false, - "columns": [ - "live_pkey" - ] - } - }, - "policies": {}, - "checkConstraints": {}, - "isRLSEnabled": false - }, - "public.prices": { - "name": "prices", - "schema": "", - "columns": { - "id": { - "name": "id", - "type": "text COLLATE \"C\"", - "primaryKey": true, - "notNull": true - }, - "org_id": { - "name": "org_id", - "type": "text", - "primaryKey": false, - "notNull": true - }, - "internal_product_id": { - "name": "internal_product_id", - "type": "text", - "primaryKey": false, - "notNull": true - }, - "config": { - "name": "config", - "type": "jsonb", - "primaryKey": false, - "notNull": false - }, - "created_at": { - "name": "created_at", - "type": "numeric", - "primaryKey": false, - "notNull": true - }, - "billing_type": { - "name": "billing_type", - "type": "text", - "primaryKey": false, - "notNull": false - }, - "is_custom": { - "name": "is_custom", - "type": "boolean", - "primaryKey": false, - "notNull": false, - "default": false - }, - "entitlement_id": { - "name": "entitlement_id", - "type": "text", - "primaryKey": false, - "notNull": false, - "default": "null" - } - }, - "indexes": {}, - "foreignKeys": { - "prices_entitlement_id_fkey": { - "name": "prices_entitlement_id_fkey", - "tableFrom": "prices", - "tableTo": "entitlements", - "columnsFrom": [ - "entitlement_id" - ], - "columnsTo": [ - "id" - ], - "onDelete": "no action", - "onUpdate": "no action" - }, - "prices_internal_product_id_fkey": { - "name": "prices_internal_product_id_fkey", - "tableFrom": "prices", - "tableTo": "products", - "columnsFrom": [ - "internal_product_id" - ], - "columnsTo": [ - "internal_id" - ], - "onDelete": "cascade", - "onUpdate": "cascade" - } - }, - "compositePrimaryKeys": {}, - "uniqueConstraints": { - "prices_id_key": { - "name": "prices_id_key", - "nullsNotDistinct": false, - "columns": [ - "id" - ] - } - }, - "policies": {}, - "checkConstraints": {}, - "isRLSEnabled": false - }, - "public.products": { - "name": "products", - "schema": "", - "columns": { - "internal_id": { - "name": "internal_id", - "type": "text COLLATE \"C\"", - "primaryKey": true, - "notNull": true - }, - "id": { - "name": "id", - "type": "text", - "primaryKey": false, - "notNull": true - }, - "name": { - "name": "name", - "type": "text", - "primaryKey": false, - "notNull": false - }, - "org_id": { - "name": "org_id", - "type": "text", - "primaryKey": false, - "notNull": true - }, - "created_at": { - "name": "created_at", - "type": "numeric", - "primaryKey": false, - "notNull": true, - "default": "ROUND(date_part('epoch', NOW()) * 1000)::BIGINT" - }, - "env": { - "name": "env", - "type": "text", - "primaryKey": false, - "notNull": true - }, - "is_add_on": { - "name": "is_add_on", - "type": "boolean", - "primaryKey": false, - "notNull": true, - "default": false - }, - "is_default": { - "name": "is_default", - "type": "boolean", - "primaryKey": false, - "notNull": true, - "default": false - }, - "group": { - "name": "group", - "type": "text", - "primaryKey": false, - "notNull": false, - "default": "''" - }, - "version": { - "name": "version", - "type": "numeric", - "primaryKey": false, - "notNull": true, - "default": 1 - }, - "processor": { - "name": "processor", - "type": "jsonb", - "primaryKey": false, - "notNull": false, - "default": "null" - } - }, - "indexes": {}, - "foreignKeys": { - "products_org_id_fkey": { - "name": "products_org_id_fkey", - "tableFrom": "products", - "tableTo": "organizations", - "columnsFrom": [ - "org_id" - ], - "columnsTo": [ - "id" - ], - "onDelete": "cascade", - "onUpdate": "no action" - } - }, - "compositePrimaryKeys": {}, - "uniqueConstraints": { - "unique_product": { - "name": "unique_product", - "nullsNotDistinct": false, - "columns": [ - "org_id", - "id", - "env", - "version" - ] - } - }, - "policies": {}, - "checkConstraints": {}, - "isRLSEnabled": false - }, - "public.referral_codes": { - "name": "referral_codes", - "schema": "", - "columns": { - "code": { - "name": "code", - "type": "text", - "primaryKey": false, - "notNull": true - }, - "org_id": { - "name": "org_id", - "type": "text", - "primaryKey": false, - "notNull": true - }, - "env": { - "name": "env", - "type": "text", - "primaryKey": false, - "notNull": true - }, - "internal_customer_id": { - "name": "internal_customer_id", - "type": "text", - "primaryKey": false, - "notNull": false - }, - "internal_reward_program_id": { - "name": "internal_reward_program_id", - "type": "text", - "primaryKey": false, - "notNull": false - }, - "id": { - "name": "id", - "type": "text", - "primaryKey": false, - "notNull": true - }, - "created_at": { - "name": "created_at", - "type": "numeric", - "primaryKey": false, - "notNull": false - } - }, - "indexes": {}, - "foreignKeys": { - "referral_codes_internal_customer_id_fkey": { - "name": "referral_codes_internal_customer_id_fkey", - "tableFrom": "referral_codes", - "tableTo": "customers", - "columnsFrom": [ - "internal_customer_id" - ], - "columnsTo": [ - "internal_id" - ], - "onDelete": "cascade", - "onUpdate": "no action" - }, - "referral_codes_internal_reward_program_id_fkey": { - "name": "referral_codes_internal_reward_program_id_fkey", - "tableFrom": "referral_codes", - "tableTo": "reward_programs", - "columnsFrom": [ - "internal_reward_program_id" - ], - "columnsTo": [ - "internal_id" - ], - "onDelete": "cascade", - "onUpdate": "no action" - }, - "referral_codes_org_id_fkey": { - "name": "referral_codes_org_id_fkey", - "tableFrom": "referral_codes", - "tableTo": "organizations", - "columnsFrom": [ - "org_id" - ], - "columnsTo": [ - "id" - ], - "onDelete": "cascade", - "onUpdate": "no action" - } - }, - "compositePrimaryKeys": { - "referral_codes_pkey": { - "name": "referral_codes_pkey", - "columns": [ - "code", - "org_id", - "env" - ] - } - }, - "uniqueConstraints": { - "referral_codes_id_key": { - "name": "referral_codes_id_key", - "nullsNotDistinct": false, - "columns": [ - "id" - ] - } - }, - "policies": {}, - "checkConstraints": {}, - "isRLSEnabled": false - }, - "public.reward_programs": { - "name": "reward_programs", - "schema": "", - "columns": { - "internal_id": { - "name": "internal_id", - "type": "text", - "primaryKey": true, - "notNull": true - }, - "id": { - "name": "id", - "type": "text", - "primaryKey": false, - "notNull": false - }, - "created_at": { - "name": "created_at", - "type": "numeric", - "primaryKey": false, - "notNull": false - }, - "internal_reward_id": { - "name": "internal_reward_id", - "type": "text", - "primaryKey": false, - "notNull": false - }, - "max_redemptions": { - "name": "max_redemptions", - "type": "numeric", - "primaryKey": false, - "notNull": false - }, - "unlimited_redemptions": { - "name": "unlimited_redemptions", - "type": "boolean", - "primaryKey": false, - "notNull": false, - "default": false - }, - "org_id": { - "name": "org_id", - "type": "text", - "primaryKey": false, - "notNull": false - }, - "env": { - "name": "env", - "type": "text", - "primaryKey": false, - "notNull": false - }, - "when": { - "name": "when", - "type": "text", - "primaryKey": false, - "notNull": false, - "default": "'immediately'" - }, - "product_ids": { - "name": "product_ids", - "type": "text[]", - "primaryKey": false, - "notNull": false, - "default": "'{\"\"}'" - }, - "exclude_trial": { - "name": "exclude_trial", - "type": "boolean", - "primaryKey": false, - "notNull": false, - "default": false - }, - "received_by": { - "name": "received_by", - "type": "text", - "primaryKey": false, - "notNull": false - } - }, - "indexes": {}, - "foreignKeys": { - "reward_triggers_internal_reward_id_fkey": { - "name": "reward_triggers_internal_reward_id_fkey", - "tableFrom": "reward_programs", - "tableTo": "rewards", - "columnsFrom": [ - "internal_reward_id" - ], - "columnsTo": [ - "internal_id" - ], - "onDelete": "cascade", - "onUpdate": "no action" - }, - "reward_triggers_org_id_fkey": { - "name": "reward_triggers_org_id_fkey", - "tableFrom": "reward_programs", - "tableTo": "organizations", - "columnsFrom": [ - "org_id" - ], - "columnsTo": [ - "id" - ], - "onDelete": "cascade", - "onUpdate": "no action" - } - }, - "compositePrimaryKeys": {}, - "uniqueConstraints": {}, - "policies": {}, - "checkConstraints": {}, - "isRLSEnabled": false - }, - "public.reward_redemptions": { - "name": "reward_redemptions", - "schema": "", - "columns": { - "id": { - "name": "id", - "type": "text", - "primaryKey": true, - "notNull": true - }, - "created_at": { - "name": "created_at", - "type": "numeric", - "primaryKey": false, - "notNull": false - }, - "updated_at": { - "name": "updated_at", - "type": "numeric", - "primaryKey": false, - "notNull": false - }, - "internal_customer_id": { - "name": "internal_customer_id", - "type": "text", - "primaryKey": false, - "notNull": false - }, - "triggered": { - "name": "triggered", - "type": "boolean", - "primaryKey": false, - "notNull": false - }, - "internal_reward_program_id": { - "name": "internal_reward_program_id", - "type": "text", - "primaryKey": false, - "notNull": false - }, - "applied": { - "name": "applied", - "type": "boolean", - "primaryKey": false, - "notNull": false, - "default": false - }, - "referral_code_id": { - "name": "referral_code_id", - "type": "text", - "primaryKey": false, - "notNull": false - } - }, - "indexes": {}, - "foreignKeys": { - "reward_redemptions_internal_customer_id_fkey": { - "name": "reward_redemptions_internal_customer_id_fkey", - "tableFrom": "reward_redemptions", - "tableTo": "customers", - "columnsFrom": [ - "internal_customer_id" - ], - "columnsTo": [ - "internal_id" - ], - "onDelete": "cascade", - "onUpdate": "no action" - }, - "reward_redemptions_internal_reward_program_id_fkey": { - "name": "reward_redemptions_internal_reward_program_id_fkey", - "tableFrom": "reward_redemptions", - "tableTo": "reward_programs", - "columnsFrom": [ - "internal_reward_program_id" - ], - "columnsTo": [ - "internal_id" - ], - "onDelete": "cascade", - "onUpdate": "no action" - }, - "reward_redemptions_referral_code_id_fkey": { - "name": "reward_redemptions_referral_code_id_fkey", - "tableFrom": "reward_redemptions", - "tableTo": "referral_codes", - "columnsFrom": [ - "referral_code_id" - ], - "columnsTo": [ - "id" - ], - "onDelete": "cascade", - "onUpdate": "no action" - } - }, - "compositePrimaryKeys": {}, - "uniqueConstraints": {}, - "policies": {}, - "checkConstraints": {}, - "isRLSEnabled": false - }, - "public.rewards": { - "name": "rewards", - "schema": "", - "columns": { - "internal_id": { - "name": "internal_id", - "type": "text", - "primaryKey": true, - "notNull": true - }, - "id": { - "name": "id", - "type": "text", - "primaryKey": false, - "notNull": false - }, - "org_id": { - "name": "org_id", - "type": "text", - "primaryKey": false, - "notNull": false - }, - "env": { - "name": "env", - "type": "text", - "primaryKey": false, - "notNull": false - }, - "created_at": { - "name": "created_at", - "type": "numeric", - "primaryKey": false, - "notNull": false - }, - "name": { - "name": "name", - "type": "text", - "primaryKey": false, - "notNull": false - }, - "discount_config": { - "name": "discount_config", - "type": "jsonb", - "primaryKey": false, - "notNull": false - }, - "free_product_id": { - "name": "free_product_id", - "type": "text", - "primaryKey": false, - "notNull": false - }, - "promo_codes": { - "name": "promo_codes", - "type": "jsonb[]", - "primaryKey": false, - "notNull": false - }, - "type": { - "name": "type", - "type": "text", - "primaryKey": false, - "notNull": false - } - }, - "indexes": {}, - "foreignKeys": { - "coupons_org_id_fkey": { - "name": "coupons_org_id_fkey", - "tableFrom": "rewards", - "tableTo": "organizations", - "columnsFrom": [ - "org_id" - ], - "columnsTo": [ - "id" - ], - "onDelete": "cascade", - "onUpdate": "no action" - } - }, - "compositePrimaryKeys": {}, - "uniqueConstraints": {}, - "policies": {}, - "checkConstraints": {}, - "isRLSEnabled": false - }, - "public.subscriptions": { - "name": "subscriptions", - "schema": "", - "columns": { - "id": { - "name": "id", - "type": "text", - "primaryKey": true, - "notNull": true - }, - "org_id": { - "name": "org_id", - "type": "text", - "primaryKey": false, - "notNull": true - }, - "stripe_id": { - "name": "stripe_id", - "type": "text", - "primaryKey": false, - "notNull": false - }, - "stripe_schedule_id": { - "name": "stripe_schedule_id", - "type": "text", - "primaryKey": false, - "notNull": false - }, - "created_at": { - "name": "created_at", - "type": "numeric", - "primaryKey": false, - "notNull": true, - "default": "ROUND(date_part('epoch', NOW()) * 1000)::BIGINT" - }, - "metadata": { - "name": "metadata", - "type": "jsonb", - "primaryKey": false, - "notNull": false, - "default": "'{}'::jsonb" - }, - "usage_features": { - "name": "usage_features", - "type": "text[]", - "primaryKey": false, - "notNull": false, - "default": "'{}'" - }, - "env": { - "name": "env", - "type": "text", - "primaryKey": false, - "notNull": false - }, - "current_period_start": { - "name": "current_period_start", - "type": "numeric", - "primaryKey": false, - "notNull": false - }, - "current_period_end": { - "name": "current_period_end", - "type": "numeric", - "primaryKey": false, - "notNull": false - } - }, - "indexes": {}, - "foreignKeys": { - "subscriptions_org_id_fkey": { - "name": "subscriptions_org_id_fkey", - "tableFrom": "subscriptions", - "tableTo": "organizations", - "columnsFrom": [ - "org_id" - ], - "columnsTo": [ - "id" - ], - "onDelete": "cascade", - "onUpdate": "no action" - } - }, - "compositePrimaryKeys": {}, - "uniqueConstraints": { - "subscriptions_stripe_id_key": { - "name": "subscriptions_stripe_id_key", - "nullsNotDistinct": false, - "columns": [ - "stripe_id" - ] - } - }, - "policies": {}, - "checkConstraints": {}, - "isRLSEnabled": false - } - }, - "enums": {}, - "schemas": {}, - "sequences": {}, - "roles": {}, - "policies": {}, - "views": {}, - "_meta": { - "columns": {}, - "schemas": {}, - "tables": {} - } -} \ No newline at end of file diff --git a/shared/drizzle/meta/0003_snapshot.json b/shared/drizzle/meta/0003_snapshot.json deleted file mode 100644 index 78722fe91..000000000 --- a/shared/drizzle/meta/0003_snapshot.json +++ /dev/null @@ -1,2525 +0,0 @@ -{ - "id": "eff9957d-e375-4fb2-bcc9-b30c6b4810cc", - "prevId": "bd68ad51-9560-4872-aa55-3fe710632cb2", - "version": "7", - "dialect": "postgresql", - "tables": { - "public.actions": { - "name": "actions", - "schema": "", - "columns": { - "id": { - "name": "id", - "type": "text COLLATE \"C\"", - "primaryKey": true, - "notNull": true - }, - "request_id": { - "name": "request_id", - "type": "text", - "primaryKey": false, - "notNull": true - }, - "org_id": { - "name": "org_id", - "type": "text", - "primaryKey": false, - "notNull": true - }, - "org_slug": { - "name": "org_slug", - "type": "text", - "primaryKey": false, - "notNull": true - }, - "env": { - "name": "env", - "type": "text", - "primaryKey": false, - "notNull": true - }, - "customer_id": { - "name": "customer_id", - "type": "text", - "primaryKey": false, - "notNull": false - }, - "internal_customer_id": { - "name": "internal_customer_id", - "type": "text", - "primaryKey": false, - "notNull": false - }, - "entity_id": { - "name": "entity_id", - "type": "text", - "primaryKey": false, - "notNull": false - }, - "internal_entity_id": { - "name": "internal_entity_id", - "type": "text", - "primaryKey": false, - "notNull": false - }, - "type": { - "name": "type", - "type": "text", - "primaryKey": false, - "notNull": true - }, - "auth_type": { - "name": "auth_type", - "type": "text", - "primaryKey": false, - "notNull": true - }, - "method": { - "name": "method", - "type": "text", - "primaryKey": false, - "notNull": true - }, - "path": { - "name": "path", - "type": "text", - "primaryKey": false, - "notNull": true - }, - "timestamp": { - "name": "timestamp", - "type": "timestamp with time zone", - "primaryKey": false, - "notNull": true, - "default": "now()" - }, - "properties": { - "name": "properties", - "type": "jsonb", - "primaryKey": false, - "notNull": false - } - }, - "indexes": {}, - "foreignKeys": { - "actions_org_id_fkey": { - "name": "actions_org_id_fkey", - "tableFrom": "actions", - "tableTo": "organizations", - "columnsFrom": [ - "org_id" - ], - "columnsTo": [ - "id" - ], - "onDelete": "set null", - "onUpdate": "no action" - }, - "actions_customer_id_fkey": { - "name": "actions_customer_id_fkey", - "tableFrom": "actions", - "tableTo": "customers", - "columnsFrom": [ - "internal_customer_id" - ], - "columnsTo": [ - "internal_id" - ], - "onDelete": "set null", - "onUpdate": "no action" - }, - "actions_entity_id_fkey": { - "name": "actions_entity_id_fkey", - "tableFrom": "actions", - "tableTo": "entities", - "columnsFrom": [ - "internal_entity_id" - ], - "columnsTo": [ - "internal_id" - ], - "onDelete": "set null", - "onUpdate": "no action" - } - }, - "compositePrimaryKeys": {}, - "uniqueConstraints": {}, - "policies": {}, - "checkConstraints": {}, - "isRLSEnabled": true - }, - "public.api_keys": { - "name": "api_keys", - "schema": "", - "columns": { - "id": { - "name": "id", - "type": "text COLLATE \"C\"", - "primaryKey": true, - "notNull": true - }, - "created_at": { - "name": "created_at", - "type": "numeric", - "primaryKey": false, - "notNull": true, - "default": "ROUND(date_part('epoch', NOW()) * 1000)::BIGINT" - }, - "name": { - "name": "name", - "type": "text", - "primaryKey": false, - "notNull": false - }, - "prefix": { - "name": "prefix", - "type": "text", - "primaryKey": false, - "notNull": false - }, - "org_id": { - "name": "org_id", - "type": "text", - "primaryKey": false, - "notNull": false - }, - "user_id": { - "name": "user_id", - "type": "text", - "primaryKey": false, - "notNull": false - }, - "env": { - "name": "env", - "type": "text", - "primaryKey": false, - "notNull": false - }, - "hashed_key": { - "name": "hashed_key", - "type": "text", - "primaryKey": false, - "notNull": false - }, - "meta": { - "name": "meta", - "type": "jsonb", - "primaryKey": false, - "notNull": false - } - }, - "indexes": {}, - "foreignKeys": { - "api_keys_org_id_fkey": { - "name": "api_keys_org_id_fkey", - "tableFrom": "api_keys", - "tableTo": "organizations", - "columnsFrom": [ - "org_id" - ], - "columnsTo": [ - "id" - ], - "onDelete": "cascade", - "onUpdate": "no action" - } - }, - "compositePrimaryKeys": {}, - "uniqueConstraints": { - "api_keys_hashed_key_key": { - "name": "api_keys_hashed_key_key", - "nullsNotDistinct": false, - "columns": [ - "hashed_key" - ] - } - }, - "policies": {}, - "checkConstraints": {}, - "isRLSEnabled": false - }, - "public.chat_results": { - "name": "chat_results", - "schema": "", - "columns": { - "id": { - "name": "id", - "type": "text COLLATE \"C\"", - "primaryKey": true, - "notNull": true - }, - "created_at": { - "name": "created_at", - "type": "numeric", - "primaryKey": false, - "notNull": false - }, - "data": { - "name": "data", - "type": "jsonb", - "primaryKey": false, - "notNull": true - } - }, - "indexes": {}, - "foreignKeys": {}, - "compositePrimaryKeys": {}, - "uniqueConstraints": {}, - "policies": {}, - "checkConstraints": {}, - "isRLSEnabled": true - }, - "public.customer_entitlements": { - "name": "customer_entitlements", - "schema": "", - "columns": { - "id": { - "name": "id", - "type": "text COLLATE \"C\"", - "primaryKey": true, - "notNull": true - }, - "customer_product_id": { - "name": "customer_product_id", - "type": "text", - "primaryKey": false, - "notNull": true - }, - "entitlement_id": { - "name": "entitlement_id", - "type": "text", - "primaryKey": false, - "notNull": true - }, - "internal_customer_id": { - "name": "internal_customer_id", - "type": "text", - "primaryKey": false, - "notNull": true - }, - "internal_feature_id": { - "name": "internal_feature_id", - "type": "text", - "primaryKey": false, - "notNull": true - }, - "unlimited": { - "name": "unlimited", - "type": "boolean", - "primaryKey": false, - "notNull": false, - "default": false - }, - "balance": { - "name": "balance", - "type": "numeric", - "primaryKey": false, - "notNull": true, - "default": 0 - }, - "created_at": { - "name": "created_at", - "type": "numeric", - "primaryKey": false, - "notNull": true - }, - "next_reset_at": { - "name": "next_reset_at", - "type": "numeric", - "primaryKey": false, - "notNull": false - }, - "usage_allowed": { - "name": "usage_allowed", - "type": "boolean", - "primaryKey": false, - "notNull": false, - "default": false - }, - "adjustment": { - "name": "adjustment", - "type": "numeric", - "primaryKey": false, - "notNull": false - }, - "entities": { - "name": "entities", - "type": "jsonb", - "primaryKey": false, - "notNull": false - }, - "customer_id": { - "name": "customer_id", - "type": "text", - "primaryKey": false, - "notNull": false - }, - "feature_id": { - "name": "feature_id", - "type": "text", - "primaryKey": false, - "notNull": false - } - }, - "indexes": {}, - "foreignKeys": { - "entitlements_internal_feature_id_fkey": { - "name": "entitlements_internal_feature_id_fkey", - "tableFrom": "customer_entitlements", - "tableTo": "features", - "columnsFrom": [ - "internal_feature_id" - ], - "columnsTo": [ - "internal_id" - ], - "onDelete": "cascade", - "onUpdate": "no action" - }, - "customer_entitlements_customer_product_id_fkey": { - "name": "customer_entitlements_customer_product_id_fkey", - "tableFrom": "customer_entitlements", - "tableTo": "customer_products", - "columnsFrom": [ - "customer_product_id" - ], - "columnsTo": [ - "id" - ], - "onDelete": "cascade", - "onUpdate": "cascade" - } - }, - "compositePrimaryKeys": {}, - "uniqueConstraints": { - "entitlements_id_key": { - "name": "entitlements_id_key", - "nullsNotDistinct": false, - "columns": [ - "id" - ] - } - }, - "policies": {}, - "checkConstraints": {}, - "isRLSEnabled": false - }, - "public.customer_prices": { - "name": "customer_prices", - "schema": "", - "columns": { - "id": { - "name": "id", - "type": "text", - "primaryKey": true, - "notNull": true - }, - "created_at": { - "name": "created_at", - "type": "numeric", - "primaryKey": false, - "notNull": true - }, - "price_id": { - "name": "price_id", - "type": "text", - "primaryKey": false, - "notNull": false - }, - "options": { - "name": "options", - "type": "jsonb", - "primaryKey": false, - "notNull": false - }, - "internal_customer_id": { - "name": "internal_customer_id", - "type": "text", - "primaryKey": false, - "notNull": false - }, - "customer_product_id": { - "name": "customer_product_id", - "type": "text", - "primaryKey": false, - "notNull": false - } - }, - "indexes": {}, - "foreignKeys": { - "customer_prices_customer_product_id_fkey": { - "name": "customer_prices_customer_product_id_fkey", - "tableFrom": "customer_prices", - "tableTo": "customer_products", - "columnsFrom": [ - "customer_product_id" - ], - "columnsTo": [ - "id" - ], - "onDelete": "cascade", - "onUpdate": "no action" - }, - "customer_prices_internal_customer_id_fkey": { - "name": "customer_prices_internal_customer_id_fkey", - "tableFrom": "customer_prices", - "tableTo": "customers", - "columnsFrom": [ - "internal_customer_id" - ], - "columnsTo": [ - "internal_id" - ], - "onDelete": "cascade", - "onUpdate": "no action" - }, - "customer_prices_price_id_fkey": { - "name": "customer_prices_price_id_fkey", - "tableFrom": "customer_prices", - "tableTo": "prices", - "columnsFrom": [ - "price_id" - ], - "columnsTo": [ - "id" - ], - "onDelete": "no action", - "onUpdate": "no action" - } - }, - "compositePrimaryKeys": {}, - "uniqueConstraints": {}, - "policies": {}, - "checkConstraints": {}, - "isRLSEnabled": false - }, - "public.customer_products": { - "name": "customer_products", - "schema": "", - "columns": { - "id": { - "name": "id", - "type": "text COLLATE \"C\"", - "primaryKey": true, - "notNull": true - }, - "internal_customer_id": { - "name": "internal_customer_id", - "type": "text", - "primaryKey": false, - "notNull": true - }, - "internal_product_id": { - "name": "internal_product_id", - "type": "text", - "primaryKey": false, - "notNull": true - }, - "internal_entity_id": { - "name": "internal_entity_id", - "type": "text", - "primaryKey": false, - "notNull": false - }, - "created_at": { - "name": "created_at", - "type": "numeric", - "primaryKey": false, - "notNull": false - }, - "status": { - "name": "status", - "type": "text", - "primaryKey": false, - "notNull": false - }, - "processor": { - "name": "processor", - "type": "jsonb", - "primaryKey": false, - "notNull": false - }, - "canceled_at": { - "name": "canceled_at", - "type": "numeric", - "primaryKey": false, - "notNull": false - }, - "ended_at": { - "name": "ended_at", - "type": "numeric", - "primaryKey": false, - "notNull": false - }, - "starts_at": { - "name": "starts_at", - "type": "numeric", - "primaryKey": false, - "notNull": false - }, - "options": { - "name": "options", - "type": "jsonb[]", - "primaryKey": false, - "notNull": false - }, - "product_id": { - "name": "product_id", - "type": "text", - "primaryKey": false, - "notNull": false - }, - "free_trial_id": { - "name": "free_trial_id", - "type": "text", - "primaryKey": false, - "notNull": false - }, - "trial_ends_at": { - "name": "trial_ends_at", - "type": "numeric", - "primaryKey": false, - "notNull": false - }, - "collection_method": { - "name": "collection_method", - "type": "text", - "primaryKey": false, - "notNull": false, - "default": "'charge_automatically'" - }, - "subscription_ids": { - "name": "subscription_ids", - "type": "text[]", - "primaryKey": false, - "notNull": false - }, - "scheduled_ids": { - "name": "scheduled_ids", - "type": "text[]", - "primaryKey": false, - "notNull": false - }, - "quantity": { - "name": "quantity", - "type": "numeric", - "primaryKey": false, - "notNull": false, - "default": 1 - }, - "is_custom": { - "name": "is_custom", - "type": "boolean", - "primaryKey": false, - "notNull": true, - "default": false - }, - "customer_id": { - "name": "customer_id", - "type": "text", - "primaryKey": false, - "notNull": false - }, - "entity_id": { - "name": "entity_id", - "type": "text", - "primaryKey": false, - "notNull": false - }, - "api_version": { - "name": "api_version", - "type": "numeric", - "primaryKey": false, - "notNull": false - } - }, - "indexes": {}, - "foreignKeys": { - "customer_products_free_trial_id_fkey": { - "name": "customer_products_free_trial_id_fkey", - "tableFrom": "customer_products", - "tableTo": "free_trials", - "columnsFrom": [ - "free_trial_id" - ], - "columnsTo": [ - "id" - ], - "onDelete": "no action", - "onUpdate": "no action" - }, - "customer_products_internal_customer_id_fkey": { - "name": "customer_products_internal_customer_id_fkey", - "tableFrom": "customer_products", - "tableTo": "customers", - "columnsFrom": [ - "internal_customer_id" - ], - "columnsTo": [ - "internal_id" - ], - "onDelete": "cascade", - "onUpdate": "cascade" - }, - "customer_products_internal_product_id_fkey": { - "name": "customer_products_internal_product_id_fkey", - "tableFrom": "customer_products", - "tableTo": "products", - "columnsFrom": [ - "internal_product_id" - ], - "columnsTo": [ - "internal_id" - ], - "onDelete": "no action", - "onUpdate": "no action" - }, - "customer_products_internal_entity_id_fkey": { - "name": "customer_products_internal_entity_id_fkey", - "tableFrom": "customer_products", - "tableTo": "entities", - "columnsFrom": [ - "internal_entity_id" - ], - "columnsTo": [ - "internal_id" - ], - "onDelete": "set null", - "onUpdate": "no action" - } - }, - "compositePrimaryKeys": {}, - "uniqueConstraints": {}, - "policies": {}, - "checkConstraints": {}, - "isRLSEnabled": false - }, - "public.customers": { - "name": "customers", - "schema": "", - "columns": { - "internal_id": { - "name": "internal_id", - "type": "text COLLATE \"C\"", - "primaryKey": true, - "notNull": true - }, - "org_id": { - "name": "org_id", - "type": "text", - "primaryKey": false, - "notNull": true - }, - "created_at": { - "name": "created_at", - "type": "numeric", - "primaryKey": false, - "notNull": true - }, - "name": { - "name": "name", - "type": "text", - "primaryKey": false, - "notNull": false - }, - "id": { - "name": "id", - "type": "text", - "primaryKey": false, - "notNull": false - }, - "email": { - "name": "email", - "type": "text", - "primaryKey": false, - "notNull": false - }, - "fingerprint": { - "name": "fingerprint", - "type": "text", - "primaryKey": false, - "notNull": false, - "default": "null" - }, - "metadata": { - "name": "metadata", - "type": "jsonb", - "primaryKey": false, - "notNull": false - }, - "env": { - "name": "env", - "type": "text", - "primaryKey": false, - "notNull": true - }, - "processor": { - "name": "processor", - "type": "jsonb", - "primaryKey": false, - "notNull": false - } - }, - "indexes": {}, - "foreignKeys": { - "customers_org_id_fkey": { - "name": "customers_org_id_fkey", - "tableFrom": "customers", - "tableTo": "organizations", - "columnsFrom": [ - "org_id" - ], - "columnsTo": [ - "id" - ], - "onDelete": "cascade", - "onUpdate": "no action" - } - }, - "compositePrimaryKeys": {}, - "uniqueConstraints": { - "cus_id_constraint": { - "name": "cus_id_constraint", - "nullsNotDistinct": false, - "columns": [ - "org_id", - "id", - "env" - ] - } - }, - "policies": {}, - "checkConstraints": {}, - "isRLSEnabled": true - }, - "public.entities": { - "name": "entities", - "schema": "", - "columns": { - "id": { - "name": "id", - "type": "text", - "primaryKey": false, - "notNull": false - }, - "org_id": { - "name": "org_id", - "type": "text", - "primaryKey": false, - "notNull": false - }, - "created_at": { - "name": "created_at", - "type": "numeric", - "primaryKey": false, - "notNull": true - }, - "internal_id": { - "name": "internal_id", - "type": "text", - "primaryKey": true, - "notNull": true - }, - "internal_customer_id": { - "name": "internal_customer_id", - "type": "text", - "primaryKey": false, - "notNull": true - }, - "env": { - "name": "env", - "type": "text", - "primaryKey": false, - "notNull": false - }, - "name": { - "name": "name", - "type": "text", - "primaryKey": false, - "notNull": false - }, - "deleted": { - "name": "deleted", - "type": "boolean", - "primaryKey": false, - "notNull": true, - "default": false - }, - "internal_feature_id": { - "name": "internal_feature_id", - "type": "text", - "primaryKey": false, - "notNull": false - }, - "feature_id": { - "name": "feature_id", - "type": "text", - "primaryKey": false, - "notNull": false - } - }, - "indexes": {}, - "foreignKeys": { - "entities_internal_customer_id_fkey": { - "name": "entities_internal_customer_id_fkey", - "tableFrom": "entities", - "tableTo": "customers", - "columnsFrom": [ - "internal_customer_id" - ], - "columnsTo": [ - "internal_id" - ], - "onDelete": "cascade", - "onUpdate": "no action" - }, - "entities_internal_feature_id_fkey": { - "name": "entities_internal_feature_id_fkey", - "tableFrom": "entities", - "tableTo": "features", - "columnsFrom": [ - "internal_feature_id" - ], - "columnsTo": [ - "internal_id" - ], - "onDelete": "cascade", - "onUpdate": "no action" - }, - "entities_org_id_fkey": { - "name": "entities_org_id_fkey", - "tableFrom": "entities", - "tableTo": "organizations", - "columnsFrom": [ - "org_id" - ], - "columnsTo": [ - "id" - ], - "onDelete": "cascade", - "onUpdate": "no action" - } - }, - "compositePrimaryKeys": {}, - "uniqueConstraints": { - "entity_id_constraint": { - "name": "entity_id_constraint", - "nullsNotDistinct": false, - "columns": [ - "org_id", - "env", - "internal_customer_id", - "id" - ] - } - }, - "policies": {}, - "checkConstraints": {}, - "isRLSEnabled": false - }, - "public.entitlements": { - "name": "entitlements", - "schema": "", - "columns": { - "id": { - "name": "id", - "type": "text COLLATE \"C\"", - "primaryKey": true, - "notNull": true - }, - "created_at": { - "name": "created_at", - "type": "numeric", - "primaryKey": false, - "notNull": true - }, - "internal_feature_id": { - "name": "internal_feature_id", - "type": "text", - "primaryKey": false, - "notNull": true - }, - "internal_product_id": { - "name": "internal_product_id", - "type": "text", - "primaryKey": false, - "notNull": true - }, - "is_custom": { - "name": "is_custom", - "type": "boolean", - "primaryKey": false, - "notNull": false, - "default": false - }, - "allowance_type": { - "name": "allowance_type", - "type": "text", - "primaryKey": false, - "notNull": false - }, - "allowance": { - "name": "allowance", - "type": "numeric", - "primaryKey": false, - "notNull": false - }, - "interval": { - "name": "interval", - "type": "text", - "primaryKey": false, - "notNull": false - }, - "carry_from_previous": { - "name": "carry_from_previous", - "type": "boolean", - "primaryKey": false, - "notNull": false, - "default": false - }, - "entity_feature_id": { - "name": "entity_feature_id", - "type": "text", - "primaryKey": false, - "notNull": false, - "default": "null" - }, - "org_id": { - "name": "org_id", - "type": "text", - "primaryKey": false, - "notNull": false - }, - "feature_id": { - "name": "feature_id", - "type": "text", - "primaryKey": false, - "notNull": false - } - }, - "indexes": {}, - "foreignKeys": { - "entitlements_internal_feature_id_fkey": { - "name": "entitlements_internal_feature_id_fkey", - "tableFrom": "entitlements", - "tableTo": "features", - "columnsFrom": [ - "internal_feature_id" - ], - "columnsTo": [ - "internal_id" - ], - "onDelete": "cascade", - "onUpdate": "no action" - }, - "entitlements_internal_product_id_fkey": { - "name": "entitlements_internal_product_id_fkey", - "tableFrom": "entitlements", - "tableTo": "products", - "columnsFrom": [ - "internal_product_id" - ], - "columnsTo": [ - "internal_id" - ], - "onDelete": "cascade", - "onUpdate": "cascade" - } - }, - "compositePrimaryKeys": {}, - "uniqueConstraints": { - "entitlements_id_key": { - "name": "entitlements_id_key", - "nullsNotDistinct": false, - "columns": [ - "id" - ] - } - }, - "policies": {}, - "checkConstraints": {}, - "isRLSEnabled": false - }, - "public.events": { - "name": "events", - "schema": "", - "columns": { - "id": { - "name": "id", - "type": "text", - "primaryKey": true, - "notNull": true - }, - "org_id": { - "name": "org_id", - "type": "text", - "primaryKey": false, - "notNull": true - }, - "org_slug": { - "name": "org_slug", - "type": "text", - "primaryKey": false, - "notNull": true - }, - "internal_customer_id": { - "name": "internal_customer_id", - "type": "text", - "primaryKey": false, - "notNull": false - }, - "env": { - "name": "env", - "type": "text", - "primaryKey": false, - "notNull": true - }, - "created_at": { - "name": "created_at", - "type": "bigint", - "primaryKey": false, - "notNull": false - }, - "timestamp": { - "name": "timestamp", - "type": "timestamp with time zone", - "primaryKey": false, - "notNull": false - }, - "event_name": { - "name": "event_name", - "type": "text", - "primaryKey": false, - "notNull": true - }, - "idempotency_key": { - "name": "idempotency_key", - "type": "text", - "primaryKey": false, - "notNull": false, - "default": "null" - }, - "value": { - "name": "value", - "type": "numeric", - "primaryKey": false, - "notNull": false - }, - "set_usage": { - "name": "set_usage", - "type": "boolean", - "primaryKey": false, - "notNull": false, - "default": false - }, - "entity_id": { - "name": "entity_id", - "type": "text", - "primaryKey": false, - "notNull": false - }, - "customer_id": { - "name": "customer_id", - "type": "text", - "primaryKey": false, - "notNull": true - }, - "properties": { - "name": "properties", - "type": "jsonb", - "primaryKey": false, - "notNull": false - } - }, - "indexes": {}, - "foreignKeys": { - "events_internal_customer_id_fkey": { - "name": "events_internal_customer_id_fkey", - "tableFrom": "events", - "tableTo": "customers", - "columnsFrom": [ - "internal_customer_id" - ], - "columnsTo": [ - "internal_id" - ], - "onDelete": "cascade", - "onUpdate": "no action" - } - }, - "compositePrimaryKeys": {}, - "uniqueConstraints": { - "unique_event_constraint": { - "name": "unique_event_constraint", - "nullsNotDistinct": false, - "columns": [ - "org_id", - "env", - "customer_id", - "event_name", - "idempotency_key" - ] - } - }, - "policies": {}, - "checkConstraints": {}, - "isRLSEnabled": false - }, - "public.features": { - "name": "features", - "schema": "", - "columns": { - "internal_id": { - "name": "internal_id", - "type": "text COLLATE \"C\"", - "primaryKey": true, - "notNull": true - }, - "org_id": { - "name": "org_id", - "type": "text", - "primaryKey": false, - "notNull": true - }, - "created_at": { - "name": "created_at", - "type": "numeric", - "primaryKey": false, - "notNull": false - }, - "env": { - "name": "env", - "type": "text", - "primaryKey": false, - "notNull": false - }, - "id": { - "name": "id", - "type": "text", - "primaryKey": false, - "notNull": true - }, - "name": { - "name": "name", - "type": "text", - "primaryKey": false, - "notNull": false - }, - "type": { - "name": "type", - "type": "text", - "primaryKey": false, - "notNull": true - }, - "config": { - "name": "config", - "type": "jsonb", - "primaryKey": false, - "notNull": false - }, - "display": { - "name": "display", - "type": "jsonb", - "primaryKey": false, - "notNull": false, - "default": "null" - } - }, - "indexes": {}, - "foreignKeys": { - "features_org_id_fkey": { - "name": "features_org_id_fkey", - "tableFrom": "features", - "tableTo": "organizations", - "columnsFrom": [ - "org_id" - ], - "columnsTo": [ - "id" - ], - "onDelete": "cascade", - "onUpdate": "no action" - } - }, - "compositePrimaryKeys": {}, - "uniqueConstraints": { - "feature_id_constraint": { - "name": "feature_id_constraint", - "nullsNotDistinct": false, - "columns": [ - "org_id", - "id", - "env" - ] - } - }, - "policies": {}, - "checkConstraints": {}, - "isRLSEnabled": false - }, - "public.free_trials": { - "name": "free_trials", - "schema": "", - "columns": { - "id": { - "name": "id", - "type": "text", - "primaryKey": true, - "notNull": true - }, - "created_at": { - "name": "created_at", - "type": "numeric", - "primaryKey": false, - "notNull": true - }, - "internal_product_id": { - "name": "internal_product_id", - "type": "text", - "primaryKey": false, - "notNull": false - }, - "duration": { - "name": "duration", - "type": "text", - "primaryKey": false, - "notNull": false, - "default": "'day'" - }, - "length": { - "name": "length", - "type": "numeric", - "primaryKey": false, - "notNull": false - }, - "unique_fingerprint": { - "name": "unique_fingerprint", - "type": "boolean", - "primaryKey": false, - "notNull": false - }, - "is_custom": { - "name": "is_custom", - "type": "boolean", - "primaryKey": false, - "notNull": false, - "default": false - } - }, - "indexes": {}, - "foreignKeys": { - "free_trials_internal_product_id_fkey": { - "name": "free_trials_internal_product_id_fkey", - "tableFrom": "free_trials", - "tableTo": "products", - "columnsFrom": [ - "internal_product_id" - ], - "columnsTo": [ - "internal_id" - ], - "onDelete": "cascade", - "onUpdate": "no action" - } - }, - "compositePrimaryKeys": {}, - "uniqueConstraints": {}, - "policies": {}, - "checkConstraints": {}, - "isRLSEnabled": false - }, - "public.invoices": { - "name": "invoices", - "schema": "", - "columns": { - "id": { - "name": "id", - "type": "text COLLATE \"C\"", - "primaryKey": true, - "notNull": true - }, - "created_at": { - "name": "created_at", - "type": "numeric", - "primaryKey": false, - "notNull": true, - "default": "ROUND(date_part('epoch', NOW()) * 1000)::BIGINT" - }, - "product_ids": { - "name": "product_ids", - "type": "text[]", - "primaryKey": false, - "notNull": false, - "default": "'{}'" - }, - "internal_product_ids": { - "name": "internal_product_ids", - "type": "text[]", - "primaryKey": false, - "notNull": false, - "default": "'{}'" - }, - "internal_customer_id": { - "name": "internal_customer_id", - "type": "text", - "primaryKey": false, - "notNull": true - }, - "internal_entity_id": { - "name": "internal_entity_id", - "type": "text", - "primaryKey": false, - "notNull": false - }, - "stripe_id": { - "name": "stripe_id", - "type": "text", - "primaryKey": false, - "notNull": true - }, - "status": { - "name": "status", - "type": "text", - "primaryKey": false, - "notNull": true, - "default": "'draft'" - }, - "hosted_invoice_url": { - "name": "hosted_invoice_url", - "type": "text", - "primaryKey": false, - "notNull": false - }, - "total": { - "name": "total", - "type": "numeric", - "primaryKey": false, - "notNull": true, - "default": 0 - }, - "currency": { - "name": "currency", - "type": "text", - "primaryKey": false, - "notNull": true, - "default": "'usd'" - }, - "discounts": { - "name": "discounts", - "type": "jsonb[]", - "primaryKey": false, - "notNull": false, - "default": "'{}'" - }, - "items": { - "name": "items", - "type": "jsonb[]", - "primaryKey": false, - "notNull": false, - "default": "'{}'" - } - }, - "indexes": {}, - "foreignKeys": { - "invoices_internal_customer_id_fkey": { - "name": "invoices_internal_customer_id_fkey", - "tableFrom": "invoices", - "tableTo": "customers", - "columnsFrom": [ - "internal_customer_id" - ], - "columnsTo": [ - "id" - ], - "onDelete": "no action", - "onUpdate": "no action" - }, - "invoices_internal_entity_id_fkey": { - "name": "invoices_internal_entity_id_fkey", - "tableFrom": "invoices", - "tableTo": "entities", - "columnsFrom": [ - "internal_entity_id" - ], - "columnsTo": [ - "id" - ], - "onDelete": "no action", - "onUpdate": "no action" - } - }, - "compositePrimaryKeys": {}, - "uniqueConstraints": {}, - "policies": {}, - "checkConstraints": {}, - "isRLSEnabled": false - }, - "public.metadata": { - "name": "metadata", - "schema": "", - "columns": { - "id": { - "name": "id", - "type": "text", - "primaryKey": true, - "notNull": true - }, - "created_at": { - "name": "created_at", - "type": "numeric", - "primaryKey": false, - "notNull": true, - "default": "ROUND(date_part('epoch', NOW()) * 1000)::BIGINT" - }, - "expires_at": { - "name": "expires_at", - "type": "numeric", - "primaryKey": false, - "notNull": false - }, - "data": { - "name": "data", - "type": "jsonb", - "primaryKey": false, - "notNull": false - } - }, - "indexes": {}, - "foreignKeys": {}, - "compositePrimaryKeys": {}, - "uniqueConstraints": {}, - "policies": {}, - "checkConstraints": {}, - "isRLSEnabled": false - }, - "public.migration_errors": { - "name": "migration_errors", - "schema": "", - "columns": { - "internal_customer_id": { - "name": "internal_customer_id", - "type": "text", - "primaryKey": false, - "notNull": true - }, - "migration_job_id": { - "name": "migration_job_id", - "type": "text", - "primaryKey": false, - "notNull": true - }, - "created_at": { - "name": "created_at", - "type": "numeric", - "primaryKey": false, - "notNull": false - }, - "updated_at": { - "name": "updated_at", - "type": "numeric", - "primaryKey": false, - "notNull": false - }, - "data": { - "name": "data", - "type": "jsonb", - "primaryKey": false, - "notNull": false - }, - "message": { - "name": "message", - "type": "text", - "primaryKey": false, - "notNull": false - }, - "code": { - "name": "code", - "type": "text", - "primaryKey": false, - "notNull": false - } - }, - "indexes": {}, - "foreignKeys": { - "migration_customers_internal_customer_id_fkey": { - "name": "migration_customers_internal_customer_id_fkey", - "tableFrom": "migration_errors", - "tableTo": "customers", - "columnsFrom": [ - "internal_customer_id" - ], - "columnsTo": [ - "internal_id" - ], - "onDelete": "cascade", - "onUpdate": "no action" - }, - "migration_customers_migration_job_id_fkey": { - "name": "migration_customers_migration_job_id_fkey", - "tableFrom": "migration_errors", - "tableTo": "migration_jobs", - "columnsFrom": [ - "migration_job_id" - ], - "columnsTo": [ - "id" - ], - "onDelete": "cascade", - "onUpdate": "no action" - } - }, - "compositePrimaryKeys": { - "migration_errors_pkey": { - "name": "migration_errors_pkey", - "columns": [ - "internal_customer_id", - "migration_job_id" - ] - } - }, - "uniqueConstraints": {}, - "policies": {}, - "checkConstraints": {}, - "isRLSEnabled": false - }, - "public.migration_jobs": { - "name": "migration_jobs", - "schema": "", - "columns": { - "id": { - "name": "id", - "type": "text", - "primaryKey": true, - "notNull": true - }, - "org_id": { - "name": "org_id", - "type": "text", - "primaryKey": false, - "notNull": true - }, - "env": { - "name": "env", - "type": "text", - "primaryKey": false, - "notNull": true - }, - "created_at": { - "name": "created_at", - "type": "numeric", - "primaryKey": false, - "notNull": true - }, - "updated_at": { - "name": "updated_at", - "type": "numeric", - "primaryKey": false, - "notNull": false - }, - "current_step": { - "name": "current_step", - "type": "text", - "primaryKey": false, - "notNull": false - }, - "from_internal_product_id": { - "name": "from_internal_product_id", - "type": "text", - "primaryKey": false, - "notNull": false - }, - "to_internal_product_id": { - "name": "to_internal_product_id", - "type": "text", - "primaryKey": false, - "notNull": false - }, - "step_details": { - "name": "step_details", - "type": "jsonb", - "primaryKey": false, - "notNull": false - } - }, - "indexes": {}, - "foreignKeys": { - "migration_jobs_from_internal_product_id_fkey": { - "name": "migration_jobs_from_internal_product_id_fkey", - "tableFrom": "migration_jobs", - "tableTo": "products", - "columnsFrom": [ - "from_internal_product_id" - ], - "columnsTo": [ - "internal_id" - ], - "onDelete": "cascade", - "onUpdate": "no action" - }, - "migration_jobs_org_id_fkey": { - "name": "migration_jobs_org_id_fkey", - "tableFrom": "migration_jobs", - "tableTo": "organizations", - "columnsFrom": [ - "org_id" - ], - "columnsTo": [ - "id" - ], - "onDelete": "cascade", - "onUpdate": "no action" - }, - "migration_jobs_to_internal_product_id_fkey": { - "name": "migration_jobs_to_internal_product_id_fkey", - "tableFrom": "migration_jobs", - "tableTo": "products", - "columnsFrom": [ - "to_internal_product_id" - ], - "columnsTo": [ - "internal_id" - ], - "onDelete": "cascade", - "onUpdate": "no action" - } - }, - "compositePrimaryKeys": {}, - "uniqueConstraints": {}, - "policies": {}, - "checkConstraints": {}, - "isRLSEnabled": false - }, - "public.organizations": { - "name": "organizations", - "schema": "", - "columns": { - "id": { - "name": "id", - "type": "text", - "primaryKey": true, - "notNull": true - }, - "slug": { - "name": "slug", - "type": "text", - "primaryKey": false, - "notNull": true - }, - "default_currency": { - "name": "default_currency", - "type": "text", - "primaryKey": false, - "notNull": true, - "default": "'usd'" - }, - "stripe_connected": { - "name": "stripe_connected", - "type": "boolean", - "primaryKey": false, - "notNull": false, - "default": false - }, - "stripe_config": { - "name": "stripe_config", - "type": "jsonb", - "primaryKey": false, - "notNull": false - }, - "test_pkey": { - "name": "test_pkey", - "type": "text", - "primaryKey": false, - "notNull": false - }, - "live_pkey": { - "name": "live_pkey", - "type": "text", - "primaryKey": false, - "notNull": false - }, - "svix_config": { - "name": "svix_config", - "type": "jsonb", - "primaryKey": false, - "notNull": true - }, - "created_at": { - "name": "created_at", - "type": "numeric", - "primaryKey": false, - "notNull": false - }, - "config": { - "name": "config", - "type": "jsonb", - "primaryKey": false, - "notNull": true, - "default": "'{}'::jsonb" - } - }, - "indexes": {}, - "foreignKeys": {}, - "compositePrimaryKeys": {}, - "uniqueConstraints": { - "organizations_test_pkey_key": { - "name": "organizations_test_pkey_key", - "nullsNotDistinct": false, - "columns": [ - "test_pkey" - ] - }, - "organizations_live_pkey_key": { - "name": "organizations_live_pkey_key", - "nullsNotDistinct": false, - "columns": [ - "live_pkey" - ] - } - }, - "policies": {}, - "checkConstraints": {}, - "isRLSEnabled": false - }, - "public.prices": { - "name": "prices", - "schema": "", - "columns": { - "id": { - "name": "id", - "type": "text COLLATE \"C\"", - "primaryKey": true, - "notNull": true - }, - "org_id": { - "name": "org_id", - "type": "text", - "primaryKey": false, - "notNull": true - }, - "internal_product_id": { - "name": "internal_product_id", - "type": "text", - "primaryKey": false, - "notNull": true - }, - "config": { - "name": "config", - "type": "jsonb", - "primaryKey": false, - "notNull": false - }, - "created_at": { - "name": "created_at", - "type": "numeric", - "primaryKey": false, - "notNull": true - }, - "billing_type": { - "name": "billing_type", - "type": "text", - "primaryKey": false, - "notNull": false - }, - "is_custom": { - "name": "is_custom", - "type": "boolean", - "primaryKey": false, - "notNull": false, - "default": false - }, - "entitlement_id": { - "name": "entitlement_id", - "type": "text", - "primaryKey": false, - "notNull": false, - "default": "null" - }, - "proration_config": { - "name": "proration_config", - "type": "jsonb", - "primaryKey": false, - "notNull": false, - "default": "null" - } - }, - "indexes": {}, - "foreignKeys": { - "prices_entitlement_id_fkey": { - "name": "prices_entitlement_id_fkey", - "tableFrom": "prices", - "tableTo": "entitlements", - "columnsFrom": [ - "entitlement_id" - ], - "columnsTo": [ - "id" - ], - "onDelete": "no action", - "onUpdate": "no action" - }, - "prices_internal_product_id_fkey": { - "name": "prices_internal_product_id_fkey", - "tableFrom": "prices", - "tableTo": "products", - "columnsFrom": [ - "internal_product_id" - ], - "columnsTo": [ - "internal_id" - ], - "onDelete": "cascade", - "onUpdate": "cascade" - } - }, - "compositePrimaryKeys": {}, - "uniqueConstraints": { - "prices_id_key": { - "name": "prices_id_key", - "nullsNotDistinct": false, - "columns": [ - "id" - ] - } - }, - "policies": {}, - "checkConstraints": {}, - "isRLSEnabled": false - }, - "public.products": { - "name": "products", - "schema": "", - "columns": { - "internal_id": { - "name": "internal_id", - "type": "text COLLATE \"C\"", - "primaryKey": true, - "notNull": true - }, - "id": { - "name": "id", - "type": "text", - "primaryKey": false, - "notNull": true - }, - "name": { - "name": "name", - "type": "text", - "primaryKey": false, - "notNull": false - }, - "org_id": { - "name": "org_id", - "type": "text", - "primaryKey": false, - "notNull": true - }, - "created_at": { - "name": "created_at", - "type": "numeric", - "primaryKey": false, - "notNull": true, - "default": "ROUND(date_part('epoch', NOW()) * 1000)::BIGINT" - }, - "env": { - "name": "env", - "type": "text", - "primaryKey": false, - "notNull": true - }, - "is_add_on": { - "name": "is_add_on", - "type": "boolean", - "primaryKey": false, - "notNull": true, - "default": false - }, - "is_default": { - "name": "is_default", - "type": "boolean", - "primaryKey": false, - "notNull": true, - "default": false - }, - "group": { - "name": "group", - "type": "text", - "primaryKey": false, - "notNull": false, - "default": "''" - }, - "version": { - "name": "version", - "type": "numeric", - "primaryKey": false, - "notNull": true, - "default": 1 - }, - "processor": { - "name": "processor", - "type": "jsonb", - "primaryKey": false, - "notNull": false, - "default": "null" - } - }, - "indexes": {}, - "foreignKeys": { - "products_org_id_fkey": { - "name": "products_org_id_fkey", - "tableFrom": "products", - "tableTo": "organizations", - "columnsFrom": [ - "org_id" - ], - "columnsTo": [ - "id" - ], - "onDelete": "cascade", - "onUpdate": "no action" - } - }, - "compositePrimaryKeys": {}, - "uniqueConstraints": { - "unique_product": { - "name": "unique_product", - "nullsNotDistinct": false, - "columns": [ - "org_id", - "id", - "env", - "version" - ] - } - }, - "policies": {}, - "checkConstraints": {}, - "isRLSEnabled": false - }, - "public.referral_codes": { - "name": "referral_codes", - "schema": "", - "columns": { - "code": { - "name": "code", - "type": "text", - "primaryKey": false, - "notNull": true - }, - "org_id": { - "name": "org_id", - "type": "text", - "primaryKey": false, - "notNull": true - }, - "env": { - "name": "env", - "type": "text", - "primaryKey": false, - "notNull": true - }, - "internal_customer_id": { - "name": "internal_customer_id", - "type": "text", - "primaryKey": false, - "notNull": false - }, - "internal_reward_program_id": { - "name": "internal_reward_program_id", - "type": "text", - "primaryKey": false, - "notNull": false - }, - "id": { - "name": "id", - "type": "text", - "primaryKey": false, - "notNull": true - }, - "created_at": { - "name": "created_at", - "type": "numeric", - "primaryKey": false, - "notNull": false - } - }, - "indexes": {}, - "foreignKeys": { - "referral_codes_internal_customer_id_fkey": { - "name": "referral_codes_internal_customer_id_fkey", - "tableFrom": "referral_codes", - "tableTo": "customers", - "columnsFrom": [ - "internal_customer_id" - ], - "columnsTo": [ - "internal_id" - ], - "onDelete": "cascade", - "onUpdate": "no action" - }, - "referral_codes_internal_reward_program_id_fkey": { - "name": "referral_codes_internal_reward_program_id_fkey", - "tableFrom": "referral_codes", - "tableTo": "reward_programs", - "columnsFrom": [ - "internal_reward_program_id" - ], - "columnsTo": [ - "internal_id" - ], - "onDelete": "cascade", - "onUpdate": "no action" - }, - "referral_codes_org_id_fkey": { - "name": "referral_codes_org_id_fkey", - "tableFrom": "referral_codes", - "tableTo": "organizations", - "columnsFrom": [ - "org_id" - ], - "columnsTo": [ - "id" - ], - "onDelete": "cascade", - "onUpdate": "no action" - } - }, - "compositePrimaryKeys": { - "referral_codes_pkey": { - "name": "referral_codes_pkey", - "columns": [ - "code", - "org_id", - "env" - ] - } - }, - "uniqueConstraints": { - "referral_codes_id_key": { - "name": "referral_codes_id_key", - "nullsNotDistinct": false, - "columns": [ - "id" - ] - } - }, - "policies": {}, - "checkConstraints": {}, - "isRLSEnabled": false - }, - "public.reward_programs": { - "name": "reward_programs", - "schema": "", - "columns": { - "internal_id": { - "name": "internal_id", - "type": "text", - "primaryKey": true, - "notNull": true - }, - "id": { - "name": "id", - "type": "text", - "primaryKey": false, - "notNull": false - }, - "created_at": { - "name": "created_at", - "type": "numeric", - "primaryKey": false, - "notNull": false - }, - "internal_reward_id": { - "name": "internal_reward_id", - "type": "text", - "primaryKey": false, - "notNull": false - }, - "max_redemptions": { - "name": "max_redemptions", - "type": "numeric", - "primaryKey": false, - "notNull": false - }, - "unlimited_redemptions": { - "name": "unlimited_redemptions", - "type": "boolean", - "primaryKey": false, - "notNull": false, - "default": false - }, - "org_id": { - "name": "org_id", - "type": "text", - "primaryKey": false, - "notNull": false - }, - "env": { - "name": "env", - "type": "text", - "primaryKey": false, - "notNull": false - }, - "when": { - "name": "when", - "type": "text", - "primaryKey": false, - "notNull": false, - "default": "'immediately'" - }, - "product_ids": { - "name": "product_ids", - "type": "text[]", - "primaryKey": false, - "notNull": false, - "default": "'{\"\"}'" - }, - "exclude_trial": { - "name": "exclude_trial", - "type": "boolean", - "primaryKey": false, - "notNull": false, - "default": false - }, - "received_by": { - "name": "received_by", - "type": "text", - "primaryKey": false, - "notNull": false - } - }, - "indexes": {}, - "foreignKeys": { - "reward_triggers_internal_reward_id_fkey": { - "name": "reward_triggers_internal_reward_id_fkey", - "tableFrom": "reward_programs", - "tableTo": "rewards", - "columnsFrom": [ - "internal_reward_id" - ], - "columnsTo": [ - "internal_id" - ], - "onDelete": "cascade", - "onUpdate": "no action" - }, - "reward_triggers_org_id_fkey": { - "name": "reward_triggers_org_id_fkey", - "tableFrom": "reward_programs", - "tableTo": "organizations", - "columnsFrom": [ - "org_id" - ], - "columnsTo": [ - "id" - ], - "onDelete": "cascade", - "onUpdate": "no action" - } - }, - "compositePrimaryKeys": {}, - "uniqueConstraints": {}, - "policies": {}, - "checkConstraints": {}, - "isRLSEnabled": false - }, - "public.reward_redemptions": { - "name": "reward_redemptions", - "schema": "", - "columns": { - "id": { - "name": "id", - "type": "text", - "primaryKey": true, - "notNull": true - }, - "created_at": { - "name": "created_at", - "type": "numeric", - "primaryKey": false, - "notNull": false - }, - "updated_at": { - "name": "updated_at", - "type": "numeric", - "primaryKey": false, - "notNull": false - }, - "internal_customer_id": { - "name": "internal_customer_id", - "type": "text", - "primaryKey": false, - "notNull": false - }, - "triggered": { - "name": "triggered", - "type": "boolean", - "primaryKey": false, - "notNull": false - }, - "internal_reward_program_id": { - "name": "internal_reward_program_id", - "type": "text", - "primaryKey": false, - "notNull": false - }, - "applied": { - "name": "applied", - "type": "boolean", - "primaryKey": false, - "notNull": false, - "default": false - }, - "referral_code_id": { - "name": "referral_code_id", - "type": "text", - "primaryKey": false, - "notNull": false - } - }, - "indexes": {}, - "foreignKeys": { - "reward_redemptions_internal_customer_id_fkey": { - "name": "reward_redemptions_internal_customer_id_fkey", - "tableFrom": "reward_redemptions", - "tableTo": "customers", - "columnsFrom": [ - "internal_customer_id" - ], - "columnsTo": [ - "internal_id" - ], - "onDelete": "cascade", - "onUpdate": "no action" - }, - "reward_redemptions_internal_reward_program_id_fkey": { - "name": "reward_redemptions_internal_reward_program_id_fkey", - "tableFrom": "reward_redemptions", - "tableTo": "reward_programs", - "columnsFrom": [ - "internal_reward_program_id" - ], - "columnsTo": [ - "internal_id" - ], - "onDelete": "cascade", - "onUpdate": "no action" - }, - "reward_redemptions_referral_code_id_fkey": { - "name": "reward_redemptions_referral_code_id_fkey", - "tableFrom": "reward_redemptions", - "tableTo": "referral_codes", - "columnsFrom": [ - "referral_code_id" - ], - "columnsTo": [ - "id" - ], - "onDelete": "cascade", - "onUpdate": "no action" - } - }, - "compositePrimaryKeys": {}, - "uniqueConstraints": {}, - "policies": {}, - "checkConstraints": {}, - "isRLSEnabled": false - }, - "public.rewards": { - "name": "rewards", - "schema": "", - "columns": { - "internal_id": { - "name": "internal_id", - "type": "text", - "primaryKey": true, - "notNull": true - }, - "id": { - "name": "id", - "type": "text", - "primaryKey": false, - "notNull": false - }, - "org_id": { - "name": "org_id", - "type": "text", - "primaryKey": false, - "notNull": false - }, - "env": { - "name": "env", - "type": "text", - "primaryKey": false, - "notNull": false - }, - "created_at": { - "name": "created_at", - "type": "numeric", - "primaryKey": false, - "notNull": false - }, - "name": { - "name": "name", - "type": "text", - "primaryKey": false, - "notNull": false - }, - "discount_config": { - "name": "discount_config", - "type": "jsonb", - "primaryKey": false, - "notNull": false - }, - "free_product_id": { - "name": "free_product_id", - "type": "text", - "primaryKey": false, - "notNull": false - }, - "promo_codes": { - "name": "promo_codes", - "type": "jsonb[]", - "primaryKey": false, - "notNull": false - }, - "type": { - "name": "type", - "type": "text", - "primaryKey": false, - "notNull": false - } - }, - "indexes": {}, - "foreignKeys": { - "coupons_org_id_fkey": { - "name": "coupons_org_id_fkey", - "tableFrom": "rewards", - "tableTo": "organizations", - "columnsFrom": [ - "org_id" - ], - "columnsTo": [ - "id" - ], - "onDelete": "cascade", - "onUpdate": "no action" - } - }, - "compositePrimaryKeys": {}, - "uniqueConstraints": {}, - "policies": {}, - "checkConstraints": {}, - "isRLSEnabled": false - }, - "public.subscriptions": { - "name": "subscriptions", - "schema": "", - "columns": { - "id": { - "name": "id", - "type": "text", - "primaryKey": true, - "notNull": true - }, - "org_id": { - "name": "org_id", - "type": "text", - "primaryKey": false, - "notNull": true - }, - "stripe_id": { - "name": "stripe_id", - "type": "text", - "primaryKey": false, - "notNull": false - }, - "stripe_schedule_id": { - "name": "stripe_schedule_id", - "type": "text", - "primaryKey": false, - "notNull": false - }, - "created_at": { - "name": "created_at", - "type": "numeric", - "primaryKey": false, - "notNull": true, - "default": "ROUND(date_part('epoch', NOW()) * 1000)::BIGINT" - }, - "metadata": { - "name": "metadata", - "type": "jsonb", - "primaryKey": false, - "notNull": false, - "default": "'{}'::jsonb" - }, - "usage_features": { - "name": "usage_features", - "type": "text[]", - "primaryKey": false, - "notNull": false, - "default": "'{}'" - }, - "env": { - "name": "env", - "type": "text", - "primaryKey": false, - "notNull": false - }, - "current_period_start": { - "name": "current_period_start", - "type": "numeric", - "primaryKey": false, - "notNull": false - }, - "current_period_end": { - "name": "current_period_end", - "type": "numeric", - "primaryKey": false, - "notNull": false - } - }, - "indexes": {}, - "foreignKeys": { - "subscriptions_org_id_fkey": { - "name": "subscriptions_org_id_fkey", - "tableFrom": "subscriptions", - "tableTo": "organizations", - "columnsFrom": [ - "org_id" - ], - "columnsTo": [ - "id" - ], - "onDelete": "cascade", - "onUpdate": "no action" - } - }, - "compositePrimaryKeys": {}, - "uniqueConstraints": { - "subscriptions_stripe_id_key": { - "name": "subscriptions_stripe_id_key", - "nullsNotDistinct": false, - "columns": [ - "stripe_id" - ] - } - }, - "policies": {}, - "checkConstraints": {}, - "isRLSEnabled": false - } - }, - "enums": {}, - "schemas": {}, - "sequences": {}, - "roles": {}, - "policies": {}, - "views": {}, - "_meta": { - "columns": {}, - "schemas": {}, - "tables": {} - } -} \ No newline at end of file diff --git a/shared/drizzle/meta/0004_snapshot.json b/shared/drizzle/meta/0004_snapshot.json deleted file mode 100644 index 70ef1a225..000000000 --- a/shared/drizzle/meta/0004_snapshot.json +++ /dev/null @@ -1,2583 +0,0 @@ -{ - "id": "e40b8996-e527-41a2-a823-9dddd2325689", - "prevId": "eff9957d-e375-4fb2-bcc9-b30c6b4810cc", - "version": "7", - "dialect": "postgresql", - "tables": { - "public.actions": { - "name": "actions", - "schema": "", - "columns": { - "id": { - "name": "id", - "type": "text COLLATE \"C\"", - "primaryKey": true, - "notNull": true - }, - "request_id": { - "name": "request_id", - "type": "text", - "primaryKey": false, - "notNull": true - }, - "org_id": { - "name": "org_id", - "type": "text", - "primaryKey": false, - "notNull": true - }, - "org_slug": { - "name": "org_slug", - "type": "text", - "primaryKey": false, - "notNull": true - }, - "env": { - "name": "env", - "type": "text", - "primaryKey": false, - "notNull": true - }, - "customer_id": { - "name": "customer_id", - "type": "text", - "primaryKey": false, - "notNull": false - }, - "internal_customer_id": { - "name": "internal_customer_id", - "type": "text", - "primaryKey": false, - "notNull": false - }, - "entity_id": { - "name": "entity_id", - "type": "text", - "primaryKey": false, - "notNull": false - }, - "internal_entity_id": { - "name": "internal_entity_id", - "type": "text", - "primaryKey": false, - "notNull": false - }, - "type": { - "name": "type", - "type": "text", - "primaryKey": false, - "notNull": true - }, - "auth_type": { - "name": "auth_type", - "type": "text", - "primaryKey": false, - "notNull": true - }, - "method": { - "name": "method", - "type": "text", - "primaryKey": false, - "notNull": true - }, - "path": { - "name": "path", - "type": "text", - "primaryKey": false, - "notNull": true - }, - "timestamp": { - "name": "timestamp", - "type": "timestamp with time zone", - "primaryKey": false, - "notNull": true, - "default": "now()" - }, - "properties": { - "name": "properties", - "type": "jsonb", - "primaryKey": false, - "notNull": false - } - }, - "indexes": {}, - "foreignKeys": { - "actions_org_id_fkey": { - "name": "actions_org_id_fkey", - "tableFrom": "actions", - "tableTo": "organizations", - "columnsFrom": [ - "org_id" - ], - "columnsTo": [ - "id" - ], - "onDelete": "set null", - "onUpdate": "no action" - }, - "actions_customer_id_fkey": { - "name": "actions_customer_id_fkey", - "tableFrom": "actions", - "tableTo": "customers", - "columnsFrom": [ - "internal_customer_id" - ], - "columnsTo": [ - "internal_id" - ], - "onDelete": "set null", - "onUpdate": "no action" - }, - "actions_entity_id_fkey": { - "name": "actions_entity_id_fkey", - "tableFrom": "actions", - "tableTo": "entities", - "columnsFrom": [ - "internal_entity_id" - ], - "columnsTo": [ - "internal_id" - ], - "onDelete": "set null", - "onUpdate": "no action" - } - }, - "compositePrimaryKeys": {}, - "uniqueConstraints": {}, - "policies": {}, - "checkConstraints": {}, - "isRLSEnabled": true - }, - "public.api_keys": { - "name": "api_keys", - "schema": "", - "columns": { - "id": { - "name": "id", - "type": "text COLLATE \"C\"", - "primaryKey": true, - "notNull": true - }, - "created_at": { - "name": "created_at", - "type": "numeric", - "primaryKey": false, - "notNull": true, - "default": "ROUND(date_part('epoch', NOW()) * 1000)::BIGINT" - }, - "name": { - "name": "name", - "type": "text", - "primaryKey": false, - "notNull": false - }, - "prefix": { - "name": "prefix", - "type": "text", - "primaryKey": false, - "notNull": false - }, - "org_id": { - "name": "org_id", - "type": "text", - "primaryKey": false, - "notNull": false - }, - "user_id": { - "name": "user_id", - "type": "text", - "primaryKey": false, - "notNull": false - }, - "env": { - "name": "env", - "type": "text", - "primaryKey": false, - "notNull": false - }, - "hashed_key": { - "name": "hashed_key", - "type": "text", - "primaryKey": false, - "notNull": false - }, - "meta": { - "name": "meta", - "type": "jsonb", - "primaryKey": false, - "notNull": false - } - }, - "indexes": {}, - "foreignKeys": { - "api_keys_org_id_fkey": { - "name": "api_keys_org_id_fkey", - "tableFrom": "api_keys", - "tableTo": "organizations", - "columnsFrom": [ - "org_id" - ], - "columnsTo": [ - "id" - ], - "onDelete": "cascade", - "onUpdate": "no action" - } - }, - "compositePrimaryKeys": {}, - "uniqueConstraints": { - "api_keys_hashed_key_key": { - "name": "api_keys_hashed_key_key", - "nullsNotDistinct": false, - "columns": [ - "hashed_key" - ] - } - }, - "policies": {}, - "checkConstraints": {}, - "isRLSEnabled": false - }, - "public.chat_results": { - "name": "chat_results", - "schema": "", - "columns": { - "id": { - "name": "id", - "type": "text COLLATE \"C\"", - "primaryKey": true, - "notNull": true - }, - "created_at": { - "name": "created_at", - "type": "numeric", - "primaryKey": false, - "notNull": false - }, - "data": { - "name": "data", - "type": "jsonb", - "primaryKey": false, - "notNull": true - } - }, - "indexes": {}, - "foreignKeys": {}, - "compositePrimaryKeys": {}, - "uniqueConstraints": {}, - "policies": {}, - "checkConstraints": {}, - "isRLSEnabled": true - }, - "public.customer_entitlements": { - "name": "customer_entitlements", - "schema": "", - "columns": { - "id": { - "name": "id", - "type": "text COLLATE \"C\"", - "primaryKey": true, - "notNull": true - }, - "customer_product_id": { - "name": "customer_product_id", - "type": "text", - "primaryKey": false, - "notNull": true - }, - "entitlement_id": { - "name": "entitlement_id", - "type": "text", - "primaryKey": false, - "notNull": true - }, - "internal_customer_id": { - "name": "internal_customer_id", - "type": "text", - "primaryKey": false, - "notNull": true - }, - "internal_feature_id": { - "name": "internal_feature_id", - "type": "text", - "primaryKey": false, - "notNull": true - }, - "unlimited": { - "name": "unlimited", - "type": "boolean", - "primaryKey": false, - "notNull": false, - "default": false - }, - "balance": { - "name": "balance", - "type": "numeric", - "primaryKey": false, - "notNull": true, - "default": 0 - }, - "created_at": { - "name": "created_at", - "type": "numeric", - "primaryKey": false, - "notNull": true - }, - "next_reset_at": { - "name": "next_reset_at", - "type": "numeric", - "primaryKey": false, - "notNull": false - }, - "usage_allowed": { - "name": "usage_allowed", - "type": "boolean", - "primaryKey": false, - "notNull": false, - "default": false - }, - "adjustment": { - "name": "adjustment", - "type": "numeric", - "primaryKey": false, - "notNull": false - }, - "entities": { - "name": "entities", - "type": "jsonb", - "primaryKey": false, - "notNull": false - }, - "customer_id": { - "name": "customer_id", - "type": "text", - "primaryKey": false, - "notNull": false - }, - "feature_id": { - "name": "feature_id", - "type": "text", - "primaryKey": false, - "notNull": false - } - }, - "indexes": {}, - "foreignKeys": { - "entitlements_internal_feature_id_fkey": { - "name": "entitlements_internal_feature_id_fkey", - "tableFrom": "customer_entitlements", - "tableTo": "features", - "columnsFrom": [ - "internal_feature_id" - ], - "columnsTo": [ - "internal_id" - ], - "onDelete": "cascade", - "onUpdate": "no action" - }, - "customer_entitlements_customer_product_id_fkey": { - "name": "customer_entitlements_customer_product_id_fkey", - "tableFrom": "customer_entitlements", - "tableTo": "customer_products", - "columnsFrom": [ - "customer_product_id" - ], - "columnsTo": [ - "id" - ], - "onDelete": "cascade", - "onUpdate": "cascade" - } - }, - "compositePrimaryKeys": {}, - "uniqueConstraints": { - "entitlements_id_key": { - "name": "entitlements_id_key", - "nullsNotDistinct": false, - "columns": [ - "id" - ] - } - }, - "policies": {}, - "checkConstraints": {}, - "isRLSEnabled": false - }, - "public.customer_prices": { - "name": "customer_prices", - "schema": "", - "columns": { - "id": { - "name": "id", - "type": "text", - "primaryKey": true, - "notNull": true - }, - "created_at": { - "name": "created_at", - "type": "numeric", - "primaryKey": false, - "notNull": true - }, - "price_id": { - "name": "price_id", - "type": "text", - "primaryKey": false, - "notNull": false - }, - "options": { - "name": "options", - "type": "jsonb", - "primaryKey": false, - "notNull": false - }, - "internal_customer_id": { - "name": "internal_customer_id", - "type": "text", - "primaryKey": false, - "notNull": false - }, - "customer_product_id": { - "name": "customer_product_id", - "type": "text", - "primaryKey": false, - "notNull": false - } - }, - "indexes": {}, - "foreignKeys": { - "customer_prices_customer_product_id_fkey": { - "name": "customer_prices_customer_product_id_fkey", - "tableFrom": "customer_prices", - "tableTo": "customer_products", - "columnsFrom": [ - "customer_product_id" - ], - "columnsTo": [ - "id" - ], - "onDelete": "cascade", - "onUpdate": "no action" - }, - "customer_prices_internal_customer_id_fkey": { - "name": "customer_prices_internal_customer_id_fkey", - "tableFrom": "customer_prices", - "tableTo": "customers", - "columnsFrom": [ - "internal_customer_id" - ], - "columnsTo": [ - "internal_id" - ], - "onDelete": "cascade", - "onUpdate": "no action" - }, - "customer_prices_price_id_fkey": { - "name": "customer_prices_price_id_fkey", - "tableFrom": "customer_prices", - "tableTo": "prices", - "columnsFrom": [ - "price_id" - ], - "columnsTo": [ - "id" - ], - "onDelete": "no action", - "onUpdate": "no action" - } - }, - "compositePrimaryKeys": {}, - "uniqueConstraints": {}, - "policies": {}, - "checkConstraints": {}, - "isRLSEnabled": false - }, - "public.customer_products": { - "name": "customer_products", - "schema": "", - "columns": { - "id": { - "name": "id", - "type": "text COLLATE \"C\"", - "primaryKey": true, - "notNull": true - }, - "internal_customer_id": { - "name": "internal_customer_id", - "type": "text", - "primaryKey": false, - "notNull": true - }, - "internal_product_id": { - "name": "internal_product_id", - "type": "text", - "primaryKey": false, - "notNull": true - }, - "internal_entity_id": { - "name": "internal_entity_id", - "type": "text", - "primaryKey": false, - "notNull": false - }, - "created_at": { - "name": "created_at", - "type": "numeric", - "primaryKey": false, - "notNull": false - }, - "status": { - "name": "status", - "type": "text", - "primaryKey": false, - "notNull": false - }, - "processor": { - "name": "processor", - "type": "jsonb", - "primaryKey": false, - "notNull": false - }, - "canceled_at": { - "name": "canceled_at", - "type": "numeric", - "primaryKey": false, - "notNull": false - }, - "ended_at": { - "name": "ended_at", - "type": "numeric", - "primaryKey": false, - "notNull": false - }, - "starts_at": { - "name": "starts_at", - "type": "numeric", - "primaryKey": false, - "notNull": false - }, - "options": { - "name": "options", - "type": "jsonb[]", - "primaryKey": false, - "notNull": false - }, - "product_id": { - "name": "product_id", - "type": "text", - "primaryKey": false, - "notNull": false - }, - "free_trial_id": { - "name": "free_trial_id", - "type": "text", - "primaryKey": false, - "notNull": false - }, - "trial_ends_at": { - "name": "trial_ends_at", - "type": "numeric", - "primaryKey": false, - "notNull": false - }, - "collection_method": { - "name": "collection_method", - "type": "text", - "primaryKey": false, - "notNull": false, - "default": "'charge_automatically'" - }, - "subscription_ids": { - "name": "subscription_ids", - "type": "text[]", - "primaryKey": false, - "notNull": false - }, - "scheduled_ids": { - "name": "scheduled_ids", - "type": "text[]", - "primaryKey": false, - "notNull": false - }, - "quantity": { - "name": "quantity", - "type": "numeric", - "primaryKey": false, - "notNull": false, - "default": 1 - }, - "is_custom": { - "name": "is_custom", - "type": "boolean", - "primaryKey": false, - "notNull": true, - "default": false - }, - "customer_id": { - "name": "customer_id", - "type": "text", - "primaryKey": false, - "notNull": false - }, - "entity_id": { - "name": "entity_id", - "type": "text", - "primaryKey": false, - "notNull": false - }, - "api_version": { - "name": "api_version", - "type": "numeric", - "primaryKey": false, - "notNull": false - } - }, - "indexes": {}, - "foreignKeys": { - "customer_products_free_trial_id_fkey": { - "name": "customer_products_free_trial_id_fkey", - "tableFrom": "customer_products", - "tableTo": "free_trials", - "columnsFrom": [ - "free_trial_id" - ], - "columnsTo": [ - "id" - ], - "onDelete": "no action", - "onUpdate": "no action" - }, - "customer_products_internal_customer_id_fkey": { - "name": "customer_products_internal_customer_id_fkey", - "tableFrom": "customer_products", - "tableTo": "customers", - "columnsFrom": [ - "internal_customer_id" - ], - "columnsTo": [ - "internal_id" - ], - "onDelete": "cascade", - "onUpdate": "cascade" - }, - "customer_products_internal_product_id_fkey": { - "name": "customer_products_internal_product_id_fkey", - "tableFrom": "customer_products", - "tableTo": "products", - "columnsFrom": [ - "internal_product_id" - ], - "columnsTo": [ - "internal_id" - ], - "onDelete": "no action", - "onUpdate": "no action" - }, - "customer_products_internal_entity_id_fkey": { - "name": "customer_products_internal_entity_id_fkey", - "tableFrom": "customer_products", - "tableTo": "entities", - "columnsFrom": [ - "internal_entity_id" - ], - "columnsTo": [ - "internal_id" - ], - "onDelete": "set null", - "onUpdate": "no action" - } - }, - "compositePrimaryKeys": {}, - "uniqueConstraints": {}, - "policies": {}, - "checkConstraints": {}, - "isRLSEnabled": false - }, - "public.customers": { - "name": "customers", - "schema": "", - "columns": { - "internal_id": { - "name": "internal_id", - "type": "text COLLATE \"C\"", - "primaryKey": true, - "notNull": true - }, - "org_id": { - "name": "org_id", - "type": "text", - "primaryKey": false, - "notNull": true - }, - "created_at": { - "name": "created_at", - "type": "numeric", - "primaryKey": false, - "notNull": true - }, - "name": { - "name": "name", - "type": "text", - "primaryKey": false, - "notNull": false - }, - "id": { - "name": "id", - "type": "text", - "primaryKey": false, - "notNull": false - }, - "email": { - "name": "email", - "type": "text", - "primaryKey": false, - "notNull": false - }, - "fingerprint": { - "name": "fingerprint", - "type": "text", - "primaryKey": false, - "notNull": false, - "default": "null" - }, - "metadata": { - "name": "metadata", - "type": "jsonb", - "primaryKey": false, - "notNull": false - }, - "env": { - "name": "env", - "type": "text", - "primaryKey": false, - "notNull": true - }, - "processor": { - "name": "processor", - "type": "jsonb", - "primaryKey": false, - "notNull": false - } - }, - "indexes": {}, - "foreignKeys": { - "customers_org_id_fkey": { - "name": "customers_org_id_fkey", - "tableFrom": "customers", - "tableTo": "organizations", - "columnsFrom": [ - "org_id" - ], - "columnsTo": [ - "id" - ], - "onDelete": "cascade", - "onUpdate": "no action" - } - }, - "compositePrimaryKeys": {}, - "uniqueConstraints": { - "cus_id_constraint": { - "name": "cus_id_constraint", - "nullsNotDistinct": false, - "columns": [ - "org_id", - "id", - "env" - ] - } - }, - "policies": {}, - "checkConstraints": {}, - "isRLSEnabled": true - }, - "public.entities": { - "name": "entities", - "schema": "", - "columns": { - "id": { - "name": "id", - "type": "text", - "primaryKey": false, - "notNull": false - }, - "org_id": { - "name": "org_id", - "type": "text", - "primaryKey": false, - "notNull": false - }, - "created_at": { - "name": "created_at", - "type": "numeric", - "primaryKey": false, - "notNull": true - }, - "internal_id": { - "name": "internal_id", - "type": "text", - "primaryKey": true, - "notNull": true - }, - "internal_customer_id": { - "name": "internal_customer_id", - "type": "text", - "primaryKey": false, - "notNull": true - }, - "env": { - "name": "env", - "type": "text", - "primaryKey": false, - "notNull": false - }, - "name": { - "name": "name", - "type": "text", - "primaryKey": false, - "notNull": false - }, - "deleted": { - "name": "deleted", - "type": "boolean", - "primaryKey": false, - "notNull": true, - "default": false - }, - "internal_feature_id": { - "name": "internal_feature_id", - "type": "text", - "primaryKey": false, - "notNull": false - }, - "feature_id": { - "name": "feature_id", - "type": "text", - "primaryKey": false, - "notNull": false - } - }, - "indexes": {}, - "foreignKeys": { - "entities_internal_customer_id_fkey": { - "name": "entities_internal_customer_id_fkey", - "tableFrom": "entities", - "tableTo": "customers", - "columnsFrom": [ - "internal_customer_id" - ], - "columnsTo": [ - "internal_id" - ], - "onDelete": "cascade", - "onUpdate": "no action" - }, - "entities_internal_feature_id_fkey": { - "name": "entities_internal_feature_id_fkey", - "tableFrom": "entities", - "tableTo": "features", - "columnsFrom": [ - "internal_feature_id" - ], - "columnsTo": [ - "internal_id" - ], - "onDelete": "cascade", - "onUpdate": "no action" - }, - "entities_org_id_fkey": { - "name": "entities_org_id_fkey", - "tableFrom": "entities", - "tableTo": "organizations", - "columnsFrom": [ - "org_id" - ], - "columnsTo": [ - "id" - ], - "onDelete": "cascade", - "onUpdate": "no action" - } - }, - "compositePrimaryKeys": {}, - "uniqueConstraints": { - "entity_id_constraint": { - "name": "entity_id_constraint", - "nullsNotDistinct": false, - "columns": [ - "org_id", - "env", - "internal_customer_id", - "id" - ] - } - }, - "policies": {}, - "checkConstraints": {}, - "isRLSEnabled": false - }, - "public.entitlements": { - "name": "entitlements", - "schema": "", - "columns": { - "id": { - "name": "id", - "type": "text COLLATE \"C\"", - "primaryKey": true, - "notNull": true - }, - "created_at": { - "name": "created_at", - "type": "numeric", - "primaryKey": false, - "notNull": true - }, - "internal_feature_id": { - "name": "internal_feature_id", - "type": "text", - "primaryKey": false, - "notNull": true - }, - "internal_product_id": { - "name": "internal_product_id", - "type": "text", - "primaryKey": false, - "notNull": true - }, - "is_custom": { - "name": "is_custom", - "type": "boolean", - "primaryKey": false, - "notNull": false, - "default": false - }, - "allowance_type": { - "name": "allowance_type", - "type": "text", - "primaryKey": false, - "notNull": false - }, - "allowance": { - "name": "allowance", - "type": "numeric", - "primaryKey": false, - "notNull": false - }, - "interval": { - "name": "interval", - "type": "text", - "primaryKey": false, - "notNull": false - }, - "carry_from_previous": { - "name": "carry_from_previous", - "type": "boolean", - "primaryKey": false, - "notNull": false, - "default": false - }, - "entity_feature_id": { - "name": "entity_feature_id", - "type": "text", - "primaryKey": false, - "notNull": false, - "default": "null" - }, - "org_id": { - "name": "org_id", - "type": "text", - "primaryKey": false, - "notNull": false - }, - "feature_id": { - "name": "feature_id", - "type": "text", - "primaryKey": false, - "notNull": false - } - }, - "indexes": {}, - "foreignKeys": { - "entitlements_internal_feature_id_fkey": { - "name": "entitlements_internal_feature_id_fkey", - "tableFrom": "entitlements", - "tableTo": "features", - "columnsFrom": [ - "internal_feature_id" - ], - "columnsTo": [ - "internal_id" - ], - "onDelete": "cascade", - "onUpdate": "no action" - }, - "entitlements_internal_product_id_fkey": { - "name": "entitlements_internal_product_id_fkey", - "tableFrom": "entitlements", - "tableTo": "products", - "columnsFrom": [ - "internal_product_id" - ], - "columnsTo": [ - "internal_id" - ], - "onDelete": "cascade", - "onUpdate": "cascade" - } - }, - "compositePrimaryKeys": {}, - "uniqueConstraints": { - "entitlements_id_key": { - "name": "entitlements_id_key", - "nullsNotDistinct": false, - "columns": [ - "id" - ] - } - }, - "policies": {}, - "checkConstraints": {}, - "isRLSEnabled": false - }, - "public.events": { - "name": "events", - "schema": "", - "columns": { - "id": { - "name": "id", - "type": "text", - "primaryKey": true, - "notNull": true - }, - "org_id": { - "name": "org_id", - "type": "text", - "primaryKey": false, - "notNull": true - }, - "org_slug": { - "name": "org_slug", - "type": "text", - "primaryKey": false, - "notNull": true - }, - "internal_customer_id": { - "name": "internal_customer_id", - "type": "text", - "primaryKey": false, - "notNull": false - }, - "env": { - "name": "env", - "type": "text", - "primaryKey": false, - "notNull": true - }, - "created_at": { - "name": "created_at", - "type": "bigint", - "primaryKey": false, - "notNull": false - }, - "timestamp": { - "name": "timestamp", - "type": "timestamp with time zone", - "primaryKey": false, - "notNull": false - }, - "event_name": { - "name": "event_name", - "type": "text", - "primaryKey": false, - "notNull": true - }, - "idempotency_key": { - "name": "idempotency_key", - "type": "text", - "primaryKey": false, - "notNull": false, - "default": "null" - }, - "value": { - "name": "value", - "type": "numeric", - "primaryKey": false, - "notNull": false - }, - "set_usage": { - "name": "set_usage", - "type": "boolean", - "primaryKey": false, - "notNull": false, - "default": false - }, - "entity_id": { - "name": "entity_id", - "type": "text", - "primaryKey": false, - "notNull": false - }, - "customer_id": { - "name": "customer_id", - "type": "text", - "primaryKey": false, - "notNull": true - }, - "properties": { - "name": "properties", - "type": "jsonb", - "primaryKey": false, - "notNull": false - } - }, - "indexes": {}, - "foreignKeys": { - "events_internal_customer_id_fkey": { - "name": "events_internal_customer_id_fkey", - "tableFrom": "events", - "tableTo": "customers", - "columnsFrom": [ - "internal_customer_id" - ], - "columnsTo": [ - "internal_id" - ], - "onDelete": "cascade", - "onUpdate": "no action" - } - }, - "compositePrimaryKeys": {}, - "uniqueConstraints": { - "unique_event_constraint": { - "name": "unique_event_constraint", - "nullsNotDistinct": false, - "columns": [ - "org_id", - "env", - "customer_id", - "event_name", - "idempotency_key" - ] - } - }, - "policies": {}, - "checkConstraints": {}, - "isRLSEnabled": false - }, - "public.features": { - "name": "features", - "schema": "", - "columns": { - "internal_id": { - "name": "internal_id", - "type": "text COLLATE \"C\"", - "primaryKey": true, - "notNull": true - }, - "org_id": { - "name": "org_id", - "type": "text", - "primaryKey": false, - "notNull": true - }, - "created_at": { - "name": "created_at", - "type": "numeric", - "primaryKey": false, - "notNull": false - }, - "env": { - "name": "env", - "type": "text", - "primaryKey": false, - "notNull": false - }, - "id": { - "name": "id", - "type": "text", - "primaryKey": false, - "notNull": true - }, - "name": { - "name": "name", - "type": "text", - "primaryKey": false, - "notNull": false - }, - "type": { - "name": "type", - "type": "text", - "primaryKey": false, - "notNull": true - }, - "config": { - "name": "config", - "type": "jsonb", - "primaryKey": false, - "notNull": false - }, - "display": { - "name": "display", - "type": "jsonb", - "primaryKey": false, - "notNull": false, - "default": "null" - } - }, - "indexes": {}, - "foreignKeys": { - "features_org_id_fkey": { - "name": "features_org_id_fkey", - "tableFrom": "features", - "tableTo": "organizations", - "columnsFrom": [ - "org_id" - ], - "columnsTo": [ - "id" - ], - "onDelete": "cascade", - "onUpdate": "no action" - } - }, - "compositePrimaryKeys": {}, - "uniqueConstraints": { - "feature_id_constraint": { - "name": "feature_id_constraint", - "nullsNotDistinct": false, - "columns": [ - "org_id", - "id", - "env" - ] - } - }, - "policies": {}, - "checkConstraints": {}, - "isRLSEnabled": false - }, - "public.free_trials": { - "name": "free_trials", - "schema": "", - "columns": { - "id": { - "name": "id", - "type": "text", - "primaryKey": true, - "notNull": true - }, - "created_at": { - "name": "created_at", - "type": "numeric", - "primaryKey": false, - "notNull": true - }, - "internal_product_id": { - "name": "internal_product_id", - "type": "text", - "primaryKey": false, - "notNull": false - }, - "duration": { - "name": "duration", - "type": "text", - "primaryKey": false, - "notNull": false, - "default": "'day'" - }, - "length": { - "name": "length", - "type": "numeric", - "primaryKey": false, - "notNull": false - }, - "unique_fingerprint": { - "name": "unique_fingerprint", - "type": "boolean", - "primaryKey": false, - "notNull": false - }, - "is_custom": { - "name": "is_custom", - "type": "boolean", - "primaryKey": false, - "notNull": false, - "default": false - } - }, - "indexes": {}, - "foreignKeys": { - "free_trials_internal_product_id_fkey": { - "name": "free_trials_internal_product_id_fkey", - "tableFrom": "free_trials", - "tableTo": "products", - "columnsFrom": [ - "internal_product_id" - ], - "columnsTo": [ - "internal_id" - ], - "onDelete": "cascade", - "onUpdate": "no action" - } - }, - "compositePrimaryKeys": {}, - "uniqueConstraints": {}, - "policies": {}, - "checkConstraints": {}, - "isRLSEnabled": false - }, - "public.invoices": { - "name": "invoices", - "schema": "", - "columns": { - "id": { - "name": "id", - "type": "text COLLATE \"C\"", - "primaryKey": true, - "notNull": true - }, - "created_at": { - "name": "created_at", - "type": "numeric", - "primaryKey": false, - "notNull": true, - "default": "ROUND(date_part('epoch', NOW()) * 1000)::BIGINT" - }, - "product_ids": { - "name": "product_ids", - "type": "text[]", - "primaryKey": false, - "notNull": false, - "default": "'{}'" - }, - "internal_product_ids": { - "name": "internal_product_ids", - "type": "text[]", - "primaryKey": false, - "notNull": false, - "default": "'{}'" - }, - "internal_customer_id": { - "name": "internal_customer_id", - "type": "text", - "primaryKey": false, - "notNull": true - }, - "internal_entity_id": { - "name": "internal_entity_id", - "type": "text", - "primaryKey": false, - "notNull": false - }, - "stripe_id": { - "name": "stripe_id", - "type": "text", - "primaryKey": false, - "notNull": true - }, - "status": { - "name": "status", - "type": "text", - "primaryKey": false, - "notNull": true, - "default": "'draft'" - }, - "hosted_invoice_url": { - "name": "hosted_invoice_url", - "type": "text", - "primaryKey": false, - "notNull": false - }, - "total": { - "name": "total", - "type": "numeric", - "primaryKey": false, - "notNull": true, - "default": 0 - }, - "currency": { - "name": "currency", - "type": "text", - "primaryKey": false, - "notNull": true, - "default": "'usd'" - }, - "discounts": { - "name": "discounts", - "type": "jsonb[]", - "primaryKey": false, - "notNull": false, - "default": "'{}'" - }, - "items": { - "name": "items", - "type": "jsonb[]", - "primaryKey": false, - "notNull": false, - "default": "'{}'" - } - }, - "indexes": {}, - "foreignKeys": { - "invoices_internal_customer_id_fkey": { - "name": "invoices_internal_customer_id_fkey", - "tableFrom": "invoices", - "tableTo": "customers", - "columnsFrom": [ - "internal_customer_id" - ], - "columnsTo": [ - "id" - ], - "onDelete": "no action", - "onUpdate": "no action" - }, - "invoices_internal_entity_id_fkey": { - "name": "invoices_internal_entity_id_fkey", - "tableFrom": "invoices", - "tableTo": "entities", - "columnsFrom": [ - "internal_entity_id" - ], - "columnsTo": [ - "id" - ], - "onDelete": "no action", - "onUpdate": "no action" - } - }, - "compositePrimaryKeys": {}, - "uniqueConstraints": {}, - "policies": {}, - "checkConstraints": {}, - "isRLSEnabled": false - }, - "public.metadata": { - "name": "metadata", - "schema": "", - "columns": { - "id": { - "name": "id", - "type": "text", - "primaryKey": true, - "notNull": true - }, - "created_at": { - "name": "created_at", - "type": "numeric", - "primaryKey": false, - "notNull": true, - "default": "ROUND(date_part('epoch', NOW()) * 1000)::BIGINT" - }, - "expires_at": { - "name": "expires_at", - "type": "numeric", - "primaryKey": false, - "notNull": false - }, - "data": { - "name": "data", - "type": "jsonb", - "primaryKey": false, - "notNull": false - } - }, - "indexes": {}, - "foreignKeys": {}, - "compositePrimaryKeys": {}, - "uniqueConstraints": {}, - "policies": {}, - "checkConstraints": {}, - "isRLSEnabled": false - }, - "public.migration_errors": { - "name": "migration_errors", - "schema": "", - "columns": { - "internal_customer_id": { - "name": "internal_customer_id", - "type": "text", - "primaryKey": false, - "notNull": true - }, - "migration_job_id": { - "name": "migration_job_id", - "type": "text", - "primaryKey": false, - "notNull": true - }, - "created_at": { - "name": "created_at", - "type": "numeric", - "primaryKey": false, - "notNull": false - }, - "updated_at": { - "name": "updated_at", - "type": "numeric", - "primaryKey": false, - "notNull": false - }, - "data": { - "name": "data", - "type": "jsonb", - "primaryKey": false, - "notNull": false - }, - "message": { - "name": "message", - "type": "text", - "primaryKey": false, - "notNull": false - }, - "code": { - "name": "code", - "type": "text", - "primaryKey": false, - "notNull": false - } - }, - "indexes": {}, - "foreignKeys": { - "migration_customers_internal_customer_id_fkey": { - "name": "migration_customers_internal_customer_id_fkey", - "tableFrom": "migration_errors", - "tableTo": "customers", - "columnsFrom": [ - "internal_customer_id" - ], - "columnsTo": [ - "internal_id" - ], - "onDelete": "cascade", - "onUpdate": "no action" - }, - "migration_customers_migration_job_id_fkey": { - "name": "migration_customers_migration_job_id_fkey", - "tableFrom": "migration_errors", - "tableTo": "migration_jobs", - "columnsFrom": [ - "migration_job_id" - ], - "columnsTo": [ - "id" - ], - "onDelete": "cascade", - "onUpdate": "no action" - } - }, - "compositePrimaryKeys": { - "migration_errors_pkey": { - "name": "migration_errors_pkey", - "columns": [ - "internal_customer_id", - "migration_job_id" - ] - } - }, - "uniqueConstraints": {}, - "policies": {}, - "checkConstraints": {}, - "isRLSEnabled": false - }, - "public.migration_jobs": { - "name": "migration_jobs", - "schema": "", - "columns": { - "id": { - "name": "id", - "type": "text", - "primaryKey": true, - "notNull": true - }, - "org_id": { - "name": "org_id", - "type": "text", - "primaryKey": false, - "notNull": true - }, - "env": { - "name": "env", - "type": "text", - "primaryKey": false, - "notNull": true - }, - "created_at": { - "name": "created_at", - "type": "numeric", - "primaryKey": false, - "notNull": true - }, - "updated_at": { - "name": "updated_at", - "type": "numeric", - "primaryKey": false, - "notNull": false - }, - "current_step": { - "name": "current_step", - "type": "text", - "primaryKey": false, - "notNull": false - }, - "from_internal_product_id": { - "name": "from_internal_product_id", - "type": "text", - "primaryKey": false, - "notNull": false - }, - "to_internal_product_id": { - "name": "to_internal_product_id", - "type": "text", - "primaryKey": false, - "notNull": false - }, - "step_details": { - "name": "step_details", - "type": "jsonb", - "primaryKey": false, - "notNull": false - } - }, - "indexes": {}, - "foreignKeys": { - "migration_jobs_from_internal_product_id_fkey": { - "name": "migration_jobs_from_internal_product_id_fkey", - "tableFrom": "migration_jobs", - "tableTo": "products", - "columnsFrom": [ - "from_internal_product_id" - ], - "columnsTo": [ - "internal_id" - ], - "onDelete": "cascade", - "onUpdate": "no action" - }, - "migration_jobs_org_id_fkey": { - "name": "migration_jobs_org_id_fkey", - "tableFrom": "migration_jobs", - "tableTo": "organizations", - "columnsFrom": [ - "org_id" - ], - "columnsTo": [ - "id" - ], - "onDelete": "cascade", - "onUpdate": "no action" - }, - "migration_jobs_to_internal_product_id_fkey": { - "name": "migration_jobs_to_internal_product_id_fkey", - "tableFrom": "migration_jobs", - "tableTo": "products", - "columnsFrom": [ - "to_internal_product_id" - ], - "columnsTo": [ - "internal_id" - ], - "onDelete": "cascade", - "onUpdate": "no action" - } - }, - "compositePrimaryKeys": {}, - "uniqueConstraints": {}, - "policies": {}, - "checkConstraints": {}, - "isRLSEnabled": false - }, - "public.organizations": { - "name": "organizations", - "schema": "", - "columns": { - "id": { - "name": "id", - "type": "text", - "primaryKey": true, - "notNull": true - }, - "slug": { - "name": "slug", - "type": "text", - "primaryKey": false, - "notNull": true - }, - "default_currency": { - "name": "default_currency", - "type": "text", - "primaryKey": false, - "notNull": true, - "default": "'usd'" - }, - "stripe_connected": { - "name": "stripe_connected", - "type": "boolean", - "primaryKey": false, - "notNull": false, - "default": false - }, - "stripe_config": { - "name": "stripe_config", - "type": "jsonb", - "primaryKey": false, - "notNull": false - }, - "test_pkey": { - "name": "test_pkey", - "type": "text", - "primaryKey": false, - "notNull": false - }, - "live_pkey": { - "name": "live_pkey", - "type": "text", - "primaryKey": false, - "notNull": false - }, - "svix_config": { - "name": "svix_config", - "type": "jsonb", - "primaryKey": false, - "notNull": true - }, - "created_at": { - "name": "created_at", - "type": "numeric", - "primaryKey": false, - "notNull": false - }, - "config": { - "name": "config", - "type": "jsonb", - "primaryKey": false, - "notNull": true, - "default": "'{}'::jsonb" - } - }, - "indexes": {}, - "foreignKeys": {}, - "compositePrimaryKeys": {}, - "uniqueConstraints": { - "organizations_test_pkey_key": { - "name": "organizations_test_pkey_key", - "nullsNotDistinct": false, - "columns": [ - "test_pkey" - ] - }, - "organizations_live_pkey_key": { - "name": "organizations_live_pkey_key", - "nullsNotDistinct": false, - "columns": [ - "live_pkey" - ] - } - }, - "policies": {}, - "checkConstraints": {}, - "isRLSEnabled": false - }, - "public.prices": { - "name": "prices", - "schema": "", - "columns": { - "id": { - "name": "id", - "type": "text COLLATE \"C\"", - "primaryKey": true, - "notNull": true - }, - "org_id": { - "name": "org_id", - "type": "text", - "primaryKey": false, - "notNull": true - }, - "internal_product_id": { - "name": "internal_product_id", - "type": "text", - "primaryKey": false, - "notNull": true - }, - "config": { - "name": "config", - "type": "jsonb", - "primaryKey": false, - "notNull": false - }, - "created_at": { - "name": "created_at", - "type": "numeric", - "primaryKey": false, - "notNull": true - }, - "billing_type": { - "name": "billing_type", - "type": "text", - "primaryKey": false, - "notNull": false - }, - "is_custom": { - "name": "is_custom", - "type": "boolean", - "primaryKey": false, - "notNull": false, - "default": false - }, - "entitlement_id": { - "name": "entitlement_id", - "type": "text", - "primaryKey": false, - "notNull": false, - "default": "null" - }, - "proration_config": { - "name": "proration_config", - "type": "jsonb", - "primaryKey": false, - "notNull": false, - "default": "null" - } - }, - "indexes": {}, - "foreignKeys": { - "prices_entitlement_id_fkey": { - "name": "prices_entitlement_id_fkey", - "tableFrom": "prices", - "tableTo": "entitlements", - "columnsFrom": [ - "entitlement_id" - ], - "columnsTo": [ - "id" - ], - "onDelete": "no action", - "onUpdate": "no action" - }, - "prices_internal_product_id_fkey": { - "name": "prices_internal_product_id_fkey", - "tableFrom": "prices", - "tableTo": "products", - "columnsFrom": [ - "internal_product_id" - ], - "columnsTo": [ - "internal_id" - ], - "onDelete": "cascade", - "onUpdate": "cascade" - } - }, - "compositePrimaryKeys": {}, - "uniqueConstraints": { - "prices_id_key": { - "name": "prices_id_key", - "nullsNotDistinct": false, - "columns": [ - "id" - ] - } - }, - "policies": {}, - "checkConstraints": {}, - "isRLSEnabled": false - }, - "public.products": { - "name": "products", - "schema": "", - "columns": { - "internal_id": { - "name": "internal_id", - "type": "text COLLATE \"C\"", - "primaryKey": true, - "notNull": true - }, - "id": { - "name": "id", - "type": "text", - "primaryKey": false, - "notNull": true - }, - "name": { - "name": "name", - "type": "text", - "primaryKey": false, - "notNull": false - }, - "org_id": { - "name": "org_id", - "type": "text", - "primaryKey": false, - "notNull": true - }, - "created_at": { - "name": "created_at", - "type": "numeric", - "primaryKey": false, - "notNull": true, - "default": "ROUND(date_part('epoch', NOW()) * 1000)::BIGINT" - }, - "env": { - "name": "env", - "type": "text", - "primaryKey": false, - "notNull": true - }, - "is_add_on": { - "name": "is_add_on", - "type": "boolean", - "primaryKey": false, - "notNull": true, - "default": false - }, - "is_default": { - "name": "is_default", - "type": "boolean", - "primaryKey": false, - "notNull": true, - "default": false - }, - "group": { - "name": "group", - "type": "text", - "primaryKey": false, - "notNull": false, - "default": "''" - }, - "version": { - "name": "version", - "type": "numeric", - "primaryKey": false, - "notNull": true, - "default": 1 - }, - "processor": { - "name": "processor", - "type": "jsonb", - "primaryKey": false, - "notNull": false, - "default": "null" - } - }, - "indexes": {}, - "foreignKeys": { - "products_org_id_fkey": { - "name": "products_org_id_fkey", - "tableFrom": "products", - "tableTo": "organizations", - "columnsFrom": [ - "org_id" - ], - "columnsTo": [ - "id" - ], - "onDelete": "cascade", - "onUpdate": "no action" - } - }, - "compositePrimaryKeys": {}, - "uniqueConstraints": { - "unique_product": { - "name": "unique_product", - "nullsNotDistinct": false, - "columns": [ - "org_id", - "id", - "env", - "version" - ] - } - }, - "policies": {}, - "checkConstraints": {}, - "isRLSEnabled": false - }, - "public.referral_codes": { - "name": "referral_codes", - "schema": "", - "columns": { - "code": { - "name": "code", - "type": "text", - "primaryKey": false, - "notNull": true - }, - "org_id": { - "name": "org_id", - "type": "text", - "primaryKey": false, - "notNull": true - }, - "env": { - "name": "env", - "type": "text", - "primaryKey": false, - "notNull": true - }, - "internal_customer_id": { - "name": "internal_customer_id", - "type": "text", - "primaryKey": false, - "notNull": false - }, - "internal_reward_program_id": { - "name": "internal_reward_program_id", - "type": "text", - "primaryKey": false, - "notNull": false - }, - "id": { - "name": "id", - "type": "text", - "primaryKey": false, - "notNull": true - }, - "created_at": { - "name": "created_at", - "type": "numeric", - "primaryKey": false, - "notNull": false - } - }, - "indexes": {}, - "foreignKeys": { - "referral_codes_internal_customer_id_fkey": { - "name": "referral_codes_internal_customer_id_fkey", - "tableFrom": "referral_codes", - "tableTo": "customers", - "columnsFrom": [ - "internal_customer_id" - ], - "columnsTo": [ - "internal_id" - ], - "onDelete": "cascade", - "onUpdate": "no action" - }, - "referral_codes_internal_reward_program_id_fkey": { - "name": "referral_codes_internal_reward_program_id_fkey", - "tableFrom": "referral_codes", - "tableTo": "reward_programs", - "columnsFrom": [ - "internal_reward_program_id" - ], - "columnsTo": [ - "internal_id" - ], - "onDelete": "cascade", - "onUpdate": "no action" - }, - "referral_codes_org_id_fkey": { - "name": "referral_codes_org_id_fkey", - "tableFrom": "referral_codes", - "tableTo": "organizations", - "columnsFrom": [ - "org_id" - ], - "columnsTo": [ - "id" - ], - "onDelete": "cascade", - "onUpdate": "no action" - } - }, - "compositePrimaryKeys": { - "referral_codes_pkey": { - "name": "referral_codes_pkey", - "columns": [ - "code", - "org_id", - "env" - ] - } - }, - "uniqueConstraints": { - "referral_codes_id_key": { - "name": "referral_codes_id_key", - "nullsNotDistinct": false, - "columns": [ - "id" - ] - } - }, - "policies": {}, - "checkConstraints": {}, - "isRLSEnabled": false - }, - "public.replaceables": { - "name": "replaceables", - "schema": "", - "columns": { - "id": { - "name": "id", - "type": "text COLLATE \"C\"", - "primaryKey": true, - "notNull": true - }, - "cus_ent_id": { - "name": "cus_ent_id", - "type": "text", - "primaryKey": false, - "notNull": true - }, - "created_at": { - "name": "created_at", - "type": "bigint", - "primaryKey": false, - "notNull": true - }, - "from_entity_id": { - "name": "from_entity_id", - "type": "text", - "primaryKey": false, - "notNull": false - }, - "delete_next_cycle": { - "name": "delete_next_cycle", - "type": "boolean", - "primaryKey": false, - "notNull": true, - "default": false - } - }, - "indexes": {}, - "foreignKeys": { - "replaceables_cus_ent_id_fkey": { - "name": "replaceables_cus_ent_id_fkey", - "tableFrom": "replaceables", - "tableTo": "customer_entitlements", - "columnsFrom": [ - "cus_ent_id" - ], - "columnsTo": [ - "id" - ], - "onDelete": "cascade", - "onUpdate": "no action" - } - }, - "compositePrimaryKeys": {}, - "uniqueConstraints": {}, - "policies": {}, - "checkConstraints": {}, - "isRLSEnabled": false - }, - "public.reward_programs": { - "name": "reward_programs", - "schema": "", - "columns": { - "internal_id": { - "name": "internal_id", - "type": "text", - "primaryKey": true, - "notNull": true - }, - "id": { - "name": "id", - "type": "text", - "primaryKey": false, - "notNull": false - }, - "created_at": { - "name": "created_at", - "type": "numeric", - "primaryKey": false, - "notNull": false - }, - "internal_reward_id": { - "name": "internal_reward_id", - "type": "text", - "primaryKey": false, - "notNull": false - }, - "max_redemptions": { - "name": "max_redemptions", - "type": "numeric", - "primaryKey": false, - "notNull": false - }, - "unlimited_redemptions": { - "name": "unlimited_redemptions", - "type": "boolean", - "primaryKey": false, - "notNull": false, - "default": false - }, - "org_id": { - "name": "org_id", - "type": "text", - "primaryKey": false, - "notNull": false - }, - "env": { - "name": "env", - "type": "text", - "primaryKey": false, - "notNull": false - }, - "when": { - "name": "when", - "type": "text", - "primaryKey": false, - "notNull": false, - "default": "'immediately'" - }, - "product_ids": { - "name": "product_ids", - "type": "text[]", - "primaryKey": false, - "notNull": false, - "default": "'{\"\"}'" - }, - "exclude_trial": { - "name": "exclude_trial", - "type": "boolean", - "primaryKey": false, - "notNull": false, - "default": false - }, - "received_by": { - "name": "received_by", - "type": "text", - "primaryKey": false, - "notNull": false - } - }, - "indexes": {}, - "foreignKeys": { - "reward_triggers_internal_reward_id_fkey": { - "name": "reward_triggers_internal_reward_id_fkey", - "tableFrom": "reward_programs", - "tableTo": "rewards", - "columnsFrom": [ - "internal_reward_id" - ], - "columnsTo": [ - "internal_id" - ], - "onDelete": "cascade", - "onUpdate": "no action" - }, - "reward_triggers_org_id_fkey": { - "name": "reward_triggers_org_id_fkey", - "tableFrom": "reward_programs", - "tableTo": "organizations", - "columnsFrom": [ - "org_id" - ], - "columnsTo": [ - "id" - ], - "onDelete": "cascade", - "onUpdate": "no action" - } - }, - "compositePrimaryKeys": {}, - "uniqueConstraints": {}, - "policies": {}, - "checkConstraints": {}, - "isRLSEnabled": false - }, - "public.reward_redemptions": { - "name": "reward_redemptions", - "schema": "", - "columns": { - "id": { - "name": "id", - "type": "text", - "primaryKey": true, - "notNull": true - }, - "created_at": { - "name": "created_at", - "type": "numeric", - "primaryKey": false, - "notNull": false - }, - "updated_at": { - "name": "updated_at", - "type": "numeric", - "primaryKey": false, - "notNull": false - }, - "internal_customer_id": { - "name": "internal_customer_id", - "type": "text", - "primaryKey": false, - "notNull": false - }, - "triggered": { - "name": "triggered", - "type": "boolean", - "primaryKey": false, - "notNull": false - }, - "internal_reward_program_id": { - "name": "internal_reward_program_id", - "type": "text", - "primaryKey": false, - "notNull": false - }, - "applied": { - "name": "applied", - "type": "boolean", - "primaryKey": false, - "notNull": false, - "default": false - }, - "referral_code_id": { - "name": "referral_code_id", - "type": "text", - "primaryKey": false, - "notNull": false - } - }, - "indexes": {}, - "foreignKeys": { - "reward_redemptions_internal_customer_id_fkey": { - "name": "reward_redemptions_internal_customer_id_fkey", - "tableFrom": "reward_redemptions", - "tableTo": "customers", - "columnsFrom": [ - "internal_customer_id" - ], - "columnsTo": [ - "internal_id" - ], - "onDelete": "cascade", - "onUpdate": "no action" - }, - "reward_redemptions_internal_reward_program_id_fkey": { - "name": "reward_redemptions_internal_reward_program_id_fkey", - "tableFrom": "reward_redemptions", - "tableTo": "reward_programs", - "columnsFrom": [ - "internal_reward_program_id" - ], - "columnsTo": [ - "internal_id" - ], - "onDelete": "cascade", - "onUpdate": "no action" - }, - "reward_redemptions_referral_code_id_fkey": { - "name": "reward_redemptions_referral_code_id_fkey", - "tableFrom": "reward_redemptions", - "tableTo": "referral_codes", - "columnsFrom": [ - "referral_code_id" - ], - "columnsTo": [ - "id" - ], - "onDelete": "cascade", - "onUpdate": "no action" - } - }, - "compositePrimaryKeys": {}, - "uniqueConstraints": {}, - "policies": {}, - "checkConstraints": {}, - "isRLSEnabled": false - }, - "public.rewards": { - "name": "rewards", - "schema": "", - "columns": { - "internal_id": { - "name": "internal_id", - "type": "text", - "primaryKey": true, - "notNull": true - }, - "id": { - "name": "id", - "type": "text", - "primaryKey": false, - "notNull": false - }, - "org_id": { - "name": "org_id", - "type": "text", - "primaryKey": false, - "notNull": false - }, - "env": { - "name": "env", - "type": "text", - "primaryKey": false, - "notNull": false - }, - "created_at": { - "name": "created_at", - "type": "numeric", - "primaryKey": false, - "notNull": false - }, - "name": { - "name": "name", - "type": "text", - "primaryKey": false, - "notNull": false - }, - "discount_config": { - "name": "discount_config", - "type": "jsonb", - "primaryKey": false, - "notNull": false - }, - "free_product_id": { - "name": "free_product_id", - "type": "text", - "primaryKey": false, - "notNull": false - }, - "promo_codes": { - "name": "promo_codes", - "type": "jsonb[]", - "primaryKey": false, - "notNull": false - }, - "type": { - "name": "type", - "type": "text", - "primaryKey": false, - "notNull": false - } - }, - "indexes": {}, - "foreignKeys": { - "coupons_org_id_fkey": { - "name": "coupons_org_id_fkey", - "tableFrom": "rewards", - "tableTo": "organizations", - "columnsFrom": [ - "org_id" - ], - "columnsTo": [ - "id" - ], - "onDelete": "cascade", - "onUpdate": "no action" - } - }, - "compositePrimaryKeys": {}, - "uniqueConstraints": {}, - "policies": {}, - "checkConstraints": {}, - "isRLSEnabled": false - }, - "public.subscriptions": { - "name": "subscriptions", - "schema": "", - "columns": { - "id": { - "name": "id", - "type": "text", - "primaryKey": true, - "notNull": true - }, - "org_id": { - "name": "org_id", - "type": "text", - "primaryKey": false, - "notNull": true - }, - "stripe_id": { - "name": "stripe_id", - "type": "text", - "primaryKey": false, - "notNull": false - }, - "stripe_schedule_id": { - "name": "stripe_schedule_id", - "type": "text", - "primaryKey": false, - "notNull": false - }, - "created_at": { - "name": "created_at", - "type": "numeric", - "primaryKey": false, - "notNull": true, - "default": "ROUND(date_part('epoch', NOW()) * 1000)::BIGINT" - }, - "metadata": { - "name": "metadata", - "type": "jsonb", - "primaryKey": false, - "notNull": false, - "default": "'{}'::jsonb" - }, - "usage_features": { - "name": "usage_features", - "type": "text[]", - "primaryKey": false, - "notNull": false, - "default": "'{}'" - }, - "env": { - "name": "env", - "type": "text", - "primaryKey": false, - "notNull": false - }, - "current_period_start": { - "name": "current_period_start", - "type": "numeric", - "primaryKey": false, - "notNull": false - }, - "current_period_end": { - "name": "current_period_end", - "type": "numeric", - "primaryKey": false, - "notNull": false - } - }, - "indexes": {}, - "foreignKeys": { - "subscriptions_org_id_fkey": { - "name": "subscriptions_org_id_fkey", - "tableFrom": "subscriptions", - "tableTo": "organizations", - "columnsFrom": [ - "org_id" - ], - "columnsTo": [ - "id" - ], - "onDelete": "cascade", - "onUpdate": "no action" - } - }, - "compositePrimaryKeys": {}, - "uniqueConstraints": { - "subscriptions_stripe_id_key": { - "name": "subscriptions_stripe_id_key", - "nullsNotDistinct": false, - "columns": [ - "stripe_id" - ] - } - }, - "policies": {}, - "checkConstraints": {}, - "isRLSEnabled": false - } - }, - "enums": {}, - "schemas": {}, - "sequences": {}, - "roles": {}, - "policies": {}, - "views": {}, - "_meta": { - "columns": {}, - "schemas": {}, - "tables": {} - } -} \ No newline at end of file diff --git a/shared/drizzle/meta/_journal.json b/shared/drizzle/meta/_journal.json deleted file mode 100644 index e8e4fff8b..000000000 --- a/shared/drizzle/meta/_journal.json +++ /dev/null @@ -1,41 +0,0 @@ -{ - "version": "7", - "dialect": "postgresql", - "entries": [ - { - "idx": 0, - "version": "7", - "when": 1748516803655, - "tag": "0000_minor_gunslinger", - "breakpoints": true - }, - { - "idx": 1, - "version": "7", - "when": 1748519767357, - "tag": "0001_complete_forgotten_one", - "breakpoints": true - }, - { - "idx": 2, - "version": "7", - "when": 1748520847010, - "tag": "0002_foamy_tombstone", - "breakpoints": true - }, - { - "idx": 3, - "version": "7", - "when": 1749201302399, - "tag": "0003_yummy_la_nuit", - "breakpoints": true - }, - { - "idx": 4, - "version": "7", - "when": 1749201355061, - "tag": "0004_broad_shocker", - "breakpoints": true - } - ] -} \ No newline at end of file diff --git a/shared/enums/ErrCode.ts b/shared/enums/ErrCode.ts index 577bed14e..f8548c322 100644 --- a/shared/enums/ErrCode.ts +++ b/shared/enums/ErrCode.ts @@ -20,6 +20,7 @@ export const ErrCode = { // Org OrgNotFound: "org_not_found", + OrgHasCustomers: "org_has_customers", // Feature FeatureNotFound: "feature_not_found", @@ -152,4 +153,7 @@ export const ErrCode = { InsertMigrationJobFailed: "insert_migration_job_failed", InsertMigrationErrorFailed: "insert_migration_error_failed", MigrationJobNotFound: "migration_job_not_found", + + // Supabase + SupabaseNotFound: "supabase_not_found", }; diff --git a/shared/index.ts b/shared/index.ts index 07b9a1b21..1111a60f6 100644 --- a/shared/index.ts +++ b/shared/index.ts @@ -2,6 +2,10 @@ import * as schemas from "./db/schema.js"; export { schemas }; +// Auth Models +export * from "./db/auth-schema.js"; +export * from "./models/authModels/membership.js"; + // Gen Models export * from "./models/genModels/genEnums.js"; export * from "./models/genModels/genModels.js"; @@ -9,6 +13,7 @@ export * from "./models/genModels/genModels.js"; // 1. Org Models export * from "./models/orgModels/orgTable.js"; export * from "./models/orgModels/orgConfig.js"; +export * from "./models/orgModels/frontendOrg.js"; // 2. Feature Models export * from "./models/featureModels/featureTable.js"; diff --git a/shared/models/authModels/membership.ts b/shared/models/authModels/membership.ts new file mode 100644 index 000000000..7612b1b1a --- /dev/null +++ b/shared/models/authModels/membership.ts @@ -0,0 +1,6 @@ +import { Member, User } from "@autumn/shared"; + +export interface Membership { + user: User; + member: Member; +} diff --git a/shared/models/cusModels/invoiceModels/invoiceTable.ts b/shared/models/cusModels/invoiceModels/invoiceTable.ts index 14535cafd..66ec92208 100644 --- a/shared/models/cusModels/invoiceModels/invoiceTable.ts +++ b/shared/models/cusModels/invoiceModels/invoiceTable.ts @@ -26,12 +26,12 @@ export const invoices = pgTable( (table) => [ foreignKey({ columns: [table.internal_customer_id], - foreignColumns: [customers.id], + foreignColumns: [customers.internal_id], name: "invoices_internal_customer_id_fkey", }), foreignKey({ columns: [table.internal_entity_id], - foreignColumns: [entities.id], + foreignColumns: [entities.internal_id], name: "invoices_internal_entity_id_fkey", }), ], diff --git a/shared/models/cusProductModels/cusEntModels/cusEntTable.ts b/shared/models/cusProductModels/cusEntModels/cusEntTable.ts index 8e363ea85..edd0a96e2 100644 --- a/shared/models/cusProductModels/cusEntModels/cusEntTable.ts +++ b/shared/models/cusProductModels/cusEntModels/cusEntTable.ts @@ -13,6 +13,7 @@ import { features } from "../../featureModels/featureTable.js"; import { collatePgColumn } from "../../../db/utils.js"; import { EntityBalance } from "./cusEntModels.js"; import { customerProducts } from "../cusProductTable.js"; +import { entitlements } from "../../../db/schema.js"; export const customerEntitlements = pgTable( "customer_entitlements", @@ -48,7 +49,13 @@ export const customerEntitlements = pgTable( }) .onUpdate("cascade") .onDelete("cascade"), - unique("entitlements_id_key").on(table.id), + foreignKey({ + columns: [table.entitlement_id], + foreignColumns: [entitlements.id], + name: "customer_entitlements_entitlement_id_fkey", + }) + .onUpdate("cascade") + .onDelete("cascade"), ], ); diff --git a/shared/models/orgModels/frontendOrg.ts b/shared/models/orgModels/frontendOrg.ts new file mode 100644 index 000000000..a398e2c09 --- /dev/null +++ b/shared/models/orgModels/frontendOrg.ts @@ -0,0 +1,15 @@ +import { z } from "zod"; + +export const FrontendOrgSchema = z.object({ + id: z.string(), + name: z.string(), + logo: z.string().nullable(), + slug: z.string(), + default_currency: z.string(), + stripe_connected: z.boolean(), + created_at: z.number(), + test_pkey: z.string().nullable(), + live_pkey: z.string().nullable(), +}); + +export type FrontendOrg = z.infer; diff --git a/shared/models/orgModels/orgRelations.ts b/shared/models/orgModels/orgRelations.ts index 696734166..4d07ad0a3 100644 --- a/shared/models/orgModels/orgRelations.ts +++ b/shared/models/orgModels/orgRelations.ts @@ -2,6 +2,7 @@ import { relations } from "drizzle-orm"; import { apiKeys } from "../devModels/apiKeyTable.js"; import { features } from "../featureModels/featureTable.js"; import { organizations } from "./orgTable.js"; +import { user } from "../../db/auth-schema.js"; export const organizationsRelations = relations(organizations, ({ many }) => ({ api_keys: many(apiKeys), diff --git a/shared/models/orgModels/orgTable.ts b/shared/models/orgModels/orgTable.ts index 367255f71..680edf020 100644 --- a/shared/models/orgModels/orgTable.ts +++ b/shared/models/orgModels/orgTable.ts @@ -5,14 +5,11 @@ import { jsonb, boolean, unique, + timestamp, } from "drizzle-orm/pg-core"; import { OrgConfig } from "./orgConfig.js"; - -export type MinOrg = { - id: string; - slug: string; -}; +import { sql } from "drizzle-orm"; export type SvixConfig = { sandbox_app_id: string; @@ -27,17 +24,32 @@ export type StripeConfig = { success_url: string; }; +// logo: text("logo"), +// createdAt: timestamp("created_at").notNull(), +// metadata: text("metadata"), + export const organizations = pgTable( "organizations", { - id: text().primaryKey().notNull(), - slug: text().notNull(), - default_currency: text("default_currency").notNull().default("usd"), + id: text().primaryKey(), + slug: text().notNull().unique(), + + // Better Auth + name: text("name").notNull(), + logo: text("logo"), + createdAt: timestamp("createdAt", { withTimezone: true }).notNull(), + metadata: text("metadata"), + + // Stripe + default_currency: text("default_currency").default("usd"), stripe_connected: boolean("stripe_connected").default(false), + stripe_config: jsonb("stripe_config").$type(), test_pkey: text("test_pkey"), live_pkey: text("live_pkey"), - svix_config: jsonb("svix_config").notNull().$type(), + svix_config: jsonb("svix_config") + .$type() + .default(sql`'{}'::jsonb`), created_at: numeric({ mode: "number" }), config: jsonb().default({}).notNull().$type(), }, diff --git a/shared/package.json b/shared/package.json index 53fbac7d0..ca36f5d51 100644 --- a/shared/package.json +++ b/shared/package.json @@ -14,15 +14,19 @@ "license": "Apache-2.0", "scripts": { "build": "tsc", + "dev": "nodemon --watch . --ext ts --ignore dist --exec 'pnpm run build'", + "db:push": "NODE_OPTIONS='--import tsx' drizzle-kit push --config drizzle.config.ts", "db:generate": "NODE_OPTIONS='--import tsx' drizzle-kit generate --config drizzle.config.ts", "db:migrate": "NODE_OPTIONS='--import tsx' drizzle-kit migrate --config drizzle.config.ts" }, "dependencies": { + "decimal.js": "^10.5.0", "drizzle-orm": "^0.43.1", - "drizzle-zod": "^0.8.1", + "drizzle-zod": "^0.8.2", "zod": "^3.25.23" }, "devDependencies": { + "nodemon": "^3.1.7", "tsx": "^4.19.4", "typescript": "^5.7.2" } diff --git a/vite/.env.example b/vite/.env.example index 47bc3eb4c..99dbaf419 100644 --- a/vite/.env.example +++ b/vite/.env.example @@ -1,10 +1,2 @@ -# Node environment variables -NODE_ENV="development" - -# Public environment variables -NEXT_PUBLIC_BACKEND_URL="" -NEXT_PUBLIC_PUBLISHABLE_KEY="" - -# Autumn specific environment variables -NEXT_PUBLIC_AUTUMN_API_KEY="" -NEXT_PUBLIC_AUTUMN_PUBLISHABLE_KEY="" +VITE_FRONTEND_URL=http://localhost:3000 +VITE_BACKEND_URL=http://localhost:8080 diff --git a/vite/package.json b/vite/package.json index 6dd69c9ab..1b019122b 100644 --- a/vite/package.json +++ b/vite/package.json @@ -1,18 +1,19 @@ { - "name": "@autumn/frontend2", + "name": "@autumn/vite", "private": true, "version": "0.0.0", "type": "module", "scripts": { - "dev": "vite --port 3000", + "dev": "vite --port 3000 --host", "build": "tsc -b && vite build", "lint": "eslint .", - "preview": "vite preview" + "preview": "vite preview", + "start": "serve -s dist" }, "author": "Recase Inc.", "license": "Apache-2.0", "dependencies": { - "@autumn/shared": "*", + "@autumn/shared": "workspace:*", "@clerk/clerk-react": "^5.24.2", "@fortawesome/free-brands-svg-icons": "^6.7.2", "@fortawesome/react-fontawesome": "^0.2.2", @@ -30,14 +31,18 @@ "@radix-ui/react-tooltip": "^1.1.8", "@supabase/ssr": "^0.5.2", "@tailwindcss/vite": "^4.0.13", + "@tanstack/react-table": "^8.21.3", "@wooorm/starry-night": "^3.6.0", "autumn-js": "^0.0.41", "axios": "^1.8.3", + "better-auth": "^1.2.9", "class-variance-authority": "^0.7.1", "clsx": "^2.1.1", "cmdk": "^1.0.0", "date-fns": "^3.6.0", + "decimal.js": "^10.5.0", "hast-util-to-html": "^9.0.5", + "input-otp": "^1.4.2", "lodash": "^4.17.21", "lucide-react": "^0.511.0", "motion": "^12.16.0", @@ -49,15 +54,18 @@ "react-confetti-explosion": "^2.1.2", "react-day-picker": "^8.10.1", "react-dom": "^18.2.0", + "react-dropzone": "^14.3.8", "react-hot-toast": "^2.5.2", "react-hotkeys-hook": "^4.6.1", "react-router": "^7.3.0", "sonner": "^2.0.1", "svix-react": "^1.13.3", + "swr": "^2.3.3", "tailwind-merge": "^3.0.2", "tailwindcss": "^4.0.13", "tailwindcss-animate": "^1.0.7", - "vaul": "^1.1.2" + "vaul": "^1.1.2", + "zod": "^3.25.23" }, "devDependencies": { "@eslint/js": "^9.21.0", @@ -74,11 +82,5 @@ "typescript": "~5.7.2", "typescript-eslint": "^8.24.1", "vite": "^6.2.0" - }, - "resolutions": { - "@rollup/rollup-linux-x64-gnu": "npm:@rollup/rollup-linux-x64-musl" - }, - "overrides": { - "@rollup/rollup-linux-x64-gnu": "npm:@rollup/rollup-linux-x64-musl" } } diff --git a/vite/public/logo_hd.png b/vite/public/logo_hd.png new file mode 100644 index 000000000..0962a2596 Binary files /dev/null and b/vite/public/logo_hd.png differ diff --git a/vite/src/App.tsx b/vite/src/App.tsx index fd12c8de8..06c1f53e3 100644 --- a/vite/src/App.tsx +++ b/vite/src/App.tsx @@ -1,3 +1,4 @@ +import { DefaultView } from "./views/DefaultView"; import { AppEnv } from "@autumn/shared"; import { BrowserRouter, Routes, Route } from "react-router"; import { MainLayout } from "./app/layout"; @@ -6,26 +7,28 @@ import CustomerProductView from "./views/customers/customer/product/CustomerProd import CustomersView from "./views/customers/CustomersView"; import DevScreen from "./views/developer/DevView"; import FeaturesView from "./views/features/FeaturesView"; -import ConnectStripe from "./views/onboarding/ConnectStripe"; import StripePage from "./views/onboarding/StripePage"; import ProductView from "./views/products/product/ProductView"; import ProductsView from "./views/products/ProductsView"; - import OnboardingView from "./views/onboarding/OnboardingView"; -import { DefaultView } from "./views/DefaultView"; import CliAuth from "./views/CliAuth"; +import { SignIn } from "./views/auth/SignIn"; +import { AcceptInvitation } from "./views/auth/AcceptInvitation"; +import { AdminView } from "./views/admin/AdminView"; export default function App() { return ( + } /> + } /> }> } /> + } /> + } /> } /> - } /> - {/* FEATURES */} { // Identify user - if (user && process.env.NODE_ENV !== "development") { - let email = user.primaryEmailAddress?.emailAddress; - if (!email) { - email = user.emailAddresses[0].emailAddress; - } + if (data && process.env.NODE_ENV !== "development") { + const email = data.user.email; posthog?.identify(email, { email, - name: user.fullName, - id: user.id, + name: data.user.name, + id: data.user.id, }); } - }, [user, posthog]); + }, [data, posthog]); // 1. If not loaded, show loading screen - if (!isUserLoaded) { + if (isPending) { return (
@@ -80,45 +71,24 @@ export function MainLayout() { } // 2. If no user, redirect to sign in - if (!user) { - return ; + if (!data) { + navigate("/sign-in"); + return; } - if (!org && !pathname.includes("/onboarding")) { - return ( - - ); - } + // if (!pathname.includes("/onboarding")) { + // return ( + // + // ); + // } return ( - { - const token = await getToken({ - template: "custom_template", - }); - return token; - }} - > +
- +
diff --git a/vite/src/components/general/AdminHover.tsx b/vite/src/components/general/AdminHover.tsx index 3ffed51f8..204c0a3da 100644 --- a/vite/src/components/general/AdminHover.tsx +++ b/vite/src/components/general/AdminHover.tsx @@ -1,42 +1,57 @@ +import React, { + useState, + forwardRef, + cloneElement, + isValidElement, +} from "react"; import { Check } from "lucide-react"; -import { useAuth, useOrganization, useUser } from "@clerk/clerk-react"; import { Tooltip, TooltipProvider, TooltipTrigger } from "../ui/tooltip"; import { TooltipContent } from "../ui/tooltip"; import { Copy } from "lucide-react"; -import { useState } from "react"; -import { notNullish } from "@/utils/genUtils"; +import { useSession } from "@/lib/auth-client"; +import { useAdmin } from "@/views/admin/hooks/useAdmin"; -export const AdminHover = ({ - children, - texts, - hide = false, -}: { - children: React.ReactNode; - texts: (string | { key: string; value: string } | undefined | null)[]; - hide?: boolean; -}) => { - const { isLoaded, user } = useUser(); - const { actor } = useAuth(); +export const AdminHover = forwardRef< + HTMLElement, + { + children: React.ReactNode; + texts: (string | { key: string; value: string } | undefined | null)[]; + hide?: boolean; + } +>(({ children, texts, hide = false }, ref) => { + // const { data, isPending } = useSession(); + const { isAdmin } = useAdmin(); - const email = user?.primaryEmailAddress?.emailAddress; + // const user = data?.user; - const isAdmin = - notNullish(actor) || - email === "johnyeocx@gmail.com" || - email === "ayush@recaseai.com" || - email === "johnyeo10@gmail.com" || - email == "npmrundemo@gmail.com"; + // // const { isLoaded, user } = useUser(); + // // const { actor } = useAuth(); - if (!isAdmin || hide) return children; + // const email = user?.email; + + // const isAdmin = + // // notNullish(actor) || + // email === "johnyeocx@gmail.com" || + // email === "ayush@recaseai.com" || + // email === "johnyeo10@gmail.com" || + // email == "npmrundemo@gmail.com"; + + if (!isAdmin || hide) return <>{children}; + + // Try to forward the ref to the child if possible + let triggerChild = children; + if (isValidElement(children)) { + triggerChild = cloneElement(children as React.ReactElement, { ref }); + } return ( - {children} + {triggerChild} - {isLoaded && ( + {isAdmin && ( ); -}; +}); const CopyText = ({ text }: { text: string }) => { const [isHover, setIsHover] = useState(false); diff --git a/vite/src/components/general/CopyButton.tsx b/vite/src/components/general/CopyButton.tsx index 65af4b59a..65c2e3ea7 100644 --- a/vite/src/components/general/CopyButton.tsx +++ b/vite/src/components/general/CopyButton.tsx @@ -30,7 +30,7 @@ function CopyButton({ size="icon" className={cn( "h-6 px-2 text-t2 w-fit font-mono rounded-md truncate justify-start", - className + className, )} onClick={(e) => { e.preventDefault(); @@ -39,7 +39,7 @@ function CopyButton({ setCopied(true); }} > - {children} + {children && {children}}
{copied ? ( diff --git a/vite/src/components/general/CustomToaster.tsx b/vite/src/components/general/CustomToaster.tsx index f308310b1..0f88bc060 100644 --- a/vite/src/components/general/CustomToaster.tsx +++ b/vite/src/components/general/CustomToaster.tsx @@ -1,12 +1,19 @@ -import { Toaster } from "react-hot-toast"; +import { Toaster as ToasterComponent } from "sonner"; export const CustomToaster = () => { return ( - ); diff --git a/vite/src/components/general/PageSectionHeader.tsx b/vite/src/components/general/PageSectionHeader.tsx index 3023e955a..447cb8629 100644 --- a/vite/src/components/general/PageSectionHeader.tsx +++ b/vite/src/components/general/PageSectionHeader.tsx @@ -2,14 +2,20 @@ import { cn } from "@/lib/utils"; export const PageSectionHeader = ({ title, + titleComponent, isOnboarding = false, addButton, className, + classNames, }: { - title: string; + title?: string; + titleComponent?: React.ReactNode; isOnboarding?: boolean; addButton?: React.ReactNode; className?: string; + classNames?: { + title?: string; + }; }) => { return (
-

{title}

+ {title && ( +

+ {title} +

+ )} + {titleComponent}
{addButton &&
{addButton}
}
diff --git a/vite/src/components/ui/button.tsx b/vite/src/components/ui/button.tsx index ad1b26e82..786dd51b0 100644 --- a/vite/src/components/ui/button.tsx +++ b/vite/src/components/ui/button.tsx @@ -46,6 +46,8 @@ const buttonVariants = cva( destructivePrimary: "bg-gradient-to-b font-semibold border-t border-red-400 outline outline-red-500 rounded-sm from-red-500/85 to-red-500 text-white hover:from-red-500 hover:to-red-500 shadow-red-500/50 transition-[background] duration-300 !h-7.5 mt-0.25", + + auth: "!gap-2 hover:bg-stone-100 border border-zinc-250 bg-white text-t1 w-full shadow-sm", }, size: { default: "h-8 px-3 flex items-center gap-1", @@ -72,6 +74,7 @@ export interface ButtonProps endIcon?: React.ReactNode; tooltipContent?: string; disableStartIcon?: boolean; + shimmer?: boolean; } const Button = React.forwardRef( @@ -89,6 +92,7 @@ const Button = React.forwardRef( tooltipContent, children, disableStartIcon = false, + shimmer = false, ...props }, ref, @@ -100,6 +104,7 @@ const Button = React.forwardRef( className={cn( buttonVariants({ variant, size, className }), isIcon && `w-${dim} h-${dim} p-0`, + shimmer && "shimmer", )} ref={ref} onClick={(e) => { @@ -110,10 +115,13 @@ const Button = React.forwardRef( } props.onClick?.(e); }} + disabled={isLoading || props.disabled || shimmer} > {isLoading && } {startIcon && !isLoading && <>{startIcon}} - {variant == "add" && !disableStartIcon && } + {!isLoading && variant == "add" && !disableStartIcon && ( + + )} {children} {endIcon && !isLoading && <>{endIcon}} diff --git a/vite/src/components/ui/dialog.tsx b/vite/src/components/ui/dialog.tsx index 0fbcaf2e9..f347c8811 100644 --- a/vite/src/components/ui/dialog.tsx +++ b/vite/src/components/ui/dialog.tsx @@ -39,7 +39,7 @@ const DialogOverlay = React.forwardRef< data-slot="dialog-overlay" className={cn( "fixed inset-0 z-50 bg-white/70 backdrop-blur-sm data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0", - className + className, )} {...props} /> @@ -62,7 +62,7 @@ function DialogContent({ bg-stone-50 min-w-sm `, - className + className, )} {...props} > @@ -86,13 +86,19 @@ function DialogHeader({ className, ...props }: React.ComponentProps<"div">) { ); } -function DialogFooter({ className, ...props }: React.ComponentProps<"div">) { +function DialogFooter({ + className, + variant = "default", + ...props +}: React.ComponentProps<"div"> & { variant?: "new" | "default" }) { return (
diff --git a/vite/src/components/ui/dropdown-menu.tsx b/vite/src/components/ui/dropdown-menu.tsx index b7fee7588..494d45590 100644 --- a/vite/src/components/ui/dropdown-menu.tsx +++ b/vite/src/components/ui/dropdown-menu.tsx @@ -23,19 +23,20 @@ const DropdownMenuSubTrigger = React.forwardRef< React.ElementRef, React.ComponentPropsWithoutRef & { inset?: boolean; + withIcon?: boolean; } ->(({ className, inset, children, ...props }, ref) => ( +>(({ className, inset, children, withIcon = true, ...props }, ref) => ( {children} - + {withIcon && } )); DropdownMenuSubTrigger.displayName = @@ -49,7 +50,7 @@ const DropdownMenuSubContent = React.forwardRef< ref={ref} className={cn( "z-50 min-w-[8rem] overflow-hidden rounded-md border border-zinc-200 bg-white p-1 text-zinc-950 shadow-lg data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2 dark:border-zinc-800 dark:bg-zinc-950 dark:text-zinc-50", - className + className, )} {...props} /> @@ -69,7 +70,7 @@ const DropdownMenuContent = React.forwardRef< className={cn( "z-50 min-w-[8rem] overflow-hidden rounded-md border border-zinc-200 bg-white p-1 text-zinc-950 shadow-md dark:border-zinc-800 dark:bg-zinc-950 dark:text-zinc-50", "data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2", - className + className, )} {...props} /> @@ -82,18 +83,19 @@ const DropdownMenuItem = React.forwardRef< React.ComponentPropsWithoutRef & { inset?: boolean; isLoading?: boolean; + shimmer?: boolean; } ->(({ className, inset, isLoading, ...props }, ref) => ( +>(({ className, inset, shimmer = false, isLoading, ...props }, ref) => ( svg]:size-4 [&>svg]:shrink-0 dark:focus:bg-zinc-800 dark:focus:text-zinc-50 - - hover:bg-zinc-100 + hover:bg-zinc-100 ${shimmer ? "shimmer" : ""} `, inset && "pl-8", - className + className, )} + disabled={shimmer || isLoading} {...props} > {isLoading ? ( @@ -116,7 +118,7 @@ const DropdownMenuCheckboxItem = React.forwardRef< ref={ref} className={cn( "relative flex cursor-default select-none items-center rounded-sm py-1.5 pl-8 pr-2 text-sm outline-none transition-colors focus:bg-zinc-100 focus:text-zinc-900 data-[disabled]:pointer-events-none data-[disabled]:opacity-50 dark:focus:bg-zinc-800 dark:focus:text-zinc-50", - className + className, )} checked={checked} {...props} @@ -140,7 +142,7 @@ const DropdownMenuRadioItem = React.forwardRef< ref={ref} className={cn( "relative flex cursor-default select-none items-center rounded-sm py-1.5 pl-8 pr-2 text-sm outline-none transition-colors focus:bg-zinc-100 focus:text-zinc-900 data-[disabled]:pointer-events-none data-[disabled]:opacity-50 dark:focus:bg-zinc-800 dark:focus:text-zinc-50", - className + className, )} {...props} > @@ -165,7 +167,7 @@ const DropdownMenuLabel = React.forwardRef< className={cn( "px-2 py-1.5 text-sm font-semibold", inset && "pl-8", - className + className, )} {...props} /> diff --git a/vite/src/components/ui/input-otp.tsx b/vite/src/components/ui/input-otp.tsx new file mode 100644 index 000000000..310175285 --- /dev/null +++ b/vite/src/components/ui/input-otp.tsx @@ -0,0 +1,75 @@ +import * as React from "react" +import { OTPInput, OTPInputContext } from "input-otp" +import { MinusIcon } from "lucide-react" + +import { cn } from "@/lib/utils" + +function InputOTP({ + className, + containerClassName, + ...props +}: React.ComponentProps & { + containerClassName?: string +}) { + return ( + + ) +} + +function InputOTPGroup({ className, ...props }: React.ComponentProps<"div">) { + return ( +
+ ) +} + +function InputOTPSlot({ + index, + className, + ...props +}: React.ComponentProps<"div"> & { + index: number +}) { + const inputOTPContext = React.useContext(OTPInputContext) + const { char, hasFakeCaret, isActive } = inputOTPContext?.slots[index] ?? {} + + return ( +
+ {char} + {hasFakeCaret && ( +
+
+
+ )} +
+ ) +} + +function InputOTPSeparator({ ...props }: React.ComponentProps<"div">) { + return ( +
+ +
+ ) +} + +export { InputOTP, InputOTPGroup, InputOTPSlot, InputOTPSeparator } diff --git a/vite/src/components/ui/input.tsx b/vite/src/components/ui/input.tsx index 5d14861d3..e5db88144 100644 --- a/vite/src/components/ui/input.tsx +++ b/vite/src/components/ui/input.tsx @@ -16,31 +16,34 @@ const Input = React.forwardRef( const handleFocus = () => setIsFocused(true); const handleBlur = () => setIsFocused(false); + const gradientBg = + "bg-[linear-gradient(180deg,white,theme(colors.stone.100))]"; return ( <> {hasAdornment ? (
( ( )} ); - // return ( - // - // ); - } + }, ); Input.displayName = "Input"; diff --git a/vite/src/components/ui/select.tsx b/vite/src/components/ui/select.tsx index e312b3fb8..e425e6328 100644 --- a/vite/src/components/ui/select.tsx +++ b/vite/src/components/ui/select.tsx @@ -42,15 +42,13 @@ function SelectTrigger({ `flex w-full items-center justify-between whitespace-nowrap rounded-md border border-zinc-200 bg-white px-3 py-2 text-sm shadow-sm ring-offset-white placeholder:text-t3 focus:outline-none disabled:cursor-not-allowed disabled:opacity-50 [&>span]:line-clamp-1 dark:border-zinc-800 dark:ring-offset-zinc-950 dark:placeholder:text-zinc-400 dark:focus:ring-zinc-300 h-8 - data-[state=open]:border-primary data-[state=open]:shadow-[0_0_2px_1px_rgba(139,92,246,0.25)] + data-[state=open]:border-focus data-[state=open]:shadow-focus focus:ring-0 - data-[placeholder]:text-t3 - transition-colors duration-100 p-2 `, - className + className, )} {...props} > @@ -88,7 +86,7 @@ function SelectTrigger({ `flex w-full items-center justify-between whitespace-nowrap rounded-md border border-zinc-200 bg-white px-3 py-2 text-sm shadow-sm ring-offset-white placeholder:text-t3 focus:outline-none disabled:cursor-not-allowed disabled:opacity-50 [&>span]:line-clamp-1 dark:border-zinc-800 dark:ring-offset-zinc-950 dark:placeholder:text-zinc-400 dark:focus:ring-zinc-300 h-8 -data-[state=open]:border-primary data-[state=open]:shadow-[0_0_2px_1px_rgba(139,92,246,0.25)] +data-[state=open]:border-focus data-[state=open]:shadow-focus focus:ring-0 data-[placeholder]:text-t3 @@ -96,7 +94,7 @@ data-[placeholder]:text-t3 transition-colors duration-100 p-2 `, - className + className, )} {...props} > @@ -122,7 +120,7 @@ function SelectContent({ "bg-popover text-popover-foreground data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2 relative z-50 max-h-(--radix-select-content-available-height) min-w-[8rem] overflow-x-hidden overflow-y-auto rounded-md border shadow-md", position === "popper" && "data-[side=bottom]:translate-y-1 data-[side=left]:-translate-x-1 data-[side=right]:translate-x-1 data-[side=top]:-translate-y-1", - className + className, )} position={position} {...props} @@ -132,7 +130,7 @@ function SelectContent({ className={cn( "p-1", position === "popper" && - "h-[var(--radix-select-trigger-height)] w-full min-w-[var(--radix-select-trigger-width)] scroll-my-1" + "h-[var(--radix-select-trigger-height)] w-full min-w-[var(--radix-select-trigger-width)] scroll-my-1", )} > {children} @@ -166,7 +164,7 @@ function SelectItem({ data-slot="select-item" className={cn( "focus:bg-accent focus:text-accent-foreground [&_svg:not([class*='text-'])]:text-muted-foreground relative flex w-full cursor-default items-center gap-2 rounded-sm py-1.5 pr-8 pl-2 text-sm outline-hidden select-none data-[disabled]:pointer-events-none data-[disabled]:opacity-50 [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-4 *:[span]:last:flex *:[span]:last:items-center *:[span]:last:gap-2", - className + className, )} {...props} > @@ -202,7 +200,7 @@ function SelectScrollUpButton({ data-slot="select-scroll-up-button" className={cn( "flex cursor-default items-center justify-center py-1", - className + className, )} {...props} > @@ -220,7 +218,7 @@ function SelectScrollDownButton({ data-slot="select-scroll-down-button" className={cn( "flex cursor-default items-center justify-center py-1", - className + className, )} {...props} > diff --git a/vite/src/components/ui/skeleton.tsx b/vite/src/components/ui/skeleton.tsx new file mode 100644 index 000000000..32ea0ef7f --- /dev/null +++ b/vite/src/components/ui/skeleton.tsx @@ -0,0 +1,13 @@ +import { cn } from "@/lib/utils" + +function Skeleton({ className, ...props }: React.ComponentProps<"div">) { + return ( +
+ ) +} + +export { Skeleton } diff --git a/vite/src/hooks/useOrg.tsx b/vite/src/hooks/useOrg.tsx new file mode 100644 index 000000000..608dbd520 --- /dev/null +++ b/vite/src/hooks/useOrg.tsx @@ -0,0 +1,28 @@ +import { + authClient, + useListOrganizations, + useSession, +} from "@/lib/auth-client"; +import { useAxiosSWR } from "@/services/useAxiosSwr"; +import { FrontendOrg } from "@autumn/shared"; +import { useEffect } from "react"; + +export const useOrg = () => { + const { data, isLoading, error, mutate } = useAxiosSWR({ + url: "/organization", + }); + + // const { data: orgList } = useListOrganizations(); + + // useEffect(() => { + // if (!data && orgList?.length === 1) { + // authClient.organization.setActive({ + // organizationId: orgList[0].id, + // }); + + // mutate(); + // } + // }, [data, orgList]); + + return { org: data as FrontendOrg, isLoading, error, mutate }; +}; diff --git a/vite/src/hooks/useOrgId.tsx b/vite/src/hooks/useOrgId.tsx new file mode 100644 index 000000000..5fd184c8c --- /dev/null +++ b/vite/src/hooks/useOrgId.tsx @@ -0,0 +1,46 @@ +import { + authClient, + useListOrganizations, + useSession, +} from "@/lib/auth-client"; +import { useAxiosSWR } from "@/services/useAxiosSwr"; +import { FrontendOrg } from "@autumn/shared"; +import { useEffect, useState } from "react"; + +export const useOrgId = () => { + const { data: session, isPending: sessionPending } = useSession(); + const { data: organizations, isPending: orgsPending } = + useListOrganizations(); + + const [orgId, setOrgId] = useState(null); + + const setFirstOrg = async () => { + if (organizations?.length === 1) { + await authClient.organization.setActive({ + organizationId: organizations[0].id, + }); + } + }; + + useEffect(() => { + const activeId = session?.session.activeOrganizationId; + if (activeId) { + setOrgId(activeId); + } + }, [session]); + + // useEffect(() => { + // if (!orgId && organizations?.length && organizations.length > 0) { + // setFirstOrg(); + // } + // }, [session, organizations]); + + useEffect(() => { + console.log("OrgId", orgId); + }, [orgId]); + + return { + orgId, + isLoading: sessionPending, + }; +}; diff --git a/vite/src/hooks/useSessionClaims.tsx b/vite/src/hooks/useSessionClaims.tsx deleted file mode 100644 index b37177106..000000000 --- a/vite/src/hooks/useSessionClaims.tsx +++ /dev/null @@ -1,14 +0,0 @@ -import { useOrganization, useSession } from "@clerk/clerk-react"; -import { useEffect } from "react"; - -export const useSessionClaims = () => { - const { isLoaded, session } = useSession(); - const { isLoaded: isOrgLoaded, organization } = useOrganization(); - useEffect(() => {}, [isOrgLoaded, isLoaded]); - - if (!isLoaded) { - return { isLoaded: false, claims: null }; - } - - return { isLoaded: true, claims: session?.lastActiveToken?.jwt?.claims }; -}; diff --git a/vite/src/hooks/useTab.tsx b/vite/src/hooks/useTab.tsx index b5f6b084f..232388e25 100644 --- a/vite/src/hooks/useTab.tsx +++ b/vite/src/hooks/useTab.tsx @@ -2,6 +2,9 @@ import { useLocation } from "react-router"; export const useTab = () => { const { pathname } = useLocation(); + if (pathname.startsWith("/admin") || pathname.startsWith("/sandbox/admin")) { + return "admin"; + } if ( pathname.startsWith("/features") || pathname.startsWith("/sandbox/features") diff --git a/vite/src/index.css b/vite/src/index.css index 40c64975e..f3edd64ca 100644 --- a/vite/src/index.css +++ b/vite/src/index.css @@ -238,6 +238,9 @@ button:focus-visible { --color-code-tabs: #2d2d2d; --color-code-bg: #1e1e1e; --color-code-tabs-active: #3c3c3c; + + --shadow-focus: 0 0 3px 1.5px rgba(139, 92, 246, 0.4); + --color-focus: rgba(139, 92, 246, 0.95); } /* @@ -255,3 +258,65 @@ button:focus-visible { button { cursor: pointer; } + +.shimmer { + position: relative; + overflow: hidden; + /* background-color: #e5e7eb; */ +} +.shimmer::after { + content: ""; + position: absolute; + top: 0; + left: -150%; + width: 100%; + height: 100%; + background: linear-gradient( + 90deg, + transparent, + rgba(255, 255, 255, 0.6), + transparent + ); + animation: shimmer 1.5s infinite; +} +@keyframes shimmer { + 100% { + left: 150%; + } +} + +.shimmer-hover { + position: relative; + overflow: hidden; +} +.shimmer-hover::after { + content: ""; + position: absolute; + top: 0; + left: -150%; + width: 100%; + height: 100%; + background: linear-gradient( + 90deg, + transparent, + rgba(255, 255, 255, 0.4), + transparent + ); + pointer-events: none; + opacity: 0; + transition: opacity 0.2s; +} +.shimmer-hover:hover::after { + animation: shimmer-once 0.8s; + opacity: 1; +} +@keyframes shimmer-once { + 0% { + left: -150%; + opacity: 1; + } + 100% { + left: 150%; + opacity: 1; + } +} diff --git a/vite/src/lib/auth-client.ts b/vite/src/lib/auth-client.ts new file mode 100644 index 000000000..162c2a299 --- /dev/null +++ b/vite/src/lib/auth-client.ts @@ -0,0 +1,20 @@ +import { createAuthClient } from "better-auth/react"; +import { adminClient, emailOTPClient } from "better-auth/client/plugins"; +import { organizationClient } from "better-auth/client/plugins"; + +export const authClient = createAuthClient({ + baseURL: "http://localhost:8080", + plugins: [emailOTPClient(), organizationClient(), adminClient()], +}); + +export const { + useSession, + signIn, + signUp, + signOut, + deleteUser, + useListOrganizations, +} = createAuthClient({ + baseURL: "http://localhost:8080", + plugins: [emailOTPClient(), organizationClient(), adminClient()], +}); diff --git a/vite/src/main.tsx b/vite/src/main.tsx index a10db9b00..be7032f0f 100644 --- a/vite/src/main.tsx +++ b/vite/src/main.tsx @@ -1,36 +1,27 @@ +import "./index.css"; +import App from "./App"; + import { StrictMode } from "react"; import { createRoot } from "react-dom/client"; -import "./index.css"; -import { ClerkProvider } from "@clerk/clerk-react"; -import App from "./App"; -import posthog from "posthog-js"; import { PostHogProvider } from "posthog-js/react"; -import { AutumnProvider } from "autumn-js/react"; - -const PUBLISHABLE_KEY = import.meta.env.VITE_CLERK_PUBLISHABLE_KEY; -if (!PUBLISHABLE_KEY) { - throw new Error("Add your Clerk Publishable Key to the .env file"); -} createRoot(document.getElementById("root")!).render( - - {process.env.NODE_ENV === "development" ? ( + {process.env.NODE_ENV === "development" ? ( + + ) : ( + - ) : ( - - - - )} - + + )} , ); diff --git a/vite/src/services/products/RewardService.tsx b/vite/src/services/products/RewardService.tsx index 589dfabe7..4ffd34c5b 100644 --- a/vite/src/services/products/RewardService.tsx +++ b/vite/src/services/products/RewardService.tsx @@ -1,6 +1,5 @@ import { Reward, CreateReward } from "@autumn/shared"; -import { SupabaseClient } from "@supabase/supabase-js"; import { AxiosInstance } from "axios"; export class RewardService { diff --git a/vite/src/services/useAxiosInstance.tsx b/vite/src/services/useAxiosInstance.tsx index f7504dd45..1a3ddf587 100644 --- a/vite/src/services/useAxiosInstance.tsx +++ b/vite/src/services/useAxiosInstance.tsx @@ -1,6 +1,5 @@ import axios from "axios"; import { endpoint } from "@/utils/constants"; -import { useAuth } from "@clerk/clerk-react"; import { AppEnv } from "@autumn/shared"; import { useEnv } from "@/utils/envUtils"; const defaultParams = { @@ -17,30 +16,50 @@ export function useAxiosInstance(params?: { env?: AppEnv; isAuth?: boolean }) { const axiosInstance = axios.create({ baseURL: endpoint, + withCredentials: true, }); - const { getToken } = useAuth(); + axiosInstance.interceptors.request.use( + async (config: any) => { + config.headers["app_env"] = trueEnv; + config.headers["x-api-version"] = "1.2"; + // const token = await getToken({ + // template: "custom_template", + // }); - if (finalParams.isAuth) { - axiosInstance.interceptors.request.use( - async (config: any) => { - const token = await getToken({ - template: "custom_template", - }); + // if (token) { + // // config.headers["Authorization"] = `Bearer ${token}`; + // config.headers["app_env"] = trueEnv; + // config.headers["x-api-version"] = "1.2"; + // } - if (token) { - config.headers["Authorization"] = `Bearer ${token}`; - config.headers["app_env"] = trueEnv; - config.headers["x-api-version"] = "1.2"; - } + return config; + }, + (error: any) => { + return Promise.reject(error); + }, + ); - return config; - }, - (error: any) => { - return Promise.reject(error); - }, - ); - } + // if (finalParams.isAuth) { + // axiosInstance.interceptors.request.use( + // async (config: any) => { + // const token = await getToken({ + // template: "custom_template", + // }); + + // if (token) { + // config.headers["Authorization"] = `Bearer ${token}`; + // config.headers["app_env"] = trueEnv; + // config.headers["x-api-version"] = "1.2"; + // } + + // return config; + // }, + // (error: any) => { + // return Promise.reject(error); + // }, + // ); + // } return axiosInstance; } diff --git a/vite/src/services/useAxiosSwr.tsx b/vite/src/services/useAxiosSwr.tsx index ea173b4c0..e2c2ba8e5 100644 --- a/vite/src/services/useAxiosSwr.tsx +++ b/vite/src/services/useAxiosSwr.tsx @@ -11,12 +11,12 @@ export function useAxiosSWR({ enabled = true, }: { url: string; - env: AppEnv; + env?: AppEnv; withAuth?: boolean; options?: SWRConfiguration; enabled?: boolean; }) { - const axiosInstance = useAxiosInstance({ env, isAuth: withAuth }); + const axiosInstance = useAxiosInstance({ isAuth: withAuth }); const fetcher = async (url: string) => { const res = await axiosInstance.get(url); diff --git a/vite/src/utils/formatUtils/formatDateUtils.ts b/vite/src/utils/formatUtils/formatDateUtils.ts index c13463ca8..42e2dd8dc 100644 --- a/vite/src/utils/formatUtils/formatDateUtils.ts +++ b/vite/src/utils/formatUtils/formatDateUtils.ts @@ -1,5 +1,9 @@ import { format } from "date-fns"; +export const formatDateStr = (date: Date | string) => { + return format(new Date(date), "dd MMM yyyy"); +}; + export const formatTimestamp = (timestamp: number | null | undefined) => { if (!timestamp) return ""; return format(new Date(timestamp), "MM/dd/yyyy"); diff --git a/vite/src/utils/formatUtils/formatTextUtils.ts b/vite/src/utils/formatUtils/formatTextUtils.ts index be1197b79..c40fb7d06 100644 --- a/vite/src/utils/formatUtils/formatTextUtils.ts +++ b/vite/src/utils/formatUtils/formatTextUtils.ts @@ -11,10 +11,13 @@ export const keyToTitleFirstCaps = (key: string) => { return res.replace(/_/g, " "); }; -export const slugify = (text: string) => { +export const slugify = ( + text: string, + type: "underscore" | "dash" = "underscore", +) => { return text .toLowerCase() - .replace(/ /g, "_") + .replace(/ /g, type == "underscore" ? "_" : "-") .replace(/[^\w\s-]/g, ""); }; diff --git a/vite/src/utils/orgUtils.ts b/vite/src/utils/orgUtils.ts new file mode 100644 index 000000000..e49637ffa --- /dev/null +++ b/vite/src/utils/orgUtils.ts @@ -0,0 +1,3 @@ +export const getOrgLogoUrl = (orgId: string) => { + return `${import.meta.env.VITE_SUPABASE_URL}/storage/v1/object/public/autumn/logo/${orgId}`; +}; diff --git a/vite/src/views/DefaultView.tsx b/vite/src/views/DefaultView.tsx index 09b9e414a..46731a928 100644 --- a/vite/src/views/DefaultView.tsx +++ b/vite/src/views/DefaultView.tsx @@ -1,5 +1,3 @@ -import { RedirectToSignIn, useOrganization, useUser } from "@clerk/clerk-react"; -import LoadingScreen from "./general/LoadingScreen"; import { Link, Navigate, useLocation } from "react-router"; import ErrorScreen from "./general/ErrorScreen"; @@ -18,11 +16,4 @@ export const DefaultView = () => { ); - - // By default, will come here - // 2. if user, redirect to customers - // return ; - // if (!user) { - // return
Hello World
; - // } }; diff --git a/vite/src/views/admin/AdminTable.tsx b/vite/src/views/admin/AdminTable.tsx new file mode 100644 index 000000000..1ea00ecaa --- /dev/null +++ b/vite/src/views/admin/AdminTable.tsx @@ -0,0 +1,91 @@ +import { useState, useCallback } from "react"; +import { useAxiosSWR } from "@/services/useAxiosSwr"; + +import { DataTable } from "./DataTable"; +import { ColumnDef } from "@tanstack/react-table"; + +export const AdminTable = ({ + path, + columns, + title, +}: { + path: string; + columns: ColumnDef[]; + title: string; +}) => { + const [search, setSearch] = useState(""); + const [after, setAfter] = useState(undefined); + const [before, setBefore] = useState(undefined); + const [sortKey, setSortKey] = useState("createdAt"); + const [sortOrder, setSortOrder] = useState<"asc" | "desc">("desc"); + const [page, setPage] = useState(1); + + // Build query string for params + const params = new URLSearchParams(); + if (search) params.append("search", search); + if (after) params.append("after", after); + if (before) params.append("before", before); + if (sortKey) params.append("sortKey", sortKey); + if (sortOrder) params.append("sortOrder", sortOrder); + const url = `${path}${params.toString() ? `?${params.toString()}` : ""}`; + + const { data, isLoading } = useAxiosSWR({ + url, + }); + + const rows = data?.rows || []; + + const pageInfo = { + hasNextPage: data?.hasNextPage || false, + hasPrevPage: rows.length !== 0, + lastItem: `${rows[rows.length - 1]?.id},${rows[rows.length - 1]?.createdAt}`, + firstItem: `${rows[0]?.id},${rows[0]?.createdAt}`, + page, + }; + + const handleSearch = useCallback((value: string) => { + setSearch(value); + setAfter(undefined); + setBefore(undefined); + setPage(1); + }, []); + + const handlePaginate = useCallback( + (direction: "next" | "prev") => { + if (direction === "next") { + setAfter(pageInfo.lastItem); + setBefore(undefined); + } else { + setBefore(pageInfo.firstItem); + setAfter(undefined); + } + setPage((p) => (direction === "next" ? p + 1 : Math.max(1, p - 1))); + }, + [pageInfo], + ); + + const handleSort = useCallback((key: string, order: "asc" | "desc") => { + setSortKey(key); + setSortOrder(order); + setAfter(undefined); + setBefore(undefined); + setPage(1); + }, []); + + return ( +
+

{title}

+ + columns={columns} + data={rows} + isLoading={isLoading} + pageInfo={pageInfo} + onSearch={handleSearch} + onPaginate={handlePaginate} + onSort={handleSort} + sortKey={sortKey} + sortOrder={sortOrder} + /> +
+ ); +}; diff --git a/vite/src/views/admin/AdminView.tsx b/vite/src/views/admin/AdminView.tsx new file mode 100644 index 000000000..65ffc21bb --- /dev/null +++ b/vite/src/views/admin/AdminView.tsx @@ -0,0 +1,58 @@ +import LoadingScreen from "../general/LoadingScreen"; +import { authClient } from "@/lib/auth-client"; +import { DefaultView } from "../DefaultView"; +import { useAdmin } from "./hooks/useAdmin"; +import { toast } from "sonner"; +import { AdminTable } from "./AdminTable"; +import { columns as userColumns } from "./userColumns"; +import { columns as orgColumns } from "./orgColumns"; +import { Button } from "@/components/ui/button"; + +export const AdminView = () => { + const { isAdmin, isPending } = useAdmin(); + + if (isPending) { + return ( +
+ +
+ ); + } + + if (!isAdmin) { + return ; + } + + const handleStopImpersonating = async () => { + const { data, error } = await authClient.admin.stopImpersonating(); + + if (error) { + toast.error("Something went wrong"); + return; + } + + window.location.reload(); + }; + + return ( +
+ {/* 1. User list */} + +
+ +
+ +
+ + +
+
+ ); +}; diff --git a/vite/src/views/admin/DataTable.tsx b/vite/src/views/admin/DataTable.tsx new file mode 100644 index 000000000..187d50df5 --- /dev/null +++ b/vite/src/views/admin/DataTable.tsx @@ -0,0 +1,190 @@ +import * as React from "react"; +import { + ColumnDef, + SortingState, + flexRender, + getCoreRowModel, + getSortedRowModel, + useReactTable, + HeaderGroup, + Header, + Row, + Cell, +} from "@tanstack/react-table"; +import { + Table, + TableBody, + TableCell, + TableHead, + TableHeader, + TableRow, +} from "@/components/ui/table"; +import { Input } from "@/components/ui/input"; +import { Button } from "@/components/ui/button"; +import { SearchIcon } from "lucide-react"; + +interface DataTableProps { + columns: ColumnDef[]; + data: TData[]; + isLoading: boolean; + pageInfo: { + hasNextPage: boolean; + hasPrevPage: boolean; + nextCursor?: string; + prevCursor?: string; + page: number; + }; + onSearch: (search: string) => void; + onPaginate: (direction: "next" | "prev") => void; + onSort: (sortKey: string, sortOrder: "asc" | "desc") => void; + sortKey: string; + sortOrder: "asc" | "desc"; +} + +export function DataTable({ + columns, + data, + isLoading, + pageInfo, + onSearch, + onPaginate, + onSort, +}: DataTableProps) { + const [search, setSearch] = React.useState(""); + const [sorting, setSorting] = React.useState([]); + + const debounceRef = React.useRef(null); + + React.useEffect(() => { + if (debounceRef.current) clearTimeout(debounceRef.current); + debounceRef.current = setTimeout(() => { + onSearch(search); + }, 300); + return () => { + if (debounceRef.current) clearTimeout(debounceRef.current); + }; + }, [search, onSearch]); + + React.useEffect(() => { + if (sorting.length > 0) { + const sort = sorting[0]; + onSort(sort.id, sort.desc ? "desc" : "asc"); + } + }, [sorting, onSort]); + + const table = useReactTable({ + data, + columns, + getCoreRowModel: getCoreRowModel(), + getSortedRowModel: getSortedRowModel(), + state: { + sorting, + }, + onSortingChange: setSorting, + manualSorting: true, + }); + + return ( +
+
+ setSearch(e.target.value)} + className="max-w-sm" + /> +
+
+ + + {table.getHeaderGroups().map((headerGroup: HeaderGroup) => ( + + {headerGroup.headers.map((header: Header) => { + const width = (header.column.columnDef as any).width; + return ( + { + if (header.column.getCanSort()) { + header.column.toggleSorting(); + } + }} + className={ + header.column.getCanSort() + ? "cursor-pointer select-none" + : "" + } + > + {flexRender( + header.column.columnDef.header, + header.getContext(), + )} + {header.column.getIsSorted() + ? header.column.getIsSorted() === "asc" + ? " ▲" + : " ▼" + : null} + + ); + })} + + ))} + + + {isLoading ? ( + + + Loading... + + + ) : data.length ? ( + table.getRowModel().rows.map((row: Row) => ( + + {row.getVisibleCells().map((cell: Cell) => { + return ( + + {flexRender( + cell.column.columnDef.cell, + cell.getContext(), + )} + + ); + })} + + )) + ) : ( + + + No results. + + + )} + +
+
+
+ + Page {pageInfo.page} + +
+
+ ); +} diff --git a/vite/src/views/admin/OrgTable.tsx b/vite/src/views/admin/OrgTable.tsx new file mode 100644 index 000000000..22cda18d4 --- /dev/null +++ b/vite/src/views/admin/OrgTable.tsx @@ -0,0 +1,3 @@ +export const OrgTable = () => { + return
OrgTable
; +}; diff --git a/vite/src/views/admin/components/AdminOnly.tsx b/vite/src/views/admin/components/AdminOnly.tsx new file mode 100644 index 000000000..2834bdebc --- /dev/null +++ b/vite/src/views/admin/components/AdminOnly.tsx @@ -0,0 +1,12 @@ +import React from "react"; +import { useAdmin } from "../hooks/useAdmin"; + +export const AdminOnly = ({ children }: { children: React.ReactNode }) => { + const { isAdmin, isPending } = useAdmin(); + + if (!isAdmin) { + return null; + } + + return {children}; +}; diff --git a/vite/src/views/admin/hooks/useAdmin.tsx b/vite/src/views/admin/hooks/useAdmin.tsx new file mode 100644 index 000000000..4768aa306 --- /dev/null +++ b/vite/src/views/admin/hooks/useAdmin.tsx @@ -0,0 +1,19 @@ +import { useSession } from "@/lib/auth-client"; +import { notNullish } from "@/utils/genUtils"; +import { useEffect, useState } from "react"; + +export const useAdmin = () => { + const { data, isPending } = useSession(); + const [isAdmin, setIsAdmin] = useState(false); + + useEffect(() => { + if ( + data?.user?.role === "admin" || + notNullish(data?.session.impersonatedBy) + ) { + setIsAdmin(true); + } + }, [data]); + + return { isAdmin, isPending }; +}; diff --git a/vite/src/views/admin/orgColumns.tsx b/vite/src/views/admin/orgColumns.tsx new file mode 100644 index 000000000..f704945de --- /dev/null +++ b/vite/src/views/admin/orgColumns.tsx @@ -0,0 +1,82 @@ +import { ColumnDef, Row } from "@tanstack/react-table"; +import CopyButton from "@/components/general/CopyButton"; +import { format } from "date-fns"; + +export type Org = { + id: string; + name: string; + slug: string; + createdAt: string; + users: string[]; +}; + +// Helper to add width and canCopy to columns +interface ExtraColumnOptions { + width?: string | number; + canCopy?: boolean; +} + +type OrgColumnDef = ColumnDef & ExtraColumnOptions; + +export const columns: OrgColumnDef[] = [ + { + accessorKey: "id", + header: "ID", + width: 60, + canCopy: true, + cell: ({ row }: { row: Row }) => { + const value = row.getValue("id") as string; + return ( +
+ +
+ ); + }, + }, + { + accessorKey: "name", + header: "Name", + width: 150, + cell: ({ row }: { row: Row }) => { + const value = row.getValue("name") as string; + return
{value}
; + }, + }, + + { + accessorKey: "slug", + header: "Slug", + canCopy: true, + width: 200, + cell: ({ row }: { row: Row }) => { + const value = row.getValue("slug") as string; + return ( + + {value} + + ); + }, + }, + { + accessorKey: "createdAt", + header: "Created At", + width: 150, + cell: ({ row }: { row: Row }) => { + const value = row.getValue("createdAt"); + return ( + + {format(new Date(value as string), "dd MMM hh:mm")} + + ); + }, + }, + { + accessorKey: "users", + header: "Users", + width: "100%", + cell: ({ row }: { row: Row }) => { + const value = row.getValue("users"); + return {(value as string[]).join(", ")}; + }, + }, +]; diff --git a/vite/src/views/admin/userColumns.tsx b/vite/src/views/admin/userColumns.tsx new file mode 100644 index 000000000..2b06cb4f4 --- /dev/null +++ b/vite/src/views/admin/userColumns.tsx @@ -0,0 +1,104 @@ +import { ColumnDef, Row } from "@tanstack/react-table"; +import { Button } from "@/components/ui/button"; +import CopyButton from "@/components/general/CopyButton"; +import { format } from "date-fns"; +import { authClient } from "@/lib/auth-client"; +import { toast } from "sonner"; + +export type User = { + id: string; + name: string; + email: string; + createdAt: string; + lastSignedIn: string; +}; + +// Helper to add width and canCopy to columns +interface ExtraColumnOptions { + width?: string | number; + canCopy?: boolean; +} + +type UserColumnDef = ColumnDef & ExtraColumnOptions; + +export const columns: UserColumnDef[] = [ + { + accessorKey: "id", + header: "ID", + width: 60, + canCopy: true, + cell: ({ row }: { row: Row }) => { + const value = row.getValue("id") as string; + return ( +
+ +
+ ); + }, + }, + { + accessorKey: "name", + header: "Name", + width: 150, + cell: ({ row }: { row: Row }) => { + const value = row.getValue("name") as string; + return
{value}
; + }, + }, + { + accessorKey: "email", + header: "Email", + canCopy: true, + width: 200, + cell: ({ row }: { row: Row }) => { + const value = row.getValue("email") as string; + return ( + + {value} + + ); + }, + }, + { + accessorKey: "createdAt", + header: "Created At", + width: 150, + cell: ({ row }: { row: Row }) => { + const value = row.getValue("createdAt"); + return ( + + {format(new Date(value as string), "dd MMM hh:mm")} + + ); + }, + }, + + { + id: "impersonate", + header: "Impersonate", + width: "100%", + cell: ({ row }: { row: Row }) => ( + + ), + enableSorting: false, + enableHiding: false, + }, +]; diff --git a/vite/src/views/auth/AcceptInvitation.tsx b/vite/src/views/auth/AcceptInvitation.tsx new file mode 100644 index 000000000..43c897d33 --- /dev/null +++ b/vite/src/views/auth/AcceptInvitation.tsx @@ -0,0 +1,22 @@ +import { useSession } from "@/lib/auth-client"; +import LoadingScreen from "../general/LoadingScreen"; +import { useNavigate } from "react-router"; + +export const AcceptInvitation = () => { + const { data, isPending } = useSession(); + const navigate = useNavigate(); + + if (isPending) + return ( +
+ +
+ ); + + if (!data) { + navigate("/sign-in"); + return; + } + + return
AcceptInvitation!
; +}; diff --git a/vite/src/views/auth/SignIn.tsx b/vite/src/views/auth/SignIn.tsx new file mode 100644 index 000000000..452300f59 --- /dev/null +++ b/vite/src/views/auth/SignIn.tsx @@ -0,0 +1,171 @@ +import { useEffect, useState } from "react"; +import { Button } from "@/components/ui/button"; +import { Input } from "@/components/ui/input"; +import { Link, useNavigate, useSearchParams } from "react-router"; +import { FontAwesomeIcon } from "@fortawesome/react-fontawesome"; +import { faGoogle } from "@fortawesome/free-brands-svg-icons"; +import { authClient, signIn, useSession } from "@/lib/auth-client"; +import { OTPSignIn } from "./components/OTPSignIn"; +import { Mail } from "lucide-react"; +import { CustomToaster } from "@/components/general/CustomToaster"; +import { toast } from "sonner"; +import { getBackendErr } from "@/utils/genUtils"; + +export const SignIn = () => { + const [email, setEmail] = useState(""); + const [googleLoading, setGoogleLoading] = useState(false); + const [sendOtpLoading, setSendOtpLoading] = useState(false); + const [otpSent, setOtpSent] = useState(false); + const { data: session } = useSession(); + + const [searchParams] = useSearchParams(); + const token = searchParams.get("token"); + + const newPath = token + ? `/sandbox/onboarding?token=${token}` + : "/sandbox/onboarding"; + const callbackPath = token + ? `/sandbox/onboarding?token=${token}` + : "/customers"; + + useEffect(() => { + if (session?.user) { + window.location.href = callbackPath; + } + }, [session]); + + const handleEmailSignIn = async (e: React.FormEvent) => { + e.preventDefault(); + setSendOtpLoading(true); + + try { + const { data, error } = await authClient.emailOtp.sendVerificationOtp({ + email: email, + type: "sign-in", + }); + + if (error) { + toast.error(error.message || "Something went wrong. Please try again."); + } else { + setOtpSent(true); + } + } catch (error) { + toast.error("Something went wrong. Please try again."); + } finally { + setSendOtpLoading(false); + } + }; + + const handleGoogleSignIn = async () => { + setGoogleLoading(true); + try { + const frontendUrl = import.meta.env.VITE_FRONTEND_URL; + const { data, error } = await signIn.social({ + provider: "google", + callbackURL: `${frontendUrl}${callbackPath}`, + newUserCallbackURL: `${frontendUrl}${newPath}`, + }); + if (error) { + toast.error(error.message || "Failed to sign in with Google"); + } + } catch (error) { + toast.error(getBackendErr(error, "Failed to sign in with Google")); + } finally { + setTimeout(() => { + setGoogleLoading(false); + }, 1000); + } + }; + + const height = "h-9"; + + return ( +
+ +
+ {/* Logo */} +
+ Autumn +
+ + {/* Title */} +
+

+ Sign in to Autumn +

+
+ + {otpSent && ( + + )} + + {!otpSent && ( + <> +
+ {/* Google Sign In Button */} + + + {/* Divider */} +
+
+ +
+
+ + Or + +
+
+ +
+
+ setEmail(e.target.value)} + required + className="text-base" + /> +
+ + {/* Sign In Button */} + +
+
+ + {/* Footer */} + {/*
+ + Create an account here + +
*/} + + )} +
+
+ ); +}; diff --git a/vite/src/views/auth/components/OTPSignIn.tsx b/vite/src/views/auth/components/OTPSignIn.tsx new file mode 100644 index 000000000..bfa88383c --- /dev/null +++ b/vite/src/views/auth/components/OTPSignIn.tsx @@ -0,0 +1,135 @@ +import { Button } from "@/components/ui/button"; +import { + InputOTP, + InputOTPGroup, + InputOTPSeparator, + InputOTPSlot, +} from "@/components/ui/input-otp"; +import { authClient } from "@/lib/auth-client"; +import { cn } from "@/lib/utils"; +import { differenceInSeconds } from "date-fns"; +import { useEffect, useState } from "react"; +import { useNavigate } from "react-router"; +import { toast } from "sonner"; + +export const OTPSignIn = ({ + email, + newPath, + callbackPath, +}: { + email: string; + newPath: string; + callbackPath: string; +}) => { + const [otp, setOtp] = useState(""); + const [resending, setResending] = useState(false); + const [resendCountdown, setResendCountdown] = useState(0); + const [verifying, setVerifying] = useState(false); + const navigate = useNavigate(); + + useEffect(() => { + if (resendCountdown > 0) { + setTimeout(() => setResendCountdown(resendCountdown - 1), 1000); + } + }, [resendCountdown]); + + const handleSubmit = async (otp: string) => { + setVerifying(true); + try { + const { data, error } = await authClient.signIn.emailOtp({ + email: email, + otp: otp, + }); + + console.log("Data", data); + console.log("Error", error); + + if (error) { + toast.error(error.message || "Failed to verify code"); + setVerifying(false); + return; + } + + const user = data.user; + + const createdRecently = + differenceInSeconds(new Date(), new Date(user.createdAt)) < 20; + + if (createdRecently) { + window.location.href = newPath; + } else { + window.location.href = callbackPath; + } + } catch (error) { + toast.error("Failed to verify code"); + } + setVerifying(false); + }; + + const handleResend = async () => { + setResending(true); + try { + const { data, error } = await authClient.emailOtp.sendVerificationOtp({ + email: email, + type: "sign-in", + }); + + console.log(data); + console.log(error); + + if (error) { + toast.error(error.message); + return; + } + + setResendCountdown(30); + } catch (error) { + toast.error("Failed to resend code"); + return; + } + + setResending(false); + }; + + return ( +
+

+ Check your email for the 6 digit code +

+
+ + + + + + + + + + + + + +
+ +
+ +
+
+ ); +}; diff --git a/vite/src/views/customers/customer/CustomerView.tsx b/vite/src/views/customers/customer/CustomerView.tsx index 869796fe0..a0c2336f5 100644 --- a/vite/src/views/customers/customer/CustomerView.tsx +++ b/vite/src/views/customers/customer/CustomerView.tsx @@ -3,13 +3,7 @@ import { useAxiosSWR } from "@/services/useAxiosSwr"; import LoadingScreen from "@/views/general/LoadingScreen"; import { AppEnv } from "@autumn/shared"; -import { - Breadcrumb, - BreadcrumbItem, - BreadcrumbLink, - BreadcrumbList, - BreadcrumbSeparator, -} from "@/components/ui/breadcrumb"; + import { CustomerContext } from "./CustomerContext"; import { Link, useNavigate, useParams, useSearchParams } from "react-router"; import { CustomerProductList } from "./CustomerProductList"; diff --git a/vite/src/views/customers/customer/add-product/NewProductDropdown.tsx b/vite/src/views/customers/customer/add-product/NewProductDropdown.tsx index 31881b051..86ca60789 100644 --- a/vite/src/views/customers/customer/add-product/NewProductDropdown.tsx +++ b/vite/src/views/customers/customer/add-product/NewProductDropdown.tsx @@ -19,6 +19,7 @@ import { OrgService } from "@/services/OrgService"; import { CusProductStatus, Entity, Product } from "@autumn/shared"; import SmallSpinner from "@/components/general/SmallSpinner"; import { Search } from "lucide-react"; +import { useOrg } from "@/hooks/useOrg"; function AddProduct() { const { products, customer, env, entityId, entities } = useCustomerContext(); @@ -26,6 +27,7 @@ function AddProduct() { const [options, setOptions] = useState([]); const [searchQuery, setSearchQuery] = useState(""); const [open, setOpen] = useState(false); + const { org } = useOrg(); const filteredProducts = products.filter((product: Product) => { if (product.is_add_on && !searchQuery) return true; @@ -52,15 +54,14 @@ function AddProduct() { const navigate = useNavigate(); const handleAddProduct = async (productId: string, setLoading: any) => { - const { data } = await OrgService.get(axiosInstance); + let stripeConnected = org?.stripe_connected; - if (!data.org) { - toast.error("Something went wrong...please try again later"); - setLoading(false); - return; + if (!stripeConnected) { + const { data: org } = await OrgService.get(axiosInstance); + stripeConnected = org?.stripe_connected; } - if (!data.org.stripe_connected) { + if (!stripeConnected) { toast.error("Connect to Stripe to add products to customers"); const redirectUrl = getRedirectUrl(`/customers/${customer.id}`, env); navigateTo(`/integrations/stripe?redirect=${redirectUrl}`, navigate, env); diff --git a/vite/src/views/main-sidebar/EnvDropdown.tsx b/vite/src/views/main-sidebar/EnvDropdown.tsx index acfa9dff0..757d46479 100644 --- a/vite/src/views/main-sidebar/EnvDropdown.tsx +++ b/vite/src/views/main-sidebar/EnvDropdown.tsx @@ -13,20 +13,12 @@ import { envToPath } from "@/utils/genUtils"; import { useLocation } from "react-router"; import { useSidebarContext } from "./SidebarContext"; import { cn } from "@/lib/utils"; -import { - Check, - ChevronDown, - ChevronLeft, - ChevronRight, - FlaskConical, - Sailboat, - TestTube, -} from "lucide-react"; +import { Check } from "lucide-react"; import { useState } from "react"; +import { ExpandedEnvTrigger } from "./env-dropdown/ExpandedEnvTrigger"; export const EnvDropdown = ({ env }: { env: AppEnv }) => { const location = useLocation(); - const expanded = true; const { state } = useSidebarContext(); @@ -38,66 +30,27 @@ export const EnvDropdown = ({ env }: { env: AppEnv }) => { } }; - let [isHovered, setIsHovered] = useState(false); - let [open, setOpen] = useState(false); + const [isHovered, setIsHovered] = useState(false); + const [open, setOpen] = useState(false); const envText = env === AppEnv.Sandbox ? "Sandbox" : "Production"; + const expanded = state == "expanded"; return (
setIsHovered(true)} onMouseLeave={() => setIsHovered(false)} > - {expanded ? ( - - {state == "expanded" ? ( -
-
- {env === AppEnv.Sandbox ? ( - - ) : ( - - )} -
-

{envText}

- {/* */} -
- ) : ( -

{envText.slice(0, 1)}

- )} -
+ + {/* {expanded ? ( ) : ( - {envText.slice(0, 1)} - )} + + )} */} { handleEnvChange(AppEnv.Sandbox); }} @@ -109,7 +62,7 @@ export const EnvDropdown = ({ env }: { env: AppEnv }) => { { handleEnvChange(AppEnv.Live); }} diff --git a/vite/src/views/main-sidebar/MainSidebar.tsx b/vite/src/views/main-sidebar/MainSidebar.tsx index 9cadbea66..73ad08133 100644 --- a/vite/src/views/main-sidebar/MainSidebar.tsx +++ b/vite/src/views/main-sidebar/MainSidebar.tsx @@ -7,8 +7,10 @@ import { useState } from "react"; import { cn } from "@/lib/utils"; import { SidebarContext } from "./SidebarContext"; import { useHotkeys } from "react-hotkeys-hook"; -import { Code, Flag, Package, Tag, User } from "lucide-react"; +import { Code, Package, Shield, User } from "lucide-react"; import { EnvDropdown } from "./EnvDropdown"; +import { OrgDropdown } from "./components/OrgDropdown"; +import { AdminOnly } from "../admin/components/AdminOnly"; export const MainSidebar = () => { const env = useEnv(); @@ -25,20 +27,14 @@ export const MainSidebar = () => { `h-full bg-stone-100 py-4 flex flex-col justify-between transition-all duration-150`, state == "expanded" ? "min-w-[200px] max-w-[200px]" - : "min-w-[50px] max-w-[50px]" + : "min-w-[50px] max-w-[50px]", )} > -
- -
- - - {/* } - title="Features" - env={env} - /> */} +
+ + {/* */} + +
} @@ -57,6 +53,14 @@ export const MainSidebar = () => { title="Developer" env={env} /> + {/* + } + title="Admin" + env={env} + /> + */}
{/* Sidebar bottom */} diff --git a/vite/src/views/main-sidebar/NavButton.tsx b/vite/src/views/main-sidebar/NavButton.tsx index 91d25359d..7d716f436 100644 --- a/vite/src/views/main-sidebar/NavButton.tsx +++ b/vite/src/views/main-sidebar/NavButton.tsx @@ -39,7 +39,7 @@ export const NavButton = ({ `cursor-pointer font-medium transition-all duration-100 text-sm flex h-9 items-center text-t2 hover:text-primary`, isActive && "font-semibold text-primary hover:text-primary/80", - className + className, )} target={href ? "_blank" : undefined} > @@ -47,12 +47,21 @@ export const NavButton = ({ className={cn( "flex justify-center w-4 h-4 items-center rounded-sm transition-all duration-100", state == "expanded" && "mr-2", - isHovered && "translate-x-[-1px]" + isHovered && "translate-x-[-1px]", )} > {icon}
- {state == "expanded" && {title}} + + {title} + {online && ( diff --git a/vite/src/views/main-sidebar/SidebarBottom.tsx b/vite/src/views/main-sidebar/SidebarBottom.tsx index 564e8d5a0..9c3661b3d 100644 --- a/vite/src/views/main-sidebar/SidebarBottom.tsx +++ b/vite/src/views/main-sidebar/SidebarBottom.tsx @@ -1,20 +1,23 @@ "use client"; -import { UserButton, useUser } from "@clerk/clerk-react"; - import { NavButton } from "./NavButton"; import { useEnv } from "@/utils/envUtils"; import { SidebarContact } from "./SidebarContact"; import { useSidebarContext } from "./SidebarContext"; import { cn } from "@/lib/utils"; import { Blocks, Book } from "lucide-react"; +import { useSession } from "@/lib/auth-client"; +import { UserButton } from "./components/UserButton"; export default function SidebarBottom() { const env = useEnv(); - const { user, isLoaded } = useUser(); + // const { user, isLoaded } = useUser(); const { state } = useSidebarContext(); const expanded = state == "expanded"; + const { data: session } = useSession(); + const user = session?.user; + return (
@@ -33,24 +36,30 @@ export default function SidebarBottom() { />
- -
-
- -
- {expanded && ( -
-

{user?.firstName}

-

{user?.primaryEmailAddress?.emailAddress}

-
- )} -
); } + +{ + /*
+
+ +
+ {expanded && ( +
+

{user?.name}

+

+ {user?.email} +

+
+ )} +
; */ +} diff --git a/vite/src/views/main-sidebar/SidebarTop.tsx b/vite/src/views/main-sidebar/SidebarTop.tsx index a9e93e9a6..47e3a7d98 100644 --- a/vite/src/views/main-sidebar/SidebarTop.tsx +++ b/vite/src/views/main-sidebar/SidebarTop.tsx @@ -1,90 +1,27 @@ import { cn } from "@/lib/utils"; -import { - OrganizationSwitcher, - useOrganization, - useUser, -} from "@clerk/clerk-react"; +import { OrganizationSwitcher, useUser } from "@clerk/clerk-react"; import { useEffect, useRef, useState } from "react"; import { Button } from "@/components/ui/button"; -import { EnvDropdown } from "./EnvDropdown"; - import { useEnv } from "@/utils/envUtils"; import { useSidebarContext } from "./SidebarContext"; -import { - Tooltip, - TooltipContent, - TooltipProvider, - TooltipTrigger, -} from "@/components/ui/tooltip"; + import { Check, ChevronLeft, ChevronRight, Copy } from "lucide-react"; import { AdminHover } from "@/components/general/AdminHover"; +import { OrgDropdown } from "./components/OrgDropdown"; export const SidebarTop = () => { - const { isLoaded, user } = useUser(); const { state, setState } = useSidebarContext(); - const primaryEmail = user?.primaryEmailAddress?.emailAddress; - const env = useEnv(); - const { organization } = useOrganization(); - const prevOrgIdRef = useRef(null); - - useEffect(() => { - // Skip the first render - if (prevOrgIdRef.current === null) { - prevOrgIdRef.current = organization?.id || null; - return; - } - - // If organization changed (switched or created/deleted) - if (prevOrgIdRef.current !== (organization?.id || null)) { - console.log("Organization changed, refreshing page"); - window.location.reload(); - } - - // Update the ref - prevOrgIdRef.current = organization?.id || null; - }, [organization]); return (
-
+ {/*
- {state == "expanded" && ( -
-
- {organization && ( - - - - )} -
-
- )} -
+
*/}
); }; @@ -141,3 +78,38 @@ const CopyText = ({ text }: { text: string }) => {
); }; + +// { +// state == "expanded" && ( +//
+//
+// +// {organization && ( +// + +// +// )} +//
+//
+// ); +// } diff --git a/vite/src/views/main-sidebar/components/CreateNewOrg.tsx b/vite/src/views/main-sidebar/components/CreateNewOrg.tsx new file mode 100644 index 000000000..bfc835232 --- /dev/null +++ b/vite/src/views/main-sidebar/components/CreateNewOrg.tsx @@ -0,0 +1,104 @@ +import FieldLabel from "@/components/general/modal-components/FieldLabel"; +import { Button } from "@/components/ui/button"; +import { + Dialog, + DialogContent, + DialogFooter, + DialogHeader, + DialogTitle, + DialogTrigger, +} from "@/components/ui/dialog"; +import { Input } from "@/components/ui/input"; +import { useOrg } from "@/hooks/useOrg"; +import { authClient } from "@/lib/auth-client"; +import { slugify } from "@/utils/formatUtils/formatTextUtils"; +import { useState } from "react"; +import { toast } from "sonner"; + +export const CreateNewOrg = ({ + dialogType, + setDialogType, +}: { + dialogType: "create" | "manage" | null; + setDialogType: (dialogType: "create" | "manage" | null) => void; +}) => { + const { mutate } = useOrg(); + const [name, setName] = useState(""); + const [slugChanged, setSlugChanged] = useState(false); + const [slug, setSlug] = useState(""); + const [isLoading, setIsLoading] = useState(false); + + const handleCreate = async () => { + setIsLoading(true); + try { + const { data, error } = await authClient.organization.create({ + name, + slug, + }); + + if (error) throw error; + + await authClient.organization.setActive({ + organizationId: data.id, + }); + + await mutate(); + + toast.success("Organization created"); + setDialogType(null); + } catch (error: any) { + console.log(error); + toast.error(error.message); + } finally { + setIsLoading(false); + } + }; + + return ( + { + if (!open) setDialogType(null); + }} + > + + +
+ + Create New Organization + +
+
+ Name + { + setName(e.target.value); + if (!slugChanged) { + setSlug(slugify(e.target.value)); + } + }} + /> +
+
+ Slug + { + if (!slugChanged) { + setSlug(slugify(e.target.value)); + } + }} + /> +
+
+
+ + + +
+
+ ); +}; diff --git a/vite/src/views/main-sidebar/components/LogOutItem.tsx b/vite/src/views/main-sidebar/components/LogOutItem.tsx new file mode 100644 index 000000000..7cd1c837d --- /dev/null +++ b/vite/src/views/main-sidebar/components/LogOutItem.tsx @@ -0,0 +1,46 @@ +import { authClient } from "@/lib/auth-client"; +import { DropdownMenuItem } from "@/components/ui/dropdown-menu"; +import { LogOut, Trash } from "lucide-react"; +import { useState } from "react"; +import React from "react"; +import { useNavigate } from "react-router"; + +export const LogOutItem = () => { + const [loading, setLoading] = useState(false); + const navigate = useNavigate(); + + return ( + + { + try { + setLoading(true); + await authClient.signOut(); + await navigate("/sign-in"); + } catch (error) { + console.error("Error signing out:", error); + } finally { + setLoading(false); + } + }} + > +
+ Log Out + +
+
+ {/* { + await authClient.deleteUser({ + callbackURL: "http://localhost:3000/sign-in", + }); + }} + > +
+ Delete Account + +
+
*/} +
+ ); +}; diff --git a/vite/src/views/main-sidebar/components/ManageOrg.tsx b/vite/src/views/main-sidebar/components/ManageOrg.tsx new file mode 100644 index 000000000..3008d462e --- /dev/null +++ b/vite/src/views/main-sidebar/components/ManageOrg.tsx @@ -0,0 +1,79 @@ +import FieldLabel from "@/components/general/modal-components/FieldLabel"; +import { Button } from "@/components/ui/button"; +import { + Dialog, + DialogContent, + DialogFooter, + DialogHeader, + DialogTitle, + DialogTrigger, +} from "@/components/ui/dialog"; + +import { OrgMembersList } from "../org-dropdown/manage-org/OrgMembersList"; +import { OrgInvitesList } from "../org-dropdown/manage-org/OrgInvitesList"; +import { PageSectionHeader } from "@/components/general/PageSectionHeader"; +import { InvitePopover } from "../org-dropdown/manage-org/InvitePopover"; +import { Tabs, TabsContent, TabsList, TabsTrigger } from "@/components/ui/tabs"; +import { OrgDetails } from "./OrgDetails"; + +export const ManageOrg = ({ + open, + setOpen, +}: { + open: boolean; + setOpen: (open: boolean) => void; +}) => { + return ( + + + +
+ + Manage Organization + +
+ + + + Details + + + Members + + + Invites + + + } + isOnboarding={true} + className="px-6" + classNames={{ + title: "text-t3", + }} + addButton={} + /> + + + + + + + + + + + + +
+
+ {/* + + */} +
+
+ ); +}; diff --git a/vite/src/views/main-sidebar/components/OrgDetails.tsx b/vite/src/views/main-sidebar/components/OrgDetails.tsx new file mode 100644 index 000000000..4a667f33f --- /dev/null +++ b/vite/src/views/main-sidebar/components/OrgDetails.tsx @@ -0,0 +1,106 @@ +import FieldLabel from "@/components/general/modal-components/FieldLabel"; +import { Button } from "@/components/ui/button"; +import { Input } from "@/components/ui/input"; +import { useOrg } from "@/hooks/useOrg"; +import { authClient } from "@/lib/auth-client"; +import { useEffect, useMemo, useState } from "react"; +import { toast } from "sonner"; +import OrgLogoUploader from "@/views/main-sidebar/org-dropdown/manage-org/OrgLogoUploader"; +import { Separator } from "@/components/ui/separator"; +import { DeleteOrgPopover } from "../org-dropdown/manage-org/DeleteOrgPopover"; + +export const OrgDetails = () => { + const { org, mutate } = useOrg(); + + const [inputs, setInputs] = useState({ + name: org?.name, + slug: org?.slug, + }); + + const [saving, setSaving] = useState(false); + + const canSave = useMemo(() => { + return inputs.name !== org?.name || inputs.slug !== org?.slug; + }, [inputs, org]); + + const handleSave = async () => { + try { + setSaving(true); + const { data, error } = await authClient.organization.update({ + data: { + name: inputs.name, + slug: inputs.slug, + }, + organizationId: org.id, + }); + + if (error) { + toast.error(error.message || "Failed to update organization"); + return; + } + + await mutate(); + + toast.success("Successfully updated organization"); + } catch (error) { + console.error(error); + } finally { + setSaving(false); + } + }; + + return ( +
+
+
+ +
+
+ setInputs({ ...inputs, name: value })} + /> + setInputs({ ...inputs, slug: value })} + /> +
+   + +
+
+
+ + +
+ ); +}; + +const OrgDetailInput = ({ + label, + value, + setValue, +}: { + label: string; + value: string; + setValue: (value: string) => void; +}) => { + return ( +
+ {label} +
+ setValue(e.target.value)} /> +
+
+ ); +}; diff --git a/vite/src/views/main-sidebar/components/OrgDropdown.tsx b/vite/src/views/main-sidebar/components/OrgDropdown.tsx new file mode 100644 index 000000000..cb45fe117 --- /dev/null +++ b/vite/src/views/main-sidebar/components/OrgDropdown.tsx @@ -0,0 +1,205 @@ +import { Button } from "@/components/ui/button"; +import { + Dialog, + DialogContent, + DialogHeader, + DialogTitle, + DialogTrigger, +} from "@/components/ui/dialog"; +import { + DropdownMenu, + DropdownMenuContent, + DropdownMenuItem, + DropdownMenuPortal, + DropdownMenuSeparator, + DropdownMenuSub, + DropdownMenuSubContent, + DropdownMenuSubTrigger, + DropdownMenuTrigger, +} from "@/components/ui/dropdown-menu"; +import { useOrg } from "@/hooks/useOrg"; +import { + authClient, + useListOrganizations, + useSession, +} from "@/lib/auth-client"; +import { FrontendOrg, user } from "@autumn/shared"; +import { DropdownMenuGroup } from "@radix-ui/react-dropdown-menu"; +import { ChevronDown, LogOut, Plus, Settings, Trash } from "lucide-react"; +import React from "react"; +import { useState } from "react"; +import { CreateNewOrg } from "./CreateNewOrg"; +import { toast } from "sonner"; +import { LogOutItem } from "./LogOutItem"; +import { cn } from "@/lib/utils"; +import { Skeleton } from "@/components/ui/skeleton"; +import { ManageOrg } from "./ManageOrg"; +import { useMemberships } from "../org-dropdown/hooks/useMemberships"; +import { useSidebarContext } from "../SidebarContext"; +import { OrgLogo } from "../org-dropdown/components/OrgLogo"; +import { AdminHover } from "@/components/general/AdminHover"; + +export const OrgDropdown = () => { + const { org, isLoading, error } = useOrg(); + const { state, setState } = useSidebarContext(); + + const { data: orgs, isPending } = useListOrganizations(); + const [dialogType, setDialogType] = useState<"create" | "manage" | null>( + null, + ); + + const { data: session } = useSession(); + + // To pre-fetch data + useMemberships(); + const [dropdownOpen, setDropdownOpen] = useState(false); + const [manageOpen, setManageOpen] = useState(false); + + if (isLoading) + return ( +
+ + +
+ ); + + if (!org || error) return null; + + const expanded = state === "expanded"; + + return ( +
+ + + + + + + + + + + +
+ {session?.user?.name} + + {session?.user?.email} + +
+
+ + + { + e.preventDefault(); + setManageOpen(true); + setDropdownOpen(false); + }} + > +
+ Manage + +
+
+ { + setDialogType("create"); + }} + > +
+ Create New + +
+
+ + + + + Switch Organization + + + + {orgs?.map((org) => ( + + ))} + + + +
+ + +
+
+
+ ); +}; + +const SwitchOrgItem = ({ org, setDropdownOpen }: any) => { + const [loading, setLoading] = useState(false); + + const { mutate } = useOrg(); + + const handleSwitchOrg = async (orgId: string) => { + setLoading(true); + + try { + await authClient.organization.setActive({ + organizationId: orgId, + }); + + window.location.reload(); + } catch (error: any) { + toast.error(error.message); + } finally { + setLoading(false); + } + }; + + return ( + { + e.preventDefault(); + await handleSwitchOrg(org.id); + setDropdownOpen(false); + }} + shimmer={loading} + className="flex justify-between" + > + {org.name} + + ); +}; diff --git a/vite/src/views/main-sidebar/components/UserButton.tsx b/vite/src/views/main-sidebar/components/UserButton.tsx new file mode 100644 index 000000000..10e611a34 --- /dev/null +++ b/vite/src/views/main-sidebar/components/UserButton.tsx @@ -0,0 +1,92 @@ +import { useSession, signOut, deleteUser } from "@/lib/auth-client"; +import { + DropdownMenu, + DropdownMenuContent, + DropdownMenuItem, + DropdownMenuLabel, + DropdownMenuSeparator, + DropdownMenuTrigger, +} from "@/components/ui/dropdown-menu"; +import { LogOut } from "lucide-react"; +import { useState } from "react"; + +export const UserButton = () => { + const { data: session } = useSession(); + const user = session?.user; + const [isLoading, setIsLoading] = useState(false); + + if (!user) return null; + + const handleSignOut = async () => { + setIsLoading(true); + try { + await signOut(); + } catch (error) { + console.error("Sign out failed:", error); + } finally { + setIsLoading(false); + } + }; + + const handleDeleteAccount = async () => { + await deleteUser(); + }; + + const getInitials = (name: string) => { + return name + .split(" ") + .map((part) => part[0]) + .join("") + .toUpperCase() + .slice(0, 2); + }; + + const displayName = user.name || user.email?.split("@")[0] || "User"; + const initials = getInitials(displayName); + + return ( + + + + + + + + + {isLoading ? "Signing out..." : "Sign out"} + + + Delete Account + + + + ); +}; diff --git a/vite/src/views/main-sidebar/env-dropdown/ExpandedEnvTrigger.tsx b/vite/src/views/main-sidebar/env-dropdown/ExpandedEnvTrigger.tsx new file mode 100644 index 000000000..23d457353 --- /dev/null +++ b/vite/src/views/main-sidebar/env-dropdown/ExpandedEnvTrigger.tsx @@ -0,0 +1,56 @@ +import { AppEnv } from "@autumn/shared"; +import { cn } from "@/lib/utils"; +import { FlaskConical, Sailboat } from "lucide-react"; +import { useEnv } from "@/utils/envUtils"; +import { DropdownMenuTrigger } from "@/components/ui/dropdown-menu"; +import { useSidebarContext } from "../SidebarContext"; + +export const sandboxStyles = + "text-amber-600 bg-amber-100 border-amber-500 w-[100px]"; +export const liveStyles = "text-primary bg-purple-100 border-primary w-[120px]"; + +export const ExpandedEnvTrigger = ({ isHovered }: { isHovered: boolean }) => { + const env = useEnv(); + const { state } = useSidebarContext(); + + const isSandbox = env === AppEnv.Sandbox; + const expanded = state == "expanded"; + return ( + +
+
+ {env === AppEnv.Sandbox ? ( + + ) : ( + + )} +
+

+ {isSandbox ? "Sandbox" : "Production"} +

+
+
+ ); +}; diff --git a/vite/src/views/main-sidebar/org-dropdown/components/OrgLogo.tsx b/vite/src/views/main-sidebar/org-dropdown/components/OrgLogo.tsx new file mode 100644 index 000000000..cc40ed08a --- /dev/null +++ b/vite/src/views/main-sidebar/org-dropdown/components/OrgLogo.tsx @@ -0,0 +1,25 @@ +import { cn } from "@/lib/utils"; +import { FrontendOrg } from "@autumn/shared"; +import { useSidebarContext } from "../../SidebarContext"; + +export const OrgLogo = ({ org }: { org: FrontendOrg }) => { + const { state } = useSidebarContext(); + const firstLetter = org.name.charAt(0).toUpperCase(); + const expanded = state === "expanded"; + return ( +
+ {org.logo ? ( + {org.name} + ) : ( + + {firstLetter} + + )} +
+ ); +}; diff --git a/vite/src/views/main-sidebar/org-dropdown/hooks/useMemberships.tsx b/vite/src/views/main-sidebar/org-dropdown/hooks/useMemberships.tsx new file mode 100644 index 000000000..b3fec796e --- /dev/null +++ b/vite/src/views/main-sidebar/org-dropdown/hooks/useMemberships.tsx @@ -0,0 +1,47 @@ +import { + authClient, + useListOrganizations, + useSession, +} from "@/lib/auth-client"; +import { useAxiosSWR } from "@/services/useAxiosSwr"; +import { useEffect } from "react"; + +export const useMemberships = () => { + const { data, error, isLoading, mutate } = useAxiosSWR({ + url: "/organization/members", + }); + + const { data: session } = useSession(); + const { data: orgs } = useListOrganizations(); + + const handleRemovedFromOrg = async () => { + const inOrg = orgs?.find( + (org: any) => org.id === session?.session?.activeOrganizationId, + ); + + if (!inOrg) { + if (orgs && orgs.length > 0) { + await authClient.organization.setActive({ + organizationId: orgs[0].id, + }); + } else { + const { data, error } = await authClient.revokeSessions(); + console.log("Revoked sessions", data, error); + } + window.location.reload(); + } + }; + + useEffect(() => { + if (!orgs) return; + handleRemovedFromOrg(); + }, [orgs]); + + return { + memberships: data?.memberships || [], + invites: data?.invites || [], + isLoading, + error, + mutate, + }; +}; diff --git a/vite/src/views/main-sidebar/org-dropdown/manage-org/DeleteOrgPopover.tsx b/vite/src/views/main-sidebar/org-dropdown/manage-org/DeleteOrgPopover.tsx new file mode 100644 index 000000000..2c508dc5a --- /dev/null +++ b/vite/src/views/main-sidebar/org-dropdown/manage-org/DeleteOrgPopover.tsx @@ -0,0 +1,102 @@ +import { Button } from "@/components/ui/button"; +import { Input } from "@/components/ui/input"; +import { + Popover, + PopoverContent, + PopoverTrigger, +} from "@/components/ui/popover"; +import { useOrg } from "@/hooks/useOrg"; +import { authClient, useListOrganizations } from "@/lib/auth-client"; +import { useAxiosInstance } from "@/services/useAxiosInstance"; +import { getBackendErr } from "@/utils/genUtils"; +import { useState } from "react"; +import { toast } from "sonner"; +import { useMemberships } from "../hooks/useMemberships"; + +export const DeleteOrgPopover = () => { + const { org } = useOrg(); + const { data: organizations } = useListOrganizations(); + const { memberships } = useMemberships(); + const [confirmText, setConfirmText] = useState(""); + const [deleting, setDeleting] = useState(false); + const axiosInstance = useAxiosInstance(); + + const deleteOrg = async () => { + if (!organizations || !memberships) { + toast.error("Failed to delete org"); + return; + } + if (organizations.length === 1) { + toast.error("You must have at least one organization"); + return; + } + + if (memberships.length > 1) { + toast.error("Can't delete org with multiple members"); + return; + } + + if (confirmText !== org?.name) { + toast.error("Please type the org name to confirm"); + return; + } + + await axiosInstance.delete(`/organization`); + + // Other org is now the active org + const otherOrg = organizations.find((o) => o.id !== org.id); + await authClient.organization.setActive({ + organizationId: otherOrg!.id, + }); + + const { data, error } = await authClient.organization.delete({ + organizationId: org.id, + }); + + if (error) { + throw error; + } + + window.location.reload(); + }; + const handleDeleteClicked = async () => { + setDeleting(true); + try { + await deleteOrg(); + } catch (error) { + toast.error(getBackendErr(error, "Failed to delete org")); + } + + setDeleting(false); + }; + return ( + + + + + +
+

+ Are you sure you want to delete this organization? +

+ setConfirmText(e.target.value)} + /> + +
+
+
+ ); +}; diff --git a/vite/src/views/main-sidebar/org-dropdown/manage-org/InvitePopover.tsx b/vite/src/views/main-sidebar/org-dropdown/manage-org/InvitePopover.tsx new file mode 100644 index 000000000..3b8eedb43 --- /dev/null +++ b/vite/src/views/main-sidebar/org-dropdown/manage-org/InvitePopover.tsx @@ -0,0 +1,87 @@ +import { Button } from "@/components/ui/button"; +import { Input } from "@/components/ui/input"; +import { + Popover, + PopoverContent, + PopoverTrigger, +} from "@/components/ui/popover"; +import { authClient } from "@/lib/auth-client"; +import { useAxiosInstance } from "@/services/useAxiosInstance"; +import { getBackendErr } from "@/utils/genUtils"; +import { Mail, PlusIcon } from "lucide-react"; +import { useState } from "react"; +import { toast } from "sonner"; +import { useMemberships } from "../hooks/useMemberships"; + +export const InvitePopover = () => { + const [email, setEmail] = useState(""); + const [loading, setLoading] = useState(false); + const axiosInstance = useAxiosInstance(); + const { mutate } = useMemberships(); + const [open, setOpen] = useState(false); + + const handleInvite = async () => { + try { + setLoading(true); + const { data, status } = await axiosInstance.post( + "/organization/invite", + { + email: email, + role: "member", + }, + ); + + if (status === 202) { + await authClient.organization.inviteMember({ + email: email, + role: "admin", + }); + toast.success(`Successfully sent invitation to ${email}`); + } else { + toast.success(data.message); + } + await mutate(); + setOpen(false); + } catch (error) { + console.error(error); + toast.error(getBackendErr(error, "Failed to invite user")); + } finally { + setLoading(false); + } + }; + + return ( + + + + + +
+ +

Invite by email

+
+ +
+ setEmail(e.target.value)} + /> + +
+
+
+ ); +}; diff --git a/vite/src/views/main-sidebar/org-dropdown/manage-org/MemberRowToolbar.tsx b/vite/src/views/main-sidebar/org-dropdown/manage-org/MemberRowToolbar.tsx new file mode 100644 index 000000000..e8c847139 --- /dev/null +++ b/vite/src/views/main-sidebar/org-dropdown/manage-org/MemberRowToolbar.tsx @@ -0,0 +1,98 @@ +import { ToolbarButton } from "@/components/general/table-components/ToolbarButton"; +import { Button } from "@/components/ui/button"; +import { + DropdownMenu, + DropdownMenuItem, + DropdownMenuContent, + DropdownMenuTrigger, +} from "@/components/ui/dropdown-menu"; +import { useOrg } from "@/hooks/useOrg"; +import { authClient } from "@/lib/auth-client"; +import { Invite, Membership } from "@autumn/shared"; +import { TrashIcon } from "lucide-react"; +import { useState } from "react"; +import { toast } from "sonner"; +import { useMemberships } from "../hooks/useMemberships"; + +export const MemberRowToolbar = ({ + membership, + invite, +}: { + membership?: Membership; + invite?: Invite; +}) => { + const [deleteLoading, setDeleteLoading] = useState(false); + const [open, setOpen] = useState(false); + const { org } = useOrg(); + const { mutate } = useMemberships(); + + const handleDeleteMember = async (e: any) => { + e.preventDefault(); + e.stopPropagation(); + + setDeleteLoading(true); + try { + const { data, error } = await authClient.organization.removeMember({ + memberIdOrEmail: membership!.member.id, + organizationId: org.id, + }); + + if (error) { + toast.error(error.message); + } else { + await mutate(); + toast.success("Member removed"); + } + } catch (error) { + toast.error("Failed to remove member"); + } + setDeleteLoading(false); + }; + + const handleDeleteInvite = async (e: any) => { + e.preventDefault(); + e.stopPropagation(); + + setDeleteLoading(true); + try { + const { data, error } = await authClient.organization.cancelInvitation({ + invitationId: invite!.id, + }); + if (error) { + toast.error(error.message); + } + + await mutate(); + toast.success("Invite cancelled"); + } catch (error) { + toast.error("Failed to remove invite"); + } + setDeleteLoading(false); + }; + + return ( + + + + + + { + if (membership) { + handleDeleteMember(e); + } else { + handleDeleteInvite(e); + } + }} + > +
+ Remove + +
+
+
+
+ ); +}; diff --git a/vite/src/views/main-sidebar/org-dropdown/manage-org/OrgInvitesList.tsx b/vite/src/views/main-sidebar/org-dropdown/manage-org/OrgInvitesList.tsx new file mode 100644 index 000000000..befb63afa --- /dev/null +++ b/vite/src/views/main-sidebar/org-dropdown/manage-org/OrgInvitesList.tsx @@ -0,0 +1,60 @@ +import { useMemberships } from "../hooks/useMemberships"; +import { Invite, Membership } from "@autumn/shared"; +import { PageSectionHeader } from "@/components/general/PageSectionHeader"; +import { Item, Row } from "@/components/general/TableGrid"; +import { cn } from "@/lib/utils"; +import { formatDateStr } from "@/utils/formatUtils/formatDateUtils"; +import { Badge } from "@/components/ui/badge"; +import { InvitePopover } from "./InvitePopover"; +import { useSession } from "@/lib/auth-client"; +import { MemberRowToolbar } from "./MemberRowToolbar"; + +export const OrgInvitesList = () => { + const { + memberships, + invites, + isLoading: isMembersLoading, + } = useMemberships(); + const { data } = useSession(); + + if (isMembersLoading) return null; + const membership = memberships.find( + (membership: Membership) => membership.user.id === data?.session?.userId, + ); + const isAdmin = + membership?.member.role === "admin" || membership?.member.role === "owner"; + + return ( +
+ + Email + Status + Role + + Expires At + + + {invites.map((invite: Invite) => { + return ( + + {invite.email} + {invite.status} + + {invite.role} + + + + {formatDateStr(invite.expiresAt)} + + + {isAdmin && } + + + ); + })} +
+ ); +}; diff --git a/vite/src/views/main-sidebar/org-dropdown/manage-org/OrgLogoUploader.tsx b/vite/src/views/main-sidebar/org-dropdown/manage-org/OrgLogoUploader.tsx new file mode 100644 index 000000000..ebfda3f4b --- /dev/null +++ b/vite/src/views/main-sidebar/org-dropdown/manage-org/OrgLogoUploader.tsx @@ -0,0 +1,155 @@ +import React, { useRef, useState } from "react"; +import { Button } from "@/components/ui/button"; +import FieldLabel from "@/components/general/modal-components/FieldLabel"; +import { toast } from "sonner"; +import { authClient } from "@/lib/auth-client"; +import { useAxiosInstance } from "@/services/useAxiosInstance"; +import axios from "axios"; +import { useOrg } from "@/hooks/useOrg"; +import { getOrgLogoUrl } from "@/utils/orgUtils"; +import { getBackendErr } from "@/utils/genUtils"; + +const MAX_SIZE_MB = 10; +const MAX_SIZE_BYTES = MAX_SIZE_MB * 1024 * 1024; + +export interface OrgLogoUploaderProps { + initialLogoUrl?: string; +} + +const OrgLogoUploader: React.FC = ({ + initialLogoUrl, +}) => { + const { org, mutate } = useOrg(); + const [error, setError] = useState(null); + const inputRef = useRef(null); + const [uploading, setUploading] = useState(false); + const axiosInstance = useAxiosInstance(); + const [logoVersion, setLogoVersion] = useState(0); + + const [removing, setRemoving] = useState(false); + + // Removal logic + const handleRemove = async () => { + setRemoving(true); + try { + const { error } = await authClient.organization.update({ + data: { + logo: "", + }, + }); + + if (error) { + toast.error(error.message || "Failed to remove logo"); + return; + } + + await mutate(); + setRemoving(false); + } catch (error) { + setRemoving(false); + } + }; + + // Upload logic + const handleUploadClick = () => { + inputRef.current?.click(); + }; + + const uploadToSupabase = async (file: File) => { + const { data } = await axiosInstance.get("/organization/upload_url"); + const { signedUrl } = data; + + await axios.put(signedUrl, file, { + headers: { + "Content-Type": file.type, + }, + }); + }; + + const handleUploading = async (e: React.ChangeEvent) => { + const file = e.target.files?.[0]; + + if (!file) return; + + setUploading(true); + try { + await uploadToSupabase(file); + + const { error } = await authClient.organization.update({ + data: { + logo: getOrgLogoUrl(org.id), + }, + }); + + if (error) { + toast.error(error.message || "Failed to update logo"); + return; + } + + await mutate(); + setLogoVersion(logoVersion + 1); + toast.success("Successfully uploaded logo"); + } catch (error) { + toast.error(getBackendErr(error, "Failed to upload logo")); + } finally { + setUploading(false); + } + }; + + return ( +
+ Logo +
+ + {org.logo ? ( + + ) : ( +
+ + +
+ )} +
+
+ + {org.logo && ( + + )} +
+ + Recommended size 1:1, up to 10MB. + + {error && {error}} +
+
+
+ ); +}; + +export default OrgLogoUploader; diff --git a/vite/src/views/main-sidebar/org-dropdown/manage-org/OrgMembersList.tsx b/vite/src/views/main-sidebar/org-dropdown/manage-org/OrgMembersList.tsx new file mode 100644 index 000000000..a9fe65ef5 --- /dev/null +++ b/vite/src/views/main-sidebar/org-dropdown/manage-org/OrgMembersList.tsx @@ -0,0 +1,70 @@ +import { useMemberships } from "../hooks/useMemberships"; +import { Membership } from "@autumn/shared"; +import { PageSectionHeader } from "@/components/general/PageSectionHeader"; +import { Item, Row } from "@/components/general/TableGrid"; +import { cn } from "@/lib/utils"; +import { formatDateStr } from "@/utils/formatUtils/formatDateUtils"; +import { Badge } from "@/components/ui/badge"; +import { InvitePopover } from "./InvitePopover"; +import { useSession } from "@/lib/auth-client"; +import { MemberRowToolbar } from "./MemberRowToolbar"; + +export const OrgMembersList = () => { + const { memberships, isLoading: isMembersLoading } = useMemberships(); + const { data } = useSession(); + + if (isMembersLoading) return null; + + const membership = memberships.find( + (membership: Membership) => membership.user.id === data?.session?.userId, + ); + + const isAdmin = + membership?.member.role === "admin" || membership?.member.role === "owner"; + + return ( +
+ {/* } + /> */} + + + Email + Name + Role + {/* */} + Created At + + + {memberships.map((membership: Membership) => { + const user = membership.user; + const member = membership.member; + return ( + + {user.email} + {user.name} + + {member.role} + + {/* */} + + {formatDateStr(member.createdAt)} + + + {isAdmin && } + + + ); + })} +
+ ); +}; diff --git a/vite/src/views/onboarding/ConnectStripe.tsx b/vite/src/views/onboarding/ConnectStripe.tsx index 78a820af9..83100fc02 100644 --- a/vite/src/views/onboarding/ConnectStripe.tsx +++ b/vite/src/views/onboarding/ConnectStripe.tsx @@ -37,6 +37,7 @@ import SmallSpinner from "@/components/general/SmallSpinner"; import { FontAwesomeIcon } from "@fortawesome/react-fontawesome"; import { faStripeS } from "@fortawesome/free-brands-svg-icons"; import { useNavigate } from "react-router"; +import { useOrg } from "@/hooks/useOrg"; function ConnectStripe({ className, @@ -45,29 +46,19 @@ function ConnectStripe({ className?: string; onboarding?: boolean; }) { + const axiosInstance = useAxiosInstance({ env: AppEnv.Live }); + const navigate = useNavigate(); + const { org, mutate, isLoading: isOrgLoading } = useOrg(); const [searchParams] = useSearchParams(); const redirect = searchParams.get("redirect"); - const axiosInstance = useAxiosInstance({ env: AppEnv.Live }); - const [testApiKey, setTestApiKey] = useState(""); const [liveApiKey, setLiveApiKey] = useState(""); const [successUrl, setSuccessUrl] = useState("https://useautumn.com"); const [defaultCurrency, setDefaultCurrency] = useState("USD"); const [isLoading, setIsLoading] = useState(false); - const { - data: orgData, - mutate: mutateOrg, - isLoading: isOrgLoading, - } = useAxiosSWR({ - url: `/organization`, - env: AppEnv.Live, - }); - - const org = orgData?.org; - const handleConnectStripe = async () => { if (!testApiKey || !successUrl || !defaultCurrency) { toast.error("Please fill in all fields"); @@ -90,7 +81,7 @@ function ConnectStripe({ }); toast.success("Successfully connected to Stripe"); - await mutateOrg(); + await mutate(); if (redirect && !onboarding) { navigate(redirect); } @@ -107,7 +98,7 @@ function ConnectStripe({ try { setIsDisconnecting(true); await OrgService.disconnectStripe(axiosInstance); - await mutateOrg(); + await mutate(); toast.success("Successfully disconnected from Stripe"); } catch (error) { toast.error(getBackendErr(error, "Failed to disconnect Stripe")); @@ -125,7 +116,7 @@ function ConnectStripe({ className={cn( "flex flex-col gap-4", className, - onboarding && "flex-row justify-between items-center" + onboarding && "flex-row justify-between items-center", )} >

Stripe Connected   ✅

@@ -222,7 +213,7 @@ export const CurrencySelect = ({ "w-full justify-between transition-colors duration-100", open && "border-[rgb(139,92,246)] shadow-[0_0_2px_1px_rgba(139,92,246,0.25)]", - className + className, )} disabled={disabled} > diff --git a/vite/src/views/onboarding/OnboardingView.tsx b/vite/src/views/onboarding/OnboardingView.tsx index a29fa519c..6471e7d86 100644 --- a/vite/src/views/onboarding/OnboardingView.tsx +++ b/vite/src/views/onboarding/OnboardingView.tsx @@ -1,42 +1,42 @@ "use client"; -import { useState, useEffect, useRef } from "react"; -import { useAuth, useOrganization } from "@clerk/clerk-react"; -import { useSearchParams } from "react-router"; +import EnvStep from "./onboarding-steps/Env"; +import MountHandler from "./onboarding-steps/MountHandler"; import Step from "@/components/general/OnboardingStep"; -import { useAxiosSWR } from "@/services/useAxiosSwr"; -import { useAxiosInstance } from "@/services/useAxiosInstance"; -import { useEnv } from "@/utils/envUtils"; -import { Book } from "lucide-react"; -import { ConnectStripeStep } from "./onboarding-steps/ConnectStripe"; -import { CreateSecretKey } from "./onboarding-steps/CreateSecretKey"; import AttachProduct from "./onboarding-steps/AttachProduct"; import CheckAccessStep from "./onboarding-steps/CheckAccess"; import Install from "./onboarding-steps/Install"; import LoadingScreen from "../general/LoadingScreen"; -import { ProductList } from "./onboarding-steps/ProductList"; -import { useCreateOrg } from "./hooks/useCreateOrg"; -import EnvStep from "./onboarding-steps/Env"; -import MountHandler from "./onboarding-steps/MountHandler"; -import { SampleApp } from "./onboarding-steps/SampleApp"; import IntegrationGuideStep from "./onboarding-steps/IntegrationGuide"; import AutumnProviderStep from "./onboarding-steps/AutumnProvider"; + +import { useState, useEffect, useRef } from "react"; +import { useSearchParams } from "react-router"; +import { useAxiosSWR } from "@/services/useAxiosSwr"; +import { useEnv } from "@/utils/envUtils"; +import { Book } from "lucide-react"; +import { ConnectStripeStep } from "./onboarding-steps/ConnectStripe"; +import { CreateSecretKey } from "./onboarding-steps/CreateSecretKey"; +import { ProductList } from "./onboarding-steps/ProductList"; +import { SampleApp } from "./onboarding-steps/SampleApp"; import { AutumnProvider } from "autumn-js/react"; +import { useSession } from "@/lib/auth-client"; +import { useAxiosInstance } from "@/services/useAxiosInstance"; function OnboardingView() { const env = useEnv(); - const { organization: org } = useOrganization(); const [searchParams] = useSearchParams(); - + const token = searchParams.get("token"); const [apiKey, setApiKey] = useState(""); const [showIntegrationSteps, setShowIntegrationSteps] = useState(false); - - const hasHandledToken = useRef(false); - const axiosInstance = useAxiosInstance(); - const token = searchParams.get("token"); const [loading, setLoading] = useState(true); - const { getToken } = useAuth(); + const { data } = useSession(); + + const axiosInstance = useAxiosInstance(); + const hasHandledToken = useRef(false); + + const orgId = data?.session?.activeOrganizationId; const { data: productData, @@ -48,12 +48,10 @@ function OnboardingView() { withAuth: true, }); - useCreateOrg({ productMutate }); - useEffect(() => { const handleToken = async () => { try { - const { data } = await axiosInstance.post("/onboarding", { + await axiosInstance.post("/onboarding", { token, }); @@ -65,17 +63,17 @@ function OnboardingView() { } }; - if (org && token && !hasHandledToken.current) { + if (token && !hasHandledToken.current) { hasHandledToken.current = true; handleToken(); } - }, [org, searchParams, token, axiosInstance, productMutate]); + }, [searchParams, token, axiosInstance, productMutate]); useEffect(() => { - if (org && !token) { + if (orgId && !token) { setLoading(false); } - }, [org, token]); + }, [orgId, token]); if (loading || productLoading) { return ; @@ -93,14 +91,7 @@ function OnboardingView() { number={2} /> { - const token = await getToken({ - template: "custom_template", - }); - return token; - }} + backendUrl={`${import.meta.env.VITE_BACKEND_URL}/demo`} > diff --git a/vite/src/views/onboarding/hooks/useCreateOrg.tsx b/vite/src/views/onboarding/hooks/useCreateOrg.tsx index 5a95df463..c0bd6a9ed 100644 --- a/vite/src/views/onboarding/hooks/useCreateOrg.tsx +++ b/vite/src/views/onboarding/hooks/useCreateOrg.tsx @@ -1,8 +1,13 @@ -import { useOrganization, useUser } from "@clerk/clerk-react"; - +import { useOrg } from "@/hooks/useOrg"; +import { + authClient, + useListOrganizations, + useSession, +} from "@/lib/auth-client"; import { useAxiosInstance } from "@/services/useAxiosInstance"; -import { useOrganizationList } from "@clerk/clerk-react"; -import { useEffect, useRef, useState } from "react"; +import { slugify } from "@/utils/formatUtils/formatTextUtils"; +import { useEffect, useRef } from "react"; +import { toast } from "sonner"; export const useCreateOrg = ({ productMutate, @@ -10,43 +15,50 @@ export const useCreateOrg = ({ productMutate: () => Promise; }) => { const axiosInstance = useAxiosInstance(); - const { user } = useUser(); - const { organization: org } = useOrganization(); - const { setActive } = useOrganizationList(); const hasCreatedOrg = useRef(false); + const { data: session } = useSession(); + const { data: organizations, isPending } = useListOrganizations(); + const { mutate } = useOrg(); + + const getOrgSlug = () => { + const randomDigits = Math.floor(10000000 + Math.random() * 90000000); + return `${slugify(session?.user!.name || "org")}_${randomDigits}`; + }; + useEffect(() => { const createDefaultOrg = async () => { - if (hasCreatedOrg.current) return; - + if (hasCreatedOrg.current || isPending || !session?.user) return; hasCreatedOrg.current = true; - // Either set first org active, or create a new org try { - if ( - user?.organizationMemberships?.length && - user.organizationMemberships.length > 0 - ) { - await setActive?.({ - organization: user.organizationMemberships[0].organization.id, + if (organizations && organizations.length > 0) { + await authClient.organization.setActive({ + organizationId: organizations[0]?.id, }); - await productMutate(); - - return; } else { - const { data } = await axiosInstance.post("/organization"); + const { data, error } = await authClient.organization.create({ + name: `${session?.user.name}'s Org`, + slug: getOrgSlug(), + }); - const res = await setActive?.({ organization: data.id }); + if (error) throw error; + await authClient.organization.setActive({ + organizationId: data?.id, + }); + + await mutate(); await productMutate(); } - } catch (error) { - console.error("Error creating organization:", error); + } catch (error: any) { + toast.error(`Error initializing org: ${error.message}`); } }; + createDefaultOrg(); - if (!org && setActive) { - createDefaultOrg(); - } - }, [org, axiosInstance, setActive, productMutate, user]); + // if (!org && setActive) { + // createDefaultOrg(); + // } + }, [session, axiosInstance, productMutate]); }; diff --git a/vite/src/views/onboarding/onboarding-steps/CreateOrg.tsx b/vite/src/views/onboarding/onboarding-steps/CreateOrg.tsx index ef7cb8a3b..25dfa312d 100644 --- a/vite/src/views/onboarding/onboarding-steps/CreateOrg.tsx +++ b/vite/src/views/onboarding/onboarding-steps/CreateOrg.tsx @@ -3,125 +3,122 @@ import { Button } from "@/components/ui/button"; import { Input } from "@/components/ui/input"; import { useAxiosInstance } from "@/services/useAxiosInstance"; import { useEnv } from "@/utils/envUtils"; -import { useOrganization, useOrganizationList } from "@clerk/clerk-react"; -import { Building } from "lucide-react"; import { useState } from "react"; import ConfettiExplosion from "react-confetti-explosion"; import { toast } from "sonner"; -export const CreateOrgStep = ({ - number, - pollForOrg, -}: { - number: number; - pollForOrg: () => Promise; -}) => { - const { organization: org } = useOrganization(); - const env = useEnv(); - const axios = useAxiosInstance({ env }); - const { createOrganization, setActive } = useOrganizationList(); +// export const CreateOrgStep = ({ +// number, +// pollForOrg, +// }: { +// number: number; +// pollForOrg: () => Promise; +// }) => { - const [isExploding, setIsExploding] = useState(false); - const [loading, setLoading] = useState(false); - const [fields, setFields] = useState({ - name: org?.name || "", - slug: "", - }); +// const env = useEnv(); +// const axios = useAxiosInstance({ env }); - const handleCreateOrg = async () => { - setLoading(true); +// const [isExploding, setIsExploding] = useState(false); +// const [loading, setLoading] = useState(false); +// const [fields, setFields] = useState({ +// name: org?.name || "", +// slug: "", +// }); - try { - if (!createOrganization) { - toast.error("Error creating organization"); - return; - } +// const handleCreateOrg = async () => { +// setLoading(true); - const org = await createOrganization({ - name: fields.name, - }); +// try { +// if (!createOrganization) { +// toast.error("Error creating organization"); +// return; +// } - // Create org in Autumn - const res = await axios.post("/organization", { - orgId: org.id, - }); +// const org = await createOrganization({ +// name: fields.name, +// }); - console.log("Org created in Autumn", res); +// // Create org in Autumn +// const res = await axios.post("/organization", { +// orgId: org.id, +// }); - await setActive({ organization: org.id }); - // await pollForOrg(); - toast.success(`Created your organization: ${org.name}`); - setIsExploding(true); - } catch (error: any) { - if (error.message) { - toast.error(error.message); - } else { - toast.error("Error creating organization"); - } - } - setLoading(false); - }; +// console.log("Org created in Autumn", res); - return ( - -
-
-

- 👋 - -   Welcome to Autumn - -

-
-

- Create an organization to get started and integrate pricing within 5 - minutes. -

- - } - > - {/*
*/} -
- { - const newFields = { ...fields, name: e.target.value }; - setFields(newFields); - }} - /> - +// await setActive({ organization: org.id }); +// // await pollForOrg(); +// toast.success(`Created your organization: ${org.name}`); +// setIsExploding(true); +// } catch (error: any) { +// if (error.message) { +// toast.error(error.message); +// } else { +// toast.error("Error creating organization"); +// } +// } +// setLoading(false); +// }; - {isExploding && ( - { - console.log("complete"); - }} - /> - )} -
- {/*
*/} -
- ); -}; +// return ( +// +//
+//
+//

+// 👋 +// +//   Welcome to Autumn +// +//

+//
+//

+// Create an organization to get started and integrate pricing within 5 +// minutes. +//

+// +// } +// > +// {/*
*/} +//
+// { +// const newFields = { ...fields, name: e.target.value }; +// setFields(newFields); +// }} +// /> +// + +// {isExploding && ( +// { +// console.log("complete"); +// }} +// /> +// )} +//
+// {/*
*/} +//
+// ); +// }; diff --git a/vite/src/views/onboarding/onboarding-steps/ProductList.tsx b/vite/src/views/onboarding/onboarding-steps/ProductList.tsx index 64f2f56cd..34f2d82e5 100644 --- a/vite/src/views/onboarding/onboarding-steps/ProductList.tsx +++ b/vite/src/views/onboarding/onboarding-steps/ProductList.tsx @@ -9,15 +9,12 @@ import { ProductsContext } from "@/views/products/ProductsContext"; import { ProductsTable } from "@/views/products/ProductsTable"; import { Product, products, ProductV2 } from "@autumn/shared"; import { - DialogHeader, DialogContent, - DialogTrigger, DialogTitle, DialogFooter, } from "@/components/ui/dialog"; import { useState } from "react"; import { Dialog } from "@/components/ui/dialog"; -import { AddProductButton } from "@/views/customers/customer/add-product/AddProductButton"; import { ProductService } from "@/services/products/ProductService"; import { useAxiosInstance } from "@/services/useAxiosInstance"; import { getBackendErr } from "@/utils/genUtils"; diff --git a/vite/src/views/products/ProductsView.tsx b/vite/src/views/products/ProductsView.tsx index cccde94d6..491c41013 100644 --- a/vite/src/views/products/ProductsView.tsx +++ b/vite/src/views/products/ProductsView.tsx @@ -8,11 +8,9 @@ import { ProductsContext } from "./ProductsContext"; import { AppEnv } from "@autumn/shared"; import CreateProduct from "./CreateProduct"; import { ProductsTable } from "./ProductsTable"; -import { ToggleDisplayButton } from "@/components/general/ToggleDisplayButton"; import { Tabs, TabsList, TabsTrigger, TabsContent } from "@/components/ui/tabs"; -import { Ticket, Package, Gift, Flag, Banknote } from "lucide-react"; -import React from "react"; +import { Package, Gift, Flag } from "lucide-react"; import { RewardsTable } from "./rewards/RewardsTable"; import CreateReward from "./rewards/CreateReward"; diff --git a/vite/src/views/products/product/prices/CreateFixedPrice.tsx b/vite/src/views/products/product/prices/CreateFixedPrice.tsx index 55c6c1718..9c31040d1 100644 --- a/vite/src/views/products/product/prices/CreateFixedPrice.tsx +++ b/vite/src/views/products/product/prices/CreateFixedPrice.tsx @@ -1,15 +1,4 @@ -import React from "react"; -import { BillingInterval, FixedPriceConfig } from "@autumn/shared"; import { Input } from "@/components/ui/input"; -import { - Select, - SelectContent, - SelectItem, - SelectTrigger, - SelectValue, -} from "@/components/ui/select"; -import { keyToTitle } from "@/utils/formatUtils/formatTextUtils"; - import FieldLabel from "@/components/general/modal-components/FieldLabel"; import { useProductContext } from "../ProductContext"; import { SelectCycle } from "../product-item/components/SelectCycle"; @@ -30,10 +19,10 @@ function CreateFixedPrice({ return (
{/*

Rates

*/} -
+
Fixed Price -
+
{ @@ -45,29 +34,11 @@ function CreateFixedPrice({ className="h-full !text-lg min-w-36" /> - {org?.default_currency.toUpperCase() || "USD"} + {org?.default_currency?.toUpperCase() || "USD"}
- {/* Billing Cycle - */}
diff --git a/vite/src/views/products/product/product-item/CreateProductItem.tsx b/vite/src/views/products/product/product-item/CreateProductItem.tsx index d0de8ffb9..787b6f212 100644 --- a/vite/src/views/products/product/product-item/CreateProductItem.tsx +++ b/vite/src/views/products/product/product-item/CreateProductItem.tsx @@ -107,12 +107,10 @@ export function CreateProductItem() {
-
+
{showCreateFeature && (
-
+
{showCreateFeature || (features.length == 0 && item.price === null) ? (
@@ -138,7 +136,7 @@ export function CreateProductItem() { />
) : ( -
+
)} diff --git a/vite/src/views/products/product/product-item/ProductItemConfig.tsx b/vite/src/views/products/product/product-item/ProductItemConfig.tsx index 663a3dfc8..1c3f8eba5 100644 --- a/vite/src/views/products/product/product-item/ProductItemConfig.tsx +++ b/vite/src/views/products/product/product-item/ProductItemConfig.tsx @@ -108,14 +108,14 @@ export const ProductItemConfig = () => { return (
1 && "w-2xl", )} > {!show.feature ? ( -
+
) : ( diff --git a/vite/src/views/products/product/product-item/components/ConfigFixedPrice.tsx b/vite/src/views/products/product/product-item/components/ConfigFixedPrice.tsx index 5c531489a..22293d786 100644 --- a/vite/src/views/products/product/product-item/components/ConfigFixedPrice.tsx +++ b/vite/src/views/products/product/product-item/components/ConfigFixedPrice.tsx @@ -9,10 +9,10 @@ export default function FixedPriceConfig({ show: any; setShow: (show: any) => void; }) { - let { item, setItem } = useProductItemContext(); + const { item, setItem } = useProductItemContext(); return ( -
+