diff --git a/.github/dependabot.yml b/.github/dependabot.yml new file mode 100644 index 00000000..802c003f --- /dev/null +++ b/.github/dependabot.yml @@ -0,0 +1,35 @@ +version: 2 +updates: + - package-ecosystem: "npm" + directory: "/" + schedule: + interval: "daily" + groups: + dev-patch-updates: + dependency-type: "development" + update-types: + - "patch" + dev-minor-updates: + dependency-type: "development" + update-types: + - "minor" + prod-patch-updates: + dependency-type: "production" + update-types: + - "patch" + prod-minor-updates: + dependency-type: "production" + update-types: + - "minor" + + - package-ecosystem: "docker" + directory: "/" + schedule: + interval: "daily" + groups: + patch-updates: + update-types: + - "patch" + minor-updates: + update-types: + - "minor" diff --git a/.github/workflows/linting.yml b/.github/workflows/linting.yml new file mode 100644 index 00000000..750f9ecc --- /dev/null +++ b/.github/workflows/linting.yml @@ -0,0 +1,34 @@ +name: ESLint + +on: + pull_request: + paths: + - '**/*.js' + - '**/*.jsx' + - '**/*.ts' + - '**/*.tsx' + - '.eslintrc*' + - 'package.json' + - 'yarn.lock' + - 'pnpm-lock.yaml' + - 'package-lock.json' + +jobs: + Linter: + runs-on: ubuntu-latest + steps: + - name: Checkout code + uses: actions/checkout@v4 + + - name: Set up Node.js + uses: actions/setup-node@v4 + with: + node-version: '20' + + - name: Install dependencies + run: | + npm ci + + - name: Run ESLint + run: | + npx eslint . --ext .js,.jsx,.ts,.tsx \ No newline at end of file diff --git a/Dockerfile b/Dockerfile index 6ec9e23d..adfe2597 100644 --- a/Dockerfile +++ b/Dockerfile @@ -8,9 +8,11 @@ RUN npm install COPY . . -RUN npx drizzle-kit generate --dialect sqlite --schema ./server/db/schemas/ --out init +RUN echo 'export * from "./sqlite";' > server/db/index.ts -RUN npm run build +RUN npx drizzle-kit generate --dialect sqlite --schema ./server/db/sqlite/schema.ts --out init + +RUN npm run build:sqlite FROM node:20-alpine AS runner @@ -32,4 +34,4 @@ COPY server/db/names.json ./dist/names.json COPY public ./public -CMD ["npm", "start"] +CMD ["npm", "run", "start:sqlite"] diff --git a/Dockerfile.pg b/Dockerfile.pg new file mode 100644 index 00000000..58c54d8c --- /dev/null +++ b/Dockerfile.pg @@ -0,0 +1,37 @@ +FROM node:20-alpine AS builder + +WORKDIR /app + +# COPY package.json package-lock.json ./ +COPY package.json ./ +RUN npm install + +COPY . . + +RUN echo 'export * from "./pg";' > server/db/index.ts + +RUN npx drizzle-kit generate --dialect postgresql --schema ./server/db/pg/schema.ts --out init + +RUN npm run build:pg + +FROM node:20-alpine AS runner + +WORKDIR /app + +# Curl used for the health checks +RUN apk add --no-cache curl + +# COPY package.json package-lock.json ./ +COPY package.json ./ +RUN npm install --only=production && npm cache clean --force + +COPY --from=builder /app/.next/standalone ./ +COPY --from=builder /app/.next/static ./.next/static +COPY --from=builder /app/dist ./dist +COPY --from=builder /app/init ./dist/init + +COPY server/db/names.json ./dist/names.json + +COPY public ./public + +CMD ["npm", "run", "start:pg"] diff --git a/Makefile b/Makefile index 793a3481..fdf5daa1 100644 --- a/Makefile +++ b/Makefile @@ -5,6 +5,8 @@ build-release: fi docker buildx build --platform linux/arm64,linux/amd64 -t fosrl/pangolin:latest -f Dockerfile --push . docker buildx build --platform linux/arm64,linux/amd64 -t fosrl/pangolin:$(tag) -f Dockerfile --push . + docker buildx build --platform linux/arm64,linux/amd64 -t fosrl/pangolin:postgresql-latest -f Dockerfile.pg --push . + docker buildx build --platform linux/arm64,linux/amd64 -t fosrl/pangolin:postgresql-$(tag) -f Dockerfile.pg --push . build-arm: docker buildx build --platform linux/arm64 -t fosrl/pangolin:latest . diff --git a/README.md b/README.md index 15ca7add..8723542c 100644 --- a/README.md +++ b/README.md @@ -1,15 +1,13 @@
-

pangolin

- -[![Documentation](https://img.shields.io/badge/docs-latest-blue.svg?style=flat-square)](https://docs.fossorial.io/) -[![Docker](https://img.shields.io/docker/pulls/fosrl/pangolin?style=flat-square)](https://hub.docker.com/r/fosrl/pangolin) -![Stars](https://img.shields.io/github/stars/fosrl/pangolin?style=flat-square) -[![Discord](https://img.shields.io/discord/1325658630518865980?logo=discord&style=flat-square)](https://discord.gg/HCJR8Xhme4) -[![Youtube](https://img.shields.io/badge/YouTube-red?logo=youtube&logoColor=white&style=flat-square)](https://www.youtube.com/@fossorial-app) - +

+ + + Pangolin Logo + +

-

Tunneled Mesh Reverse Proxy Server with Access Control

+

Tunneled Reverse Proxy Server with Access Control

_Your own self-hosted zero trust tunnel._ @@ -30,6 +28,12 @@ _Your own self-hosted zero trust tunnel._ Contact Us + +[![Docker](https://img.shields.io/docker/pulls/fosrl/pangolin?style=flat-square)](https://hub.docker.com/r/fosrl/pangolin) +![Stars](https://img.shields.io/github/stars/fosrl/pangolin?style=flat-square) +[![Discord](https://img.shields.io/discord/1325658630518865980?logo=discord&style=flat-square)](https://discord.gg/HCJR8Xhme4) +[![Youtube](https://img.shields.io/badge/YouTube-red?logo=youtube&logoColor=white&style=flat-square)](https://www.youtube.com/@fossorial-app) +
Pangolin is a self-hosted tunneled reverse proxy server with identity and access control, designed to securely expose private resources on distributed networks. Acting as a central hub, it connects isolated networks — even those behind restrictive firewalls — through encrypted tunnels, enabling easy access to remote services without opening ports. @@ -83,7 +87,7 @@ _Resources page of Pangolin dashboard (dark mode) showing multiple resources ava ### Modular Design -- Extend functionality with existing [Traefik](https://github.com/traefik/traefik) plugins, such as [CrowdSec](https://plugins.traefik.io/plugins/6335346ca4caa9ddeffda116/crowdsec-bouncer-traefik-plugin) and [Geoblock](github.com/PascalMinder/geoblock). +- Extend functionality with existing [Traefik](https://github.com/traefik/traefik) plugins, such as [CrowdSec](https://plugins.traefik.io/plugins/6335346ca4caa9ddeffda116/crowdsec-bouncer-traefik-plugin) and [Geoblock](https://github.com/PascalMinder/geoblock). - **Automatically install and configure Crowdsec via Pangolin's installer script.** - Attach as many sites to the central server as you wish. @@ -96,19 +100,19 @@ _Resources page of Pangolin dashboard (dark mode) showing multiple resources ava - Deploy the Docker Compose stack onto a VPS hosted on a cloud platform like RackNerd, Amazon EC2, DigitalOcean Droplet, or similar. There are many cheap VPS hosting options available to suit your needs. > [!TIP] -> Many of our users have had a great experience with [RackNerd](https://my.racknerd.com/aff.php?aff=13788). Depending on promotions, you can likely get a **VPS with 1 vCPU, 1GB RAM, and ~20GB SSD for just around $12/year**. That's a great deal! +> Many of our users have had a great experience with [RackNerd](https://my.racknerd.com/aff.php?aff=13788). Depending on promotions, you can get a [**VPS with 1 vCPU, 1GB RAM, and ~20GB SSD for just around $12/year**](https://my.racknerd.com/aff.php?aff=13788&pid=912). That's a great deal! > We are part of the [RackNerd](https://my.racknerd.com/aff.php?aff=13788) affiliate program, so if you purchase through [our link](https://my.racknerd.com/aff.php?aff=13788), we receive a small commission which helps us maintain the project and keep it free for everyone. -2. **Domain Configuration**: +1. **Domain Configuration**: - Point your domain name to the VPS and configure Pangolin with your preferred settings. -3. **Connect Private Sites**: +2. **Connect Private Sites**: - Install Newt or use another WireGuard client on private sites. - Automatically establish a connection from these sites to the central server. -4. **Expose Resources**: +3. **Expose Resources**: - Add resources to the central server and configure access control rules. - Access these resources securely from anywhere. diff --git a/drizzle.pg.config.ts b/drizzle.pg.config.ts new file mode 100644 index 00000000..14aeba5b --- /dev/null +++ b/drizzle.pg.config.ts @@ -0,0 +1,12 @@ +import { defineConfig } from "drizzle-kit"; +import path from "path"; + +export default defineConfig({ + dialect: "postgresql", + schema: path.join("server", "db", "pg", "schema.ts"), + out: path.join("server", "migrations"), + verbose: true, + dbCredentials: { + url: process.env.DATABASE_URL as string + } +}); diff --git a/drizzle.config.ts b/drizzle.sqlite.config.ts similarity index 83% rename from drizzle.config.ts rename to drizzle.sqlite.config.ts index dcfc55c6..94574a89 100644 --- a/drizzle.config.ts +++ b/drizzle.sqlite.config.ts @@ -4,7 +4,7 @@ import path from "path"; export default defineConfig({ dialect: "sqlite", - schema: path.join("server", "db", "schemas"), + schema: path.join("server", "db", "sqlite", "schema.ts"), out: path.join("server", "migrations"), verbose: true, dbCredentials: { diff --git a/eslint.config.js b/eslint.config.js index 71dc862c..dfc194bc 100644 --- a/eslint.config.js +++ b/eslint.config.js @@ -1,9 +1,19 @@ -// eslint.config.js -export default [ - { - rules: { - semi: "error", - "prefer-const": "error" - } +import tseslint from 'typescript-eslint'; + +export default tseslint.config({ + files: ["**/*.{ts,tsx,js,jsx}"], + languageOptions: { + parser: tseslint.parser, + parserOptions: { + ecmaVersion: "latest", + sourceType: "module", + ecmaFeatures: { + jsx: true + } } -]; + }, + rules: { + "semi": "error", + "prefer-const": "warn" + } +}); \ No newline at end of file diff --git a/install/config/config.yml b/install/config/config.yml index 3a4fa1ab..a5b452e5 100644 --- a/install/config/config.yml +++ b/install/config/config.yml @@ -26,7 +26,7 @@ server: cors: origins: ["https://{{.DashboardDomain}}"] methods: ["GET", "POST", "PUT", "DELETE", "PATCH"] - headers: ["X-CSRF-Token", "Content-Type"] + allowed_headers: ["X-CSRF-Token", "Content-Type"] credentials: false traefik: diff --git a/install/config/docker-compose.yml b/install/config/docker-compose.yml index ca2890b5..90349b7a 100644 --- a/install/config/docker-compose.yml +++ b/install/config/docker-compose.yml @@ -35,7 +35,7 @@ services: - 80:80 # Port for traefik because of the network_mode {{end}} traefik: - image: traefik:v3.4.0 + image: traefik:v3.4.1 container_name: traefik restart: unless-stopped {{if .InstallGerbil}} @@ -58,4 +58,4 @@ services: networks: default: driver: bridge - name: pangolin \ No newline at end of file + name: pangolin diff --git a/install/main.go b/install/main.go index a0d74a43..9ee4fd1f 100644 --- a/install/main.go +++ b/install/main.go @@ -9,6 +9,7 @@ import ( "io/fs" "os" "os/exec" + "os/user" "path/filepath" "runtime" "strings" @@ -17,6 +18,7 @@ import ( "time" "unicode" "math/rand" + "strconv" "golang.org/x/term" ) @@ -57,9 +59,18 @@ type Config struct { func main() { reader := bufio.NewReader(os.Stdin) - // check if the user is root - if os.Geteuid() != 0 { - fmt.Println("This script must be run as root") + // check if docker is not installed and the user is root + if !isDockerInstalled() { + if os.Geteuid() != 0 { + fmt.Println("Docker is not installed. Please install Docker manually or run this installer as root.") + os.Exit(1) + } + } + + // check if the user is in the docker group (linux only) + if !isUserInDockerGroup() { + fmt.Println("You are not in the docker group.") + fmt.Println("The installer will not be able to run docker commands without running it as root.") os.Exit(1) } @@ -83,6 +94,27 @@ func main() { if !isDockerInstalled() && runtime.GOOS == "linux" { if readBool(reader, "Docker is not installed. Would you like to install it?", true) { installDocker() + // try to start docker service but ignore errors + if err := startDockerService(); err != nil { + fmt.Println("Error starting Docker service:", err) + } else { + fmt.Println("Docker service started successfully!") + } + // wait 10 seconds for docker to start checking if docker is running every 2 seconds + fmt.Println("Waiting for Docker to start...") + for i := 0; i < 5; i++ { + if isDockerRunning() { + fmt.Println("Docker is running!") + break + } + fmt.Println("Docker is not running yet, waiting...") + time.Sleep(2 * time.Second) + } + if !isDockerRunning() { + fmt.Println("Docker is still not running after 10 seconds. Please check the installation.") + os.Exit(1) + } + fmt.Println("Docker installed successfully!") } } @@ -397,7 +429,7 @@ func installDocker() error { return fmt.Errorf("failed to detect Linux distribution: %v", err) } osRelease := string(output) - + // Detect system architecture archCmd := exec.Command("uname", "-m") archOutput, err := archCmd.Output() @@ -405,7 +437,7 @@ func installDocker() error { return fmt.Errorf("failed to detect system architecture: %v", err) } arch := strings.TrimSpace(string(archOutput)) - + // Map architecture to Docker's architecture naming var dockerArch string switch arch { @@ -438,11 +470,31 @@ func installDocker() error { apt-get install -y docker-ce docker-ce-cli containerd.io docker-compose-plugin `, dockerArch)) case strings.Contains(osRelease, "ID=fedora"): - installCmd = exec.Command("bash", "-c", ` + // Detect Fedora version to handle DNF 5 changes + versionCmd := exec.Command("bash", "-c", "grep VERSION_ID /etc/os-release | cut -d'=' -f2 | tr -d '\"'") + versionOutput, err := versionCmd.Output() + var fedoraVersion int + if err == nil { + if v, parseErr := strconv.Atoi(strings.TrimSpace(string(versionOutput))); parseErr == nil { + fedoraVersion = v + } + } + + // Use appropriate DNF syntax based on version + var repoCmd string + if fedoraVersion >= 41 { + // DNF 5 syntax for Fedora 41+ + repoCmd = "dnf config-manager addrepo --from-repofile=https://download.docker.com/linux/fedora/docker-ce.repo" + } else { + // DNF 4 syntax for Fedora < 41 + repoCmd = "dnf config-manager --add-repo https://download.docker.com/linux/fedora/docker-ce.repo" + } + + installCmd = exec.Command("bash", "-c", fmt.Sprintf(` dnf -y install dnf-plugins-core && - dnf config-manager --add-repo https://download.docker.com/linux/fedora/docker-ce.repo && + %s && dnf install -y docker-ce docker-ce-cli containerd.io docker-compose-plugin - `) + `, repoCmd)) case strings.Contains(osRelease, "ID=opensuse") || strings.Contains(osRelease, "ID=\"opensuse-"): installCmd = exec.Command("bash", "-c", ` zypper install -y docker docker-compose && @@ -466,11 +518,26 @@ func installDocker() error { default: return fmt.Errorf("unsupported Linux distribution") } + installCmd.Stdout = os.Stdout installCmd.Stderr = os.Stderr return installCmd.Run() } +func startDockerService() error { + if runtime.GOOS == "linux" { + cmd := exec.Command("systemctl", "enable", "--now", "docker") + cmd.Stdout = os.Stdout + cmd.Stderr = os.Stderr + return cmd.Run() + } else if runtime.GOOS == "darwin" { + // On macOS, Docker is usually started via the Docker Desktop application + fmt.Println("Please start Docker Desktop manually on macOS.") + return nil + } + return fmt.Errorf("unsupported operating system for starting Docker service") +} + func isDockerInstalled() bool { cmd := exec.Command("docker", "--version") if err := cmd.Run(); err != nil { @@ -479,6 +546,43 @@ func isDockerInstalled() bool { return true } +func isUserInDockerGroup() bool { + if runtime.GOOS == "darwin" { + // Docker group is not applicable on macOS + // So we assume that the user can run Docker commands + return true + } + + if os.Geteuid() == 0 { + return true // Root user can run Docker commands anyway + } + + // Check if the current user is in the docker group + if dockerGroup, err := user.LookupGroup("docker"); err == nil { + if currentUser, err := user.Current(); err == nil { + if currentUserGroupIds, err := currentUser.GroupIds(); err == nil { + for _, groupId := range currentUserGroupIds { + if groupId == dockerGroup.Gid { + return true + } + } + } + } + } + + // Eventually, if any of the checks fail, we assume the user cannot run Docker commands + return false +} + +// isDockerRunning checks if the Docker daemon is running by using the `docker info` command. +func isDockerRunning() bool { + cmd := exec.Command("docker", "info") + if err := cmd.Run(); err != nil { + return false + } + return true +} + // executeDockerComposeCommandWithArgs executes the appropriate docker command with arguments supplied func executeDockerComposeCommandWithArgs(args ...string) error { var cmd *exec.Cmd @@ -619,4 +723,4 @@ func generateRandomSecretKey() string { b[i] = charset[seededRand.Intn(len(charset))] } return string(b) -} \ No newline at end of file +} diff --git a/newt b/newt deleted file mode 100755 index 3805c736..00000000 Binary files a/newt and /dev/null differ diff --git a/next.config.mjs b/next.config.mjs index fce5b1fa..5b5eafc1 100644 --- a/next.config.mjs +++ b/next.config.mjs @@ -1,7 +1,7 @@ /** @type {import('next').NextConfig} */ const nextConfig = { eslint: { - ignoreDuringBuilds: true, + ignoreDuringBuilds: true }, output: "standalone" }; diff --git a/package-lock.json b/package-lock.json index 0bf2541a..0a8b2d0b 100644 --- a/package-lock.json +++ b/package-lock.json @@ -9,17 +9,18 @@ "version": "0.0.0", "license": "SEE LICENSE IN LICENSE AND README.md", "dependencies": { - "@asteasolutions/zod-to-openapi": "^7.3.0", + "@asteasolutions/zod-to-openapi": "^7.3.2", "@hookform/resolvers": "3.9.1", - "@node-rs/argon2": "2.0.2", + "@node-rs/argon2": "^2.0.2", "@oslojs/crypto": "1.0.1", "@oslojs/encoding": "1.1.0", - "@radix-ui/react-avatar": "1.1.2", - "@radix-ui/react-checkbox": "1.1.3", - "@radix-ui/react-collapsible": "1.1.2", - "@radix-ui/react-dialog": "1.1.4", - "@radix-ui/react-dropdown-menu": "2.1.4", + "@radix-ui/react-avatar": "1.1.10", + "@radix-ui/react-checkbox": "1.3.2", + "@radix-ui/react-collapsible": "1.1.11", + "@radix-ui/react-dialog": "1.1.14", + "@radix-ui/react-dropdown-menu": "2.1.15", "@radix-ui/react-icons": "1.3.2", +<<<<<<< HEAD "@radix-ui/react-label": "2.1.1", "@radix-ui/react-popover": "1.1.4", "@radix-ui/react-progress": "^1.1.4", @@ -34,68 +35,85 @@ "@react-email/components": "0.0.36", "@react-email/render": "^1.0.6", "@react-email/tailwind": "1.0.4", +======= + "@radix-ui/react-label": "2.1.7", + "@radix-ui/react-popover": "1.1.14", + "@radix-ui/react-progress": "^1.1.7", + "@radix-ui/react-radio-group": "1.3.7", + "@radix-ui/react-scroll-area": "^1.2.9", + "@radix-ui/react-select": "2.2.5", + "@radix-ui/react-separator": "1.1.7", + "@radix-ui/react-slot": "1.2.3", + "@radix-ui/react-switch": "1.2.5", + "@radix-ui/react-tabs": "1.1.12", + "@radix-ui/react-toast": "1.2.14", + "@react-email/components": "0.0.41", + "@react-email/render": "^1.1.2", + "@react-email/tailwind": "1.0.5", +>>>>>>> dev "@tailwindcss/forms": "^0.5.10", - "@tanstack/react-table": "8.20.6", - "arctic": "^3.6.0", - "axios": "1.8.4", + "@tanstack/react-table": "8.21.3", + "arctic": "^3.7.0", + "axios": "1.9.0", "better-sqlite3": "11.7.0", "canvas-confetti": "1.9.3", "class-variance-authority": "0.7.1", "clsx": "2.1.1", - "cmdk": "1.0.4", + "cmdk": "1.1.1", "cookie": "^1.0.2", "cookie-parser": "1.4.7", "cookies": "^0.9.1", "cors": "2.8.5", "crypto-js": "^4.2.0", "drizzle-orm": "0.38.3", - "eslint": "9.17.0", - "eslint-config-next": "15.1.3", + "eslint": "9.28.0", + "eslint-config-next": "15.3.3", "express": "4.21.2", "express-rate-limit": "7.5.0", - "glob": "11.0.0", - "helmet": "8.0.0", + "glob": "11.0.2", + "helmet": "8.1.0", "http-errors": "2.0.0", "i": "^0.3.7", - "input-otp": "1.4.1", + "input-otp": "1.4.2", "jmespath": "^0.16.0", "js-yaml": "4.1.0", "jsonwebtoken": "^9.0.2", - "lucide-react": "0.469.0", + "lucide-react": "0.511.0", "moment": "2.30.1", - "next": "15.2.4", - "next-themes": "0.4.4", + "next": "15.3.3", + "next-themes": "0.4.6", "node-cache": "5.1.2", "node-fetch": "3.3.2", "nodemailer": "6.9.16", - "npm": "^11.2.0", + "npm": "^11.4.1", "oslo": "1.2.1", + "pg": "^8.16.0", "qrcode.react": "4.2.0", - "react": "19.0.0", - "react-dom": "19.0.0", + "react": "19.1.0", + "react-dom": "19.1.0", "react-easy-sort": "^1.6.0", - "react-hook-form": "7.54.2", + "react-hook-form": "7.56.4", "react-icons": "^5.5.0", "rebuild": "0.1.2", - "semver": "7.6.3", + "semver": "7.7.2", "swagger-ui-express": "^5.0.1", "tailwind-merge": "2.6.0", - "tw-animate-css": "^1.2.5", + "tw-animate-css": "^1.3.3", "uuid": "^11.1.0", "vaul": "1.1.2", "winston": "3.17.0", "winston-daily-rotate-file": "5.0.0", - "ws": "8.18.0", - "zod": "3.24.1", - "zod-validation-error": "3.4.0" + "ws": "8.18.2", + "zod": "3.25.56", + "zod-validation-error": "3.4.1" }, "devDependencies": { - "@dotenvx/dotenvx": "1.32.0", + "@dotenvx/dotenvx": "1.44.1", "@esbuild-plugins/tsconfig-paths": "0.1.2", - "@tailwindcss/postcss": "^4.1.3", + "@tailwindcss/postcss": "^4.1.8", "@types/better-sqlite3": "7.6.12", - "@types/cookie-parser": "1.4.8", - "@types/cors": "2.8.17", + "@types/cookie-parser": "1.4.9", + "@types/cors": "2.8.19", "@types/crypto-js": "^4.2.2", "@types/express": "5.0.0", "@types/jmespath": "^0.15.2", @@ -103,22 +121,23 @@ "@types/jsonwebtoken": "^9.0.9", "@types/node": "^22", "@types/nodemailer": "6.4.17", - "@types/react": "19.1.1", - "@types/react-dom": "19.1.2", - "@types/semver": "7.5.8", + "@types/react": "19.1.7", + "@types/react-dom": "19.1.6", + "@types/semver": "7.7.0", "@types/swagger-ui-express": "^4.1.8", - "@types/ws": "8.5.13", + "@types/ws": "8.18.1", "@types/yargs": "17.0.33", - "drizzle-kit": "0.30.6", - "esbuild": "0.25.2", + "drizzle-kit": "0.31.1", + "esbuild": "0.25.5", "esbuild-node-externals": "1.18.0", "postcss": "^8", - "react-email": "4.0.6", + "react-email": "4.0.16", "tailwindcss": "^4.1.4", - "tsc-alias": "1.8.10", - "tsx": "4.19.3", + "tsc-alias": "1.8.16", + "tsx": "4.19.4", "typescript": "^5", - "yargs": "17.7.2" + "typescript-eslint": "^8.34.0", + "yargs": "18.0.0" } }, "node_modules/@alloc/quick-lru": { @@ -149,9 +168,9 @@ } }, "node_modules/@asteasolutions/zod-to-openapi": { - "version": "7.3.0", - "resolved": "https://registry.npmjs.org/@asteasolutions/zod-to-openapi/-/zod-to-openapi-7.3.0.tgz", - "integrity": "sha512-7tE/r1gXwMIvGnXVUdIqUhCU1RevEFC4Jk6Bussa0fk1ecbnnINkZzj1EOAJyE/M3AI25DnHT/zKQL1/FPFi8Q==", + "version": "7.3.3", + "resolved": "https://registry.npmjs.org/@asteasolutions/zod-to-openapi/-/zod-to-openapi-7.3.3.tgz", + "integrity": "sha512-ioiw+R+gBGAUwmDp+/gJA16tedBivzDaji5wOvWej0ZYDE0CXTSSfJfXbrBIuWKh6JQhuXgNDniJdeDueKUZTA==", "license": "MIT", "dependencies": { "openapi3-ts": "^4.1.2" @@ -176,6 +195,7 @@ } }, "node_modules/@babel/generator": { +<<<<<<< HEAD "version": "7.27.1", "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.27.1.tgz", "integrity": "sha512-UnJfnIpc/+JO0/+KRVQNGU+y5taA5vCbwN8+azkX6beii/ZF+enZJSOKo11ZSzGJjlNfJHfQtmQT8H+9TXPG2w==", @@ -184,6 +204,16 @@ "dependencies": { "@babel/parser": "^7.27.1", "@babel/types": "^7.27.1", +======= + "version": "7.27.5", + "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.27.5.tgz", + "integrity": "sha512-ZGhA37l0e/g2s1Cnzdix0O3aLYm66eF8aufiVteOgnwxgnRP8GoyMj7VWsgWnQbVKXyge7hqrFh2K2TQM6t1Hw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/parser": "^7.27.5", + "@babel/types": "^7.27.3", +>>>>>>> dev "@jridgewell/gen-mapping": "^0.3.5", "@jridgewell/trace-mapping": "^0.3.25", "jsesc": "^3.0.2" @@ -192,6 +222,7 @@ "node": ">=6.9.0" } }, +<<<<<<< HEAD "node_modules/@babel/generator/node_modules/@babel/parser": { "version": "7.27.2", "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.27.2.tgz", @@ -208,6 +239,8 @@ "node": ">=6.0.0" } }, +======= +>>>>>>> dev "node_modules/@babel/helper-string-parser": { "version": "7.27.1", "resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.27.1.tgz", @@ -229,11 +262,14 @@ } }, "node_modules/@babel/parser": { - "version": "7.24.5", - "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.24.5.tgz", - "integrity": "sha512-EOv5IK8arwh3LI47dz1b0tKUb/1uhHAnHJOrjgtQMIpu1uXd9mlFrJg9IUgGUgZ41Ch0K8REPTYpO7B76b4vJg==", + "version": "7.27.5", + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.27.5.tgz", + "integrity": "sha512-OsQd175SxWkGlzbny8J3K8TnnDD0N3lrIUtB92xwyRpzaenGZhxDvxN/JgU00U3CDZNj9tPuDJ5H0WS4Nt3vKg==", "dev": true, "license": "MIT", + "dependencies": { + "@babel/types": "^7.27.3" + }, "bin": { "parser": "bin/babel-parser.js" }, @@ -256,6 +292,7 @@ "node": ">=6.9.0" } }, +<<<<<<< HEAD "node_modules/@babel/template/node_modules/@babel/parser": { "version": "7.27.2", "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.27.2.tgz", @@ -272,18 +309,20 @@ "node": ">=6.0.0" } }, +======= +>>>>>>> dev "node_modules/@babel/traverse": { - "version": "7.25.6", - "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.25.6.tgz", - "integrity": "sha512-9Vrcx5ZW6UwK5tvqsj0nGpp/XzqthkT0dqIc9g1AdtygFToNtTF67XzYS//dm+SAK9cp3B9R4ZO/46p63SCjlQ==", + "version": "7.27.4", + "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.27.4.tgz", + "integrity": "sha512-oNcu2QbHqts9BtOWJosOVJapWjBDSxGCpFvikNR5TGDYDQf3JwpIoMzIKrvfoti93cLfPJEG4tH9SPVeyCGgdA==", "dev": true, "license": "MIT", "dependencies": { - "@babel/code-frame": "^7.24.7", - "@babel/generator": "^7.25.6", - "@babel/parser": "^7.25.6", - "@babel/template": "^7.25.0", - "@babel/types": "^7.25.6", + "@babel/code-frame": "^7.27.1", + "@babel/generator": "^7.27.3", + "@babel/parser": "^7.27.4", + "@babel/template": "^7.27.2", + "@babel/types": "^7.27.3", "debug": "^4.3.1", "globals": "^11.1.0" }, @@ -291,6 +330,7 @@ "node": ">=6.9.0" } }, +<<<<<<< HEAD "node_modules/@babel/traverse/node_modules/@babel/parser": { "version": "7.27.2", "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.27.2.tgz", @@ -307,6 +347,8 @@ "node": ">=6.0.0" } }, +======= +>>>>>>> dev "node_modules/@babel/traverse/node_modules/globals": { "version": "11.12.0", "resolved": "https://registry.npmjs.org/globals/-/globals-11.12.0.tgz", @@ -318,9 +360,15 @@ } }, "node_modules/@babel/types": { +<<<<<<< HEAD "version": "7.27.1", "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.27.1.tgz", "integrity": "sha512-+EzkxvLNfiUeKMgy/3luqfsCWFRXLb7U6wNQTk60tovuckwB15B191tJWvpp4HjiQWdJkCxO3Wbvc6jlk3Xb2Q==", +======= + "version": "7.27.6", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.27.6.tgz", + "integrity": "sha512-ETyHEk2VHHvl9b9jZP5IHPavHYk57EhanlRRuae9XCpb/j5bDCbPPMOBfCWhnl/7EDJz0jEMCi/RhccCE8r1+Q==", +>>>>>>> dev "dev": true, "license": "MIT", "dependencies": { @@ -352,9 +400,9 @@ } }, "node_modules/@dotenvx/dotenvx": { - "version": "1.32.0", - "resolved": "https://registry.npmjs.org/@dotenvx/dotenvx/-/dotenvx-1.32.0.tgz", - "integrity": "sha512-oQaGYijYfQx6pY9D+FQ08gUOckF1R0RSVK7Jqk+Ma2RyeceoMIawQl1KoogRaJ12i0SmyVWhiGyQxDU01/k13g==", + "version": "1.44.1", + "resolved": "https://registry.npmjs.org/@dotenvx/dotenvx/-/dotenvx-1.44.1.tgz", + "integrity": "sha512-j1QImCqf/XJmhIjC1OPpgiZV9g370HG9MNT9s/CDwCKsoYzNCPEKK+GfsidahJx7yIlBbm+4dPLlGec+bKn7oA==", "dev": true, "license": "BSD-3-Clause", "dependencies": { @@ -882,9 +930,9 @@ } }, "node_modules/@esbuild/aix-ppc64": { - "version": "0.25.2", - "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.25.2.tgz", - "integrity": "sha512-wCIboOL2yXZym2cgm6mlA742s9QeJ8DjGVaL39dLN4rRwrOgOyYSnOaFPhKZGLb2ngj4EyfAFjsNJwPXZvseag==", + "version": "0.25.5", + "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.25.5.tgz", + "integrity": "sha512-9o3TMmpmftaCMepOdA5k/yDw8SfInyzWWTjYTFCX3kPSDJMROQTb8jg+h9Cnwnmm1vOzvxN7gIfB5V2ewpjtGA==", "cpu": [ "ppc64" ], @@ -899,9 +947,9 @@ } }, "node_modules/@esbuild/android-arm": { - "version": "0.25.2", - "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.25.2.tgz", - "integrity": "sha512-NQhH7jFstVY5x8CKbcfa166GoV0EFkaPkCKBQkdPJFvo5u+nGXLEH/ooniLb3QI8Fk58YAx7nsPLozUWfCBOJA==", + "version": "0.25.5", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.25.5.tgz", + "integrity": "sha512-AdJKSPeEHgi7/ZhuIPtcQKr5RQdo6OO2IL87JkianiMYMPbCtot9fxPbrMiBADOWWm3T2si9stAiVsGbTQFkbA==", "cpu": [ "arm" ], @@ -916,9 +964,9 @@ } }, "node_modules/@esbuild/android-arm64": { - "version": "0.25.2", - "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.25.2.tgz", - "integrity": "sha512-5ZAX5xOmTligeBaeNEPnPaeEuah53Id2tX4c2CVP3JaROTH+j4fnfHCkr1PjXMd78hMst+TlkfKcW/DlTq0i4w==", + "version": "0.25.5", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.25.5.tgz", + "integrity": "sha512-VGzGhj4lJO+TVGV1v8ntCZWJktV7SGCs3Pn1GRWI1SBFtRALoomm8k5E9Pmwg3HOAal2VDc2F9+PM/rEY6oIDg==", "cpu": [ "arm64" ], @@ -933,9 +981,9 @@ } }, "node_modules/@esbuild/android-x64": { - "version": "0.25.2", - "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.25.2.tgz", - "integrity": "sha512-Ffcx+nnma8Sge4jzddPHCZVRvIfQ0kMsUsCMcJRHkGJ1cDmhe4SsrYIjLUKn1xpHZybmOqCWwB0zQvsjdEHtkg==", + "version": "0.25.5", + "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.25.5.tgz", + "integrity": "sha512-D2GyJT1kjvO//drbRT3Hib9XPwQeWd9vZoBJn+bu/lVsOZ13cqNdDeqIF/xQ5/VmWvMduP6AmXvylO/PIc2isw==", "cpu": [ "x64" ], @@ -950,9 +998,9 @@ } }, "node_modules/@esbuild/darwin-arm64": { - "version": "0.25.2", - "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.25.2.tgz", - "integrity": "sha512-MpM6LUVTXAzOvN4KbjzU/q5smzryuoNjlriAIx+06RpecwCkL9JpenNzpKd2YMzLJFOdPqBpuub6eVRP5IgiSA==", + "version": "0.25.5", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.25.5.tgz", + "integrity": "sha512-GtaBgammVvdF7aPIgH2jxMDdivezgFu6iKpmT+48+F8Hhg5J/sfnDieg0aeG/jfSvkYQU2/pceFPDKlqZzwnfQ==", "cpu": [ "arm64" ], @@ -967,9 +1015,9 @@ } }, "node_modules/@esbuild/darwin-x64": { - "version": "0.25.2", - "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.25.2.tgz", - "integrity": "sha512-5eRPrTX7wFyuWe8FqEFPG2cU0+butQQVNcT4sVipqjLYQjjh8a8+vUTfgBKM88ObB85ahsnTwF7PSIt6PG+QkA==", + "version": "0.25.5", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.25.5.tgz", + "integrity": "sha512-1iT4FVL0dJ76/q1wd7XDsXrSW+oLoquptvh4CLR4kITDtqi2e/xwXwdCVH8hVHU43wgJdsq7Gxuzcs6Iq/7bxQ==", "cpu": [ "x64" ], @@ -984,9 +1032,9 @@ } }, "node_modules/@esbuild/freebsd-arm64": { - "version": "0.25.2", - "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.25.2.tgz", - "integrity": "sha512-mLwm4vXKiQ2UTSX4+ImyiPdiHjiZhIaE9QvC7sw0tZ6HoNMjYAqQpGyui5VRIi5sGd+uWq940gdCbY3VLvsO1w==", + "version": "0.25.5", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.25.5.tgz", + "integrity": "sha512-nk4tGP3JThz4La38Uy/gzyXtpkPW8zSAmoUhK9xKKXdBCzKODMc2adkB2+8om9BDYugz+uGV7sLmpTYzvmz6Sw==", "cpu": [ "arm64" ], @@ -1001,9 +1049,9 @@ } }, "node_modules/@esbuild/freebsd-x64": { - "version": "0.25.2", - "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.25.2.tgz", - "integrity": "sha512-6qyyn6TjayJSwGpm8J9QYYGQcRgc90nmfdUb0O7pp1s4lTY+9D0H9O02v5JqGApUyiHOtkz6+1hZNvNtEhbwRQ==", + "version": "0.25.5", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.25.5.tgz", + "integrity": "sha512-PrikaNjiXdR2laW6OIjlbeuCPrPaAl0IwPIaRv+SMV8CiM8i2LqVUHFC1+8eORgWyY7yhQY+2U2fA55mBzReaw==", "cpu": [ "x64" ], @@ -1018,9 +1066,9 @@ } }, "node_modules/@esbuild/linux-arm": { - "version": "0.25.2", - "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.25.2.tgz", - "integrity": "sha512-UHBRgJcmjJv5oeQF8EpTRZs/1knq6loLxTsjc3nxO9eXAPDLcWW55flrMVc97qFPbmZP31ta1AZVUKQzKTzb0g==", + "version": "0.25.5", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.25.5.tgz", + "integrity": "sha512-cPzojwW2okgh7ZlRpcBEtsX7WBuqbLrNXqLU89GxWbNt6uIg78ET82qifUy3W6OVww6ZWobWub5oqZOVtwolfw==", "cpu": [ "arm" ], @@ -1035,9 +1083,9 @@ } }, "node_modules/@esbuild/linux-arm64": { - "version": "0.25.2", - "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.25.2.tgz", - "integrity": "sha512-gq/sjLsOyMT19I8obBISvhoYiZIAaGF8JpeXu1u8yPv8BE5HlWYobmlsfijFIZ9hIVGYkbdFhEqC0NvM4kNO0g==", + "version": "0.25.5", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.25.5.tgz", + "integrity": "sha512-Z9kfb1v6ZlGbWj8EJk9T6czVEjjq2ntSYLY2cw6pAZl4oKtfgQuS4HOq41M/BcoLPzrUbNd+R4BXFyH//nHxVg==", "cpu": [ "arm64" ], @@ -1052,9 +1100,9 @@ } }, "node_modules/@esbuild/linux-ia32": { - "version": "0.25.2", - "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.25.2.tgz", - "integrity": "sha512-bBYCv9obgW2cBP+2ZWfjYTU+f5cxRoGGQ5SeDbYdFCAZpYWrfjjfYwvUpP8MlKbP0nwZ5gyOU/0aUzZ5HWPuvQ==", + "version": "0.25.5", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.25.5.tgz", + "integrity": "sha512-sQ7l00M8bSv36GLV95BVAdhJ2QsIbCuCjh/uYrWiMQSUuV+LpXwIqhgJDcvMTj+VsQmqAHL2yYaasENvJ7CDKA==", "cpu": [ "ia32" ], @@ -1069,9 +1117,9 @@ } }, "node_modules/@esbuild/linux-loong64": { - "version": "0.25.2", - "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.25.2.tgz", - "integrity": "sha512-SHNGiKtvnU2dBlM5D8CXRFdd+6etgZ9dXfaPCeJtz+37PIUlixvlIhI23L5khKXs3DIzAn9V8v+qb1TRKrgT5w==", + "version": "0.25.5", + "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.25.5.tgz", + "integrity": "sha512-0ur7ae16hDUC4OL5iEnDb0tZHDxYmuQyhKhsPBV8f99f6Z9KQM02g33f93rNH5A30agMS46u2HP6qTdEt6Q1kg==", "cpu": [ "loong64" ], @@ -1086,9 +1134,9 @@ } }, "node_modules/@esbuild/linux-mips64el": { - "version": "0.25.2", - "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.25.2.tgz", - "integrity": "sha512-hDDRlzE6rPeoj+5fsADqdUZl1OzqDYow4TB4Y/3PlKBD0ph1e6uPHzIQcv2Z65u2K0kpeByIyAjCmjn1hJgG0Q==", + "version": "0.25.5", + "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.25.5.tgz", + "integrity": "sha512-kB/66P1OsHO5zLz0i6X0RxlQ+3cu0mkxS3TKFvkb5lin6uwZ/ttOkP3Z8lfR9mJOBk14ZwZ9182SIIWFGNmqmg==", "cpu": [ "mips64el" ], @@ -1103,9 +1151,9 @@ } }, "node_modules/@esbuild/linux-ppc64": { - "version": "0.25.2", - "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.25.2.tgz", - "integrity": "sha512-tsHu2RRSWzipmUi9UBDEzc0nLc4HtpZEI5Ba+Omms5456x5WaNuiG3u7xh5AO6sipnJ9r4cRWQB2tUjPyIkc6g==", + "version": "0.25.5", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.25.5.tgz", + "integrity": "sha512-UZCmJ7r9X2fe2D6jBmkLBMQetXPXIsZjQJCjgwpVDz+YMcS6oFR27alkgGv3Oqkv07bxdvw7fyB71/olceJhkQ==", "cpu": [ "ppc64" ], @@ -1120,9 +1168,9 @@ } }, "node_modules/@esbuild/linux-riscv64": { - "version": "0.25.2", - "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.25.2.tgz", - "integrity": "sha512-k4LtpgV7NJQOml/10uPU0s4SAXGnowi5qBSjaLWMojNCUICNu7TshqHLAEbkBdAszL5TabfvQ48kK84hyFzjnw==", + "version": "0.25.5", + "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.25.5.tgz", + "integrity": "sha512-kTxwu4mLyeOlsVIFPfQo+fQJAV9mh24xL+y+Bm6ej067sYANjyEw1dNHmvoqxJUCMnkBdKpvOn0Ahql6+4VyeA==", "cpu": [ "riscv64" ], @@ -1137,9 +1185,9 @@ } }, "node_modules/@esbuild/linux-s390x": { - "version": "0.25.2", - "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.25.2.tgz", - "integrity": "sha512-GRa4IshOdvKY7M/rDpRR3gkiTNp34M0eLTaC1a08gNrh4u488aPhuZOCpkF6+2wl3zAN7L7XIpOFBhnaE3/Q8Q==", + "version": "0.25.5", + "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.25.5.tgz", + "integrity": "sha512-K2dSKTKfmdh78uJ3NcWFiqyRrimfdinS5ErLSn3vluHNeHVnBAFWC8a4X5N+7FgVE1EjXS1QDZbpqZBjfrqMTQ==", "cpu": [ "s390x" ], @@ -1154,9 +1202,9 @@ } }, "node_modules/@esbuild/linux-x64": { - "version": "0.25.2", - "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.25.2.tgz", - "integrity": "sha512-QInHERlqpTTZ4FRB0fROQWXcYRD64lAoiegezDunLpalZMjcUcld3YzZmVJ2H/Cp0wJRZ8Xtjtj0cEHhYc/uUg==", + "version": "0.25.5", + "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.25.5.tgz", + "integrity": "sha512-uhj8N2obKTE6pSZ+aMUbqq+1nXxNjZIIjCjGLfsWvVpy7gKCOL6rsY1MhRh9zLtUtAI7vpgLMK6DxjO8Qm9lJw==", "cpu": [ "x64" ], @@ -1171,9 +1219,9 @@ } }, "node_modules/@esbuild/netbsd-arm64": { - "version": "0.25.2", - "resolved": "https://registry.npmjs.org/@esbuild/netbsd-arm64/-/netbsd-arm64-0.25.2.tgz", - "integrity": "sha512-talAIBoY5M8vHc6EeI2WW9d/CkiO9MQJ0IOWX8hrLhxGbro/vBXJvaQXefW2cP0z0nQVTdQ/eNyGFV1GSKrxfw==", + "version": "0.25.5", + "resolved": "https://registry.npmjs.org/@esbuild/netbsd-arm64/-/netbsd-arm64-0.25.5.tgz", + "integrity": "sha512-pwHtMP9viAy1oHPvgxtOv+OkduK5ugofNTVDilIzBLpoWAM16r7b/mxBvfpuQDpRQFMfuVr5aLcn4yveGvBZvw==", "cpu": [ "arm64" ], @@ -1188,9 +1236,9 @@ } }, "node_modules/@esbuild/netbsd-x64": { - "version": "0.25.2", - "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.25.2.tgz", - "integrity": "sha512-voZT9Z+tpOxrvfKFyfDYPc4DO4rk06qamv1a/fkuzHpiVBMOhpjK+vBmWM8J1eiB3OLSMFYNaOaBNLXGChf5tg==", + "version": "0.25.5", + "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.25.5.tgz", + "integrity": "sha512-WOb5fKrvVTRMfWFNCroYWWklbnXH0Q5rZppjq0vQIdlsQKuw6mdSihwSo4RV/YdQ5UCKKvBy7/0ZZYLBZKIbwQ==", "cpu": [ "x64" ], @@ -1205,9 +1253,9 @@ } }, "node_modules/@esbuild/openbsd-arm64": { - "version": "0.25.2", - "resolved": "https://registry.npmjs.org/@esbuild/openbsd-arm64/-/openbsd-arm64-0.25.2.tgz", - "integrity": "sha512-dcXYOC6NXOqcykeDlwId9kB6OkPUxOEqU+rkrYVqJbK2hagWOMrsTGsMr8+rW02M+d5Op5NNlgMmjzecaRf7Tg==", + "version": "0.25.5", + "resolved": "https://registry.npmjs.org/@esbuild/openbsd-arm64/-/openbsd-arm64-0.25.5.tgz", + "integrity": "sha512-7A208+uQKgTxHd0G0uqZO8UjK2R0DDb4fDmERtARjSHWxqMTye4Erz4zZafx7Di9Cv+lNHYuncAkiGFySoD+Mw==", "cpu": [ "arm64" ], @@ -1222,9 +1270,9 @@ } }, "node_modules/@esbuild/openbsd-x64": { - "version": "0.25.2", - "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.25.2.tgz", - "integrity": "sha512-t/TkWwahkH0Tsgoq1Ju7QfgGhArkGLkF1uYz8nQS/PPFlXbP5YgRpqQR3ARRiC2iXoLTWFxc6DJMSK10dVXluw==", + "version": "0.25.5", + "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.25.5.tgz", + "integrity": "sha512-G4hE405ErTWraiZ8UiSoesH8DaCsMm0Cay4fsFWOOUcz8b8rC6uCvnagr+gnioEjWn0wC+o1/TAHt+It+MpIMg==", "cpu": [ "x64" ], @@ -1239,9 +1287,9 @@ } }, "node_modules/@esbuild/sunos-x64": { - "version": "0.25.2", - "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.25.2.tgz", - "integrity": "sha512-cfZH1co2+imVdWCjd+D1gf9NjkchVhhdpgb1q5y6Hcv9TP6Zi9ZG/beI3ig8TvwT9lH9dlxLq5MQBBgwuj4xvA==", + "version": "0.25.5", + "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.25.5.tgz", + "integrity": "sha512-l+azKShMy7FxzY0Rj4RCt5VD/q8mG/e+mDivgspo+yL8zW7qEwctQ6YqKX34DTEleFAvCIUviCFX1SDZRSyMQA==", "cpu": [ "x64" ], @@ -1256,9 +1304,9 @@ } }, "node_modules/@esbuild/win32-arm64": { - "version": "0.25.2", - "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.25.2.tgz", - "integrity": "sha512-7Loyjh+D/Nx/sOTzV8vfbB3GJuHdOQyrOryFdZvPHLf42Tk9ivBU5Aedi7iyX+x6rbn2Mh68T4qq1SDqJBQO5Q==", + "version": "0.25.5", + "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.25.5.tgz", + "integrity": "sha512-O2S7SNZzdcFG7eFKgvwUEZ2VG9D/sn/eIiz8XRZ1Q/DO5a3s76Xv0mdBzVM5j5R639lXQmPmSo0iRpHqUUrsxw==", "cpu": [ "arm64" ], @@ -1273,9 +1321,9 @@ } }, "node_modules/@esbuild/win32-ia32": { - "version": "0.25.2", - "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.25.2.tgz", - "integrity": "sha512-WRJgsz9un0nqZJ4MfhabxaD9Ft8KioqU3JMinOTvobbX6MOSUigSBlogP8QB3uxpJDsFS6yN+3FDBdqE5lg9kg==", + "version": "0.25.5", + "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.25.5.tgz", + "integrity": "sha512-onOJ02pqs9h1iMJ1PQphR+VZv8qBMQ77Klcsqv9CNW2w6yLqoURLcgERAIurY6QE63bbLuqgP9ATqajFLK5AMQ==", "cpu": [ "ia32" ], @@ -1290,9 +1338,9 @@ } }, "node_modules/@esbuild/win32-x64": { - "version": "0.25.2", - "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.25.2.tgz", - "integrity": "sha512-kM3HKb16VIXZyIeVrM1ygYmZBKybX8N4p754bw390wGO3Tf2j4L2/WYL+4suWujpgf6GBYs3jv7TyUivdd05JA==", + "version": "0.25.5", + "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.25.5.tgz", + "integrity": "sha512-TXv6YnJ8ZMVdX+SXWVBo/0p8LTcrUYngpWjvm91TMjjBQii7Oz11Lw5lbDV5Y0TzuhSJHwiH4hEtC1I42mMS0g==", "cpu": [ "x64" ], @@ -1346,9 +1394,15 @@ } }, "node_modules/@eslint/config-array": { +<<<<<<< HEAD "version": "0.19.2", "resolved": "https://registry.npmjs.org/@eslint/config-array/-/config-array-0.19.2.tgz", "integrity": "sha512-GNKqxfHG2ySmJOBSHg7LxeUx4xpuCoFjacmlCoYWEbaPXLwvfIjixRI12xCQZeULksQb23uiA8F40w5TojpV7w==", +======= + "version": "0.20.0", + "resolved": "https://registry.npmjs.org/@eslint/config-array/-/config-array-0.20.0.tgz", + "integrity": "sha512-fxlS1kkIjx8+vy2SjuCB94q3htSNrufYTXubwiBFeaQHbH6Ipi43gFJq2zCMt6PHhImH3Xmr0NksKDvchWlpQQ==", +>>>>>>> dev "license": "Apache-2.0", "dependencies": { "@eslint/object-schema": "^2.1.6", @@ -1359,10 +1413,19 @@ "node": "^18.18.0 || ^20.9.0 || >=21.1.0" } }, + "node_modules/@eslint/config-helpers": { + "version": "0.2.2", + "resolved": "https://registry.npmjs.org/@eslint/config-helpers/-/config-helpers-0.2.2.tgz", + "integrity": "sha512-+GPzk8PlG0sPpzdU5ZvIRMPidzAnZDl/s9L+y13iodqvb8leL53bTannOrQ/Im7UkpsmFU5Ily5U60LWixnmLg==", + "license": "Apache-2.0", + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + } + }, "node_modules/@eslint/core": { - "version": "0.9.1", - "resolved": "https://registry.npmjs.org/@eslint/core/-/core-0.9.1.tgz", - "integrity": "sha512-GuUdqkyyzQI5RMIWkHhvTWLCyLo1jNK3vzkSyaExH5kHPDHcuL2VOpHjmMY+y3+NC69qAKToBqldTBgYeLSr9Q==", + "version": "0.14.0", + "resolved": "https://registry.npmjs.org/@eslint/core/-/core-0.14.0.tgz", + "integrity": "sha512-qIbV0/JZr7iSDjqAc60IqbLdsj9GDt16xQtWD+B78d/HAlvysGdZZ6rpJHGAc2T0FQx1X6thsSPdnoiGKdNtdg==", "license": "Apache-2.0", "dependencies": { "@types/json-schema": "^7.0.15" @@ -1395,12 +1458,15 @@ } }, "node_modules/@eslint/js": { - "version": "9.17.0", - "resolved": "https://registry.npmjs.org/@eslint/js/-/js-9.17.0.tgz", - "integrity": "sha512-Sxc4hqcs1kTu0iID3kcZDW3JHq2a77HO9P8CP6YEA/FpH3Ll8UXE2r/86Rz9YJLKme39S9vU5OWNjC6Xl0Cr3w==", + "version": "9.28.0", + "resolved": "https://registry.npmjs.org/@eslint/js/-/js-9.28.0.tgz", + "integrity": "sha512-fnqSjGWd/CoIp4EXIxWVK/sHA6DOHN4+8Ix2cX5ycOY7LG0UY8nHCU5pIp2eaE1Mc7Qd8kHspYNzYXT2ojPLzg==", "license": "MIT", "engines": { "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "url": "https://eslint.org/donate" } }, "node_modules/@eslint/object-schema": { @@ -1413,18 +1479,28 @@ } }, "node_modules/@eslint/plugin-kit": { +<<<<<<< HEAD "version": "0.2.8", "resolved": "https://registry.npmjs.org/@eslint/plugin-kit/-/plugin-kit-0.2.8.tgz", "integrity": "sha512-ZAoA40rNMPwSm+AeHpCq8STiNAwzWLJuP8Xv4CHIc9wv/PSuExjMrmjfYNj682vW0OOiZ1HKxzvjQr9XZIisQA==", "license": "Apache-2.0", "dependencies": { "@eslint/core": "^0.13.0", +======= + "version": "0.3.1", + "resolved": "https://registry.npmjs.org/@eslint/plugin-kit/-/plugin-kit-0.3.1.tgz", + "integrity": "sha512-0J+zgWxHN+xXONWIyPWKFMgVuJoZuGiIFu8yxk7RJjxkzpGmyja5wRFqZIVtjDVOQpV+Rw0iOAjYPE2eQyjr0w==", + "license": "Apache-2.0", + "dependencies": { + "@eslint/core": "^0.14.0", +>>>>>>> dev "levn": "^0.4.1" }, "engines": { "node": "^18.18.0 || ^20.9.0 || >=21.1.0" } }, +<<<<<<< HEAD "node_modules/@eslint/plugin-kit/node_modules/@eslint/core": { "version": "0.13.0", "resolved": "https://registry.npmjs.org/@eslint/core/-/core-0.13.0.tgz", @@ -1441,25 +1517,40 @@ "version": "1.7.0", "resolved": "https://registry.npmjs.org/@floating-ui/core/-/core-1.7.0.tgz", "integrity": "sha512-FRdBLykrPPA6P76GGGqlex/e7fbe0F1ykgxHYNXQsH/iTEtjMj/f9bpY5oQqbjt5VgZvgz/uKXbGuROijh3VLA==", +======= + "node_modules/@floating-ui/core": { + "version": "1.7.1", + "resolved": "https://registry.npmjs.org/@floating-ui/core/-/core-1.7.1.tgz", + "integrity": "sha512-azI0DrjMMfIug/ExbBaeDVJXcY0a7EPvPjb2xAJPa4HeimBX+Z18HK8QQR3jb6356SnDDdxx+hinMLcJEDdOjw==", +>>>>>>> dev "license": "MIT", "dependencies": { "@floating-ui/utils": "^0.2.9" } }, "node_modules/@floating-ui/dom": { +<<<<<<< HEAD "version": "1.7.0", "resolved": "https://registry.npmjs.org/@floating-ui/dom/-/dom-1.7.0.tgz", "integrity": "sha512-lGTor4VlXcesUMh1cupTUTDoCxMb0V6bm3CnxHzQcw8Eaf1jQbgQX4i02fYgT0vJ82tb5MZ4CZk1LRGkktJCzg==", "license": "MIT", "dependencies": { "@floating-ui/core": "^1.7.0", +======= + "version": "1.7.1", + "resolved": "https://registry.npmjs.org/@floating-ui/dom/-/dom-1.7.1.tgz", + "integrity": "sha512-cwsmW/zyw5ltYTUeeYJ60CnQuPqmGwuGVhG9w0PRaRKkAyi38BT5CKrpIbb+jtahSwUl04cWzSx9ZOIxeS6RsQ==", + "license": "MIT", + "dependencies": { + "@floating-ui/core": "^1.7.1", +>>>>>>> dev "@floating-ui/utils": "^0.2.9" } }, "node_modules/@floating-ui/react-dom": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/@floating-ui/react-dom/-/react-dom-2.1.2.tgz", - "integrity": "sha512-06okr5cgPzMNBy+Ycse2A6udMi4bqwW/zgBF/rwjcNqWkyr82Mcg8b0vjX8OJpZFy/FKjJmw6wV7t44kK6kW7A==", + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/@floating-ui/react-dom/-/react-dom-2.1.3.tgz", + "integrity": "sha512-huMBfiU9UnQ2oBwIhgzyIiSpVgvlDstU8CX0AF+wS+KzmYMs0J2a3GwuFHV1Lz+jlrQGeC1fF+Nv0QoumyV0bA==", "license": "MIT", "dependencies": { "@floating-ui/dom": "^1.0.0" @@ -1546,9 +1637,9 @@ } }, "node_modules/@img/sharp-darwin-arm64": { - "version": "0.33.5", - "resolved": "https://registry.npmjs.org/@img/sharp-darwin-arm64/-/sharp-darwin-arm64-0.33.5.tgz", - "integrity": "sha512-UT4p+iz/2H4twwAoLCqfA9UH5pI6DggwKEGuaPy7nCVQ8ZsiY5PIcrRvD1DzuY3qYL07NtIQcWnBSY/heikIFQ==", + "version": "0.34.2", + "resolved": "https://registry.npmjs.org/@img/sharp-darwin-arm64/-/sharp-darwin-arm64-0.34.2.tgz", + "integrity": "sha512-OfXHZPppddivUJnqyKoi5YVeHRkkNE2zUFT2gbpKxp/JZCFYEYubnMg+gOp6lWfasPrTS+KPosKqdI+ELYVDtg==", "cpu": [ "arm64" ], @@ -1564,7 +1655,29 @@ "url": "https://opencollective.com/libvips" }, "optionalDependencies": { - "@img/sharp-libvips-darwin-arm64": "1.0.4" + "@img/sharp-libvips-darwin-arm64": "1.1.0" + } + }, + "node_modules/@img/sharp-darwin-x64": { + "version": "0.34.2", + "resolved": "https://registry.npmjs.org/@img/sharp-darwin-x64/-/sharp-darwin-x64-0.34.2.tgz", + "integrity": "sha512-dYvWqmjU9VxqXmjEtjmvHnGqF8GrVjM2Epj9rJ6BUIXvk8slvNDJbhGFvIoXzkDhrJC2jUxNLz/GUjjvSzfw+g==", + "cpu": [ + "x64" + ], + "license": "Apache-2.0", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": "^18.17.0 || ^20.3.0 || >=21.0.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + }, + "optionalDependencies": { + "@img/sharp-libvips-darwin-x64": "1.1.0" } }, "node_modules/@img/sharp-darwin-x64": { @@ -1590,9 +1703,9 @@ } }, "node_modules/@img/sharp-libvips-darwin-arm64": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/@img/sharp-libvips-darwin-arm64/-/sharp-libvips-darwin-arm64-1.0.4.tgz", - "integrity": "sha512-XblONe153h0O2zuFfTAbQYAX2JhYmDHeWikp1LM9Hul9gVPjFY427k6dFEcOL72O01QxQsWi761svJ/ev9xEDg==", + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@img/sharp-libvips-darwin-arm64/-/sharp-libvips-darwin-arm64-1.1.0.tgz", + "integrity": "sha512-HZ/JUmPwrJSoM4DIQPv/BfNh9yrOA8tlBbqbLz4JZ5uew2+o22Ik+tHQJcih7QJuSa0zo5coHTfD5J8inqj9DA==", "cpu": [ "arm64" ], @@ -1606,9 +1719,15 @@ } }, "node_modules/@img/sharp-libvips-darwin-x64": { +<<<<<<< HEAD "version": "1.0.4", "resolved": "https://registry.npmjs.org/@img/sharp-libvips-darwin-x64/-/sharp-libvips-darwin-x64-1.0.4.tgz", "integrity": "sha512-xnGR8YuZYfJGmWPvmlunFaWJsb9T/AO2ykoP3Fz/0X5XV2aoYBPkX6xqCQvUTKKiLddarLaxpzNe+b1hjeWHAQ==", +======= + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@img/sharp-libvips-darwin-x64/-/sharp-libvips-darwin-x64-1.1.0.tgz", + "integrity": "sha512-Xzc2ToEmHN+hfvsl9wja0RlnXEgpKNmftriQp6XzY/RaSfwD9th+MSh0WQKzUreLKKINb3afirxW7A0fz2YWuQ==", +>>>>>>> dev "cpu": [ "x64" ], @@ -1622,9 +1741,15 @@ } }, "node_modules/@img/sharp-libvips-linux-arm": { +<<<<<<< HEAD "version": "1.0.5", "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linux-arm/-/sharp-libvips-linux-arm-1.0.5.tgz", "integrity": "sha512-gvcC4ACAOPRNATg/ov8/MnbxFDJqf/pDePbBnuBDcjsI8PssmjoKMAz4LtLaVi+OnSb5FK/yIOamqDwGmXW32g==", +======= + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linux-arm/-/sharp-libvips-linux-arm-1.1.0.tgz", + "integrity": "sha512-s8BAd0lwUIvYCJyRdFqvsj+BJIpDBSxs6ivrOPm/R7piTs5UIwY5OjXrP2bqXC9/moGsyRa37eYWYCOGVXxVrA==", +>>>>>>> dev "cpu": [ "arm" ], @@ -1638,9 +1763,15 @@ } }, "node_modules/@img/sharp-libvips-linux-arm64": { +<<<<<<< HEAD "version": "1.0.4", "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linux-arm64/-/sharp-libvips-linux-arm64-1.0.4.tgz", "integrity": "sha512-9B+taZ8DlyyqzZQnoeIvDVR/2F4EbMepXMc/NdVbkzsJbzkUjhXv/70GQJ7tdLA4YJgNP25zukcxpX2/SueNrA==", +======= + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linux-arm64/-/sharp-libvips-linux-arm64-1.1.0.tgz", + "integrity": "sha512-IVfGJa7gjChDET1dK9SekxFFdflarnUB8PwW8aGwEoF3oAsSDuNUTYS+SKDOyOJxQyDC1aPFMuRYLoDInyV9Ew==", +>>>>>>> dev "cpu": [ "arm64" ], @@ -1653,10 +1784,33 @@ "url": "https://opencollective.com/libvips" } }, +<<<<<<< HEAD "node_modules/@img/sharp-libvips-linux-s390x": { "version": "1.0.4", "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linux-s390x/-/sharp-libvips-linux-s390x-1.0.4.tgz", "integrity": "sha512-u7Wz6ntiSSgGSGcjZ55im6uvTrOxSIS8/dgoVMoiGE9I6JAfU50yH5BoDlYA1tcuGS7g/QNtetJnxA6QEsCVTA==", +======= + "node_modules/@img/sharp-libvips-linux-ppc64": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linux-ppc64/-/sharp-libvips-linux-ppc64-1.1.0.tgz", + "integrity": "sha512-tiXxFZFbhnkWE2LA8oQj7KYR+bWBkiV2nilRldT7bqoEZ4HiDOcePr9wVDAZPi/Id5fT1oY9iGnDq20cwUz8lQ==", + "cpu": [ + "ppc64" + ], + "license": "LGPL-3.0-or-later", + "optional": true, + "os": [ + "linux" + ], + "funding": { + "url": "https://opencollective.com/libvips" + } + }, + "node_modules/@img/sharp-libvips-linux-s390x": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linux-s390x/-/sharp-libvips-linux-s390x-1.1.0.tgz", + "integrity": "sha512-xukSwvhguw7COyzvmjydRb3x/09+21HykyapcZchiCUkTThEQEOMtBj9UhkaBRLuBrgLFzQ2wbxdeCCJW/jgJA==", +>>>>>>> dev "cpu": [ "s390x" ], @@ -1670,9 +1824,15 @@ } }, "node_modules/@img/sharp-libvips-linux-x64": { +<<<<<<< HEAD "version": "1.0.4", "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linux-x64/-/sharp-libvips-linux-x64-1.0.4.tgz", "integrity": "sha512-MmWmQ3iPFZr0Iev+BAgVMb3ZyC4KeFc3jFxnNbEPas60e1cIfevbtuyf9nDGIzOaW9PdnDciJm+wFFaTlj5xYw==", +======= + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linux-x64/-/sharp-libvips-linux-x64-1.1.0.tgz", + "integrity": "sha512-yRj2+reB8iMg9W5sULM3S74jVS7zqSzHG3Ol/twnAAkAhnGQnpjj6e4ayUz7V+FpKypwgs82xbRdYtchTTUB+Q==", +>>>>>>> dev "cpu": [ "x64" ], @@ -1686,9 +1846,15 @@ } }, "node_modules/@img/sharp-libvips-linuxmusl-arm64": { +<<<<<<< HEAD "version": "1.0.4", "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linuxmusl-arm64/-/sharp-libvips-linuxmusl-arm64-1.0.4.tgz", "integrity": "sha512-9Ti+BbTYDcsbp4wfYib8Ctm1ilkugkA/uscUn6UXK1ldpC1JjiXbLfFZtRlBhjPZ5o1NCLiDbg8fhUPKStHoTA==", +======= + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linuxmusl-arm64/-/sharp-libvips-linuxmusl-arm64-1.1.0.tgz", + "integrity": "sha512-jYZdG+whg0MDK+q2COKbYidaqW/WTz0cc1E+tMAusiDygrM4ypmSCjOJPmFTvHHJ8j/6cAGyeDWZOsK06tP33w==", +>>>>>>> dev "cpu": [ "arm64" ], @@ -1702,9 +1868,15 @@ } }, "node_modules/@img/sharp-libvips-linuxmusl-x64": { +<<<<<<< HEAD "version": "1.0.4", "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linuxmusl-x64/-/sharp-libvips-linuxmusl-x64-1.0.4.tgz", "integrity": "sha512-viYN1KX9m+/hGkJtvYYp+CCLgnJXwiQB39damAO7WMdKWlIhmYTfHjwSbQeUK/20vY154mwezd9HflVFM1wVSw==", +======= + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linuxmusl-x64/-/sharp-libvips-linuxmusl-x64-1.1.0.tgz", + "integrity": "sha512-wK7SBdwrAiycjXdkPnGCPLjYb9lD4l6Ze2gSdAGVZrEL05AOUJESWU2lhlC+Ffn5/G+VKuSm6zzbQSzFX/P65A==", +>>>>>>> dev "cpu": [ "x64" ], @@ -1718,9 +1890,15 @@ } }, "node_modules/@img/sharp-linux-arm": { +<<<<<<< HEAD "version": "0.33.5", "resolved": "https://registry.npmjs.org/@img/sharp-linux-arm/-/sharp-linux-arm-0.33.5.tgz", "integrity": "sha512-JTS1eldqZbJxjvKaAkxhZmBqPRGmxgu+qFKSInv8moZ2AmT5Yib3EQ1c6gp493HvrvV8QgdOXdyaIBrhvFhBMQ==", +======= + "version": "0.34.2", + "resolved": "https://registry.npmjs.org/@img/sharp-linux-arm/-/sharp-linux-arm-0.34.2.tgz", + "integrity": "sha512-0DZzkvuEOqQUP9mo2kjjKNok5AmnOr1jB2XYjkaoNRwpAYMDzRmAqUIa1nRi58S2WswqSfPOWLNOr0FDT3H5RQ==", +>>>>>>> dev "cpu": [ "arm" ], @@ -1736,6 +1914,7 @@ "url": "https://opencollective.com/libvips" }, "optionalDependencies": { +<<<<<<< HEAD "@img/sharp-libvips-linux-arm": "1.0.5" } }, @@ -1743,6 +1922,15 @@ "version": "0.33.5", "resolved": "https://registry.npmjs.org/@img/sharp-linux-arm64/-/sharp-linux-arm64-0.33.5.tgz", "integrity": "sha512-JMVv+AMRyGOHtO1RFBiJy/MBsgz0x4AWrT6QoEVVTyh1E39TrCUpTRI7mx9VksGX4awWASxqCYLCV4wBZHAYxA==", +======= + "@img/sharp-libvips-linux-arm": "1.1.0" + } + }, + "node_modules/@img/sharp-linux-arm64": { + "version": "0.34.2", + "resolved": "https://registry.npmjs.org/@img/sharp-linux-arm64/-/sharp-linux-arm64-0.34.2.tgz", + "integrity": "sha512-D8n8wgWmPDakc83LORcfJepdOSN6MvWNzzz2ux0MnIbOqdieRZwVYY32zxVx+IFUT8er5KPcyU3XXsn+GzG/0Q==", +>>>>>>> dev "cpu": [ "arm64" ], @@ -1758,6 +1946,7 @@ "url": "https://opencollective.com/libvips" }, "optionalDependencies": { +<<<<<<< HEAD "@img/sharp-libvips-linux-arm64": "1.0.4" } }, @@ -1765,6 +1954,15 @@ "version": "0.33.5", "resolved": "https://registry.npmjs.org/@img/sharp-linux-s390x/-/sharp-linux-s390x-0.33.5.tgz", "integrity": "sha512-y/5PCd+mP4CA/sPDKl2961b+C9d+vPAveS33s6Z3zfASk2j5upL6fXVPZi7ztePZ5CuH+1kW8JtvxgbuXHRa4Q==", +======= + "@img/sharp-libvips-linux-arm64": "1.1.0" + } + }, + "node_modules/@img/sharp-linux-s390x": { + "version": "0.34.2", + "resolved": "https://registry.npmjs.org/@img/sharp-linux-s390x/-/sharp-linux-s390x-0.34.2.tgz", + "integrity": "sha512-EGZ1xwhBI7dNISwxjChqBGELCWMGDvmxZXKjQRuqMrakhO8QoMgqCrdjnAqJq/CScxfRn+Bb7suXBElKQpPDiw==", +>>>>>>> dev "cpu": [ "s390x" ], @@ -1780,6 +1978,7 @@ "url": "https://opencollective.com/libvips" }, "optionalDependencies": { +<<<<<<< HEAD "@img/sharp-libvips-linux-s390x": "1.0.4" } }, @@ -1787,6 +1986,15 @@ "version": "0.33.5", "resolved": "https://registry.npmjs.org/@img/sharp-linux-x64/-/sharp-linux-x64-0.33.5.tgz", "integrity": "sha512-opC+Ok5pRNAzuvq1AG0ar+1owsu842/Ab+4qvU879ippJBHvyY5n2mxF1izXqkPYlGuP/M556uh53jRLJmzTWA==", +======= + "@img/sharp-libvips-linux-s390x": "1.1.0" + } + }, + "node_modules/@img/sharp-linux-x64": { + "version": "0.34.2", + "resolved": "https://registry.npmjs.org/@img/sharp-linux-x64/-/sharp-linux-x64-0.34.2.tgz", + "integrity": "sha512-sD7J+h5nFLMMmOXYH4DD9UtSNBD05tWSSdWAcEyzqW8Cn5UxXvsHAxmxSesYUsTOBmUnjtxghKDl15EvfqLFbQ==", +>>>>>>> dev "cpu": [ "x64" ], @@ -1802,6 +2010,7 @@ "url": "https://opencollective.com/libvips" }, "optionalDependencies": { +<<<<<<< HEAD "@img/sharp-libvips-linux-x64": "1.0.4" } }, @@ -1809,6 +2018,15 @@ "version": "0.33.5", "resolved": "https://registry.npmjs.org/@img/sharp-linuxmusl-arm64/-/sharp-linuxmusl-arm64-0.33.5.tgz", "integrity": "sha512-XrHMZwGQGvJg2V/oRSUfSAfjfPxO+4DkiRh6p2AFjLQztWUuY/o8Mq0eMQVIY7HJ1CDQUJlxGGZRw1a5bqmd1g==", +======= + "@img/sharp-libvips-linux-x64": "1.1.0" + } + }, + "node_modules/@img/sharp-linuxmusl-arm64": { + "version": "0.34.2", + "resolved": "https://registry.npmjs.org/@img/sharp-linuxmusl-arm64/-/sharp-linuxmusl-arm64-0.34.2.tgz", + "integrity": "sha512-NEE2vQ6wcxYav1/A22OOxoSOGiKnNmDzCYFOZ949xFmrWZOVII1Bp3NqVVpvj+3UeHMFyN5eP/V5hzViQ5CZNA==", +>>>>>>> dev "cpu": [ "arm64" ], @@ -1824,6 +2042,7 @@ "url": "https://opencollective.com/libvips" }, "optionalDependencies": { +<<<<<<< HEAD "@img/sharp-libvips-linuxmusl-arm64": "1.0.4" } }, @@ -1831,6 +2050,15 @@ "version": "0.33.5", "resolved": "https://registry.npmjs.org/@img/sharp-linuxmusl-x64/-/sharp-linuxmusl-x64-0.33.5.tgz", "integrity": "sha512-WT+d/cgqKkkKySYmqoZ8y3pxx7lx9vVejxW/W4DOFMYVSkErR+w7mf2u8m/y4+xHe7yY9DAXQMWQhpnMuFfScw==", +======= + "@img/sharp-libvips-linuxmusl-arm64": "1.1.0" + } + }, + "node_modules/@img/sharp-linuxmusl-x64": { + "version": "0.34.2", + "resolved": "https://registry.npmjs.org/@img/sharp-linuxmusl-x64/-/sharp-linuxmusl-x64-0.34.2.tgz", + "integrity": "sha512-DOYMrDm5E6/8bm/yQLCWyuDJwUnlevR8xtF8bs+gjZ7cyUNYXiSf/E8Kp0Ss5xasIaXSHzb888V1BE4i1hFhAA==", +>>>>>>> dev "cpu": [ "x64" ], @@ -1846,6 +2074,7 @@ "url": "https://opencollective.com/libvips" }, "optionalDependencies": { +<<<<<<< HEAD "@img/sharp-libvips-linuxmusl-x64": "1.0.4" } }, @@ -1853,13 +2082,26 @@ "version": "0.33.5", "resolved": "https://registry.npmjs.org/@img/sharp-wasm32/-/sharp-wasm32-0.33.5.tgz", "integrity": "sha512-ykUW4LVGaMcU9lu9thv85CbRMAwfeadCJHRsg2GmeRa/cJxsVY9Rbd57JcMxBkKHag5U/x7TSBpScF4U8ElVzg==", +======= + "@img/sharp-libvips-linuxmusl-x64": "1.1.0" + } + }, + "node_modules/@img/sharp-wasm32": { + "version": "0.34.2", + "resolved": "https://registry.npmjs.org/@img/sharp-wasm32/-/sharp-wasm32-0.34.2.tgz", + "integrity": "sha512-/VI4mdlJ9zkaq53MbIG6rZY+QRN3MLbR6usYlgITEzi4Rpx5S6LFKsycOQjkOGmqTNmkIdLjEvooFKwww6OpdQ==", +>>>>>>> dev "cpu": [ "wasm32" ], "license": "Apache-2.0 AND LGPL-3.0-or-later AND MIT", "optional": true, "dependencies": { +<<<<<<< HEAD "@emnapi/runtime": "^1.2.0" +======= + "@emnapi/runtime": "^1.4.3" +>>>>>>> dev }, "engines": { "node": "^18.17.0 || ^20.3.0 || >=21.0.0" @@ -1868,10 +2110,36 @@ "url": "https://opencollective.com/libvips" } }, +<<<<<<< HEAD "node_modules/@img/sharp-win32-ia32": { "version": "0.33.5", "resolved": "https://registry.npmjs.org/@img/sharp-win32-ia32/-/sharp-win32-ia32-0.33.5.tgz", "integrity": "sha512-T36PblLaTwuVJ/zw/LaH0PdZkRz5rd3SmMHX8GSmR7vtNSP5Z6bQkExdSK7xGWyxLw4sUknBuugTelgw2faBbQ==", +======= + "node_modules/@img/sharp-win32-arm64": { + "version": "0.34.2", + "resolved": "https://registry.npmjs.org/@img/sharp-win32-arm64/-/sharp-win32-arm64-0.34.2.tgz", + "integrity": "sha512-cfP/r9FdS63VA5k0xiqaNaEoGxBg9k7uE+RQGzuK9fHt7jib4zAVVseR9LsE4gJcNWgT6APKMNnCcnyOtmSEUQ==", + "cpu": [ + "arm64" + ], + "license": "Apache-2.0 AND LGPL-3.0-or-later", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": "^18.17.0 || ^20.3.0 || >=21.0.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + } + }, + "node_modules/@img/sharp-win32-ia32": { + "version": "0.34.2", + "resolved": "https://registry.npmjs.org/@img/sharp-win32-ia32/-/sharp-win32-ia32-0.34.2.tgz", + "integrity": "sha512-QLjGGvAbj0X/FXl8n1WbtQ6iVBpWU7JO94u/P2M4a8CFYsvQi4GW2mRy/JqkRx0qpBzaOdKJKw8uc930EX2AHw==", +>>>>>>> dev "cpu": [ "ia32" ], @@ -1888,9 +2156,15 @@ } }, "node_modules/@img/sharp-win32-x64": { +<<<<<<< HEAD "version": "0.33.5", "resolved": "https://registry.npmjs.org/@img/sharp-win32-x64/-/sharp-win32-x64-0.33.5.tgz", "integrity": "sha512-MpY/o8/8kj+EcnxwvrP4aTJSWw/aZ7JIGR4aBeZkZw5B7/Jn+tY9/VNwtcoGmdT7GfggGIU4kygOMSbYnOrAbg==", +======= + "version": "0.34.2", + "resolved": "https://registry.npmjs.org/@img/sharp-win32-x64/-/sharp-win32-x64-0.34.2.tgz", + "integrity": "sha512-aUdT6zEYtDKCaxkofmmJDJYGCf0+pJg3eU9/oBuqvEeoB9dKI6ZLc/1iLJCTuJQDO4ptntAlkUmHgGjyuobZbw==", +>>>>>>> dev "cpu": [ "x64" ], @@ -1927,6 +2201,10 @@ "version": "4.0.1", "resolved": "https://registry.npmjs.org/@isaacs/fs-minipass/-/fs-minipass-4.0.1.tgz", "integrity": "sha512-wgm9Ehl2jpeqP3zw/7mo3kRHFp5MEDhqAdwy1fTGkHAwnkGOVsgpvQhL8B5n1qlb01jV3n/bI0ZfZp5lWA1k4w==", +<<<<<<< HEAD +======= + "dev": true, +>>>>>>> dev "license": "ISC", "dependencies": { "minipass": "^7.0.4" @@ -1989,6 +2267,7 @@ } }, "node_modules/@napi-rs/wasm-runtime": { +<<<<<<< HEAD "version": "0.2.9", "resolved": "https://registry.npmjs.org/@napi-rs/wasm-runtime/-/wasm-runtime-0.2.9.tgz", "integrity": "sha512-OKRBiajrrxB9ATokgEQoG87Z25c67pCpYcCwmXYX8PBftC9pBfN18gnm/fh1wurSLEKIAt+QRFLFCQISrb66Jg==", @@ -1997,28 +2276,38 @@ "dependencies": { "@emnapi/core": "^1.4.0", "@emnapi/runtime": "^1.4.0", +======= + "version": "0.2.10", + "resolved": "https://registry.npmjs.org/@napi-rs/wasm-runtime/-/wasm-runtime-0.2.10.tgz", + "integrity": "sha512-bCsCyeZEwVErsGmyPNSzwfwFn4OdxBj0mmv6hOFucB/k81Ojdu68RbZdxYsRQUPc9l6SU5F/cG+bXgWs3oUgsQ==", + "license": "MIT", + "optional": true, + "dependencies": { + "@emnapi/core": "^1.4.3", + "@emnapi/runtime": "^1.4.3", +>>>>>>> dev "@tybys/wasm-util": "^0.9.0" } }, "node_modules/@next/env": { - "version": "15.2.4", - "resolved": "https://registry.npmjs.org/@next/env/-/env-15.2.4.tgz", - "integrity": "sha512-+SFtMgoiYP3WoSswuNmxJOCwi06TdWE733D+WPjpXIe4LXGULwEaofiiAy6kbS0+XjM5xF5n3lKuBwN2SnqD9g==", + "version": "15.3.3", + "resolved": "https://registry.npmjs.org/@next/env/-/env-15.3.3.tgz", + "integrity": "sha512-OdiMrzCl2Xi0VTjiQQUK0Xh7bJHnOuET2s+3V+Y40WJBAXrJeGA3f+I8MZJ/YQ3mVGi5XGR1L66oFlgqXhQ4Vw==", "license": "MIT" }, "node_modules/@next/eslint-plugin-next": { - "version": "15.1.3", - "resolved": "https://registry.npmjs.org/@next/eslint-plugin-next/-/eslint-plugin-next-15.1.3.tgz", - "integrity": "sha512-oeP1vnc5Cq9UoOb8SYHAEPbCXMzOgG70l+Zfd+Ie00R25FOm+CCVNrcIubJvB1tvBgakXE37MmqSycksXVPRqg==", + "version": "15.3.3", + "resolved": "https://registry.npmjs.org/@next/eslint-plugin-next/-/eslint-plugin-next-15.3.3.tgz", + "integrity": "sha512-VKZJEiEdpKkfBmcokGjHu0vGDG+8CehGs90tBEy/IDoDDKGngeyIStt2MmE5FYNyU9BhgR7tybNWTAJY/30u+Q==", "license": "MIT", "dependencies": { "fast-glob": "3.3.1" } }, "node_modules/@next/swc-darwin-arm64": { - "version": "15.2.4", - "resolved": "https://registry.npmjs.org/@next/swc-darwin-arm64/-/swc-darwin-arm64-15.2.4.tgz", - "integrity": "sha512-1AnMfs655ipJEDC/FHkSr0r3lXBgpqKo4K1kiwfUf3iE68rDFXZ1TtHdMvf7D0hMItgDZ7Vuq3JgNMbt/+3bYw==", + "version": "15.3.3", + "resolved": "https://registry.npmjs.org/@next/swc-darwin-arm64/-/swc-darwin-arm64-15.3.3.tgz", + "integrity": "sha512-WRJERLuH+O3oYB4yZNVahSVFmtxRNjNF1I1c34tYMoJb0Pve+7/RaLAJJizyYiFhjYNGHRAE1Ri2Fd23zgDqhg==", "cpu": [ "arm64" ], @@ -2032,9 +2321,9 @@ } }, "node_modules/@next/swc-darwin-x64": { - "version": "15.2.4", - "resolved": "https://registry.npmjs.org/@next/swc-darwin-x64/-/swc-darwin-x64-15.2.4.tgz", - "integrity": "sha512-3qK2zb5EwCwxnO2HeO+TRqCubeI/NgCe+kL5dTJlPldV/uwCnUgC7VbEzgmxbfrkbjehL4H9BPztWOEtsoMwew==", + "version": "15.3.3", + "resolved": "https://registry.npmjs.org/@next/swc-darwin-x64/-/swc-darwin-x64-15.3.3.tgz", + "integrity": "sha512-XHdzH/yBc55lu78k/XwtuFR/ZXUTcflpRXcsu0nKmF45U96jt1tsOZhVrn5YH+paw66zOANpOnFQ9i6/j+UYvw==", "cpu": [ "x64" ], @@ -2048,9 +2337,9 @@ } }, "node_modules/@next/swc-linux-arm64-gnu": { - "version": "15.2.4", - "resolved": "https://registry.npmjs.org/@next/swc-linux-arm64-gnu/-/swc-linux-arm64-gnu-15.2.4.tgz", - "integrity": "sha512-HFN6GKUcrTWvem8AZN7tT95zPb0GUGv9v0d0iyuTb303vbXkkbHDp/DxufB04jNVD+IN9yHy7y/6Mqq0h0YVaQ==", + "version": "15.3.3", + "resolved": "https://registry.npmjs.org/@next/swc-linux-arm64-gnu/-/swc-linux-arm64-gnu-15.3.3.tgz", + "integrity": "sha512-VZ3sYL2LXB8znNGcjhocikEkag/8xiLgnvQts41tq6i+wql63SMS1Q6N8RVXHw5pEUjiof+II3HkDd7GFcgkzw==", "cpu": [ "arm64" ], @@ -2064,9 +2353,9 @@ } }, "node_modules/@next/swc-linux-arm64-musl": { - "version": "15.2.4", - "resolved": "https://registry.npmjs.org/@next/swc-linux-arm64-musl/-/swc-linux-arm64-musl-15.2.4.tgz", - "integrity": "sha512-Oioa0SORWLwi35/kVB8aCk5Uq+5/ZIumMK1kJV+jSdazFm2NzPDztsefzdmzzpx5oGCJ6FkUC7vkaUseNTStNA==", + "version": "15.3.3", + "resolved": "https://registry.npmjs.org/@next/swc-linux-arm64-musl/-/swc-linux-arm64-musl-15.3.3.tgz", + "integrity": "sha512-h6Y1fLU4RWAp1HPNJWDYBQ+e3G7sLckyBXhmH9ajn8l/RSMnhbuPBV/fXmy3muMcVwoJdHL+UtzRzs0nXOf9SA==", "cpu": [ "arm64" ], @@ -2080,9 +2369,9 @@ } }, "node_modules/@next/swc-linux-x64-gnu": { - "version": "15.2.4", - "resolved": "https://registry.npmjs.org/@next/swc-linux-x64-gnu/-/swc-linux-x64-gnu-15.2.4.tgz", - "integrity": "sha512-yb5WTRaHdkgOqFOZiu6rHV1fAEK0flVpaIN2HB6kxHVSy/dIajWbThS7qON3W9/SNOH2JWkVCyulgGYekMePuw==", + "version": "15.3.3", + "resolved": "https://registry.npmjs.org/@next/swc-linux-x64-gnu/-/swc-linux-x64-gnu-15.3.3.tgz", + "integrity": "sha512-jJ8HRiF3N8Zw6hGlytCj5BiHyG/K+fnTKVDEKvUCyiQ/0r5tgwO7OgaRiOjjRoIx2vwLR+Rz8hQoPrnmFbJdfw==", "cpu": [ "x64" ], @@ -2096,9 +2385,9 @@ } }, "node_modules/@next/swc-linux-x64-musl": { - "version": "15.2.4", - "resolved": "https://registry.npmjs.org/@next/swc-linux-x64-musl/-/swc-linux-x64-musl-15.2.4.tgz", - "integrity": "sha512-Dcdv/ix6srhkM25fgXiyOieFUkz+fOYkHlydWCtB0xMST6X9XYI3yPDKBZt1xuhOytONsIFJFB08xXYsxUwJLw==", + "version": "15.3.3", + "resolved": "https://registry.npmjs.org/@next/swc-linux-x64-musl/-/swc-linux-x64-musl-15.3.3.tgz", + "integrity": "sha512-HrUcTr4N+RgiiGn3jjeT6Oo208UT/7BuTr7K0mdKRBtTbT4v9zJqCDKO97DUqqoBK1qyzP1RwvrWTvU6EPh/Cw==", "cpu": [ "x64" ], @@ -2112,9 +2401,9 @@ } }, "node_modules/@next/swc-win32-arm64-msvc": { - "version": "15.2.4", - "resolved": "https://registry.npmjs.org/@next/swc-win32-arm64-msvc/-/swc-win32-arm64-msvc-15.2.4.tgz", - "integrity": "sha512-dW0i7eukvDxtIhCYkMrZNQfNicPDExt2jPb9AZPpL7cfyUo7QSNl1DjsHjmmKp6qNAqUESyT8YFl/Aw91cNJJg==", + "version": "15.3.3", + "resolved": "https://registry.npmjs.org/@next/swc-win32-arm64-msvc/-/swc-win32-arm64-msvc-15.3.3.tgz", + "integrity": "sha512-SxorONgi6K7ZUysMtRF3mIeHC5aA3IQLmKFQzU0OuhuUYwpOBc1ypaLJLP5Bf3M9k53KUUUj4vTPwzGvl/NwlQ==", "cpu": [ "arm64" ], @@ -2128,9 +2417,9 @@ } }, "node_modules/@next/swc-win32-x64-msvc": { - "version": "15.2.4", - "resolved": "https://registry.npmjs.org/@next/swc-win32-x64-msvc/-/swc-win32-x64-msvc-15.2.4.tgz", - "integrity": "sha512-SbnWkJmkS7Xl3kre8SdMF6F/XDh1DTFEhp0jRTj/uB8iPKoU2bb2NDfcu+iifv1+mxQEd1g2vvSxcZbXSKyWiQ==", + "version": "15.3.3", + "resolved": "https://registry.npmjs.org/@next/swc-win32-x64-msvc/-/swc-win32-x64-msvc-15.3.3.tgz", + "integrity": "sha512-4QZG6F8enl9/S2+yIiOiju0iCTFd93d8VC1q9LZS4p/Xuk81W2QDjCFeoogmrWWkAD59z8ZxepBQap2dKS5ruw==", "cpu": [ "x64" ], @@ -2157,9 +2446,15 @@ } }, "node_modules/@noble/curves": { +<<<<<<< HEAD "version": "1.9.0", "resolved": "https://registry.npmjs.org/@noble/curves/-/curves-1.9.0.tgz", "integrity": "sha512-7YDlXiNMdO1YZeH6t/kvopHHbIZzlxrCV9WLqCY6QhcXOoXiNCMDqJIglZ9Yjx5+w7Dz30TITFrlTjnRg7sKEg==", +======= + "version": "1.9.2", + "resolved": "https://registry.npmjs.org/@noble/curves/-/curves-1.9.2.tgz", + "integrity": "sha512-HxngEd2XUcg9xi20JkwlLCtYwfoFw4JGkuZpT+WlsPD4gB/cxkvTD8fSsoAnphGZhFdZYKeQIPCuFlWPm1uE0g==", +>>>>>>> dev "dev": true, "license": "MIT", "dependencies": { @@ -2810,43 +3105,25 @@ "integrity": "sha512-hkjo6MuIK/kQR5CrGNdAPZhS01ZCXuWDRJ187zh6qqF2+yMHZpD9fAYpX8q2bOO6Ryhl3XpCT6kUX76N8hhm4Q==", "license": "MIT" }, - "node_modules/@petamoriken/float16": { - "version": "3.9.2", - "resolved": "https://registry.npmjs.org/@petamoriken/float16/-/float16-3.9.2.tgz", - "integrity": "sha512-VgffxawQde93xKxT3qap3OH+meZf7VaSB5Sqd4Rqc+FP5alWbpOyan/7tRbOAvynjpG3GpdtAuGU/NdhQpmrog==", - "dev": true, - "license": "MIT" - }, - "node_modules/@pkgjs/parseargs": { - "version": "0.11.0", - "resolved": "https://registry.npmjs.org/@pkgjs/parseargs/-/parseargs-0.11.0.tgz", - "integrity": "sha512-+1VkjdD0QBLPodGrJUeqarH8VAIvQODIbwh9XpP5Syisf7YoQgsJKPNFoqqLQlu+VQ/tVSshMR6loPMn8U+dPg==", - "dev": true, - "license": "MIT", - "optional": true, - "engines": { - "node": ">=14" - } - }, "node_modules/@radix-ui/number": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/@radix-ui/number/-/number-1.1.0.tgz", - "integrity": "sha512-V3gRzhVNU1ldS5XhAPTom1fOIo4ccrjjJgmE+LI2h/WaFpHmx0MQApT+KZHnx8abG6Avtfcz4WoEciMnpFT3HQ==", + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/@radix-ui/number/-/number-1.1.1.tgz", + "integrity": "sha512-MkKCwxlXTgz6CFoJx3pCwn07GKp36+aZyu/u2Ln2VrA5DcdyCZkASEDBTd8x5whTQQL5CiYf4prXKLcgQdv29g==", "license": "MIT" }, "node_modules/@radix-ui/primitive": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/@radix-ui/primitive/-/primitive-1.1.1.tgz", - "integrity": "sha512-SJ31y+Q/zAyShtXJc8x83i9TYdbAfHZ++tUZnvjJJqFjzsdUnKsxPL6IEtBlxKkU7yzer//GQtZSV4GbldL3YA==", + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/@radix-ui/primitive/-/primitive-1.1.2.tgz", + "integrity": "sha512-XnbHrrprsNqZKQhStrSwgRUQzoCI1glLzdw79xiZPoofhGICeZRSQ3dIxAKH1gb3OHfNf4d6f+vAv3kil2eggA==", "license": "MIT" }, "node_modules/@radix-ui/react-arrow": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/@radix-ui/react-arrow/-/react-arrow-1.1.1.tgz", - "integrity": "sha512-NaVpZfmv8SKeZbn4ijN2V3jlHA9ngBG16VnIIm22nUR0Yk8KUALyBxT3KYEUnNuch9sTE8UTsS3whzBgKOL30w==", + "version": "1.1.7", + "resolved": "https://registry.npmjs.org/@radix-ui/react-arrow/-/react-arrow-1.1.7.tgz", + "integrity": "sha512-F+M1tLhO+mlQaOWspE8Wstg+z6PwxwRd8oQ8IXceWz92kfAmalTRf0EjrouQeo7QssEPfCn05B4Ihs1K9WQ/7w==", "license": "MIT", "dependencies": { - "@radix-ui/react-primitive": "2.0.1" + "@radix-ui/react-primitive": "2.1.3" }, "peerDependencies": { "@types/react": "*", @@ -2864,15 +3141,16 @@ } }, "node_modules/@radix-ui/react-avatar": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/@radix-ui/react-avatar/-/react-avatar-1.1.2.tgz", - "integrity": "sha512-GaC7bXQZ5VgZvVvsJ5mu/AEbjYLnhhkoidOboC50Z6FFlLA03wG2ianUoH+zgDQ31/9gCF59bE4+2bBgTyMiig==", + "version": "1.1.10", + "resolved": "https://registry.npmjs.org/@radix-ui/react-avatar/-/react-avatar-1.1.10.tgz", + "integrity": "sha512-V8piFfWapM5OmNCXTzVQY+E1rDa53zY+MQ4Y7356v4fFz6vqCyUtIz2rUD44ZEdwg78/jKmMJHj07+C/Z/rcog==", "license": "MIT", "dependencies": { - "@radix-ui/react-context": "1.1.1", - "@radix-ui/react-primitive": "2.0.1", - "@radix-ui/react-use-callback-ref": "1.1.0", - "@radix-ui/react-use-layout-effect": "1.1.0" + "@radix-ui/react-context": "1.1.2", + "@radix-ui/react-primitive": "2.1.3", + "@radix-ui/react-use-callback-ref": "1.1.1", + "@radix-ui/react-use-is-hydrated": "0.1.0", + "@radix-ui/react-use-layout-effect": "1.1.1" }, "peerDependencies": { "@types/react": "*", @@ -2890,19 +3168,19 @@ } }, "node_modules/@radix-ui/react-checkbox": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/@radix-ui/react-checkbox/-/react-checkbox-1.1.3.tgz", - "integrity": "sha512-HD7/ocp8f1B3e6OHygH0n7ZKjONkhciy1Nh0yuBgObqThc3oyx+vuMfFHKAknXRHHWVE9XvXStxJFyjUmB8PIw==", + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/@radix-ui/react-checkbox/-/react-checkbox-1.3.2.tgz", + "integrity": "sha512-yd+dI56KZqawxKZrJ31eENUwqc1QSqg4OZ15rybGjF2ZNwMO+wCyHzAVLRp9qoYJf7kYy0YpZ2b0JCzJ42HZpA==", "license": "MIT", "dependencies": { - "@radix-ui/primitive": "1.1.1", - "@radix-ui/react-compose-refs": "1.1.1", - "@radix-ui/react-context": "1.1.1", - "@radix-ui/react-presence": "1.1.2", - "@radix-ui/react-primitive": "2.0.1", - "@radix-ui/react-use-controllable-state": "1.1.0", - "@radix-ui/react-use-previous": "1.1.0", - "@radix-ui/react-use-size": "1.1.0" + "@radix-ui/primitive": "1.1.2", + "@radix-ui/react-compose-refs": "1.1.2", + "@radix-ui/react-context": "1.1.2", + "@radix-ui/react-presence": "1.1.4", + "@radix-ui/react-primitive": "2.1.3", + "@radix-ui/react-use-controllable-state": "1.2.2", + "@radix-ui/react-use-previous": "1.1.1", + "@radix-ui/react-use-size": "1.1.1" }, "peerDependencies": { "@types/react": "*", @@ -2920,19 +3198,19 @@ } }, "node_modules/@radix-ui/react-collapsible": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/@radix-ui/react-collapsible/-/react-collapsible-1.1.2.tgz", - "integrity": "sha512-PliMB63vxz7vggcyq0IxNYk8vGDrLXVWw4+W4B8YnwI1s18x7YZYqlG9PLX7XxAJUi0g2DxP4XKJMFHh/iVh9A==", + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/@radix-ui/react-collapsible/-/react-collapsible-1.1.11.tgz", + "integrity": "sha512-2qrRsVGSCYasSz1RFOorXwl0H7g7J1frQtgpQgYrt+MOidtPAINHn9CPovQXb83r8ahapdx3Tu0fa/pdFFSdPg==", "license": "MIT", "dependencies": { - "@radix-ui/primitive": "1.1.1", - "@radix-ui/react-compose-refs": "1.1.1", - "@radix-ui/react-context": "1.1.1", - "@radix-ui/react-id": "1.1.0", - "@radix-ui/react-presence": "1.1.2", - "@radix-ui/react-primitive": "2.0.1", - "@radix-ui/react-use-controllable-state": "1.1.0", - "@radix-ui/react-use-layout-effect": "1.1.0" + "@radix-ui/primitive": "1.1.2", + "@radix-ui/react-compose-refs": "1.1.2", + "@radix-ui/react-context": "1.1.2", + "@radix-ui/react-id": "1.1.1", + "@radix-ui/react-presence": "1.1.4", + "@radix-ui/react-primitive": "2.1.3", + "@radix-ui/react-use-controllable-state": "1.2.2", + "@radix-ui/react-use-layout-effect": "1.1.1" }, "peerDependencies": { "@types/react": "*", @@ -2950,15 +3228,15 @@ } }, "node_modules/@radix-ui/react-collection": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/@radix-ui/react-collection/-/react-collection-1.1.1.tgz", - "integrity": "sha512-LwT3pSho9Dljg+wY2KN2mrrh6y3qELfftINERIzBUO9e0N+t0oMTyn3k9iv+ZqgrwGkRnLpNJrsMv9BZlt2yuA==", + "version": "1.1.7", + "resolved": "https://registry.npmjs.org/@radix-ui/react-collection/-/react-collection-1.1.7.tgz", + "integrity": "sha512-Fh9rGN0MoI4ZFUNyfFVNU4y9LUz93u9/0K+yLgA2bwRojxM8JU1DyvvMBabnZPBgMWREAJvU2jjVzq+LrFUglw==", "license": "MIT", "dependencies": { - "@radix-ui/react-compose-refs": "1.1.1", - "@radix-ui/react-context": "1.1.1", - "@radix-ui/react-primitive": "2.0.1", - "@radix-ui/react-slot": "1.1.1" + "@radix-ui/react-compose-refs": "1.1.2", + "@radix-ui/react-context": "1.1.2", + "@radix-ui/react-primitive": "2.1.3", + "@radix-ui/react-slot": "1.2.3" }, "peerDependencies": { "@types/react": "*", @@ -2976,9 +3254,9 @@ } }, "node_modules/@radix-ui/react-compose-refs": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/@radix-ui/react-compose-refs/-/react-compose-refs-1.1.1.tgz", - "integrity": "sha512-Y9VzoRDSJtgFMUCoiZBDVo084VQ5hfpXxVE+NgkdNsjiDBByiImMZKKhxMwCbdHvhlENG6a833CbFkOQvTricw==", + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/@radix-ui/react-compose-refs/-/react-compose-refs-1.1.2.tgz", + "integrity": "sha512-z4eqJvfiNnFMHIIvXP3CY57y2WJs5g2v3X0zm9mEJkrkNv4rDxu+sg9Jh8EkXyeqBkB7SOcboo9dMVqhyrACIg==", "license": "MIT", "peerDependencies": { "@types/react": "*", @@ -2991,9 +3269,9 @@ } }, "node_modules/@radix-ui/react-context": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/@radix-ui/react-context/-/react-context-1.1.1.tgz", - "integrity": "sha512-UASk9zi+crv9WteK/NU4PLvOoL3OuE6BWVKNF6hPRBtYBDXQ2u5iu3O59zUlJiTVvkyuycnqrztsHVJwcK9K+Q==", + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/@radix-ui/react-context/-/react-context-1.1.2.tgz", + "integrity": "sha512-jCi/QKUM2r1Ju5a3J64TH2A5SpKAgh0LpknyqdQ4m6DCV0xJ2HG1xARRwNGPQfi1SLdLWZ1OJz6F4OMBBNiGJA==", "license": "MIT", "peerDependencies": { "@types/react": "*", @@ -3006,25 +3284,25 @@ } }, "node_modules/@radix-ui/react-dialog": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/@radix-ui/react-dialog/-/react-dialog-1.1.4.tgz", - "integrity": "sha512-Ur7EV1IwQGCyaAuyDRiOLA5JIUZxELJljF+MbM/2NC0BYwfuRrbpS30BiQBJrVruscgUkieKkqXYDOoByaxIoA==", + "version": "1.1.14", + "resolved": "https://registry.npmjs.org/@radix-ui/react-dialog/-/react-dialog-1.1.14.tgz", + "integrity": "sha512-+CpweKjqpzTmwRwcYECQcNYbI8V9VSQt0SNFKeEBLgfucbsLssU6Ppq7wUdNXEGb573bMjFhVjKVll8rmV6zMw==", "license": "MIT", "dependencies": { - "@radix-ui/primitive": "1.1.1", - "@radix-ui/react-compose-refs": "1.1.1", - "@radix-ui/react-context": "1.1.1", - "@radix-ui/react-dismissable-layer": "1.1.3", - "@radix-ui/react-focus-guards": "1.1.1", - "@radix-ui/react-focus-scope": "1.1.1", - "@radix-ui/react-id": "1.1.0", - "@radix-ui/react-portal": "1.1.3", - "@radix-ui/react-presence": "1.1.2", - "@radix-ui/react-primitive": "2.0.1", - "@radix-ui/react-slot": "1.1.1", - "@radix-ui/react-use-controllable-state": "1.1.0", - "aria-hidden": "^1.1.1", - "react-remove-scroll": "^2.6.1" + "@radix-ui/primitive": "1.1.2", + "@radix-ui/react-compose-refs": "1.1.2", + "@radix-ui/react-context": "1.1.2", + "@radix-ui/react-dismissable-layer": "1.1.10", + "@radix-ui/react-focus-guards": "1.1.2", + "@radix-ui/react-focus-scope": "1.1.7", + "@radix-ui/react-id": "1.1.1", + "@radix-ui/react-portal": "1.1.9", + "@radix-ui/react-presence": "1.1.4", + "@radix-ui/react-primitive": "2.1.3", + "@radix-ui/react-slot": "1.2.3", + "@radix-ui/react-use-controllable-state": "1.2.2", + "aria-hidden": "^1.2.4", + "react-remove-scroll": "^2.6.3" }, "peerDependencies": { "@types/react": "*", @@ -3042,9 +3320,9 @@ } }, "node_modules/@radix-ui/react-direction": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/@radix-ui/react-direction/-/react-direction-1.1.0.tgz", - "integrity": "sha512-BUuBvgThEiAXh2DWu93XsT+a3aWrGqolGlqqw5VU1kG7p/ZH2cuDlM1sRLNnY3QcBS69UIz2mcKhMxDsdewhjg==", + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/@radix-ui/react-direction/-/react-direction-1.1.1.tgz", + "integrity": "sha512-1UEWRX6jnOA2y4H5WczZ44gOOjTEmlqv1uNW4GAJEO5+bauCBhv8snY65Iw5/VOS/ghKN9gr2KjnLKxrsvoMVw==", "license": "MIT", "peerDependencies": { "@types/react": "*", @@ -3057,16 +3335,16 @@ } }, "node_modules/@radix-ui/react-dismissable-layer": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/@radix-ui/react-dismissable-layer/-/react-dismissable-layer-1.1.3.tgz", - "integrity": "sha512-onrWn/72lQoEucDmJnr8uczSNTujT0vJnA/X5+3AkChVPowr8n1yvIKIabhWyMQeMvvmdpsvcyDqx3X1LEXCPg==", + "version": "1.1.10", + "resolved": "https://registry.npmjs.org/@radix-ui/react-dismissable-layer/-/react-dismissable-layer-1.1.10.tgz", + "integrity": "sha512-IM1zzRV4W3HtVgftdQiiOmA0AdJlCtMLe00FXaHwgt3rAnNsIyDqshvkIW3hj/iu5hu8ERP7KIYki6NkqDxAwQ==", "license": "MIT", "dependencies": { - "@radix-ui/primitive": "1.1.1", - "@radix-ui/react-compose-refs": "1.1.1", - "@radix-ui/react-primitive": "2.0.1", - "@radix-ui/react-use-callback-ref": "1.1.0", - "@radix-ui/react-use-escape-keydown": "1.1.0" + "@radix-ui/primitive": "1.1.2", + "@radix-ui/react-compose-refs": "1.1.2", + "@radix-ui/react-primitive": "2.1.3", + "@radix-ui/react-use-callback-ref": "1.1.1", + "@radix-ui/react-use-escape-keydown": "1.1.1" }, "peerDependencies": { "@types/react": "*", @@ -3084,18 +3362,18 @@ } }, "node_modules/@radix-ui/react-dropdown-menu": { - "version": "2.1.4", - "resolved": "https://registry.npmjs.org/@radix-ui/react-dropdown-menu/-/react-dropdown-menu-2.1.4.tgz", - "integrity": "sha512-iXU1Ab5ecM+yEepGAWK8ZhMyKX4ubFdCNtol4sT9D0OVErG9PNElfx3TQhjw7n7BC5nFVz68/5//clWy+8TXzA==", + "version": "2.1.15", + "resolved": "https://registry.npmjs.org/@radix-ui/react-dropdown-menu/-/react-dropdown-menu-2.1.15.tgz", + "integrity": "sha512-mIBnOjgwo9AH3FyKaSWoSu/dYj6VdhJ7frEPiGTeXCdUFHjl9h3mFh2wwhEtINOmYXWhdpf1rY2minFsmaNgVQ==", "license": "MIT", "dependencies": { - "@radix-ui/primitive": "1.1.1", - "@radix-ui/react-compose-refs": "1.1.1", - "@radix-ui/react-context": "1.1.1", - "@radix-ui/react-id": "1.1.0", - "@radix-ui/react-menu": "2.1.4", - "@radix-ui/react-primitive": "2.0.1", - "@radix-ui/react-use-controllable-state": "1.1.0" + "@radix-ui/primitive": "1.1.2", + "@radix-ui/react-compose-refs": "1.1.2", + "@radix-ui/react-context": "1.1.2", + "@radix-ui/react-id": "1.1.1", + "@radix-ui/react-menu": "2.1.15", + "@radix-ui/react-primitive": "2.1.3", + "@radix-ui/react-use-controllable-state": "1.2.2" }, "peerDependencies": { "@types/react": "*", @@ -3113,9 +3391,9 @@ } }, "node_modules/@radix-ui/react-focus-guards": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/@radix-ui/react-focus-guards/-/react-focus-guards-1.1.1.tgz", - "integrity": "sha512-pSIwfrT1a6sIoDASCSpFwOasEwKTZWDw/iBdtnqKO7v6FeOzYJ7U53cPzYFVR3geGGXgVHaH+CdngrrAzqUGxg==", + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/@radix-ui/react-focus-guards/-/react-focus-guards-1.1.2.tgz", + "integrity": "sha512-fyjAACV62oPV925xFCrH8DR5xWhg9KYtJT4s3u54jxp+L/hbpTY2kIeEFFbFe+a/HCE94zGQMZLIpVTPVZDhaA==", "license": "MIT", "peerDependencies": { "@types/react": "*", @@ -3128,14 +3406,14 @@ } }, "node_modules/@radix-ui/react-focus-scope": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/@radix-ui/react-focus-scope/-/react-focus-scope-1.1.1.tgz", - "integrity": "sha512-01omzJAYRxXdG2/he/+xy+c8a8gCydoQ1yOxnWNcRhrrBW5W+RQJ22EK1SaO8tb3WoUsuEw7mJjBozPzihDFjA==", + "version": "1.1.7", + "resolved": "https://registry.npmjs.org/@radix-ui/react-focus-scope/-/react-focus-scope-1.1.7.tgz", + "integrity": "sha512-t2ODlkXBQyn7jkl6TNaw/MtVEVvIGelJDCG41Okq/KwUsJBwQ4XVZsHAVUkK4mBv3ewiAS3PGuUWuY2BoK4ZUw==", "license": "MIT", "dependencies": { - "@radix-ui/react-compose-refs": "1.1.1", - "@radix-ui/react-primitive": "2.0.1", - "@radix-ui/react-use-callback-ref": "1.1.0" + "@radix-ui/react-compose-refs": "1.1.2", + "@radix-ui/react-primitive": "2.1.3", + "@radix-ui/react-use-callback-ref": "1.1.1" }, "peerDependencies": { "@types/react": "*", @@ -3162,12 +3440,12 @@ } }, "node_modules/@radix-ui/react-id": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/@radix-ui/react-id/-/react-id-1.1.0.tgz", - "integrity": "sha512-EJUrI8yYh7WOjNOqpoJaf1jlFIH2LvtgAl+YcFqNCa+4hj64ZXmPkAKOFs/ukjz3byN6bdb/AVUqHkI8/uWWMA==", + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/@radix-ui/react-id/-/react-id-1.1.1.tgz", + "integrity": "sha512-kGkGegYIdQsOb4XjsfM97rXsiHaBwco+hFI66oO4s9LU+PLAC5oJ7khdOVFxkhsmlbpUqDAvXw11CluXP+jkHg==", "license": "MIT", "dependencies": { - "@radix-ui/react-use-layout-effect": "1.1.0" + "@radix-ui/react-use-layout-effect": "1.1.1" }, "peerDependencies": { "@types/react": "*", @@ -3180,12 +3458,12 @@ } }, "node_modules/@radix-ui/react-label": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/@radix-ui/react-label/-/react-label-2.1.1.tgz", - "integrity": "sha512-UUw5E4e/2+4kFMH7+YxORXGWggtY6sM8WIwh5RZchhLuUg2H1hc98Py+pr8HMz6rdaYrK2t296ZEjYLOCO5uUw==", + "version": "2.1.7", + "resolved": "https://registry.npmjs.org/@radix-ui/react-label/-/react-label-2.1.7.tgz", + "integrity": "sha512-YT1GqPSL8kJn20djelMX7/cTRp/Y9w5IZHvfxQTVHrOqa2yMl7i/UfMqKRU5V7mEyKTrUVgJXhNQPVCG8PBLoQ==", "license": "MIT", "dependencies": { - "@radix-ui/react-primitive": "2.0.1" + "@radix-ui/react-primitive": "2.1.3" }, "peerDependencies": { "@types/react": "*", @@ -3203,29 +3481,29 @@ } }, "node_modules/@radix-ui/react-menu": { - "version": "2.1.4", - "resolved": "https://registry.npmjs.org/@radix-ui/react-menu/-/react-menu-2.1.4.tgz", - "integrity": "sha512-BnOgVoL6YYdHAG6DtXONaR29Eq4nvbi8rutrV/xlr3RQCMMb3yqP85Qiw/3NReozrSW+4dfLkK+rc1hb4wPU/A==", + "version": "2.1.15", + "resolved": "https://registry.npmjs.org/@radix-ui/react-menu/-/react-menu-2.1.15.tgz", + "integrity": "sha512-tVlmA3Vb9n8SZSd+YSbuFR66l87Wiy4du+YE+0hzKQEANA+7cWKH1WgqcEX4pXqxUFQKrWQGHdvEfw00TjFiew==", "license": "MIT", "dependencies": { - "@radix-ui/primitive": "1.1.1", - "@radix-ui/react-collection": "1.1.1", - "@radix-ui/react-compose-refs": "1.1.1", - "@radix-ui/react-context": "1.1.1", - "@radix-ui/react-direction": "1.1.0", - "@radix-ui/react-dismissable-layer": "1.1.3", - "@radix-ui/react-focus-guards": "1.1.1", - "@radix-ui/react-focus-scope": "1.1.1", - "@radix-ui/react-id": "1.1.0", - "@radix-ui/react-popper": "1.2.1", - "@radix-ui/react-portal": "1.1.3", - "@radix-ui/react-presence": "1.1.2", - "@radix-ui/react-primitive": "2.0.1", - "@radix-ui/react-roving-focus": "1.1.1", - "@radix-ui/react-slot": "1.1.1", - "@radix-ui/react-use-callback-ref": "1.1.0", - "aria-hidden": "^1.1.1", - "react-remove-scroll": "^2.6.1" + "@radix-ui/primitive": "1.1.2", + "@radix-ui/react-collection": "1.1.7", + "@radix-ui/react-compose-refs": "1.1.2", + "@radix-ui/react-context": "1.1.2", + "@radix-ui/react-direction": "1.1.1", + "@radix-ui/react-dismissable-layer": "1.1.10", + "@radix-ui/react-focus-guards": "1.1.2", + "@radix-ui/react-focus-scope": "1.1.7", + "@radix-ui/react-id": "1.1.1", + "@radix-ui/react-popper": "1.2.7", + "@radix-ui/react-portal": "1.1.9", + "@radix-ui/react-presence": "1.1.4", + "@radix-ui/react-primitive": "2.1.3", + "@radix-ui/react-roving-focus": "1.1.10", + "@radix-ui/react-slot": "1.2.3", + "@radix-ui/react-use-callback-ref": "1.1.1", + "aria-hidden": "^1.2.4", + "react-remove-scroll": "^2.6.3" }, "peerDependencies": { "@types/react": "*", @@ -3243,26 +3521,26 @@ } }, "node_modules/@radix-ui/react-popover": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/@radix-ui/react-popover/-/react-popover-1.1.4.tgz", - "integrity": "sha512-aUACAkXx8LaFymDma+HQVji7WhvEhpFJ7+qPz17Nf4lLZqtreGOFRiNQWQmhzp7kEWg9cOyyQJpdIMUMPc/CPw==", + "version": "1.1.14", + "resolved": "https://registry.npmjs.org/@radix-ui/react-popover/-/react-popover-1.1.14.tgz", + "integrity": "sha512-ODz16+1iIbGUfFEfKx2HTPKizg2MN39uIOV8MXeHnmdd3i/N9Wt7vU46wbHsqA0xoaQyXVcs0KIlBdOA2Y95bw==", "license": "MIT", "dependencies": { - "@radix-ui/primitive": "1.1.1", - "@radix-ui/react-compose-refs": "1.1.1", - "@radix-ui/react-context": "1.1.1", - "@radix-ui/react-dismissable-layer": "1.1.3", - "@radix-ui/react-focus-guards": "1.1.1", - "@radix-ui/react-focus-scope": "1.1.1", - "@radix-ui/react-id": "1.1.0", - "@radix-ui/react-popper": "1.2.1", - "@radix-ui/react-portal": "1.1.3", - "@radix-ui/react-presence": "1.1.2", - "@radix-ui/react-primitive": "2.0.1", - "@radix-ui/react-slot": "1.1.1", - "@radix-ui/react-use-controllable-state": "1.1.0", - "aria-hidden": "^1.1.1", - "react-remove-scroll": "^2.6.1" + "@radix-ui/primitive": "1.1.2", + "@radix-ui/react-compose-refs": "1.1.2", + "@radix-ui/react-context": "1.1.2", + "@radix-ui/react-dismissable-layer": "1.1.10", + "@radix-ui/react-focus-guards": "1.1.2", + "@radix-ui/react-focus-scope": "1.1.7", + "@radix-ui/react-id": "1.1.1", + "@radix-ui/react-popper": "1.2.7", + "@radix-ui/react-portal": "1.1.9", + "@radix-ui/react-presence": "1.1.4", + "@radix-ui/react-primitive": "2.1.3", + "@radix-ui/react-slot": "1.2.3", + "@radix-ui/react-use-controllable-state": "1.2.2", + "aria-hidden": "^1.2.4", + "react-remove-scroll": "^2.6.3" }, "peerDependencies": { "@types/react": "*", @@ -3280,21 +3558,21 @@ } }, "node_modules/@radix-ui/react-popper": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/@radix-ui/react-popper/-/react-popper-1.2.1.tgz", - "integrity": "sha512-3kn5Me69L+jv82EKRuQCXdYyf1DqHwD2U/sxoNgBGCB7K9TRc3bQamQ+5EPM9EvyPdli0W41sROd+ZU1dTCztw==", + "version": "1.2.7", + "resolved": "https://registry.npmjs.org/@radix-ui/react-popper/-/react-popper-1.2.7.tgz", + "integrity": "sha512-IUFAccz1JyKcf/RjB552PlWwxjeCJB8/4KxT7EhBHOJM+mN7LdW+B3kacJXILm32xawcMMjb2i0cIZpo+f9kiQ==", "license": "MIT", "dependencies": { "@floating-ui/react-dom": "^2.0.0", - "@radix-ui/react-arrow": "1.1.1", - "@radix-ui/react-compose-refs": "1.1.1", - "@radix-ui/react-context": "1.1.1", - "@radix-ui/react-primitive": "2.0.1", - "@radix-ui/react-use-callback-ref": "1.1.0", - "@radix-ui/react-use-layout-effect": "1.1.0", - "@radix-ui/react-use-rect": "1.1.0", - "@radix-ui/react-use-size": "1.1.0", - "@radix-ui/rect": "1.1.0" + "@radix-ui/react-arrow": "1.1.7", + "@radix-ui/react-compose-refs": "1.1.2", + "@radix-ui/react-context": "1.1.2", + "@radix-ui/react-primitive": "2.1.3", + "@radix-ui/react-use-callback-ref": "1.1.1", + "@radix-ui/react-use-layout-effect": "1.1.1", + "@radix-ui/react-use-rect": "1.1.1", + "@radix-ui/react-use-size": "1.1.1", + "@radix-ui/rect": "1.1.1" }, "peerDependencies": { "@types/react": "*", @@ -3312,13 +3590,13 @@ } }, "node_modules/@radix-ui/react-portal": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/@radix-ui/react-portal/-/react-portal-1.1.3.tgz", - "integrity": "sha512-NciRqhXnGojhT93RPyDaMPfLH3ZSl4jjIFbZQ1b/vxvZEdHsBZ49wP9w8L3HzUQwep01LcWtkUvm0OVB5JAHTw==", + "version": "1.1.9", + "resolved": "https://registry.npmjs.org/@radix-ui/react-portal/-/react-portal-1.1.9.tgz", + "integrity": "sha512-bpIxvq03if6UNwXZ+HTK71JLh4APvnXntDc6XOX8UVq4XQOVl7lwok0AvIl+b8zgCw3fSaVTZMpAPPagXbKmHQ==", "license": "MIT", "dependencies": { - "@radix-ui/react-primitive": "2.0.1", - "@radix-ui/react-use-layout-effect": "1.1.0" + "@radix-ui/react-primitive": "2.1.3", + "@radix-ui/react-use-layout-effect": "1.1.1" }, "peerDependencies": { "@types/react": "*", @@ -3336,13 +3614,13 @@ } }, "node_modules/@radix-ui/react-presence": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/@radix-ui/react-presence/-/react-presence-1.1.2.tgz", - "integrity": "sha512-18TFr80t5EVgL9x1SwF/YGtfG+l0BS0PRAlCWBDoBEiDQjeKgnNZRVJp/oVBl24sr3Gbfwc/Qpj4OcWTQMsAEg==", + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/@radix-ui/react-presence/-/react-presence-1.1.4.tgz", + "integrity": "sha512-ueDqRbdc4/bkaQT3GIpLQssRlFgWaL/U2z/S31qRwwLWoxHLgry3SIfCwhxeQNbirEUXFa+lq3RL3oBYXtcmIA==", "license": "MIT", "dependencies": { - "@radix-ui/react-compose-refs": "1.1.1", - "@radix-ui/react-use-layout-effect": "1.1.0" + "@radix-ui/react-compose-refs": "1.1.2", + "@radix-ui/react-use-layout-effect": "1.1.1" }, "peerDependencies": { "@types/react": "*", @@ -3360,12 +3638,12 @@ } }, "node_modules/@radix-ui/react-primitive": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/@radix-ui/react-primitive/-/react-primitive-2.0.1.tgz", - "integrity": "sha512-sHCWTtxwNn3L3fH8qAfnF3WbUZycW93SM1j3NFDzXBiz8D6F5UTTy8G1+WFEaiCdvCVRJWj6N2R4Xq6HdiHmDg==", + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/@radix-ui/react-primitive/-/react-primitive-2.1.3.tgz", + "integrity": "sha512-m9gTwRkhy2lvCPe6QJp4d3G1TYEUHn/FzJUtq9MjH46an1wJU+GdoGC5VLof8RX8Ft/DlpshApkhswDLZzHIcQ==", "license": "MIT", "dependencies": { - "@radix-ui/react-slot": "1.1.1" + "@radix-ui/react-slot": "1.2.3" }, "peerDependencies": { "@types/react": "*", @@ -3383,6 +3661,7 @@ } }, "node_modules/@radix-ui/react-progress": { +<<<<<<< HEAD "version": "1.1.6", "resolved": "https://registry.npmjs.org/@radix-ui/react-progress/-/react-progress-1.1.6.tgz", "integrity": "sha512-QzN9a36nKk2eZKMf9EBCia35x3TT+SOgZuzQBVIHyRrmYYi73VYBRK3zKwdJ6az/F5IZ6QlacGJBg7zfB85liA==", @@ -3390,6 +3669,15 @@ "dependencies": { "@radix-ui/react-context": "1.1.2", "@radix-ui/react-primitive": "2.1.2" +======= + "version": "1.1.7", + "resolved": "https://registry.npmjs.org/@radix-ui/react-progress/-/react-progress-1.1.7.tgz", + "integrity": "sha512-vPdg/tF6YC/ynuBIJlk1mm7Le0VgW6ub6J2UWnTQ7/D23KXcPI1qy+0vBkgKgd38RCMJavBXpB83HPNFMTb0Fg==", + "license": "MIT", + "dependencies": { + "@radix-ui/react-context": "1.1.2", + "@radix-ui/react-primitive": "2.1.3" +>>>>>>> dev }, "peerDependencies": { "@types/react": "*", @@ -3406,6 +3694,7 @@ } } }, +<<<<<<< HEAD "node_modules/@radix-ui/react-progress/node_modules/@radix-ui/react-compose-refs": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/@radix-ui/react-compose-refs/-/react-compose-refs-1.1.2.tgz", @@ -3477,22 +3766,24 @@ } } }, +======= +>>>>>>> dev "node_modules/@radix-ui/react-radio-group": { - "version": "1.2.2", - "resolved": "https://registry.npmjs.org/@radix-ui/react-radio-group/-/react-radio-group-1.2.2.tgz", - "integrity": "sha512-E0MLLGfOP0l8P/NxgVzfXJ8w3Ch8cdO6UDzJfDChu4EJDy+/WdO5LqpdY8PYnCErkmZH3gZhDL1K7kQ41fAHuQ==", + "version": "1.3.7", + "resolved": "https://registry.npmjs.org/@radix-ui/react-radio-group/-/react-radio-group-1.3.7.tgz", + "integrity": "sha512-9w5XhD0KPOrm92OTTE0SysH3sYzHsSTHNvZgUBo/VZ80VdYyB5RneDbc0dKpURS24IxkoFRu/hI0i4XyfFwY6g==", "license": "MIT", "dependencies": { - "@radix-ui/primitive": "1.1.1", - "@radix-ui/react-compose-refs": "1.1.1", - "@radix-ui/react-context": "1.1.1", - "@radix-ui/react-direction": "1.1.0", - "@radix-ui/react-presence": "1.1.2", - "@radix-ui/react-primitive": "2.0.1", - "@radix-ui/react-roving-focus": "1.1.1", - "@radix-ui/react-use-controllable-state": "1.1.0", - "@radix-ui/react-use-previous": "1.1.0", - "@radix-ui/react-use-size": "1.1.0" + "@radix-ui/primitive": "1.1.2", + "@radix-ui/react-compose-refs": "1.1.2", + "@radix-ui/react-context": "1.1.2", + "@radix-ui/react-direction": "1.1.1", + "@radix-ui/react-presence": "1.1.4", + "@radix-ui/react-primitive": "2.1.3", + "@radix-ui/react-roving-focus": "1.1.10", + "@radix-ui/react-use-controllable-state": "1.2.2", + "@radix-ui/react-use-previous": "1.1.1", + "@radix-ui/react-use-size": "1.1.1" }, "peerDependencies": { "@types/react": "*", @@ -3510,20 +3801,51 @@ } }, "node_modules/@radix-ui/react-roving-focus": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/@radix-ui/react-roving-focus/-/react-roving-focus-1.1.1.tgz", - "integrity": "sha512-QE1RoxPGJ/Nm8Qmk0PxP8ojmoaS67i0s7hVssS7KuI2FQoc/uzVlZsqKfQvxPE6D8hICCPHJ4D88zNhT3OOmkw==", + "version": "1.1.10", + "resolved": "https://registry.npmjs.org/@radix-ui/react-roving-focus/-/react-roving-focus-1.1.10.tgz", + "integrity": "sha512-dT9aOXUen9JSsxnMPv/0VqySQf5eDQ6LCk5Sw28kamz8wSOW2bJdlX2Bg5VUIIcV+6XlHpWTIuTPCf/UNIyq8Q==", "license": "MIT", "dependencies": { - "@radix-ui/primitive": "1.1.1", - "@radix-ui/react-collection": "1.1.1", - "@radix-ui/react-compose-refs": "1.1.1", - "@radix-ui/react-context": "1.1.1", - "@radix-ui/react-direction": "1.1.0", - "@radix-ui/react-id": "1.1.0", - "@radix-ui/react-primitive": "2.0.1", - "@radix-ui/react-use-callback-ref": "1.1.0", - "@radix-ui/react-use-controllable-state": "1.1.0" + "@radix-ui/primitive": "1.1.2", + "@radix-ui/react-collection": "1.1.7", + "@radix-ui/react-compose-refs": "1.1.2", + "@radix-ui/react-context": "1.1.2", + "@radix-ui/react-direction": "1.1.1", + "@radix-ui/react-id": "1.1.1", + "@radix-ui/react-primitive": "2.1.3", + "@radix-ui/react-use-callback-ref": "1.1.1", + "@radix-ui/react-use-controllable-state": "1.2.2" + }, + "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 + } + } + }, + "node_modules/@radix-ui/react-scroll-area": { + "version": "1.2.9", + "resolved": "https://registry.npmjs.org/@radix-ui/react-scroll-area/-/react-scroll-area-1.2.9.tgz", + "integrity": "sha512-YSjEfBXnhUELsO2VzjdtYYD4CfQjvao+lhhrX5XsHD7/cyUNzljF1FHEbgTPN7LH2MClfwRMIsYlqTYpKTTe2A==", + "license": "MIT", + "dependencies": { + "@radix-ui/number": "1.1.1", + "@radix-ui/primitive": "1.1.2", + "@radix-ui/react-compose-refs": "1.1.2", + "@radix-ui/react-context": "1.1.2", + "@radix-ui/react-direction": "1.1.1", + "@radix-ui/react-presence": "1.1.4", + "@radix-ui/react-primitive": "2.1.3", + "@radix-ui/react-use-callback-ref": "1.1.1", + "@radix-ui/react-use-layout-effect": "1.1.1" }, "peerDependencies": { "@types/react": "*", @@ -3613,32 +3935,32 @@ } }, "node_modules/@radix-ui/react-select": { - "version": "2.1.4", - "resolved": "https://registry.npmjs.org/@radix-ui/react-select/-/react-select-2.1.4.tgz", - "integrity": "sha512-pOkb2u8KgO47j/h7AylCj7dJsm69BXcjkrvTqMptFqsE2i0p8lHkfgneXKjAgPzBMivnoMyt8o4KiV4wYzDdyQ==", + "version": "2.2.5", + "resolved": "https://registry.npmjs.org/@radix-ui/react-select/-/react-select-2.2.5.tgz", + "integrity": "sha512-HnMTdXEVuuyzx63ME0ut4+sEMYW6oouHWNGUZc7ddvUWIcfCva/AMoqEW/3wnEllriMWBa0RHspCYnfCWJQYmA==", "license": "MIT", "dependencies": { - "@radix-ui/number": "1.1.0", - "@radix-ui/primitive": "1.1.1", - "@radix-ui/react-collection": "1.1.1", - "@radix-ui/react-compose-refs": "1.1.1", - "@radix-ui/react-context": "1.1.1", - "@radix-ui/react-direction": "1.1.0", - "@radix-ui/react-dismissable-layer": "1.1.3", - "@radix-ui/react-focus-guards": "1.1.1", - "@radix-ui/react-focus-scope": "1.1.1", - "@radix-ui/react-id": "1.1.0", - "@radix-ui/react-popper": "1.2.1", - "@radix-ui/react-portal": "1.1.3", - "@radix-ui/react-primitive": "2.0.1", - "@radix-ui/react-slot": "1.1.1", - "@radix-ui/react-use-callback-ref": "1.1.0", - "@radix-ui/react-use-controllable-state": "1.1.0", - "@radix-ui/react-use-layout-effect": "1.1.0", - "@radix-ui/react-use-previous": "1.1.0", - "@radix-ui/react-visually-hidden": "1.1.1", - "aria-hidden": "^1.1.1", - "react-remove-scroll": "^2.6.1" + "@radix-ui/number": "1.1.1", + "@radix-ui/primitive": "1.1.2", + "@radix-ui/react-collection": "1.1.7", + "@radix-ui/react-compose-refs": "1.1.2", + "@radix-ui/react-context": "1.1.2", + "@radix-ui/react-direction": "1.1.1", + "@radix-ui/react-dismissable-layer": "1.1.10", + "@radix-ui/react-focus-guards": "1.1.2", + "@radix-ui/react-focus-scope": "1.1.7", + "@radix-ui/react-id": "1.1.1", + "@radix-ui/react-popper": "1.2.7", + "@radix-ui/react-portal": "1.1.9", + "@radix-ui/react-primitive": "2.1.3", + "@radix-ui/react-slot": "1.2.3", + "@radix-ui/react-use-callback-ref": "1.1.1", + "@radix-ui/react-use-controllable-state": "1.2.2", + "@radix-ui/react-use-layout-effect": "1.1.1", + "@radix-ui/react-use-previous": "1.1.1", + "@radix-ui/react-visually-hidden": "1.2.3", + "aria-hidden": "^1.2.4", + "react-remove-scroll": "^2.6.3" }, "peerDependencies": { "@types/react": "*", @@ -3656,12 +3978,12 @@ } }, "node_modules/@radix-ui/react-separator": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/@radix-ui/react-separator/-/react-separator-1.1.1.tgz", - "integrity": "sha512-RRiNRSrD8iUiXriq/Y5n4/3iE8HzqgLHsusUSg5jVpU2+3tqcUFPJXHDymwEypunc2sWxDUS3UC+rkZRlHedsw==", + "version": "1.1.7", + "resolved": "https://registry.npmjs.org/@radix-ui/react-separator/-/react-separator-1.1.7.tgz", + "integrity": "sha512-0HEb8R9E8A+jZjvmFCy/J4xhbXy3TV+9XSnGJ3KvTtjlIUy/YQ/p6UYZvi7YbeoeXdyU9+Y3scizK6hkY37baA==", "license": "MIT", "dependencies": { - "@radix-ui/react-primitive": "2.0.1" + "@radix-ui/react-primitive": "2.1.3" }, "peerDependencies": { "@types/react": "*", @@ -3679,12 +4001,12 @@ } }, "node_modules/@radix-ui/react-slot": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/@radix-ui/react-slot/-/react-slot-1.1.1.tgz", - "integrity": "sha512-RApLLOcINYJA+dMVbOju7MYv1Mb2EBp2nH4HdDzXTSyaR5optlm6Otrz1euW3HbdOR8UmmFK06TD+A9frYWv+g==", + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/@radix-ui/react-slot/-/react-slot-1.2.3.tgz", + "integrity": "sha512-aeNmHnBxbi2St0au6VBVC7JXFlhLlOnvIIlePNniyUNAClzmtAUEY8/pBiK3iHjufOlwA+c20/8jngo7xcrg8A==", "license": "MIT", "dependencies": { - "@radix-ui/react-compose-refs": "1.1.1" + "@radix-ui/react-compose-refs": "1.1.2" }, "peerDependencies": { "@types/react": "*", @@ -3697,18 +4019,18 @@ } }, "node_modules/@radix-ui/react-switch": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/@radix-ui/react-switch/-/react-switch-1.1.2.tgz", - "integrity": "sha512-zGukiWHjEdBCRyXvKR6iXAQG6qXm2esuAD6kDOi9Cn+1X6ev3ASo4+CsYaD6Fov9r/AQFekqnD/7+V0Cs6/98g==", + "version": "1.2.5", + "resolved": "https://registry.npmjs.org/@radix-ui/react-switch/-/react-switch-1.2.5.tgz", + "integrity": "sha512-5ijLkak6ZMylXsaImpZ8u4Rlf5grRmoc0p0QeX9VJtlrM4f5m3nCTX8tWga/zOA8PZYIR/t0p2Mnvd7InrJ6yQ==", "license": "MIT", "dependencies": { - "@radix-ui/primitive": "1.1.1", - "@radix-ui/react-compose-refs": "1.1.1", - "@radix-ui/react-context": "1.1.1", - "@radix-ui/react-primitive": "2.0.1", - "@radix-ui/react-use-controllable-state": "1.1.0", - "@radix-ui/react-use-previous": "1.1.0", - "@radix-ui/react-use-size": "1.1.0" + "@radix-ui/primitive": "1.1.2", + "@radix-ui/react-compose-refs": "1.1.2", + "@radix-ui/react-context": "1.1.2", + "@radix-ui/react-primitive": "2.1.3", + "@radix-ui/react-use-controllable-state": "1.2.2", + "@radix-ui/react-use-previous": "1.1.1", + "@radix-ui/react-use-size": "1.1.1" }, "peerDependencies": { "@types/react": "*", @@ -3726,19 +4048,19 @@ } }, "node_modules/@radix-ui/react-tabs": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/@radix-ui/react-tabs/-/react-tabs-1.1.2.tgz", - "integrity": "sha512-9u/tQJMcC2aGq7KXpGivMm1mgq7oRJKXphDwdypPd/j21j/2znamPU8WkXgnhUaTrSFNIt8XhOyCAupg8/GbwQ==", + "version": "1.1.12", + "resolved": "https://registry.npmjs.org/@radix-ui/react-tabs/-/react-tabs-1.1.12.tgz", + "integrity": "sha512-GTVAlRVrQrSw3cEARM0nAx73ixrWDPNZAruETn3oHCNP6SbZ/hNxdxp+u7VkIEv3/sFoLq1PfcHrl7Pnp0CDpw==", "license": "MIT", "dependencies": { - "@radix-ui/primitive": "1.1.1", - "@radix-ui/react-context": "1.1.1", - "@radix-ui/react-direction": "1.1.0", - "@radix-ui/react-id": "1.1.0", - "@radix-ui/react-presence": "1.1.2", - "@radix-ui/react-primitive": "2.0.1", - "@radix-ui/react-roving-focus": "1.1.1", - "@radix-ui/react-use-controllable-state": "1.1.0" + "@radix-ui/primitive": "1.1.2", + "@radix-ui/react-context": "1.1.2", + "@radix-ui/react-direction": "1.1.1", + "@radix-ui/react-id": "1.1.1", + "@radix-ui/react-presence": "1.1.4", + "@radix-ui/react-primitive": "2.1.3", + "@radix-ui/react-roving-focus": "1.1.10", + "@radix-ui/react-use-controllable-state": "1.2.2" }, "peerDependencies": { "@types/react": "*", @@ -3756,23 +4078,23 @@ } }, "node_modules/@radix-ui/react-toast": { - "version": "1.2.4", - "resolved": "https://registry.npmjs.org/@radix-ui/react-toast/-/react-toast-1.2.4.tgz", - "integrity": "sha512-Sch9idFJHJTMH9YNpxxESqABcAFweJG4tKv+0zo0m5XBvUSL8FM5xKcJLFLXononpePs8IclyX1KieL5SDUNgA==", + "version": "1.2.14", + "resolved": "https://registry.npmjs.org/@radix-ui/react-toast/-/react-toast-1.2.14.tgz", + "integrity": "sha512-nAP5FBxBJGQ/YfUB+r+O6USFVkWq3gAInkxyEnmvEV5jtSbfDhfa4hwX8CraCnbjMLsE7XSf/K75l9xXY7joWg==", "license": "MIT", "dependencies": { - "@radix-ui/primitive": "1.1.1", - "@radix-ui/react-collection": "1.1.1", - "@radix-ui/react-compose-refs": "1.1.1", - "@radix-ui/react-context": "1.1.1", - "@radix-ui/react-dismissable-layer": "1.1.3", - "@radix-ui/react-portal": "1.1.3", - "@radix-ui/react-presence": "1.1.2", - "@radix-ui/react-primitive": "2.0.1", - "@radix-ui/react-use-callback-ref": "1.1.0", - "@radix-ui/react-use-controllable-state": "1.1.0", - "@radix-ui/react-use-layout-effect": "1.1.0", - "@radix-ui/react-visually-hidden": "1.1.1" + "@radix-ui/primitive": "1.1.2", + "@radix-ui/react-collection": "1.1.7", + "@radix-ui/react-compose-refs": "1.1.2", + "@radix-ui/react-context": "1.1.2", + "@radix-ui/react-dismissable-layer": "1.1.10", + "@radix-ui/react-portal": "1.1.9", + "@radix-ui/react-presence": "1.1.4", + "@radix-ui/react-primitive": "2.1.3", + "@radix-ui/react-use-callback-ref": "1.1.1", + "@radix-ui/react-use-controllable-state": "1.2.2", + "@radix-ui/react-use-layout-effect": "1.1.1", + "@radix-ui/react-visually-hidden": "1.2.3" }, "peerDependencies": { "@types/react": "*", @@ -3790,9 +4112,9 @@ } }, "node_modules/@radix-ui/react-use-callback-ref": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/@radix-ui/react-use-callback-ref/-/react-use-callback-ref-1.1.0.tgz", - "integrity": "sha512-CasTfvsy+frcFkbXtSJ2Zu9JHpN8TYKxkgJGWbjiZhFivxaeW7rMeZt7QELGVLaYVfFMsKHjb7Ak0nMEe+2Vfw==", + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/@radix-ui/react-use-callback-ref/-/react-use-callback-ref-1.1.1.tgz", + "integrity": "sha512-FkBMwD+qbGQeMu1cOHnuGB6x4yzPjho8ap5WtbEJ26umhgqVXbhekKUQO+hZEL1vU92a3wHwdp0HAcqAUF5iDg==", "license": "MIT", "peerDependencies": { "@types/react": "*", @@ -3805,12 +4127,31 @@ } }, "node_modules/@radix-ui/react-use-controllable-state": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/@radix-ui/react-use-controllable-state/-/react-use-controllable-state-1.1.0.tgz", - "integrity": "sha512-MtfMVJiSr2NjzS0Aa90NPTnvTSg6C/JLCV7ma0W6+OMV78vd8OyRpID+Ng9LxzsPbLeuBnWBA1Nq30AtBIDChw==", + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/@radix-ui/react-use-controllable-state/-/react-use-controllable-state-1.2.2.tgz", + "integrity": "sha512-BjasUjixPFdS+NKkypcyyN5Pmg83Olst0+c6vGov0diwTEo6mgdqVR6hxcEgFuh4QrAs7Rc+9KuGJ9TVCj0Zzg==", "license": "MIT", "dependencies": { - "@radix-ui/react-use-callback-ref": "1.1.0" + "@radix-ui/react-use-effect-event": "0.0.2", + "@radix-ui/react-use-layout-effect": "1.1.1" + }, + "peerDependencies": { + "@types/react": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-use-effect-event": { + "version": "0.0.2", + "resolved": "https://registry.npmjs.org/@radix-ui/react-use-effect-event/-/react-use-effect-event-0.0.2.tgz", + "integrity": "sha512-Qp8WbZOBe+blgpuUT+lw2xheLP8q0oatc9UpmiemEICxGvFLYmHm9QowVZGHtJlGbS6A6yJ3iViad/2cVjnOiA==", + "license": "MIT", + "dependencies": { + "@radix-ui/react-use-layout-effect": "1.1.1" }, "peerDependencies": { "@types/react": "*", @@ -3823,12 +4164,30 @@ } }, "node_modules/@radix-ui/react-use-escape-keydown": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/@radix-ui/react-use-escape-keydown/-/react-use-escape-keydown-1.1.0.tgz", - "integrity": "sha512-L7vwWlR1kTTQ3oh7g1O0CBF3YCyyTj8NmhLR+phShpyA50HCfBFKVJTpshm9PzLiKmehsrQzTYTpX9HvmC9rhw==", + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/@radix-ui/react-use-escape-keydown/-/react-use-escape-keydown-1.1.1.tgz", + "integrity": "sha512-Il0+boE7w/XebUHyBjroE+DbByORGR9KKmITzbR7MyQ4akpORYP/ZmbhAr0DG7RmmBqoOnZdy2QlvajJ2QA59g==", "license": "MIT", "dependencies": { - "@radix-ui/react-use-callback-ref": "1.1.0" + "@radix-ui/react-use-callback-ref": "1.1.1" + }, + "peerDependencies": { + "@types/react": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-use-is-hydrated": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/@radix-ui/react-use-is-hydrated/-/react-use-is-hydrated-0.1.0.tgz", + "integrity": "sha512-U+UORVEq+cTnRIaostJv9AGdV3G6Y+zbVd+12e18jQ5A3c0xL03IhnHuiU4UV69wolOQp5GfR58NW/EgdQhwOA==", + "license": "MIT", + "dependencies": { + "use-sync-external-store": "^1.5.0" }, "peerDependencies": { "@types/react": "*", @@ -3841,9 +4200,9 @@ } }, "node_modules/@radix-ui/react-use-layout-effect": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/@radix-ui/react-use-layout-effect/-/react-use-layout-effect-1.1.0.tgz", - "integrity": "sha512-+FPE0rOdziWSrH9athwI1R0HDVbWlEhd+FR+aSDk4uWGmSJ9Z54sdZVDQPZAinJhJXwfT+qnj969mCsT2gfm5w==", + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/@radix-ui/react-use-layout-effect/-/react-use-layout-effect-1.1.1.tgz", + "integrity": "sha512-RbJRS4UWQFkzHTTwVymMTUv8EqYhOp8dOOviLj2ugtTiXRaRQS7GLGxZTLL1jWhMeoSCf5zmcZkqTl9IiYfXcQ==", "license": "MIT", "peerDependencies": { "@types/react": "*", @@ -3856,9 +4215,9 @@ } }, "node_modules/@radix-ui/react-use-previous": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/@radix-ui/react-use-previous/-/react-use-previous-1.1.0.tgz", - "integrity": "sha512-Z/e78qg2YFnnXcW88A4JmTtm4ADckLno6F7OXotmkQfeuCVaKuYzqAATPhVzl3delXE7CxIV8shofPn3jPc5Og==", + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/@radix-ui/react-use-previous/-/react-use-previous-1.1.1.tgz", + "integrity": "sha512-2dHfToCj/pzca2Ck724OZ5L0EVrr3eHRNsG/b3xQJLA2hZpVCS99bLAX+hm1IHXDEnzU6by5z/5MIY794/a8NQ==", "license": "MIT", "peerDependencies": { "@types/react": "*", @@ -3871,12 +4230,12 @@ } }, "node_modules/@radix-ui/react-use-rect": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/@radix-ui/react-use-rect/-/react-use-rect-1.1.0.tgz", - "integrity": "sha512-0Fmkebhr6PiseyZlYAOtLS+nb7jLmpqTrJyv61Pe68MKYW6OWdRE2kI70TaYY27u7H0lajqM3hSMMLFq18Z7nQ==", + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/@radix-ui/react-use-rect/-/react-use-rect-1.1.1.tgz", + "integrity": "sha512-QTYuDesS0VtuHNNvMh+CjlKJ4LJickCMUAqjlE3+j8w+RlRpwyX3apEQKGFzbZGdo7XNG1tXa+bQqIE7HIXT2w==", "license": "MIT", "dependencies": { - "@radix-ui/rect": "1.1.0" + "@radix-ui/rect": "1.1.1" }, "peerDependencies": { "@types/react": "*", @@ -3889,12 +4248,12 @@ } }, "node_modules/@radix-ui/react-use-size": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/@radix-ui/react-use-size/-/react-use-size-1.1.0.tgz", - "integrity": "sha512-XW3/vWuIXHa+2Uwcc2ABSfcCledmXhhQPlGbfcRXbiUQI5Icjcg19BGCZVKKInYbvUCut/ufbbLLPFC5cbb1hw==", + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/@radix-ui/react-use-size/-/react-use-size-1.1.1.tgz", + "integrity": "sha512-ewrXRDTAqAXlkl6t/fkXWNAhFX9I+CkKlw6zjEwk86RSPKwZr3xpBRso655aqYafwtnbpHLj6toFzmd6xdVptQ==", "license": "MIT", "dependencies": { - "@radix-ui/react-use-layout-effect": "1.1.0" + "@radix-ui/react-use-layout-effect": "1.1.1" }, "peerDependencies": { "@types/react": "*", @@ -3907,12 +4266,12 @@ } }, "node_modules/@radix-ui/react-visually-hidden": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/@radix-ui/react-visually-hidden/-/react-visually-hidden-1.1.1.tgz", - "integrity": "sha512-vVfA2IZ9q/J+gEamvj761Oq1FpWgCDaNOOIfbPVp2MVPLEomUr5+Vf7kJGwQ24YxZSlQVar7Bes8kyTo5Dshpg==", + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/@radix-ui/react-visually-hidden/-/react-visually-hidden-1.2.3.tgz", + "integrity": "sha512-pzJq12tEaaIhqjbzpCuv/OypJY/BPavOofm+dbab+MHLajy277+1lLm6JFcGgF5eskJ6mquGirhXY2GD/8u8Ug==", "license": "MIT", "dependencies": { - "@radix-ui/react-primitive": "2.0.1" + "@radix-ui/react-primitive": "2.1.3" }, "peerDependencies": { "@types/react": "*", @@ -3930,9 +4289,9 @@ } }, "node_modules/@radix-ui/rect": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/@radix-ui/rect/-/rect-1.1.0.tgz", - "integrity": "sha512-A9+lCBZoaMJlVKcRBz2YByCG+Cp2t6nAnMnNba+XiWxnj6r4JUFqfsgwocMBZU9LPtdxC6wB56ySYpc7LQIoJg==", + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/@radix-ui/rect/-/rect-1.1.1.tgz", + "integrity": "sha512-HPwpGIzkl28mWyZqG52jiqDJ12waP11Pa1lGoiyUkIEuMLBP0oeK/C89esbXrxsky5we7dfd8U58nm0SgAWpVw==", "license": "MIT" }, "node_modules/@react-email/body": { @@ -3957,12 +4316,12 @@ } }, "node_modules/@react-email/code-block": { - "version": "0.0.12", - "resolved": "https://registry.npmjs.org/@react-email/code-block/-/code-block-0.0.12.tgz", - "integrity": "sha512-Faw3Ij9+/Qwq6moWaeHnV8Hn7ekc/EqyAzPi6yUar21dhcqYugCC4Da1x4d9nA9zC0H9KU3lYVJczh8D3cA+Eg==", + "version": "0.0.13", + "resolved": "https://registry.npmjs.org/@react-email/code-block/-/code-block-0.0.13.tgz", + "integrity": "sha512-4DE4yPSgKEOnZMzcrDvRuD6mxsNxOex0hCYEG9F9q23geYgb2WCCeGBvIUXVzK69l703Dg4Vzrd5qUjl+JfcwA==", "license": "MIT", "dependencies": { - "prismjs": "1.30.0" + "prismjs": "^1.30.0" }, "engines": { "node": ">=18.0.0" @@ -3996,14 +4355,14 @@ } }, "node_modules/@react-email/components": { - "version": "0.0.36", - "resolved": "https://registry.npmjs.org/@react-email/components/-/components-0.0.36.tgz", - "integrity": "sha512-VMh+OQplAnG8JMLlJjdnjt+ThJZ+JVkp0q2YMS2NEz+T88N22bLD2p7DZO0QgtNaKgumOhJI/0a2Q7VzCrwu5g==", + "version": "0.0.41", + "resolved": "https://registry.npmjs.org/@react-email/components/-/components-0.0.41.tgz", + "integrity": "sha512-WUI3wHwra3QS0pwrovSU6b0I0f3TvY33ph0y44LuhSYDSQlMRyeOzgoT6HRDY5FXMDF57cHYq9WoKwpwP0yd7Q==", "license": "MIT", "dependencies": { "@react-email/body": "0.0.11", "@react-email/button": "0.0.19", - "@react-email/code-block": "0.0.12", + "@react-email/code-block": "0.0.13", "@react-email/code-inline": "0.0.5", "@react-email/column": "0.0.13", "@react-email/container": "0.0.15", @@ -4014,13 +4373,13 @@ "@react-email/html": "0.0.11", "@react-email/img": "0.0.11", "@react-email/link": "0.0.12", - "@react-email/markdown": "0.0.14", - "@react-email/preview": "0.0.12", - "@react-email/render": "1.0.6", + "@react-email/markdown": "0.0.15", + "@react-email/preview": "0.0.13", + "@react-email/render": "1.1.2", "@react-email/row": "0.0.12", "@react-email/section": "0.0.16", - "@react-email/tailwind": "1.0.4", - "@react-email/text": "0.1.1" + "@react-email/tailwind": "1.0.5", + "@react-email/text": "0.1.4" }, "engines": { "node": ">=18.0.0" @@ -4141,12 +4500,12 @@ } }, "node_modules/@react-email/markdown": { - "version": "0.0.14", - "resolved": "https://registry.npmjs.org/@react-email/markdown/-/markdown-0.0.14.tgz", - "integrity": "sha512-5IsobCyPkb4XwnQO8uFfGcNOxnsg3311GRXhJ3uKv51P7Jxme4ycC/MITnwIZ10w2zx7HIyTiqVzTj4XbuIHbg==", + "version": "0.0.15", + "resolved": "https://registry.npmjs.org/@react-email/markdown/-/markdown-0.0.15.tgz", + "integrity": "sha512-UQA9pVm5sbflgtg3EX3FquUP4aMBzmLReLbGJ6DZQZnAskBF36aI56cRykDq1o+1jT+CKIK1CducPYziaXliag==", "license": "MIT", "dependencies": { - "md-to-react-email": "5.0.5" + "md-to-react-email": "^5.0.5" }, "engines": { "node": ">=18.0.0" @@ -4156,9 +4515,9 @@ } }, "node_modules/@react-email/preview": { - "version": "0.0.12", - "resolved": "https://registry.npmjs.org/@react-email/preview/-/preview-0.0.12.tgz", - "integrity": "sha512-g/H5fa9PQPDK6WUEG7iTlC19sAktI23qyoiJtMLqQiXFCfWeQMhqjLGKeLSKkfzszqmfJCjZtpSiKtBoOdxp3Q==", + "version": "0.0.13", + "resolved": "https://registry.npmjs.org/@react-email/preview/-/preview-0.0.13.tgz", + "integrity": "sha512-F7j9FJ0JN/A4d7yr+aw28p4uX7VLWs7hTHtLo7WRyw4G+Lit6Zucq4UWKRxJC8lpsUdzVmG7aBJnKOT+urqs/w==", "license": "MIT", "engines": { "node": ">=18.0.0" @@ -4168,9 +4527,15 @@ } }, "node_modules/@react-email/render": { +<<<<<<< HEAD "version": "1.1.0", "resolved": "https://registry.npmjs.org/@react-email/render/-/render-1.1.0.tgz", "integrity": "sha512-X4CsHvXi5X7kTn5NgXNGg8Y5U1VtVJmlpNLlTc2E8RVHKFS3bpr+o/ZXhEPN4yRkdY+ZYN5eqVTV922Hujqsxw==", +======= + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/@react-email/render/-/render-1.1.2.tgz", + "integrity": "sha512-RnRehYN3v9gVlNMehHPHhyp2RQo7+pSkHDtXPvg3s0GbzM9SQMW4Qrf8GRNvtpLC4gsI+Wt0VatNRUFqjvevbw==", +>>>>>>> dev "license": "MIT", "dependencies": { "html-to-text": "^9.0.5", @@ -4210,9 +4575,9 @@ } }, "node_modules/@react-email/tailwind": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/@react-email/tailwind/-/tailwind-1.0.4.tgz", - "integrity": "sha512-tJdcusncdqgvTUYZIuhNC6LYTfL9vNTSQpwWdTCQhQ1lsrNCEE4OKCSdzSV3S9F32pi0i0xQ+YPJHKIzGjdTSA==", + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/@react-email/tailwind/-/tailwind-1.0.5.tgz", + "integrity": "sha512-BH00cZSeFfP9HiDASl+sPHi7Hh77W5nzDgdnxtsVr/m3uQD9g180UwxcE3PhOfx0vRdLzQUU8PtmvvDfbztKQg==", "license": "MIT", "engines": { "node": ">=18.0.0" @@ -4222,9 +4587,9 @@ } }, "node_modules/@react-email/text": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/@react-email/text/-/text-0.1.1.tgz", - "integrity": "sha512-Zo9tSEzkO3fODLVH1yVhzVCiwETfeEL5wU93jXKWo2DHoMuiZ9Iabaso3T0D0UjhrCB1PBMeq2YiejqeToTyIQ==", + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/@react-email/text/-/text-0.1.4.tgz", + "integrity": "sha512-cMNE02y8172DocpNGh97uV5HSTawaS4CKG/zOku8Pu+m6ehBKbAjgtQZDIxhgstw8+TWraFB8ltS1DPjfG8nLA==", "license": "MIT", "engines": { "node": ">=18.0.0" @@ -4300,15 +4665,22 @@ } }, "node_modules/@tailwindcss/node": { +<<<<<<< HEAD "version": "4.1.6", "resolved": "https://registry.npmjs.org/@tailwindcss/node/-/node-4.1.6.tgz", "integrity": "sha512-ed6zQbgmKsjsVvodAS1q1Ld2BolEuxJOSyyNc+vhkjdmfNUDCmQnlXBfQkHrlzNmslxHsQU/bFmzcEbv4xXsLg==", +======= + "version": "4.1.8", + "resolved": "https://registry.npmjs.org/@tailwindcss/node/-/node-4.1.8.tgz", + "integrity": "sha512-OWwBsbC9BFAJelmnNcrKuf+bka2ZxCE2A4Ft53Tkg4uoiE67r/PMEYwCsourC26E+kmxfwE0hVzMdxqeW+xu7Q==", +>>>>>>> dev "dev": true, "license": "MIT", "dependencies": { "@ampproject/remapping": "^2.3.0", "enhanced-resolve": "^5.18.1", "jiti": "^2.4.2", +<<<<<<< HEAD "lightningcss": "1.29.2", "magic-string": "^0.30.17", "source-map-js": "^1.2.1", @@ -4319,6 +4691,18 @@ "version": "4.1.6", "resolved": "https://registry.npmjs.org/@tailwindcss/oxide/-/oxide-4.1.6.tgz", "integrity": "sha512-0bpEBQiGx+227fW4G0fLQ8vuvyy5rsB1YIYNapTq3aRsJ9taF3f5cCaovDjN5pUGKKzcpMrZst/mhNaKAPOHOA==", +======= + "lightningcss": "1.30.1", + "magic-string": "^0.30.17", + "source-map-js": "^1.2.1", + "tailwindcss": "4.1.8" + } + }, + "node_modules/@tailwindcss/oxide": { + "version": "4.1.8", + "resolved": "https://registry.npmjs.org/@tailwindcss/oxide/-/oxide-4.1.8.tgz", + "integrity": "sha512-d7qvv9PsM5N3VNKhwVUhpK6r4h9wtLkJ6lz9ZY9aeZgrUWk1Z8VPyqyDT9MZlem7GTGseRQHkeB1j3tC7W1P+A==", +>>>>>>> dev "dev": true, "hasInstallScript": true, "license": "MIT", @@ -4330,6 +4714,7 @@ "node": ">= 10" }, "optionalDependencies": { +<<<<<<< HEAD "@tailwindcss/oxide-android-arm64": "4.1.6", "@tailwindcss/oxide-darwin-arm64": "4.1.6", "@tailwindcss/oxide-darwin-x64": "4.1.6", @@ -4348,6 +4733,26 @@ "version": "4.1.6", "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-android-arm64/-/oxide-android-arm64-4.1.6.tgz", "integrity": "sha512-VHwwPiwXtdIvOvqT/0/FLH/pizTVu78FOnI9jQo64kSAikFSZT7K4pjyzoDpSMaveJTGyAKvDjuhxJxKfmvjiQ==", +======= + "@tailwindcss/oxide-android-arm64": "4.1.8", + "@tailwindcss/oxide-darwin-arm64": "4.1.8", + "@tailwindcss/oxide-darwin-x64": "4.1.8", + "@tailwindcss/oxide-freebsd-x64": "4.1.8", + "@tailwindcss/oxide-linux-arm-gnueabihf": "4.1.8", + "@tailwindcss/oxide-linux-arm64-gnu": "4.1.8", + "@tailwindcss/oxide-linux-arm64-musl": "4.1.8", + "@tailwindcss/oxide-linux-x64-gnu": "4.1.8", + "@tailwindcss/oxide-linux-x64-musl": "4.1.8", + "@tailwindcss/oxide-wasm32-wasi": "4.1.8", + "@tailwindcss/oxide-win32-arm64-msvc": "4.1.8", + "@tailwindcss/oxide-win32-x64-msvc": "4.1.8" + } + }, + "node_modules/@tailwindcss/oxide-android-arm64": { + "version": "4.1.8", + "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-android-arm64/-/oxide-android-arm64-4.1.8.tgz", + "integrity": "sha512-Fbz7qni62uKYceWYvUjRqhGfZKwhZDQhlrJKGtnZfuNtHFqa8wmr+Wn74CTWERiW2hn3mN5gTpOoxWKk0jRxjg==", +>>>>>>> dev "cpu": [ "arm64" ], @@ -4362,9 +4767,15 @@ } }, "node_modules/@tailwindcss/oxide-darwin-arm64": { +<<<<<<< HEAD "version": "4.1.6", "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-darwin-arm64/-/oxide-darwin-arm64-4.1.6.tgz", "integrity": "sha512-weINOCcqv1HVBIGptNrk7c6lWgSFFiQMcCpKM4tnVi5x8OY2v1FrV76jwLukfT6pL1hyajc06tyVmZFYXoxvhQ==", +======= + "version": "4.1.8", + "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-darwin-arm64/-/oxide-darwin-arm64-4.1.8.tgz", + "integrity": "sha512-RdRvedGsT0vwVVDztvyXhKpsU2ark/BjgG0huo4+2BluxdXo8NDgzl77qh0T1nUxmM11eXwR8jA39ibvSTbi7A==", +>>>>>>> dev "cpu": [ "arm64" ], @@ -4379,9 +4790,15 @@ } }, "node_modules/@tailwindcss/oxide-darwin-x64": { +<<<<<<< HEAD "version": "4.1.6", "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-darwin-x64/-/oxide-darwin-x64-4.1.6.tgz", "integrity": "sha512-3FzekhHG0ww1zQjQ1lPoq0wPrAIVXAbUkWdWM8u5BnYFZgb9ja5ejBqyTgjpo5mfy0hFOoMnMuVDI+7CXhXZaQ==", +======= + "version": "4.1.8", + "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-darwin-x64/-/oxide-darwin-x64-4.1.8.tgz", + "integrity": "sha512-t6PgxjEMLp5Ovf7uMb2OFmb3kqzVTPPakWpBIFzppk4JE4ix0yEtbtSjPbU8+PZETpaYMtXvss2Sdkx8Vs4XRw==", +>>>>>>> dev "cpu": [ "x64" ], @@ -4396,9 +4813,15 @@ } }, "node_modules/@tailwindcss/oxide-freebsd-x64": { +<<<<<<< HEAD "version": "4.1.6", "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-freebsd-x64/-/oxide-freebsd-x64-4.1.6.tgz", "integrity": "sha512-4m5F5lpkBZhVQJq53oe5XgJ+aFYWdrgkMwViHjRsES3KEu2m1udR21B1I77RUqie0ZYNscFzY1v9aDssMBZ/1w==", +======= + "version": "4.1.8", + "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-freebsd-x64/-/oxide-freebsd-x64-4.1.8.tgz", + "integrity": "sha512-g8C8eGEyhHTqwPStSwZNSrOlyx0bhK/V/+zX0Y+n7DoRUzyS8eMbVshVOLJTDDC+Qn9IJnilYbIKzpB9n4aBsg==", +>>>>>>> dev "cpu": [ "x64" ], @@ -4413,9 +4836,15 @@ } }, "node_modules/@tailwindcss/oxide-linux-arm-gnueabihf": { +<<<<<<< HEAD "version": "4.1.6", "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-linux-arm-gnueabihf/-/oxide-linux-arm-gnueabihf-4.1.6.tgz", "integrity": "sha512-qU0rHnA9P/ZoaDKouU1oGPxPWzDKtIfX7eOGi5jOWJKdxieUJdVV+CxWZOpDWlYTd4N3sFQvcnVLJWJ1cLP5TA==", +======= + "version": "4.1.8", + "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-linux-arm-gnueabihf/-/oxide-linux-arm-gnueabihf-4.1.8.tgz", + "integrity": "sha512-Jmzr3FA4S2tHhaC6yCjac3rGf7hG9R6Gf2z9i9JFcuyy0u79HfQsh/thifbYTF2ic82KJovKKkIB6Z9TdNhCXQ==", +>>>>>>> dev "cpu": [ "arm" ], @@ -4430,9 +4859,15 @@ } }, "node_modules/@tailwindcss/oxide-linux-arm64-gnu": { +<<<<<<< HEAD "version": "4.1.6", "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-linux-arm64-gnu/-/oxide-linux-arm64-gnu-4.1.6.tgz", "integrity": "sha512-jXy3TSTrbfgyd3UxPQeXC3wm8DAgmigzar99Km9Sf6L2OFfn/k+u3VqmpgHQw5QNfCpPe43em6Q7V76Wx7ogIQ==", +======= + "version": "4.1.8", + "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-linux-arm64-gnu/-/oxide-linux-arm64-gnu-4.1.8.tgz", + "integrity": "sha512-qq7jXtO1+UEtCmCeBBIRDrPFIVI4ilEQ97qgBGdwXAARrUqSn/L9fUrkb1XP/mvVtoVeR2bt/0L77xx53bPZ/Q==", +>>>>>>> dev "cpu": [ "arm64" ], @@ -4447,9 +4882,15 @@ } }, "node_modules/@tailwindcss/oxide-linux-arm64-musl": { +<<<<<<< HEAD "version": "4.1.6", "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-linux-arm64-musl/-/oxide-linux-arm64-musl-4.1.6.tgz", "integrity": "sha512-8kjivE5xW0qAQ9HX9reVFmZj3t+VmljDLVRJpVBEoTR+3bKMnvC7iLcoSGNIUJGOZy1mLVq7x/gerVg0T+IsYw==", +======= + "version": "4.1.8", + "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-linux-arm64-musl/-/oxide-linux-arm64-musl-4.1.8.tgz", + "integrity": "sha512-O6b8QesPbJCRshsNApsOIpzKt3ztG35gfX9tEf4arD7mwNinsoCKxkj8TgEE0YRjmjtO3r9FlJnT/ENd9EVefQ==", +>>>>>>> dev "cpu": [ "arm64" ], @@ -4464,9 +4905,15 @@ } }, "node_modules/@tailwindcss/oxide-linux-x64-gnu": { +<<<<<<< HEAD "version": "4.1.6", "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-linux-x64-gnu/-/oxide-linux-x64-gnu-4.1.6.tgz", "integrity": "sha512-A4spQhwnWVpjWDLXnOW9PSinO2PTKJQNRmL/aIl2U/O+RARls8doDfs6R41+DAXK0ccacvRyDpR46aVQJJCoCg==", +======= + "version": "4.1.8", + "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-linux-x64-gnu/-/oxide-linux-x64-gnu-4.1.8.tgz", + "integrity": "sha512-32iEXX/pXwikshNOGnERAFwFSfiltmijMIAbUhnNyjFr3tmWmMJWQKU2vNcFX0DACSXJ3ZWcSkzNbaKTdngH6g==", +>>>>>>> dev "cpu": [ "x64" ], @@ -4481,9 +4928,15 @@ } }, "node_modules/@tailwindcss/oxide-linux-x64-musl": { +<<<<<<< HEAD "version": "4.1.6", "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-linux-x64-musl/-/oxide-linux-x64-musl-4.1.6.tgz", "integrity": "sha512-YRee+6ZqdzgiQAHVSLfl3RYmqeeaWVCk796MhXhLQu2kJu2COHBkqlqsqKYx3p8Hmk5pGCQd2jTAoMWWFeyG2A==", +======= + "version": "4.1.8", + "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-linux-x64-musl/-/oxide-linux-x64-musl-4.1.8.tgz", + "integrity": "sha512-s+VSSD+TfZeMEsCaFaHTaY5YNj3Dri8rST09gMvYQKwPphacRG7wbuQ5ZJMIJXN/puxPcg/nU+ucvWguPpvBDg==", +>>>>>>> dev "cpu": [ "x64" ], @@ -4498,9 +4951,15 @@ } }, "node_modules/@tailwindcss/oxide-wasm32-wasi": { +<<<<<<< HEAD "version": "4.1.6", "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-wasm32-wasi/-/oxide-wasm32-wasi-4.1.6.tgz", "integrity": "sha512-qAp4ooTYrBQ5pk5jgg54/U1rCJ/9FLYOkkQ/nTE+bVMseMfB6O7J8zb19YTpWuu4UdfRf5zzOrNKfl6T64MNrQ==", +======= + "version": "4.1.8", + "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-wasm32-wasi/-/oxide-wasm32-wasi-4.1.8.tgz", + "integrity": "sha512-CXBPVFkpDjM67sS1psWohZ6g/2/cd+cq56vPxK4JeawelxwK4YECgl9Y9TjkE2qfF+9/s1tHHJqrC4SS6cVvSg==", +>>>>>>> dev "bundleDependencies": [ "@napi-rs/wasm-runtime", "@emnapi/core", @@ -4519,7 +4978,11 @@ "@emnapi/core": "^1.4.3", "@emnapi/runtime": "^1.4.3", "@emnapi/wasi-threads": "^1.0.2", +<<<<<<< HEAD "@napi-rs/wasm-runtime": "^0.2.9", +======= + "@napi-rs/wasm-runtime": "^0.2.10", +>>>>>>> dev "@tybys/wasm-util": "^0.9.0", "tslib": "^2.8.0" }, @@ -4528,9 +4991,15 @@ } }, "node_modules/@tailwindcss/oxide-win32-arm64-msvc": { +<<<<<<< HEAD "version": "4.1.6", "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-win32-arm64-msvc/-/oxide-win32-arm64-msvc-4.1.6.tgz", "integrity": "sha512-nqpDWk0Xr8ELO/nfRUDjk1pc9wDJ3ObeDdNMHLaymc4PJBWj11gdPCWZFKSK2AVKjJQC7J2EfmSmf47GN7OuLg==", +======= + "version": "4.1.8", + "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-win32-arm64-msvc/-/oxide-win32-arm64-msvc-4.1.8.tgz", + "integrity": "sha512-7GmYk1n28teDHUjPlIx4Z6Z4hHEgvP5ZW2QS9ygnDAdI/myh3HTHjDqtSqgu1BpRoI4OiLx+fThAyA1JePoENA==", +>>>>>>> dev "cpu": [ "arm64" ], @@ -4545,9 +5014,15 @@ } }, "node_modules/@tailwindcss/oxide-win32-x64-msvc": { +<<<<<<< HEAD "version": "4.1.6", "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-win32-x64-msvc/-/oxide-win32-x64-msvc-4.1.6.tgz", "integrity": "sha512-5k9xF33xkfKpo9wCvYcegQ21VwIBU1/qEbYlVukfEIyQbEA47uK8AAwS7NVjNE3vHzcmxMYwd0l6L4pPjjm1rQ==", +======= + "version": "4.1.8", + "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-win32-x64-msvc/-/oxide-win32-x64-msvc-4.1.8.tgz", + "integrity": "sha512-fou+U20j+Jl0EHwK92spoWISON2OBnCazIc038Xj2TdweYV33ZRkS9nwqiUi2d/Wba5xg5UoHfvynnb/UB49cQ==", +>>>>>>> dev "cpu": [ "x64" ], @@ -4562,26 +5037,39 @@ } }, "node_modules/@tailwindcss/postcss": { +<<<<<<< HEAD "version": "4.1.6", "resolved": "https://registry.npmjs.org/@tailwindcss/postcss/-/postcss-4.1.6.tgz", "integrity": "sha512-ELq+gDMBuRXPJlpE3PEen+1MhnHAQQrh2zF0dI1NXOlEWfr2qWf2CQdr5jl9yANv8RErQaQ2l6nIFO9OSCVq/g==", +======= + "version": "4.1.8", + "resolved": "https://registry.npmjs.org/@tailwindcss/postcss/-/postcss-4.1.8.tgz", + "integrity": "sha512-vB/vlf7rIky+w94aWMw34bWW1ka6g6C3xIOdICKX2GC0VcLtL6fhlLiafF0DVIwa9V6EHz8kbWMkS2s2QvvNlw==", +>>>>>>> dev "dev": true, "license": "MIT", "dependencies": { "@alloc/quick-lru": "^5.2.0", +<<<<<<< HEAD "@tailwindcss/node": "4.1.6", "@tailwindcss/oxide": "4.1.6", "postcss": "^8.4.41", "tailwindcss": "4.1.6" +======= + "@tailwindcss/node": "4.1.8", + "@tailwindcss/oxide": "4.1.8", + "postcss": "^8.4.41", + "tailwindcss": "4.1.8" +>>>>>>> dev } }, "node_modules/@tanstack/react-table": { - "version": "8.20.6", - "resolved": "https://registry.npmjs.org/@tanstack/react-table/-/react-table-8.20.6.tgz", - "integrity": "sha512-w0jluT718MrOKthRcr2xsjqzx+oEM7B7s/XXyfs19ll++hlId3fjTm+B2zrR3ijpANpkzBAr15j1XGVOMxpggQ==", + "version": "8.21.3", + "resolved": "https://registry.npmjs.org/@tanstack/react-table/-/react-table-8.21.3.tgz", + "integrity": "sha512-5nNMTSETP4ykGegmVkhjcS8tTLW6Vl4axfEGQN3v0zdHYbK4UfoqfPChclTrJ4EoK9QynqAu9oUf8VEmrpZ5Ww==", "license": "MIT", "dependencies": { - "@tanstack/table-core": "8.20.5" + "@tanstack/table-core": "8.21.3" }, "engines": { "node": ">=12" @@ -4596,9 +5084,9 @@ } }, "node_modules/@tanstack/table-core": { - "version": "8.20.5", - "resolved": "https://registry.npmjs.org/@tanstack/table-core/-/table-core-8.20.5.tgz", - "integrity": "sha512-P9dF7XbibHph2PFRz8gfBKEXEY/HJPOhym8CHmjF8y3q5mWpKx9xtZapXQUWCgkqvsK0R46Azuz+VaxD4Xl+Tg==", + "version": "8.21.3", + "resolved": "https://registry.npmjs.org/@tanstack/table-core/-/table-core-8.21.3.tgz", + "integrity": "sha512-ldZXEhOBb8Is7xLs01fR3YEc3DERiz5silj8tnGkFZytt1abEvl/GhUmCE0PMLaMPTa3Jk4HbKmRlHmu+gCftg==", "license": "MIT", "engines": { "node": ">=12" @@ -4629,9 +5117,9 @@ } }, "node_modules/@types/body-parser": { - "version": "1.19.5", - "resolved": "https://registry.npmjs.org/@types/body-parser/-/body-parser-1.19.5.tgz", - "integrity": "sha512-fB3Zu92ucau0iQ0JMCFQE7b/dv8Ot07NI3KaZIkIUNXq82k4eBAqUaneXfleGY9JWskeS9y+u0nXMyspcuQrCg==", + "version": "1.19.6", + "resolved": "https://registry.npmjs.org/@types/body-parser/-/body-parser-1.19.6.tgz", + "integrity": "sha512-HLFeCYgz89uk22N5Qg3dvGvsv46B8GLvKKo1zKG4NybA8U2DiEO3w9lqGg29t/tfLRJpJ6iQxnVw4OnB7MoM9g==", "dev": true, "license": "MIT", "dependencies": { @@ -4650,9 +5138,9 @@ } }, "node_modules/@types/cookie-parser": { - "version": "1.4.8", - "resolved": "https://registry.npmjs.org/@types/cookie-parser/-/cookie-parser-1.4.8.tgz", - "integrity": "sha512-l37JqFrOJ9yQfRQkljb41l0xVphc7kg5JTjjr+pLRZ0IyZ49V4BQ8vbF4Ut2C2e+WH4al3xD3ZwYwIUfnbT4NQ==", + "version": "1.4.9", + "resolved": "https://registry.npmjs.org/@types/cookie-parser/-/cookie-parser-1.4.9.tgz", + "integrity": "sha512-tGZiZ2Gtc4m3wIdLkZ8mkj1T6CEHb35+VApbL2T14Dew8HA7c+04dmKqsKRNC+8RJPm16JEK0tFSwdZqubfc4g==", "dev": true, "license": "MIT", "peerDependencies": { @@ -4660,9 +5148,9 @@ } }, "node_modules/@types/cors": { - "version": "2.8.17", - "resolved": "https://registry.npmjs.org/@types/cors/-/cors-2.8.17.tgz", - "integrity": "sha512-8CGDvrBj1zgo2qE+oS3pOCyYNqCPryMWY2bGfwA0dcfopWGgxs+78df0Rs3rc9THP4JkOhLsAa+15VdpAqkcUA==", + "version": "2.8.19", + "resolved": "https://registry.npmjs.org/@types/cors/-/cors-2.8.19.tgz", + "integrity": "sha512-mFNylyeyqN93lfe/9CSxOGREz8cpzAhH+E93xJ4xWQf62V8sQ/24reV2nyzUWM6H6Xji+GGHpkbLe7pVoUEskg==", "dev": true, "license": "MIT", "dependencies": { @@ -4677,9 +5165,15 @@ "license": "MIT" }, "node_modules/@types/estree": { +<<<<<<< HEAD "version": "1.0.7", "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.7.tgz", "integrity": "sha512-w28IoSUCJpidD/TGviZwwMJckNESJZXFu7NBZ5YJ4mEUnNraUn9Pm8HSZm/jDF1pDWYKspWE7oVphigUPRakIQ==", +======= + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.8.tgz", + "integrity": "sha512-dWHzHa2WqEXI/O1E9OjrocMTKJl2mSrEolh1Iomrv6U+JuNwaHXsXx9bLu5gG7BUWFIN0skIQJQ/L1rIex4X6w==", +>>>>>>> dev "license": "MIT" }, "node_modules/@types/express": { @@ -4709,9 +5203,9 @@ } }, "node_modules/@types/http-errors": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/@types/http-errors/-/http-errors-2.0.4.tgz", - "integrity": "sha512-D0CFMMtydbJAegzOyHjtiKPLlvnm3iTZyZRSZoLq2mRhDdmLfIWOCYPfQJ4cu2erKghU++QvjcUjp/5h7hESpA==", + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/@types/http-errors/-/http-errors-2.0.5.tgz", + "integrity": "sha512-r8Tayk8HJnX0FztbZN7oVqGccWgw98T/0neJphO91KkmOzug1KkofZURD4UaD5uH8AqcFLfdPErnBod0u71/qg==", "dev": true, "license": "MIT" }, @@ -4767,9 +5261,15 @@ "license": "MIT" }, "node_modules/@types/node": { +<<<<<<< HEAD "version": "22.15.17", "resolved": "https://registry.npmjs.org/@types/node/-/node-22.15.17.tgz", "integrity": "sha512-wIX2aSZL5FE+MR0JlvF87BNVrtFWf6AE6rxSE9X7OwnVvoyCQjpzSRJ+M87se/4QCkCiebQAqrJ0y6fwIyi7nw==", +======= + "version": "22.15.30", + "resolved": "https://registry.npmjs.org/@types/node/-/node-22.15.30.tgz", + "integrity": "sha512-6Q7lr06bEHdlfplU6YRbgG1SFBdlsfNC4/lX+SkhiTs0cpJkOElmWls8PxDFv4yY/xKb8Y6SO0OmSX4wgqTZbA==", +>>>>>>> dev "devOptional": true, "license": "MIT", "dependencies": { @@ -4787,9 +5287,9 @@ } }, "node_modules/@types/qs": { - "version": "6.9.18", - "resolved": "https://registry.npmjs.org/@types/qs/-/qs-6.9.18.tgz", - "integrity": "sha512-kK7dgTYDyGqS+e2Q4aK9X3D7q234CIZ1Bv0q/7Z5IwRDoADNU81xXJK/YVyLbLTZCoIwUoDoffFeF+p/eIklAA==", + "version": "6.14.0", + "resolved": "https://registry.npmjs.org/@types/qs/-/qs-6.14.0.tgz", + "integrity": "sha512-eOunJqu0K1923aExK6y8p6fsihYEn/BYuQ4g0CxAAgFc4b/ZLN4CrsRZ55srTdqoiLzU2B2evC+apEIxprEzkQ==", "dev": true, "license": "MIT" }, @@ -4801,9 +5301,9 @@ "license": "MIT" }, "node_modules/@types/react": { - "version": "19.1.1", - "resolved": "https://registry.npmjs.org/@types/react/-/react-19.1.1.tgz", - "integrity": "sha512-ePapxDL7qrgqSF67s0h9m412d9DbXyC1n59O2st+9rjuuamWsZuD2w55rqY12CbzsZ7uVXb5Nw0gEp9Z8MMutQ==", + "version": "19.1.7", + "resolved": "https://registry.npmjs.org/@types/react/-/react-19.1.7.tgz", + "integrity": "sha512-BnsPLV43ddr05N71gaGzyZ5hzkCmGwhMvYc8zmvI8Ci1bRkkDSzDDVfAXfN2tk748OwI7ediiPX6PfT9p0QGVg==", "devOptional": true, "license": "MIT", "dependencies": { @@ -4811,9 +5311,9 @@ } }, "node_modules/@types/react-dom": { - "version": "19.1.2", - "resolved": "https://registry.npmjs.org/@types/react-dom/-/react-dom-19.1.2.tgz", - "integrity": "sha512-XGJkWF41Qq305SKWEILa1O8vzhb3aOo3ogBlSmiqNko/WmRb6QIaweuZCXjKygVDXpzXb5wyxKTSOsmkuqj+Qw==", + "version": "19.1.6", + "resolved": "https://registry.npmjs.org/@types/react-dom/-/react-dom-19.1.6.tgz", + "integrity": "sha512-4hOiT/dwO8Ko0gV1m/TJZYk3y0KBnY9vzDh7W+DH17b2HFSOGgdj33dhihPeuy3l0q23+4e+hoXHV6hCC4dCXw==", "devOptional": true, "license": "MIT", "peerDependencies": { @@ -4821,16 +5321,16 @@ } }, "node_modules/@types/semver": { - "version": "7.5.8", - "resolved": "https://registry.npmjs.org/@types/semver/-/semver-7.5.8.tgz", - "integrity": "sha512-I8EUhyrgfLrcTkzV3TSsGyl1tSuPrEDzr0yd5m90UgNxQkyDXULk3b6MlQqTCpZpNtWe1K0hzclnZkTcLBe2UQ==", + "version": "7.7.0", + "resolved": "https://registry.npmjs.org/@types/semver/-/semver-7.7.0.tgz", + "integrity": "sha512-k107IF4+Xr7UHjwDc7Cfd6PRQfbdkiRabXGRjo07b4WyPahFBZCZ1sE+BNxYIJPPg73UkfOsVOLwqVc/6ETrIA==", "dev": true, "license": "MIT" }, "node_modules/@types/send": { - "version": "0.17.4", - "resolved": "https://registry.npmjs.org/@types/send/-/send-0.17.4.tgz", - "integrity": "sha512-x2EM6TJOybec7c52BX0ZspPodMsQUd5L6PRwOunVyVUhXiBSKf3AezDL8Dgvgt5o0UfKNfuA0eMLr2wLT4AiBA==", + "version": "0.17.5", + "resolved": "https://registry.npmjs.org/@types/send/-/send-0.17.5.tgz", + "integrity": "sha512-z6F2D3cOStZvuk2SaP6YrwkNO65iTZcwA2ZkSABegdkAh/lf+Aa/YQndZVfmEXT5vgAp6zv06VQ3ejSVjAny4w==", "dev": true, "license": "MIT", "dependencies": { @@ -4839,9 +5339,9 @@ } }, "node_modules/@types/serve-static": { - "version": "1.15.7", - "resolved": "https://registry.npmjs.org/@types/serve-static/-/serve-static-1.15.7.tgz", - "integrity": "sha512-W8Ym+h8nhuRwaKPaDw34QUkwsGi6Rc4yYqvKFo5rm2FUEhCFbzVWrxXUxuKK8TASjWsysJY0nsmNCGhCOIsrOw==", + "version": "1.15.8", + "resolved": "https://registry.npmjs.org/@types/serve-static/-/serve-static-1.15.8.tgz", + "integrity": "sha512-roei0UY3LhpOJvjbIP6ZZFngyLKl5dskOtDhxY5THRSpO+ZI+nzJ+m5yUMzGrp89YRa7lvknKkMYjqQFGwA7Sg==", "dev": true, "license": "MIT", "dependencies": { @@ -4868,9 +5368,9 @@ "license": "MIT" }, "node_modules/@types/ws": { - "version": "8.5.13", - "resolved": "https://registry.npmjs.org/@types/ws/-/ws-8.5.13.tgz", - "integrity": "sha512-osM/gWBTPKgHV8XkTunnegTRIsvF6owmf5w+JtAfOw472dptdm0dlGv4xCt6GwQRcC2XVOvvRE/0bAoQcL2QkA==", + "version": "8.18.1", + "resolved": "https://registry.npmjs.org/@types/ws/-/ws-8.18.1.tgz", + "integrity": "sha512-ThVF6DCVhA8kUGy+aazFQ4kXQ7E1Ty7A3ypFOe0IcJV8O/M511G99AW24irKrW56Wt44yG9+ij8FaqoBGkuBXg==", "dev": true, "license": "MIT", "dependencies": { @@ -4895,6 +5395,7 @@ "license": "MIT" }, "node_modules/@typescript-eslint/eslint-plugin": { +<<<<<<< HEAD "version": "8.32.0", "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-8.32.0.tgz", "integrity": "sha512-/jU9ettcntkBFmWUzzGgsClEi2ZFiikMX5eEQsmxIAWMOn4H3D4rvHssstmAHGVvrYnaMqdWWWg0b5M6IN/MTQ==", @@ -4905,8 +5406,20 @@ "@typescript-eslint/type-utils": "8.32.0", "@typescript-eslint/utils": "8.32.0", "@typescript-eslint/visitor-keys": "8.32.0", +======= + "version": "8.34.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-8.34.0.tgz", + "integrity": "sha512-QXwAlHlbcAwNlEEMKQS2RCgJsgXrTJdjXT08xEgbPFa2yYQgVjBymxP5DrfrE7X7iodSzd9qBUHUycdyVJTW1w==", + "license": "MIT", + "dependencies": { + "@eslint-community/regexpp": "^4.10.0", + "@typescript-eslint/scope-manager": "8.34.0", + "@typescript-eslint/type-utils": "8.34.0", + "@typescript-eslint/utils": "8.34.0", + "@typescript-eslint/visitor-keys": "8.34.0", +>>>>>>> dev "graphemer": "^1.4.0", - "ignore": "^5.3.1", + "ignore": "^7.0.0", "natural-compare": "^1.4.0", "ts-api-utils": "^2.1.0" }, @@ -4918,9 +5431,10 @@ "url": "https://opencollective.com/typescript-eslint" }, "peerDependencies": { - "@typescript-eslint/parser": "^8.0.0 || ^8.0.0-alpha.0", + "@typescript-eslint/parser": "^8.34.0", "eslint": "^8.57.0 || ^9.0.0", "typescript": ">=4.8.4 <5.9.0" +<<<<<<< HEAD } }, "node_modules/@typescript-eslint/parser": { @@ -4933,6 +5447,29 @@ "@typescript-eslint/types": "8.32.0", "@typescript-eslint/typescript-estree": "8.32.0", "@typescript-eslint/visitor-keys": "8.32.0", +======= + } + }, + "node_modules/@typescript-eslint/eslint-plugin/node_modules/ignore": { + "version": "7.0.5", + "resolved": "https://registry.npmjs.org/ignore/-/ignore-7.0.5.tgz", + "integrity": "sha512-Hs59xBNfUIunMFgWAbGX5cq6893IbWg4KnrjbYwX3tx0ztorVgTDA6B2sxf8ejHJ4wz8BqGUMYlnzNBer5NvGg==", + "license": "MIT", + "engines": { + "node": ">= 4" + } + }, + "node_modules/@typescript-eslint/parser": { + "version": "8.34.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-8.34.0.tgz", + "integrity": "sha512-vxXJV1hVFx3IXz/oy2sICsJukaBrtDEQSBiV48/YIV5KWjX1dO+bcIr/kCPrW6weKXvsaGKFNlwH0v2eYdRRbA==", + "license": "MIT", + "dependencies": { + "@typescript-eslint/scope-manager": "8.34.0", + "@typescript-eslint/types": "8.34.0", + "@typescript-eslint/typescript-estree": "8.34.0", + "@typescript-eslint/visitor-keys": "8.34.0", +>>>>>>> dev "debug": "^4.3.4" }, "engines": { @@ -4945,6 +5482,7 @@ "peerDependencies": { "eslint": "^8.57.0 || ^9.0.0", "typescript": ">=4.8.4 <5.9.0" +<<<<<<< HEAD } }, "node_modules/@typescript-eslint/scope-manager": { @@ -4955,6 +5493,39 @@ "dependencies": { "@typescript-eslint/types": "8.32.0", "@typescript-eslint/visitor-keys": "8.32.0" +======= + } + }, + "node_modules/@typescript-eslint/project-service": { + "version": "8.34.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/project-service/-/project-service-8.34.0.tgz", + "integrity": "sha512-iEgDALRf970/B2YExmtPMPF54NenZUf4xpL3wsCRx/lgjz6ul/l13R81ozP/ZNuXfnLCS+oPmG7JIxfdNYKELw==", + "license": "MIT", + "dependencies": { + "@typescript-eslint/tsconfig-utils": "^8.34.0", + "@typescript-eslint/types": "^8.34.0", + "debug": "^4.3.4" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "typescript": ">=4.8.4 <5.9.0" + } + }, + "node_modules/@typescript-eslint/scope-manager": { + "version": "8.34.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-8.34.0.tgz", + "integrity": "sha512-9Ac0X8WiLykl0aj1oYQNcLZjHgBojT6cW68yAgZ19letYu+Hxd0rE0veI1XznSSst1X5lwnxhPbVdwjDRIomRw==", + "license": "MIT", + "dependencies": { + "@typescript-eslint/types": "8.34.0", + "@typescript-eslint/visitor-keys": "8.34.0" +>>>>>>> dev }, "engines": { "node": "^18.18.0 || ^20.9.0 || >=21.1.0" @@ -4964,7 +5535,24 @@ "url": "https://opencollective.com/typescript-eslint" } }, + "node_modules/@typescript-eslint/tsconfig-utils": { + "version": "8.34.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/tsconfig-utils/-/tsconfig-utils-8.34.0.tgz", + "integrity": "sha512-+W9VYHKFIzA5cBeooqQxqNriAP0QeQ7xTiDuIOr71hzgffm3EL2hxwWBIIj4GuofIbKxGNarpKqIq6Q6YrShOA==", + "license": "MIT", + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "typescript": ">=4.8.4 <5.9.0" + } + }, "node_modules/@typescript-eslint/type-utils": { +<<<<<<< HEAD "version": "8.32.0", "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-8.32.0.tgz", "integrity": "sha512-t2vouuYQKEKSLtJaa5bB4jHeha2HJczQ6E5IXPDPgIty9EqcJxpr1QHQ86YyIPwDwxvUmLfP2YADQ5ZY4qddZg==", @@ -4972,6 +5560,15 @@ "dependencies": { "@typescript-eslint/typescript-estree": "8.32.0", "@typescript-eslint/utils": "8.32.0", +======= + "version": "8.34.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-8.34.0.tgz", + "integrity": "sha512-n7zSmOcUVhcRYC75W2pnPpbO1iwhJY3NLoHEtbJwJSNlVAZuwqu05zY3f3s2SDWWDSo9FdN5szqc73DCtDObAg==", + "license": "MIT", + "dependencies": { + "@typescript-eslint/typescript-estree": "8.34.0", + "@typescript-eslint/utils": "8.34.0", +>>>>>>> dev "debug": "^4.3.4", "ts-api-utils": "^2.1.0" }, @@ -4988,9 +5585,15 @@ } }, "node_modules/@typescript-eslint/types": { +<<<<<<< HEAD "version": "8.32.0", "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-8.32.0.tgz", "integrity": "sha512-O5Id6tGadAZEMThM6L9HmVf5hQUXNSxLVKeGJYWNhhVseps/0LddMkp7//VDkzwJ69lPL0UmZdcZwggj9akJaA==", +======= + "version": "8.34.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-8.34.0.tgz", + "integrity": "sha512-9V24k/paICYPniajHfJ4cuAWETnt7Ssy+R0Rbcqo5sSFr3QEZ/8TSoUi9XeXVBGXCaLtwTOKSLGcInCAvyZeMA==", +>>>>>>> dev "license": "MIT", "engines": { "node": "^18.18.0 || ^20.9.0 || >=21.1.0" @@ -5001,6 +5604,7 @@ } }, "node_modules/@typescript-eslint/typescript-estree": { +<<<<<<< HEAD "version": "8.32.0", "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-8.32.0.tgz", "integrity": "sha512-pU9VD7anSCOIoBFnhTGfOzlVFQIA1XXiQpH/CezqOBaDppRwTglJzCC6fUQGpfwey4T183NKhF1/mfatYmjRqQ==", @@ -5008,6 +5612,17 @@ "dependencies": { "@typescript-eslint/types": "8.32.0", "@typescript-eslint/visitor-keys": "8.32.0", +======= + "version": "8.34.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-8.34.0.tgz", + "integrity": "sha512-rOi4KZxI7E0+BMqG7emPSK1bB4RICCpF7QD3KCLXn9ZvWoESsOMlHyZPAHyG04ujVplPaHbmEvs34m+wjgtVtg==", + "license": "MIT", + "dependencies": { + "@typescript-eslint/project-service": "8.34.0", + "@typescript-eslint/tsconfig-utils": "8.34.0", + "@typescript-eslint/types": "8.34.0", + "@typescript-eslint/visitor-keys": "8.34.0", +>>>>>>> dev "debug": "^4.3.4", "fast-glob": "^3.3.2", "is-glob": "^4.0.3", @@ -5079,6 +5694,7 @@ } }, "node_modules/@typescript-eslint/utils": { +<<<<<<< HEAD "version": "8.32.0", "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-8.32.0.tgz", "integrity": "sha512-8S9hXau6nQ/sYVtC3D6ISIDoJzS1NsCK+gluVhLN2YkBPX+/1wkwyUiDKnxRh15579WoOIyVWnoyIf3yGI9REw==", @@ -5088,6 +5704,17 @@ "@typescript-eslint/scope-manager": "8.32.0", "@typescript-eslint/types": "8.32.0", "@typescript-eslint/typescript-estree": "8.32.0" +======= + "version": "8.34.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-8.34.0.tgz", + "integrity": "sha512-8L4tWatGchV9A1cKbjaavS6mwYwp39jql8xUmIIKJdm+qiaeHy5KMKlBrf30akXAWBzn2SqKsNOtSENWUwg7XQ==", + "license": "MIT", + "dependencies": { + "@eslint-community/eslint-utils": "^4.7.0", + "@typescript-eslint/scope-manager": "8.34.0", + "@typescript-eslint/types": "8.34.0", + "@typescript-eslint/typescript-estree": "8.34.0" +>>>>>>> dev }, "engines": { "node": "^18.18.0 || ^20.9.0 || >=21.1.0" @@ -5102,12 +5729,21 @@ } }, "node_modules/@typescript-eslint/visitor-keys": { +<<<<<<< HEAD "version": "8.32.0", "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-8.32.0.tgz", "integrity": "sha512-1rYQTCLFFzOI5Nl0c8LUpJT8HxpwVRn9E4CkMsYfuN6ctmQqExjSTzzSk0Tz2apmXy7WU6/6fyaZVVA/thPN+w==", "license": "MIT", "dependencies": { "@typescript-eslint/types": "8.32.0", +======= + "version": "8.34.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-8.34.0.tgz", + "integrity": "sha512-qHV7pW7E85A0x6qyrFn+O+q1k1p3tQCsqIZ1KZ5ESLXY57aTvUd3/a4rdPTeXisvhXn2VQG0VSKUqs8KHF2zcA==", + "license": "MIT", + "dependencies": { + "@typescript-eslint/types": "8.34.0", +>>>>>>> dev "eslint-visitor-keys": "^4.2.0" }, "engines": { @@ -5119,9 +5755,15 @@ } }, "node_modules/@unrs/resolver-binding-darwin-arm64": { +<<<<<<< HEAD "version": "1.7.2", "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-darwin-arm64/-/resolver-binding-darwin-arm64-1.7.2.tgz", "integrity": "sha512-vxtBno4xvowwNmO/ASL0Y45TpHqmNkAaDtz4Jqb+clmcVSSl8XCG/PNFFkGsXXXS6AMjP+ja/TtNCFFa1QwLRg==", +======= + "version": "1.7.11", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-darwin-arm64/-/resolver-binding-darwin-arm64-1.7.11.tgz", + "integrity": "sha512-i3/wlWjQJXMh1uiGtiv7k1EYvrrS3L1hdwmWJJiz1D8jWy726YFYPIxQWbEIVPVAgrfRR0XNlLrTQwq17cuCGw==", +>>>>>>> dev "cpu": [ "arm64" ], @@ -5132,9 +5774,15 @@ ] }, "node_modules/@unrs/resolver-binding-darwin-x64": { +<<<<<<< HEAD "version": "1.7.2", "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-darwin-x64/-/resolver-binding-darwin-x64-1.7.2.tgz", "integrity": "sha512-qhVa8ozu92C23Hsmv0BF4+5Dyyd5STT1FolV4whNgbY6mj3kA0qsrGPe35zNR3wAN7eFict3s4Rc2dDTPBTuFQ==", +======= + "version": "1.7.11", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-darwin-x64/-/resolver-binding-darwin-x64-1.7.11.tgz", + "integrity": "sha512-8XXyFvc6w6kmMmi6VYchZhjd5CDcp+Lv6Cn1YmUme0ypsZ/0Kzd+9ESrWtDrWibKPTgSteDTxp75cvBOY64FQQ==", +>>>>>>> dev "cpu": [ "x64" ], @@ -5145,9 +5793,15 @@ ] }, "node_modules/@unrs/resolver-binding-freebsd-x64": { +<<<<<<< HEAD "version": "1.7.2", "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-freebsd-x64/-/resolver-binding-freebsd-x64-1.7.2.tgz", "integrity": "sha512-zKKdm2uMXqLFX6Ac7K5ElnnG5VIXbDlFWzg4WJ8CGUedJryM5A3cTgHuGMw1+P5ziV8CRhnSEgOnurTI4vpHpg==", +======= + "version": "1.7.11", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-freebsd-x64/-/resolver-binding-freebsd-x64-1.7.11.tgz", + "integrity": "sha512-0qJBYzP8Qk24CZ05RSWDQUjdiQUeIJGfqMMzbtXgCKl/a5xa6thfC0MQkGIr55LCLd6YmMyO640ifYUa53lybQ==", +>>>>>>> dev "cpu": [ "x64" ], @@ -5158,9 +5812,15 @@ ] }, "node_modules/@unrs/resolver-binding-linux-arm-gnueabihf": { +<<<<<<< HEAD "version": "1.7.2", "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-linux-arm-gnueabihf/-/resolver-binding-linux-arm-gnueabihf-1.7.2.tgz", "integrity": "sha512-8N1z1TbPnHH+iDS/42GJ0bMPLiGK+cUqOhNbMKtWJ4oFGzqSJk/zoXFzcQkgtI63qMcUI7wW1tq2usZQSb2jxw==", +======= + "version": "1.7.11", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-linux-arm-gnueabihf/-/resolver-binding-linux-arm-gnueabihf-1.7.11.tgz", + "integrity": "sha512-1sGwpgvx+WZf0GFT6vkkOm6UJ+mlsVnjw+Yv9esK71idWeRAG3bbpkf3AoY8KIqKqmnzJExi0uKxXpakQ5Pcbg==", +>>>>>>> dev "cpu": [ "arm" ], @@ -5171,9 +5831,15 @@ ] }, "node_modules/@unrs/resolver-binding-linux-arm-musleabihf": { +<<<<<<< HEAD "version": "1.7.2", "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-linux-arm-musleabihf/-/resolver-binding-linux-arm-musleabihf-1.7.2.tgz", "integrity": "sha512-tjYzI9LcAXR9MYd9rO45m1s0B/6bJNuZ6jeOxo1pq1K6OBuRMMmfyvJYval3s9FPPGmrldYA3mi4gWDlWuTFGA==", +======= + "version": "1.7.11", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-linux-arm-musleabihf/-/resolver-binding-linux-arm-musleabihf-1.7.11.tgz", + "integrity": "sha512-D/1F/2lTe+XAl3ohkYj51NjniVly8sIqkA/n1aOND3ZMO418nl2JNU95iVa1/RtpzaKcWEsNTtHRogykrUflJg==", +>>>>>>> dev "cpu": [ "arm" ], @@ -5184,9 +5850,15 @@ ] }, "node_modules/@unrs/resolver-binding-linux-arm64-gnu": { +<<<<<<< HEAD "version": "1.7.2", "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-linux-arm64-gnu/-/resolver-binding-linux-arm64-gnu-1.7.2.tgz", "integrity": "sha512-jon9M7DKRLGZ9VYSkFMflvNqu9hDtOCEnO2QAryFWgT6o6AXU8du56V7YqnaLKr6rAbZBWYsYpikF226v423QA==", +======= + "version": "1.7.11", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-linux-arm64-gnu/-/resolver-binding-linux-arm64-gnu-1.7.11.tgz", + "integrity": "sha512-7vFWHLCCNFLEQlmwKQfVy066ohLLArZl+AV/AdmrD1/pD1FlmqM+FKbtnONnIwbHtgetFUCV/SRi1q4D49aTlw==", +>>>>>>> dev "cpu": [ "arm64" ], @@ -5197,9 +5869,15 @@ ] }, "node_modules/@unrs/resolver-binding-linux-arm64-musl": { +<<<<<<< HEAD "version": "1.7.2", "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-linux-arm64-musl/-/resolver-binding-linux-arm64-musl-1.7.2.tgz", "integrity": "sha512-c8Cg4/h+kQ63pL43wBNaVMmOjXI/X62wQmru51qjfTvI7kmCy5uHTJvK/9LrF0G8Jdx8r34d019P1DVJmhXQpA==", +======= + "version": "1.7.11", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-linux-arm64-musl/-/resolver-binding-linux-arm64-musl-1.7.11.tgz", + "integrity": "sha512-tYkGIx8hjWPh4zcn17jLEHU8YMmdP2obRTGkdaB3BguGHh31VCS3ywqC4QjTODjmhhNyZYkj/1Dz/+0kKvg9YA==", +>>>>>>> dev "cpu": [ "arm64" ], @@ -5210,9 +5888,15 @@ ] }, "node_modules/@unrs/resolver-binding-linux-ppc64-gnu": { +<<<<<<< HEAD "version": "1.7.2", "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-linux-ppc64-gnu/-/resolver-binding-linux-ppc64-gnu-1.7.2.tgz", "integrity": "sha512-A+lcwRFyrjeJmv3JJvhz5NbcCkLQL6Mk16kHTNm6/aGNc4FwPHPE4DR9DwuCvCnVHvF5IAd9U4VIs/VvVir5lg==", +======= + "version": "1.7.11", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-linux-ppc64-gnu/-/resolver-binding-linux-ppc64-gnu-1.7.11.tgz", + "integrity": "sha512-6F328QIUev29vcZeRX6v6oqKxfUoGwIIAhWGD8wSysnBYFY0nivp25jdWmAb1GildbCCaQvOKEhCok7YfWkj4Q==", +>>>>>>> dev "cpu": [ "ppc64" ], @@ -5223,9 +5907,15 @@ ] }, "node_modules/@unrs/resolver-binding-linux-riscv64-gnu": { +<<<<<<< HEAD "version": "1.7.2", "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-linux-riscv64-gnu/-/resolver-binding-linux-riscv64-gnu-1.7.2.tgz", "integrity": "sha512-hQQ4TJQrSQW8JlPm7tRpXN8OCNP9ez7PajJNjRD1ZTHQAy685OYqPrKjfaMw/8LiHCt8AZ74rfUVHP9vn0N69Q==", +======= + "version": "1.7.11", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-linux-riscv64-gnu/-/resolver-binding-linux-riscv64-gnu-1.7.11.tgz", + "integrity": "sha512-NqhWmiGJGdzbZbeucPZIG9Iav4lyYLCarEnxAceguMx9qlpeEF7ENqYKOwB8Zqk7/CeuYMEcLYMaW2li6HyDzQ==", +>>>>>>> dev "cpu": [ "riscv64" ], @@ -5236,9 +5926,15 @@ ] }, "node_modules/@unrs/resolver-binding-linux-riscv64-musl": { +<<<<<<< HEAD "version": "1.7.2", "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-linux-riscv64-musl/-/resolver-binding-linux-riscv64-musl-1.7.2.tgz", "integrity": "sha512-NoAGbiqrxtY8kVooZ24i70CjLDlUFI7nDj3I9y54U94p+3kPxwd2L692YsdLa+cqQ0VoqMWoehDFp21PKRUoIQ==", +======= + "version": "1.7.11", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-linux-riscv64-musl/-/resolver-binding-linux-riscv64-musl-1.7.11.tgz", + "integrity": "sha512-J2RPIFKMdTrLtBdfR1cUMKl8Gcy05nlQ+bEs/6al7EdWLk9cs3tnDREHZ7mV9uGbeghpjo4i8neNZNx3PYUY9w==", +>>>>>>> dev "cpu": [ "riscv64" ], @@ -5249,9 +5945,15 @@ ] }, "node_modules/@unrs/resolver-binding-linux-s390x-gnu": { +<<<<<<< HEAD "version": "1.7.2", "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-linux-s390x-gnu/-/resolver-binding-linux-s390x-gnu-1.7.2.tgz", "integrity": "sha512-KaZByo8xuQZbUhhreBTW+yUnOIHUsv04P8lKjQ5otiGoSJ17ISGYArc+4vKdLEpGaLbemGzr4ZeUbYQQsLWFjA==", +======= + "version": "1.7.11", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-linux-s390x-gnu/-/resolver-binding-linux-s390x-gnu-1.7.11.tgz", + "integrity": "sha512-bDpGRerHvvHdhun7MmFUNDpMiYcJSqWckwAVVRTJf8F+RyqYJOp/mx04PDc7DhpNPeWdnTMu91oZRMV+gGaVcQ==", +>>>>>>> dev "cpu": [ "s390x" ], @@ -5262,9 +5964,15 @@ ] }, "node_modules/@unrs/resolver-binding-linux-x64-gnu": { +<<<<<<< HEAD "version": "1.7.2", "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-linux-x64-gnu/-/resolver-binding-linux-x64-gnu-1.7.2.tgz", "integrity": "sha512-dEidzJDubxxhUCBJ/SHSMJD/9q7JkyfBMT77Px1npl4xpg9t0POLvnWywSk66BgZS/b2Hy9Y1yFaoMTFJUe9yg==", +======= + "version": "1.7.11", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-linux-x64-gnu/-/resolver-binding-linux-x64-gnu-1.7.11.tgz", + "integrity": "sha512-G9U7bVmylzRLma3cK39RBm3guoD1HOvY4o0NS4JNm37AD0lS7/xyMt7kn0JejYyc0Im8J+rH69/dXGM9DAJcSQ==", +>>>>>>> dev "cpu": [ "x64" ], @@ -5275,9 +5983,15 @@ ] }, "node_modules/@unrs/resolver-binding-linux-x64-musl": { +<<<<<<< HEAD "version": "1.7.2", "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-linux-x64-musl/-/resolver-binding-linux-x64-musl-1.7.2.tgz", "integrity": "sha512-RvP+Ux3wDjmnZDT4XWFfNBRVG0fMsc+yVzNFUqOflnDfZ9OYujv6nkh+GOr+watwrW4wdp6ASfG/e7bkDradsw==", +======= + "version": "1.7.11", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-linux-x64-musl/-/resolver-binding-linux-x64-musl-1.7.11.tgz", + "integrity": "sha512-7qL20SBKomekSunm7M9Fe5L93bFbn+FbHiGJbfTlp0RKhPVoJDP73vOxf1QrmJHyDPECsGWPFnKa/f8fO2FsHw==", +>>>>>>> dev "cpu": [ "x64" ], @@ -5288,25 +6002,41 @@ ] }, "node_modules/@unrs/resolver-binding-wasm32-wasi": { +<<<<<<< HEAD "version": "1.7.2", "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-wasm32-wasi/-/resolver-binding-wasm32-wasi-1.7.2.tgz", "integrity": "sha512-y797JBmO9IsvXVRCKDXOxjyAE4+CcZpla2GSoBQ33TVb3ILXuFnMrbR/QQZoauBYeOFuu4w3ifWLw52sdHGz6g==", +======= + "version": "1.7.11", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-wasm32-wasi/-/resolver-binding-wasm32-wasi-1.7.11.tgz", + "integrity": "sha512-jisvIva8MidjI+B1lFRZZMfCPaCISePgTyR60wNT1MeQvIh5Ksa0G3gvI+Iqyj3jqYbvOHByenpa5eDGcSdoSg==", +>>>>>>> dev "cpu": [ "wasm32" ], "license": "MIT", "optional": true, "dependencies": { +<<<<<<< HEAD "@napi-rs/wasm-runtime": "^0.2.9" +======= + "@napi-rs/wasm-runtime": "^0.2.10" +>>>>>>> dev }, "engines": { "node": ">=14.0.0" } }, "node_modules/@unrs/resolver-binding-win32-arm64-msvc": { +<<<<<<< HEAD "version": "1.7.2", "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-win32-arm64-msvc/-/resolver-binding-win32-arm64-msvc-1.7.2.tgz", "integrity": "sha512-gtYTh4/VREVSLA+gHrfbWxaMO/00y+34htY7XpioBTy56YN2eBjkPrY1ML1Zys89X3RJDKVaogzwxlM1qU7egg==", +======= + "version": "1.7.11", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-win32-arm64-msvc/-/resolver-binding-win32-arm64-msvc-1.7.11.tgz", + "integrity": "sha512-G+H5nQZ8sRZ8ebMY6mRGBBvTEzMYEcgVauLsNHpvTUavZoCCRVP1zWkCZgOju2dW3O22+8seTHniTdl1/uLz3g==", +>>>>>>> dev "cpu": [ "arm64" ], @@ -5317,9 +6047,15 @@ ] }, "node_modules/@unrs/resolver-binding-win32-ia32-msvc": { +<<<<<<< HEAD "version": "1.7.2", "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-win32-ia32-msvc/-/resolver-binding-win32-ia32-msvc-1.7.2.tgz", "integrity": "sha512-Ywv20XHvHTDRQs12jd3MY8X5C8KLjDbg/jyaal/QLKx3fAShhJyD4blEANInsjxW3P7isHx1Blt56iUDDJO3jg==", +======= + "version": "1.7.11", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-win32-ia32-msvc/-/resolver-binding-win32-ia32-msvc-1.7.11.tgz", + "integrity": "sha512-Hfy46DBfFzyv0wgR0MMOwFFib2W2+Btc8oE5h4XlPhpelnSyA6nFxkVIyTgIXYGTdFaLoZFNn62fmqx3rjEg3A==", +>>>>>>> dev "cpu": [ "ia32" ], @@ -5330,9 +6066,15 @@ ] }, "node_modules/@unrs/resolver-binding-win32-x64-msvc": { +<<<<<<< HEAD "version": "1.7.2", "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-win32-x64-msvc/-/resolver-binding-win32-x64-msvc-1.7.2.tgz", "integrity": "sha512-friS8NEQfHaDbkThxopGk+LuE5v3iY0StruifjQEt7SLbA46OnfgMO15sOTkbpJkol6RB+1l1TYPXh0sCddpvA==", +======= + "version": "1.7.11", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-win32-x64-msvc/-/resolver-binding-win32-x64-msvc-1.7.11.tgz", + "integrity": "sha512-7L8NdsQlCJ8T106Gbz/AjzM4QKWVsoQbKpB9bMBGcIZswUuAnJMHpvbqGW3RBqLHCIwX4XZ5fxSBHEFcK2h9wA==", +>>>>>>> dev "cpu": [ "x64" ], @@ -5447,9 +6189,15 @@ } }, "node_modules/arctic": { +<<<<<<< HEAD "version": "3.6.1", "resolved": "https://registry.npmjs.org/arctic/-/arctic-3.6.1.tgz", "integrity": "sha512-zM3a1Y+HAhdXF3MFtNnesyI4X4f0yW7SsNGVeR1gYyZ6TSqH1346GUMU4dNDplTEoxWOxEjl7wrhXgkNTqUacw==", +======= + "version": "3.7.0", + "resolved": "https://registry.npmjs.org/arctic/-/arctic-3.7.0.tgz", + "integrity": "sha512-ZMQ+f6VazDgUJOd+qNV+H7GohNSYal1mVjm5kEaZfE2Ifb7Ss70w+Q7xpJC87qZDkMZIXYf0pTIYZA0OPasSbw==", +>>>>>>> dev "license": "MIT", "dependencies": { "@oslojs/crypto": "1.0.1", @@ -5464,9 +6212,9 @@ "license": "Python-2.0" }, "node_modules/aria-hidden": { - "version": "1.2.4", - "resolved": "https://registry.npmjs.org/aria-hidden/-/aria-hidden-1.2.4.tgz", - "integrity": "sha512-y+CcFFwelSXpLZk/7fMB2mUbGtX9lKycf1MWJ7CaTIERyitVlyQx6C+sxcROU2BAJ24OiZyK+8wj2i8AlBoS3A==", + "version": "1.2.6", + "resolved": "https://registry.npmjs.org/aria-hidden/-/aria-hidden-1.2.6.tgz", + "integrity": "sha512-ik3ZgC9dY/lYVVM++OISsaYDeg1tb0VtP5uL3ouh1koGOaUMDPpbFIei4JkFimWUFPn90sbMNMXQAIVOlnYKJA==", "license": "MIT", "dependencies": { "tslib": "^2.0.0" @@ -5507,17 +6255,19 @@ "license": "MIT" }, "node_modules/array-includes": { - "version": "3.1.8", - "resolved": "https://registry.npmjs.org/array-includes/-/array-includes-3.1.8.tgz", - "integrity": "sha512-itaWrbYbqpGXkGhZPGUulwnhVf5Hpy1xiCFsGqyIGglbBxmG5vSjxQen3/WGOjPpNEv1RtBLKxbmVXm8HpJStQ==", + "version": "3.1.9", + "resolved": "https://registry.npmjs.org/array-includes/-/array-includes-3.1.9.tgz", + "integrity": "sha512-FmeCCAenzH0KH381SPT5FZmiA/TmpndpcaShhfgEN9eCVjnFBqq3l1xrI42y8+PPLI6hypzou4GXw00WHmPBLQ==", "license": "MIT", "dependencies": { - "call-bind": "^1.0.7", + "call-bind": "^1.0.8", + "call-bound": "^1.0.4", "define-properties": "^1.2.1", - "es-abstract": "^1.23.2", - "es-object-atoms": "^1.0.0", - "get-intrinsic": "^1.2.4", - "is-string": "^1.0.7" + "es-abstract": "^1.24.0", + "es-object-atoms": "^1.1.1", + "get-intrinsic": "^1.3.0", + "is-string": "^1.1.1", + "math-intrinsics": "^1.1.0" }, "engines": { "node": ">= 0.4" @@ -5714,9 +6464,9 @@ } }, "node_modules/axios": { - "version": "1.8.4", - "resolved": "https://registry.npmjs.org/axios/-/axios-1.8.4.tgz", - "integrity": "sha512-eBSYY4Y68NNlHbHBMdeDmKNtDgXWhQsJcGqzO3iLUM0GraQFSS9cVgPX5I9b3lbdFKyYoAEGAZF1DwhTaljNAw==", + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/axios/-/axios-1.9.0.tgz", + "integrity": "sha512-re4CqKTJaURpzbLHtIi6XpDv20/CnpXOtjRY5/CU32L8gU8ek9UIivcfvSWvmKEngmVbrUtPpdDwWDWL7DNHvg==", "license": "MIT", "dependencies": { "follow-redirects": "^1.15.6", @@ -5988,9 +6738,15 @@ } }, "node_modules/caniuse-lite": { +<<<<<<< HEAD "version": "1.0.30001717", "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001717.tgz", "integrity": "sha512-auPpttCq6BDEG8ZAuHJIplGw6GODhjw+/11e7IjpnYCxZcW/ONgPs0KVBJ0d1bY3e2+7PRe5RCLyP+PfwVgkYw==", +======= + "version": "1.0.30001721", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001721.tgz", + "integrity": "sha512-cOuvmUVtKrtEaoKiO0rSc29jcjwMwX5tOHDy4MgVFEWiUXj4uBMJkwI8MDySkgXidpMiHUcviogAvFi4pA2hDQ==", +>>>>>>> dev "funding": [ { "type": "opencollective", @@ -6053,6 +6809,10 @@ "version": "3.0.0", "resolved": "https://registry.npmjs.org/chownr/-/chownr-3.0.0.tgz", "integrity": "sha512-+IxzY9BZOQd/XuYPRmrvEVjF/nqj5kgT4kEq7VofrDoM1MxoRjEWkrCC3EtLi59TVawxTAn+orJwFQcrqEN1+g==", +<<<<<<< HEAD +======= + "dev": true, +>>>>>>> dev "license": "BlueOak-1.0.0", "engines": { "node": ">=18" @@ -6071,16 +6831,19 @@ } }, "node_modules/cli-cursor": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/cli-cursor/-/cli-cursor-3.1.0.tgz", - "integrity": "sha512-I/zHAwsKf9FqGoXM4WWRACob9+SNukZTd94DWF57E4toouRulbCxcUh6RKUEOQlYTHJnzkPMySvPNaaSLNfLZw==", + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/cli-cursor/-/cli-cursor-5.0.0.tgz", + "integrity": "sha512-aCj4O5wKyszjMmDT4tZj93kxyydN/K5zPWSCe6/0AV/AA1pqe5ZBIw0a2ZfPQV7lL5/yb5HsUreJ6UFAF1tEQw==", "dev": true, "license": "MIT", "dependencies": { - "restore-cursor": "^3.1.0" + "restore-cursor": "^5.0.0" }, "engines": { - "node": ">=8" + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, "node_modules/cli-spinners": { @@ -6103,78 +6866,71 @@ "license": "MIT" }, "node_modules/cliui": { - "version": "8.0.1", - "resolved": "https://registry.npmjs.org/cliui/-/cliui-8.0.1.tgz", - "integrity": "sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ==", + "version": "9.0.1", + "resolved": "https://registry.npmjs.org/cliui/-/cliui-9.0.1.tgz", + "integrity": "sha512-k7ndgKhwoQveBL+/1tqGJYNz097I7WOvwbmmU2AR5+magtbjPWQTS1C5vzGkBC8Ym8UWRzfKUzUUqFLypY4Q+w==", "dev": true, "license": "ISC", "dependencies": { - "string-width": "^4.2.0", - "strip-ansi": "^6.0.1", - "wrap-ansi": "^7.0.0" + "string-width": "^7.2.0", + "strip-ansi": "^7.1.0", + "wrap-ansi": "^9.0.0" }, "engines": { - "node": ">=12" + "node": ">=20" } }, - "node_modules/cliui/node_modules/ansi-regex": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", - "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", + "node_modules/cliui/node_modules/ansi-styles": { + "version": "6.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-6.2.1.tgz", + "integrity": "sha512-bN798gFfQX+viw3R7yrGWRqnrN2oRkEkUjjl4JNn4E8GxxbjtG3FbrEIIY3l8/hrwUwIeCZvi4QuOTP4MErVug==", "dev": true, "license": "MIT", "engines": { - "node": ">=8" + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" } }, "node_modules/cliui/node_modules/emoji-regex": { - "version": "8.0.0", - "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", - "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", + "version": "10.4.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-10.4.0.tgz", + "integrity": "sha512-EC+0oUMY1Rqm4O6LLrgjtYDvcVYTy7chDnM4Q7030tP4Kwj3u/pR6gP9ygnp2CJMK5Gq+9Q2oqmrFJAz01DXjw==", "dev": true, "license": "MIT" }, "node_modules/cliui/node_modules/string-width": { - "version": "4.2.3", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", - "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-7.2.0.tgz", + "integrity": "sha512-tsaTIkKW9b4N+AEj+SVA+WhJzV7/zMhcSu78mLKWSk7cXMOSHsBKFWUs0fWwq8QyK3MgJBQRX6Gbi4kYbdvGkQ==", "dev": true, "license": "MIT", "dependencies": { - "emoji-regex": "^8.0.0", - "is-fullwidth-code-point": "^3.0.0", - "strip-ansi": "^6.0.1" + "emoji-regex": "^10.3.0", + "get-east-asian-width": "^1.0.0", + "strip-ansi": "^7.1.0" }, "engines": { - "node": ">=8" - } - }, - "node_modules/cliui/node_modules/strip-ansi": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", - "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", - "dev": true, - "license": "MIT", - "dependencies": { - "ansi-regex": "^5.0.1" + "node": ">=18" }, - "engines": { - "node": ">=8" + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, "node_modules/cliui/node_modules/wrap-ansi": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", - "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", + "version": "9.0.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-9.0.0.tgz", + "integrity": "sha512-G8ura3S+3Z2G+mkgNRq8dqaFZAuxfsxpBB8OCTGRTCtp+l/v9nbFNmCUP1BZMts3G1142MsZfn6eeUKrr4PD1Q==", "dev": true, "license": "MIT", "dependencies": { - "ansi-styles": "^4.0.0", - "string-width": "^4.1.0", - "strip-ansi": "^6.0.0" + "ansi-styles": "^6.2.1", + "string-width": "^7.0.0", + "strip-ansi": "^7.1.0" }, "engines": { - "node": ">=10" + "node": ">=18" }, "funding": { "url": "https://github.com/chalk/wrap-ansi?sponsor=1" @@ -6199,15 +6955,15 @@ } }, "node_modules/cmdk": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/cmdk/-/cmdk-1.0.4.tgz", - "integrity": "sha512-AnsjfHyHpQ/EFeAnG216WY7A5LiYCoZzCSygiLvfXC3H3LFGCprErteUcszaVluGOhuOTbJS3jWHrSDYPBBygg==", + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/cmdk/-/cmdk-1.1.1.tgz", + "integrity": "sha512-Vsv7kFaXm+ptHDMZ7izaRsP70GgrW9NBNGswt9OZaVBLlE0SNpDq8eu/VGXyF9r7M0azK3Wy7OlYXsuyYLFzHg==", "license": "MIT", "dependencies": { - "@radix-ui/react-dialog": "^1.1.2", + "@radix-ui/react-compose-refs": "^1.1.1", + "@radix-ui/react-dialog": "^1.1.6", "@radix-ui/react-id": "^1.1.0", - "@radix-ui/react-primitive": "^2.0.0", - "use-sync-external-store": "^1.2.2" + "@radix-ui/react-primitive": "^2.0.2" }, "peerDependencies": { "react": "^18 || ^19 || ^19.0.0-rc", @@ -6518,9 +7274,9 @@ } }, "node_modules/debounce": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/debounce/-/debounce-2.0.0.tgz", - "integrity": "sha512-xRetU6gL1VJbs85Mc4FoEGSjQxzpdxRyFhe3lmWFyy2EzydIcD4xzUvRJMD+NPDfMwKNhxa3PvsIOU32luIWeA==", + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/debounce/-/debounce-2.2.0.tgz", + "integrity": "sha512-Xks6RUDLZFdz8LIdR6q0MTH44k7FikOmnh5xkSjMig6ch45afc8sjTjRQf3P6ax8dMgcQrYO/AR2RGWURrruqw==", "dev": true, "license": "MIT", "engines": { @@ -6531,9 +7287,9 @@ } }, "node_modules/debug": { - "version": "4.4.0", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.0.tgz", - "integrity": "sha512-6WTZ/IxCY/T6BALoZHaE4ctp9xm+Z5kY/pzYaCHRFeyVhojxlrm+46y68HA6hr0TcwEssoxNiDEUJQjfPZ/RYA==", + "version": "4.4.1", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.1.tgz", + "integrity": "sha512-KcKCqiftBJcZr++7ykoDIEwSa3XWowTfNPo92BYxjXiyYEVrUQh2aLyhxBCwww+heortUFxEJYcRzosstTEBYQ==", "license": "MIT", "dependencies": { "ms": "^2.1.3" @@ -6586,6 +7342,7 @@ "node": ">=0.10.0" } }, +<<<<<<< HEAD "node_modules/defaults": { "version": "1.0.4", "resolved": "https://registry.npmjs.org/defaults/-/defaults-1.0.4.tgz", @@ -6609,6 +7366,8 @@ "node": ">=0.8" } }, +======= +>>>>>>> dev "node_modules/define-data-property": { "version": "1.1.4", "resolved": "https://registry.npmjs.org/define-data-property/-/define-data-property-1.1.4.tgz", @@ -6780,452 +7539,21 @@ } }, "node_modules/drizzle-kit": { - "version": "0.30.6", - "resolved": "https://registry.npmjs.org/drizzle-kit/-/drizzle-kit-0.30.6.tgz", - "integrity": "sha512-U4wWit0fyZuGuP7iNmRleQyK2V8wCuv57vf5l3MnG4z4fzNTjY/U13M8owyQ5RavqvqxBifWORaR3wIUzlN64g==", + "version": "0.31.1", + "resolved": "https://registry.npmjs.org/drizzle-kit/-/drizzle-kit-0.31.1.tgz", + "integrity": "sha512-PUjYKWtzOzPtdtQlTHQG3qfv4Y0XT8+Eas6UbxCmxTj7qgMf+39dDujf1BP1I+qqZtw9uzwTh8jYtkMuCq+B0Q==", "dev": true, "license": "MIT", "dependencies": { "@drizzle-team/brocli": "^0.10.2", "@esbuild-kit/esm-loader": "^2.5.5", - "esbuild": "^0.19.7", - "esbuild-register": "^3.5.0", - "gel": "^2.0.0" + "esbuild": "^0.25.2", + "esbuild-register": "^3.5.0" }, "bin": { "drizzle-kit": "bin.cjs" } }, - "node_modules/drizzle-kit/node_modules/@esbuild/aix-ppc64": { - "version": "0.19.12", - "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.19.12.tgz", - "integrity": "sha512-bmoCYyWdEL3wDQIVbcyzRyeKLgk2WtWLTWz1ZIAZF/EGbNOwSA6ew3PftJ1PqMiOOGu0OyFMzG53L0zqIpPeNA==", - "cpu": [ - "ppc64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "aix" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/drizzle-kit/node_modules/@esbuild/android-arm": { - "version": "0.19.12", - "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.19.12.tgz", - "integrity": "sha512-qg/Lj1mu3CdQlDEEiWrlC4eaPZ1KztwGJ9B6J+/6G+/4ewxJg7gqj8eVYWvao1bXrqGiW2rsBZFSX3q2lcW05w==", - "cpu": [ - "arm" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "android" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/drizzle-kit/node_modules/@esbuild/android-arm64": { - "version": "0.19.12", - "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.19.12.tgz", - "integrity": "sha512-P0UVNGIienjZv3f5zq0DP3Nt2IE/3plFzuaS96vihvD0Hd6H/q4WXUGpCxD/E8YrSXfNyRPbpTq+T8ZQioSuPA==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "android" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/drizzle-kit/node_modules/@esbuild/android-x64": { - "version": "0.19.12", - "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.19.12.tgz", - "integrity": "sha512-3k7ZoUW6Q6YqhdhIaq/WZ7HwBpnFBlW905Fa4s4qWJyiNOgT1dOqDiVAQFwBH7gBRZr17gLrlFCRzF6jFh7Kew==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "android" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/drizzle-kit/node_modules/@esbuild/darwin-arm64": { - "version": "0.19.12", - "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.19.12.tgz", - "integrity": "sha512-B6IeSgZgtEzGC42jsI+YYu9Z3HKRxp8ZT3cqhvliEHovq8HSX2YX8lNocDn79gCKJXOSaEot9MVYky7AKjCs8g==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "darwin" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/drizzle-kit/node_modules/@esbuild/darwin-x64": { - "version": "0.19.12", - "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.19.12.tgz", - "integrity": "sha512-hKoVkKzFiToTgn+41qGhsUJXFlIjxI/jSYeZf3ugemDYZldIXIxhvwN6erJGlX4t5h417iFuheZ7l+YVn05N3A==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "darwin" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/drizzle-kit/node_modules/@esbuild/freebsd-arm64": { - "version": "0.19.12", - "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.19.12.tgz", - "integrity": "sha512-4aRvFIXmwAcDBw9AueDQ2YnGmz5L6obe5kmPT8Vd+/+x/JMVKCgdcRwH6APrbpNXsPz+K653Qg8HB/oXvXVukA==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "freebsd" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/drizzle-kit/node_modules/@esbuild/freebsd-x64": { - "version": "0.19.12", - "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.19.12.tgz", - "integrity": "sha512-EYoXZ4d8xtBoVN7CEwWY2IN4ho76xjYXqSXMNccFSx2lgqOG/1TBPW0yPx1bJZk94qu3tX0fycJeeQsKovA8gg==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "freebsd" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/drizzle-kit/node_modules/@esbuild/linux-arm": { - "version": "0.19.12", - "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.19.12.tgz", - "integrity": "sha512-J5jPms//KhSNv+LO1S1TX1UWp1ucM6N6XuL6ITdKWElCu8wXP72l9MM0zDTzzeikVyqFE6U8YAV9/tFyj0ti+w==", - "cpu": [ - "arm" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/drizzle-kit/node_modules/@esbuild/linux-arm64": { - "version": "0.19.12", - "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.19.12.tgz", - "integrity": "sha512-EoTjyYyLuVPfdPLsGVVVC8a0p1BFFvtpQDB/YLEhaXyf/5bczaGeN15QkR+O4S5LeJ92Tqotve7i1jn35qwvdA==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/drizzle-kit/node_modules/@esbuild/linux-ia32": { - "version": "0.19.12", - "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.19.12.tgz", - "integrity": "sha512-Thsa42rrP1+UIGaWz47uydHSBOgTUnwBwNq59khgIwktK6x60Hivfbux9iNR0eHCHzOLjLMLfUMLCypBkZXMHA==", - "cpu": [ - "ia32" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/drizzle-kit/node_modules/@esbuild/linux-loong64": { - "version": "0.19.12", - "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.19.12.tgz", - "integrity": "sha512-LiXdXA0s3IqRRjm6rV6XaWATScKAXjI4R4LoDlvO7+yQqFdlr1Bax62sRwkVvRIrwXxvtYEHHI4dm50jAXkuAA==", - "cpu": [ - "loong64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/drizzle-kit/node_modules/@esbuild/linux-mips64el": { - "version": "0.19.12", - "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.19.12.tgz", - "integrity": "sha512-fEnAuj5VGTanfJ07ff0gOA6IPsvrVHLVb6Lyd1g2/ed67oU1eFzL0r9WL7ZzscD+/N6i3dWumGE1Un4f7Amf+w==", - "cpu": [ - "mips64el" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/drizzle-kit/node_modules/@esbuild/linux-ppc64": { - "version": "0.19.12", - "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.19.12.tgz", - "integrity": "sha512-nYJA2/QPimDQOh1rKWedNOe3Gfc8PabU7HT3iXWtNUbRzXS9+vgB0Fjaqr//XNbd82mCxHzik2qotuI89cfixg==", - "cpu": [ - "ppc64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/drizzle-kit/node_modules/@esbuild/linux-riscv64": { - "version": "0.19.12", - "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.19.12.tgz", - "integrity": "sha512-2MueBrlPQCw5dVJJpQdUYgeqIzDQgw3QtiAHUC4RBz9FXPrskyyU3VI1hw7C0BSKB9OduwSJ79FTCqtGMWqJHg==", - "cpu": [ - "riscv64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/drizzle-kit/node_modules/@esbuild/linux-s390x": { - "version": "0.19.12", - "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.19.12.tgz", - "integrity": "sha512-+Pil1Nv3Umes4m3AZKqA2anfhJiVmNCYkPchwFJNEJN5QxmTs1uzyy4TvmDrCRNT2ApwSari7ZIgrPeUx4UZDg==", - "cpu": [ - "s390x" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/drizzle-kit/node_modules/@esbuild/linux-x64": { - "version": "0.19.12", - "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.19.12.tgz", - "integrity": "sha512-B71g1QpxfwBvNrfyJdVDexenDIt1CiDN1TIXLbhOw0KhJzE78KIFGX6OJ9MrtC0oOqMWf+0xop4qEU8JrJTwCg==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/drizzle-kit/node_modules/@esbuild/netbsd-x64": { - "version": "0.19.12", - "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.19.12.tgz", - "integrity": "sha512-3ltjQ7n1owJgFbuC61Oj++XhtzmymoCihNFgT84UAmJnxJfm4sYCiSLTXZtE00VWYpPMYc+ZQmB6xbSdVh0JWA==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "netbsd" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/drizzle-kit/node_modules/@esbuild/openbsd-x64": { - "version": "0.19.12", - "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.19.12.tgz", - "integrity": "sha512-RbrfTB9SWsr0kWmb9srfF+L933uMDdu9BIzdA7os2t0TXhCRjrQyCeOt6wVxr79CKD4c+p+YhCj31HBkYcXebw==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "openbsd" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/drizzle-kit/node_modules/@esbuild/sunos-x64": { - "version": "0.19.12", - "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.19.12.tgz", - "integrity": "sha512-HKjJwRrW8uWtCQnQOz9qcU3mUZhTUQvi56Q8DPTLLB+DawoiQdjsYq+j+D3s9I8VFtDr+F9CjgXKKC4ss89IeA==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "sunos" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/drizzle-kit/node_modules/@esbuild/win32-arm64": { - "version": "0.19.12", - "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.19.12.tgz", - "integrity": "sha512-URgtR1dJnmGvX864pn1B2YUYNzjmXkuJOIqG2HdU62MVS4EHpU2946OZoTMnRUHklGtJdJZ33QfzdjGACXhn1A==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "win32" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/drizzle-kit/node_modules/@esbuild/win32-ia32": { - "version": "0.19.12", - "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.19.12.tgz", - "integrity": "sha512-+ZOE6pUkMOJfmxmBZElNOx72NKpIa/HFOMGzu8fqzQJ5kgf6aTGrcJaFsNiVMH4JKpMipyK+7k0n2UXN7a8YKQ==", - "cpu": [ - "ia32" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "win32" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/drizzle-kit/node_modules/@esbuild/win32-x64": { - "version": "0.19.12", - "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.19.12.tgz", - "integrity": "sha512-T1QyPSDCyMXaO3pzBkF96E8xMkiRYbUEZADd29SyPGabqxMViNoii+NcK7eWJAEoU6RZyEm5lVSIjTmcdoB9HA==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "win32" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/drizzle-kit/node_modules/esbuild": { - "version": "0.19.12", - "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.19.12.tgz", - "integrity": "sha512-aARqgq8roFBj054KvQr5f1sFu0D65G+miZRCuJyJ0G13Zwx7vRar5Zhn2tkQNzIXcBrNVsv/8stehpj+GAjgbg==", - "dev": true, - "hasInstallScript": true, - "license": "MIT", - "bin": { - "esbuild": "bin/esbuild" - }, - "engines": { - "node": ">=12" - }, - "optionalDependencies": { - "@esbuild/aix-ppc64": "0.19.12", - "@esbuild/android-arm": "0.19.12", - "@esbuild/android-arm64": "0.19.12", - "@esbuild/android-x64": "0.19.12", - "@esbuild/darwin-arm64": "0.19.12", - "@esbuild/darwin-x64": "0.19.12", - "@esbuild/freebsd-arm64": "0.19.12", - "@esbuild/freebsd-x64": "0.19.12", - "@esbuild/linux-arm": "0.19.12", - "@esbuild/linux-arm64": "0.19.12", - "@esbuild/linux-ia32": "0.19.12", - "@esbuild/linux-loong64": "0.19.12", - "@esbuild/linux-mips64el": "0.19.12", - "@esbuild/linux-ppc64": "0.19.12", - "@esbuild/linux-riscv64": "0.19.12", - "@esbuild/linux-s390x": "0.19.12", - "@esbuild/linux-x64": "0.19.12", - "@esbuild/netbsd-x64": "0.19.12", - "@esbuild/openbsd-x64": "0.19.12", - "@esbuild/sunos-x64": "0.19.12", - "@esbuild/win32-arm64": "0.19.12", - "@esbuild/win32-ia32": "0.19.12", - "@esbuild/win32-x64": "0.19.12" - } - }, "node_modules/drizzle-orm": { "version": "0.38.3", "resolved": "https://registry.npmjs.org/drizzle-orm/-/drizzle-orm-0.38.3.tgz", @@ -7381,16 +7709,22 @@ } }, "node_modules/eciesjs": { +<<<<<<< HEAD "version": "0.4.14", "resolved": "https://registry.npmjs.org/eciesjs/-/eciesjs-0.4.14.tgz", "integrity": "sha512-eJAgf9pdv214Hn98FlUzclRMYWF7WfoLlkS9nWMTm1qcCwn6Ad4EGD9lr9HXMBfSrZhYQujRE+p0adPRkctC6A==", +======= + "version": "0.4.15", + "resolved": "https://registry.npmjs.org/eciesjs/-/eciesjs-0.4.15.tgz", + "integrity": "sha512-r6kEJXDKecVOCj2nLMuXK/FCPeurW33+3JRpfXVbjLja3XUYFfD9I/JBreH6sUyzcm3G/YQboBjMla6poKeSdA==", +>>>>>>> dev "dev": true, "license": "MIT", "dependencies": { - "@ecies/ciphers": "^0.2.2", - "@noble/ciphers": "^1.0.0", - "@noble/curves": "^1.6.0", - "@noble/hashes": "^1.5.0" + "@ecies/ciphers": "^0.2.3", + "@noble/ciphers": "^1.3.0", + "@noble/curves": "^1.9.1", + "@noble/hashes": "^1.8.0" }, "engines": { "bun": ">=1", @@ -7541,41 +7875,28 @@ "url": "https://github.com/fb55/entities?sponsor=1" } }, - "node_modules/env-paths": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/env-paths/-/env-paths-3.0.0.tgz", - "integrity": "sha512-dtJUTepzMW3Lm/NPxRf3wP4642UWhjL2sQxc+ym2YMj1m/H2zDNQOlezafzkHwn6sMstjHTwG6iQQsctDW/b1A==", - "dev": true, - "license": "MIT", - "engines": { - "node": "^12.20.0 || ^14.13.1 || >=16.0.0" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, "node_modules/es-abstract": { - "version": "1.23.9", - "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.23.9.tgz", - "integrity": "sha512-py07lI0wjxAC/DcfK1S6G7iANonniZwTISvdPzk9hzeH0IZIshbuuFxLIU96OyF89Yb9hiqWn8M/bY83KY5vzA==", + "version": "1.24.0", + "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.24.0.tgz", + "integrity": "sha512-WSzPgsdLtTcQwm4CROfS5ju2Wa1QQcVeT37jFjYzdFz1r9ahadC8B8/a4qxJxM+09F18iumCdRmlr96ZYkQvEg==", "license": "MIT", "dependencies": { "array-buffer-byte-length": "^1.0.2", "arraybuffer.prototype.slice": "^1.0.4", "available-typed-arrays": "^1.0.7", "call-bind": "^1.0.8", - "call-bound": "^1.0.3", + "call-bound": "^1.0.4", "data-view-buffer": "^1.0.2", "data-view-byte-length": "^1.0.2", "data-view-byte-offset": "^1.0.1", "es-define-property": "^1.0.1", "es-errors": "^1.3.0", - "es-object-atoms": "^1.0.0", + "es-object-atoms": "^1.1.1", "es-set-tostringtag": "^2.1.0", "es-to-primitive": "^1.3.0", "function.prototype.name": "^1.1.8", - "get-intrinsic": "^1.2.7", - "get-proto": "^1.0.0", + "get-intrinsic": "^1.3.0", + "get-proto": "^1.0.1", "get-symbol-description": "^1.1.0", "globalthis": "^1.0.4", "gopd": "^1.2.0", @@ -7587,21 +7908,24 @@ "is-array-buffer": "^3.0.5", "is-callable": "^1.2.7", "is-data-view": "^1.0.2", + "is-negative-zero": "^2.0.3", "is-regex": "^1.2.1", + "is-set": "^2.0.3", "is-shared-array-buffer": "^1.0.4", "is-string": "^1.1.1", "is-typed-array": "^1.1.15", - "is-weakref": "^1.1.0", + "is-weakref": "^1.1.1", "math-intrinsics": "^1.1.0", - "object-inspect": "^1.13.3", + "object-inspect": "^1.13.4", "object-keys": "^1.1.1", "object.assign": "^4.1.7", "own-keys": "^1.0.1", - "regexp.prototype.flags": "^1.5.3", + "regexp.prototype.flags": "^1.5.4", "safe-array-concat": "^1.1.3", "safe-push-apply": "^1.0.0", "safe-regex-test": "^1.1.0", "set-proto": "^1.0.0", + "stop-iteration-iterator": "^1.1.0", "string.prototype.trim": "^1.2.10", "string.prototype.trimend": "^1.0.9", "string.prototype.trimstart": "^1.0.8", @@ -7610,7 +7934,7 @@ "typed-array-byte-offset": "^1.0.4", "typed-array-length": "^1.0.7", "unbox-primitive": "^1.1.0", - "which-typed-array": "^1.1.18" + "which-typed-array": "^1.1.19" }, "engines": { "node": ">= 0.4" @@ -7721,9 +8045,9 @@ } }, "node_modules/esbuild": { - "version": "0.25.2", - "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.25.2.tgz", - "integrity": "sha512-16854zccKPnC+toMywC+uKNeYSv+/eXkevRAfwRD/G9Cleq66m8XFIrigkbvauLLlCfDL45Q2cWegSg53gGBnQ==", + "version": "0.25.5", + "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.25.5.tgz", + "integrity": "sha512-P8OtKZRv/5J5hhz0cUAdu/cLuPIKXpQl1R9pZtvmHWQvrAUVd0UNIPT4IB4W3rNOqVO0rlqHmCIbSwxh/c9yUQ==", "dev": true, "hasInstallScript": true, "license": "MIT", @@ -7734,31 +8058,31 @@ "node": ">=18" }, "optionalDependencies": { - "@esbuild/aix-ppc64": "0.25.2", - "@esbuild/android-arm": "0.25.2", - "@esbuild/android-arm64": "0.25.2", - "@esbuild/android-x64": "0.25.2", - "@esbuild/darwin-arm64": "0.25.2", - "@esbuild/darwin-x64": "0.25.2", - "@esbuild/freebsd-arm64": "0.25.2", - "@esbuild/freebsd-x64": "0.25.2", - "@esbuild/linux-arm": "0.25.2", - "@esbuild/linux-arm64": "0.25.2", - "@esbuild/linux-ia32": "0.25.2", - "@esbuild/linux-loong64": "0.25.2", - "@esbuild/linux-mips64el": "0.25.2", - "@esbuild/linux-ppc64": "0.25.2", - "@esbuild/linux-riscv64": "0.25.2", - "@esbuild/linux-s390x": "0.25.2", - "@esbuild/linux-x64": "0.25.2", - "@esbuild/netbsd-arm64": "0.25.2", - "@esbuild/netbsd-x64": "0.25.2", - "@esbuild/openbsd-arm64": "0.25.2", - "@esbuild/openbsd-x64": "0.25.2", - "@esbuild/sunos-x64": "0.25.2", - "@esbuild/win32-arm64": "0.25.2", - "@esbuild/win32-ia32": "0.25.2", - "@esbuild/win32-x64": "0.25.2" + "@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" } }, "node_modules/esbuild-node-externals": { @@ -7819,21 +8143,22 @@ } }, "node_modules/eslint": { - "version": "9.17.0", - "resolved": "https://registry.npmjs.org/eslint/-/eslint-9.17.0.tgz", - "integrity": "sha512-evtlNcpJg+cZLcnVKwsai8fExnqjGPicK7gnUtlNuzu+Fv9bI0aLpND5T44VLQtoMEnI57LoXO9XAkIXwohKrA==", + "version": "9.28.0", + "resolved": "https://registry.npmjs.org/eslint/-/eslint-9.28.0.tgz", + "integrity": "sha512-ocgh41VhRlf9+fVpe7QKzwLj9c92fDiqOj8Y3Sd4/ZmVA4Btx4PlUYPq4pp9JDyupkf1upbEXecxL2mwNV7jPQ==", "license": "MIT", "dependencies": { "@eslint-community/eslint-utils": "^4.2.0", "@eslint-community/regexpp": "^4.12.1", - "@eslint/config-array": "^0.19.0", - "@eslint/core": "^0.9.0", - "@eslint/eslintrc": "^3.2.0", - "@eslint/js": "9.17.0", - "@eslint/plugin-kit": "^0.2.3", + "@eslint/config-array": "^0.20.0", + "@eslint/config-helpers": "^0.2.1", + "@eslint/core": "^0.14.0", + "@eslint/eslintrc": "^3.3.1", + "@eslint/js": "9.28.0", + "@eslint/plugin-kit": "^0.3.1", "@humanfs/node": "^0.16.6", "@humanwhocodes/module-importer": "^1.0.1", - "@humanwhocodes/retry": "^0.4.1", + "@humanwhocodes/retry": "^0.4.2", "@types/estree": "^1.0.6", "@types/json-schema": "^7.0.15", "ajv": "^6.12.4", @@ -7841,7 +8166,7 @@ "cross-spawn": "^7.0.6", "debug": "^4.3.2", "escape-string-regexp": "^4.0.0", - "eslint-scope": "^8.2.0", + "eslint-scope": "^8.3.0", "eslint-visitor-keys": "^4.2.0", "espree": "^10.3.0", "esquery": "^1.5.0", @@ -7878,12 +8203,12 @@ } }, "node_modules/eslint-config-next": { - "version": "15.1.3", - "resolved": "https://registry.npmjs.org/eslint-config-next/-/eslint-config-next-15.1.3.tgz", - "integrity": "sha512-wGYlNuWnh4ujuKtZvH+7B2Z2vy9nONZE6ztd+DKF7hAsIabkrxmD4TzYHzASHENo42lmz2tnT2B+zN2sOHvpJg==", + "version": "15.3.3", + "resolved": "https://registry.npmjs.org/eslint-config-next/-/eslint-config-next-15.3.3.tgz", + "integrity": "sha512-QJLv/Ouk2vZnxL4b67njJwTLjTf7uZRltI0LL4GERYR4qMF5z08+gxkfODAeaK7TiC6o+cER91bDaEnwrTWV6Q==", "license": "MIT", "dependencies": { - "@next/eslint-plugin-next": "15.1.3", + "@next/eslint-plugin-next": "15.3.3", "@rushstack/eslint-patch": "^1.10.3", "@typescript-eslint/eslint-plugin": "^5.4.2 || ^6.0.0 || ^7.0.0 || ^8.0.0", "@typescript-eslint/parser": "^5.4.2 || ^6.0.0 || ^7.0.0 || ^8.0.0", @@ -8404,9 +8729,15 @@ } }, "node_modules/fdir": { +<<<<<<< HEAD "version": "6.4.4", "resolved": "https://registry.npmjs.org/fdir/-/fdir-6.4.4.tgz", "integrity": "sha512-1NZP+GK4GfuAv3PqKvxQRDMjdSRZjnkq7KfhlNrCNNlZ0ygQFpebfrnfnq/W7fpUnAv9aGWmY1zKx7FYL3gwhg==", +======= + "version": "6.4.5", + "resolved": "https://registry.npmjs.org/fdir/-/fdir-6.4.5.tgz", + "integrity": "sha512-4BG7puHpVsIYxZUbiUE3RqGloLaSSwzYie5jvasC4LWuBWzZawynvYouhjbQKw2JuIGYdm0DzIxl8iVidKlUEw==", +>>>>>>> dev "license": "MIT", "peerDependencies": { "picomatch": "^3 || ^4" @@ -8623,14 +8954,24 @@ } }, "node_modules/form-data": { +<<<<<<< HEAD "version": "4.0.2", "resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.2.tgz", "integrity": "sha512-hGfm/slu0ZabnNt4oaRZ6uREyfCj6P4fT/n6A1rGV+Z0VdGXjfOhVUpkn6qVQONHGIFwmveGXyDs75+nr6FM8w==", +======= + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.3.tgz", + "integrity": "sha512-qsITQPfmvMOSAdeyZ+12I1c+CKSstAFAwu+97zrnWAbIr5u8wfsExUzCesVLC8NgHuRUqNN4Zy6UPWUTRGslcA==", +>>>>>>> dev "license": "MIT", "dependencies": { "asynckit": "^0.4.0", "combined-stream": "^1.0.8", "es-set-tostringtag": "^2.1.0", +<<<<<<< HEAD +======= + "hasown": "^2.0.2", +>>>>>>> dev "mime-types": "^2.1.12" }, "engines": { @@ -8733,6 +9074,7 @@ "url": "https://github.com/sponsors/ljharb" } }, +<<<<<<< HEAD "node_modules/gel": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/gel/-/gel-2.1.0.tgz", @@ -8754,6 +9096,8 @@ "node": ">= 18.0.0" } }, +======= +>>>>>>> dev "node_modules/get-caller-file": { "version": "2.0.5", "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz", @@ -8764,6 +9108,19 @@ "node": "6.* || 8.* || >= 10.*" } }, + "node_modules/get-east-asian-width": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/get-east-asian-width/-/get-east-asian-width-1.3.0.tgz", + "integrity": "sha512-vpeMIQKxczTD/0s2CdEWHcb0eeJe6TFjxb+J5xgX7hScxqrGuyjmv4c1D4A/gelKfyox0gJJwIHF+fLjeaM8kQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/get-intrinsic": { "version": "1.3.0", "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.3.0.tgz", @@ -8841,9 +9198,9 @@ } }, "node_modules/get-tsconfig": { - "version": "4.10.0", - "resolved": "https://registry.npmjs.org/get-tsconfig/-/get-tsconfig-4.10.0.tgz", - "integrity": "sha512-kGzZ3LWWQcGIAmg6iWvXn0ei6WDtV26wzHRMwDSzmAbcXrTEXxHy6IehI6/4eT6VRKyMP1eF1VqwrVUmE/LR7A==", + "version": "4.10.1", + "resolved": "https://registry.npmjs.org/get-tsconfig/-/get-tsconfig-4.10.1.tgz", + "integrity": "sha512-auHyJ4AgMz7vgS8Hp3N6HXSmlMdUyhSUrfBF16w153rxtLIEOE+HGqaBppczZvnHLqQJfiHotCYpNhl0lUROFQ==", "license": "MIT", "dependencies": { "resolve-pkg-maps": "^1.0.0" @@ -8859,9 +9216,9 @@ "license": "MIT" }, "node_modules/glob": { - "version": "11.0.0", - "resolved": "https://registry.npmjs.org/glob/-/glob-11.0.0.tgz", - "integrity": "sha512-9UiX/Bl6J2yaBbxKoEBRm4Cipxgok8kQYcOPEhScPwebu2I0HoQOuYdIO6S3hLuWoZgpDpwQZMzTFxgpkyT76g==", + "version": "11.0.2", + "resolved": "https://registry.npmjs.org/glob/-/glob-11.0.2.tgz", + "integrity": "sha512-YT7U7Vye+t5fZ/QMkBFrTJ7ZQxInIUjwyAjVj84CYXqgBdv30MFUPGnBR6sQaVq6Is15wYJUsnzTuWaGRBhBAQ==", "license": "ISC", "dependencies": { "foreground-child": "^3.1.0", @@ -8982,6 +9339,7 @@ "version": "4.2.11", "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.11.tgz", "integrity": "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==", + "dev": true, "license": "ISC" }, "node_modules/graphemer": { @@ -9078,9 +9436,9 @@ } }, "node_modules/helmet": { - "version": "8.0.0", - "resolved": "https://registry.npmjs.org/helmet/-/helmet-8.0.0.tgz", - "integrity": "sha512-VyusHLEIIO5mjQPUI1wpOAEu+wl6Q0998jzTxqUYGE45xCIcAxy3MsbEK/yyJUJ3ADeMoB6MornPH6GMWAf+Pw==", + "version": "8.1.0", + "resolved": "https://registry.npmjs.org/helmet/-/helmet-8.1.0.tgz", + "integrity": "sha512-jOiHyAZsmnr8LqoPGmCjYAaiuWwjAPLgY8ZX2XrmHawt99/u1y6RgrZMTeoPfpUbV96HOalYgz1qzkRbw54Pmg==", "license": "MIT", "engines": { "node": ">=18.0.0" @@ -9234,9 +9592,9 @@ "license": "ISC" }, "node_modules/input-otp": { - "version": "1.4.1", - "resolved": "https://registry.npmjs.org/input-otp/-/input-otp-1.4.1.tgz", - "integrity": "sha512-+yvpmKYKHi9jIGngxagY9oWiiblPB7+nEO75F2l2o4vs+6vpPZZmUl4tBNYuTCvQjhvEIbdNeJu70bhfYP2nbw==", + "version": "1.4.2", + "resolved": "https://registry.npmjs.org/input-otp/-/input-otp-1.4.2.tgz", + "integrity": "sha512-l3jWwYNvrEa6NTCt7BECfCm48GvwuZzkoeG3gBL2w4CHeOXW3eKFmf9UNYkNfYc3mxMrthMnxjIE07MT0zLBQA==", "license": "MIT", "peerDependencies": { "react": "^16.8 || ^17.0 || ^18.0 || ^19.0.0 || ^19.0.0-rc", @@ -9359,6 +9717,7 @@ "license": "MIT", "dependencies": { "semver": "^7.7.1" +<<<<<<< HEAD } }, "node_modules/is-bun-module/node_modules/semver": { @@ -9371,6 +9730,8 @@ }, "engines": { "node": ">=10" +======= +>>>>>>> dev } }, "node_modules/is-callable": { @@ -9497,13 +9858,16 @@ } }, "node_modules/is-interactive": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-interactive/-/is-interactive-1.0.0.tgz", - "integrity": "sha512-2HvIEKRoqS62guEC+qBjpvRubdX910WCMuJTZ+I9yvqKU2/12eSL549HMwtabb4oupdj2sMP50k+XJfB/8JE6w==", + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/is-interactive/-/is-interactive-2.0.0.tgz", + "integrity": "sha512-qP1vozQRI+BMOPcjFzrjXuQvdak2pHNUMZoeG2eRbiSqyvbEf/wQtEOTOX1guk6E3t36RkaqiSt8A/6YElNxLQ==", "dev": true, "license": "MIT", "engines": { - "node": ">=8" + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, "node_modules/is-map": { @@ -9518,6 +9882,18 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/is-negative-zero": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/is-negative-zero/-/is-negative-zero-2.0.3.tgz", + "integrity": "sha512-5KoIu2Ngpyek75jXodFvnafB6DJgr3u8uuK0LEZJjrU19DrMD3EVERaR8sjz8CCGgpZvxPl9SuE1GMVPFHx1mw==", + "license": "MIT", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/is-number": { "version": "7.0.0", "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", @@ -9649,13 +10025,13 @@ } }, "node_modules/is-unicode-supported": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/is-unicode-supported/-/is-unicode-supported-0.1.0.tgz", - "integrity": "sha512-knxG2q4UC3u8stRGyAVJCOdxFmv5DZiRcdlIaAQXAbSfJya+OhopNotLQrstBhququ4ZpuKbDc/8S6mgXgPFPw==", + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/is-unicode-supported/-/is-unicode-supported-2.1.0.tgz", + "integrity": "sha512-mE00Gnza5EEB3Ds0HfMyllZzbBrmLOX3vfWoj9A9PEnTfratQ/BcaJOuMhnkhjXvb2+FkY3VuHqtAGpTPmglFQ==", "dev": true, "license": "MIT", "engines": { - "node": ">=10" + "node": ">=18" }, "funding": { "url": "https://github.com/sponsors/sindresorhus" @@ -9737,9 +10113,15 @@ } }, "node_modules/jackspeak": { +<<<<<<< HEAD "version": "4.1.0", "resolved": "https://registry.npmjs.org/jackspeak/-/jackspeak-4.1.0.tgz", "integrity": "sha512-9DDdhb5j6cpeitCbvLO7n7J4IxnbM6hoF6O1g4HQ5TfhvvKN8ywDM7668ZhMHRqVmxqhps/F6syWK2KcPxYlkw==", +======= + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/jackspeak/-/jackspeak-4.1.1.tgz", + "integrity": "sha512-zptv57P3GpL+O0I7VdMJNBZCu+BPHVQUk55Ft8/QCJjTVxrnJHuVuX/0Bl2A6/+2oyR/ZMEuFKwmzqqZ/U5nPQ==", +>>>>>>> dev "license": "BlueOak-1.0.0", "dependencies": { "@isaacs/cliui": "^8.0.2" @@ -9957,9 +10339,9 @@ } }, "node_modules/lightningcss": { - "version": "1.29.2", - "resolved": "https://registry.npmjs.org/lightningcss/-/lightningcss-1.29.2.tgz", - "integrity": "sha512-6b6gd/RUXKaw5keVdSEtqFVdzWnU5jMxTUjA2bVcMNPLwSQ08Sv/UodBVtETLCn7k4S1Ibxwh7k68IwLZPgKaA==", + "version": "1.30.1", + "resolved": "https://registry.npmjs.org/lightningcss/-/lightningcss-1.30.1.tgz", + "integrity": "sha512-xi6IyHML+c9+Q3W0S4fCQJOym42pyurFiJUHEcEyHS0CeKzia4yZDEsLlqOFykxOdHpNy0NmvVO31vcSqAxJCg==", "dev": true, "license": "MPL-2.0", "dependencies": { @@ -9973,22 +10355,22 @@ "url": "https://opencollective.com/parcel" }, "optionalDependencies": { - "lightningcss-darwin-arm64": "1.29.2", - "lightningcss-darwin-x64": "1.29.2", - "lightningcss-freebsd-x64": "1.29.2", - "lightningcss-linux-arm-gnueabihf": "1.29.2", - "lightningcss-linux-arm64-gnu": "1.29.2", - "lightningcss-linux-arm64-musl": "1.29.2", - "lightningcss-linux-x64-gnu": "1.29.2", - "lightningcss-linux-x64-musl": "1.29.2", - "lightningcss-win32-arm64-msvc": "1.29.2", - "lightningcss-win32-x64-msvc": "1.29.2" + "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" } }, "node_modules/lightningcss-darwin-arm64": { - "version": "1.29.2", - "resolved": "https://registry.npmjs.org/lightningcss-darwin-arm64/-/lightningcss-darwin-arm64-1.29.2.tgz", - "integrity": "sha512-cK/eMabSViKn/PG8U/a7aCorpeKLMlK0bQeNHmdb7qUnBkNPnL+oV5DjJUo0kqWsJUapZsM4jCfYItbqBDvlcA==", + "version": "1.30.1", + "resolved": "https://registry.npmjs.org/lightningcss-darwin-arm64/-/lightningcss-darwin-arm64-1.30.1.tgz", + "integrity": "sha512-c8JK7hyE65X1MHMN+Viq9n11RRC7hgin3HhYKhrMyaXflk5GVplZ60IxyoVtzILeKr+xAJwg6zK6sjTBJ0FKYQ==", "cpu": [ "arm64" ], @@ -10007,9 +10389,9 @@ } }, "node_modules/lightningcss-darwin-x64": { - "version": "1.29.2", - "resolved": "https://registry.npmjs.org/lightningcss-darwin-x64/-/lightningcss-darwin-x64-1.29.2.tgz", - "integrity": "sha512-j5qYxamyQw4kDXX5hnnCKMf3mLlHvG44f24Qyi2965/Ycz829MYqjrVg2H8BidybHBp9kom4D7DR5VqCKDXS0w==", + "version": "1.30.1", + "resolved": "https://registry.npmjs.org/lightningcss-darwin-x64/-/lightningcss-darwin-x64-1.30.1.tgz", + "integrity": "sha512-k1EvjakfumAQoTfcXUcHQZhSpLlkAuEkdMBsI/ivWw9hL+7FtilQc0Cy3hrx0AAQrVtQAbMI7YjCgYgvn37PzA==", "cpu": [ "x64" ], @@ -10028,9 +10410,9 @@ } }, "node_modules/lightningcss-freebsd-x64": { - "version": "1.29.2", - "resolved": "https://registry.npmjs.org/lightningcss-freebsd-x64/-/lightningcss-freebsd-x64-1.29.2.tgz", - "integrity": "sha512-wDk7M2tM78Ii8ek9YjnY8MjV5f5JN2qNVO+/0BAGZRvXKtQrBC4/cn4ssQIpKIPP44YXw6gFdpUF+Ps+RGsCwg==", + "version": "1.30.1", + "resolved": "https://registry.npmjs.org/lightningcss-freebsd-x64/-/lightningcss-freebsd-x64-1.30.1.tgz", + "integrity": "sha512-kmW6UGCGg2PcyUE59K5r0kWfKPAVy4SltVeut+umLCFoJ53RdCUWxcRDzO1eTaxf/7Q2H7LTquFHPL5R+Gjyig==", "cpu": [ "x64" ], @@ -10049,9 +10431,9 @@ } }, "node_modules/lightningcss-linux-arm-gnueabihf": { - "version": "1.29.2", - "resolved": "https://registry.npmjs.org/lightningcss-linux-arm-gnueabihf/-/lightningcss-linux-arm-gnueabihf-1.29.2.tgz", - "integrity": "sha512-IRUrOrAF2Z+KExdExe3Rz7NSTuuJ2HvCGlMKoquK5pjvo2JY4Rybr+NrKnq0U0hZnx5AnGsuFHjGnNT14w26sg==", + "version": "1.30.1", + "resolved": "https://registry.npmjs.org/lightningcss-linux-arm-gnueabihf/-/lightningcss-linux-arm-gnueabihf-1.30.1.tgz", + "integrity": "sha512-MjxUShl1v8pit+6D/zSPq9S9dQ2NPFSQwGvxBCYaBYLPlCWuPh9/t1MRS8iUaR8i+a6w7aps+B4N0S1TYP/R+Q==", "cpu": [ "arm" ], @@ -10070,9 +10452,9 @@ } }, "node_modules/lightningcss-linux-arm64-gnu": { - "version": "1.29.2", - "resolved": "https://registry.npmjs.org/lightningcss-linux-arm64-gnu/-/lightningcss-linux-arm64-gnu-1.29.2.tgz", - "integrity": "sha512-KKCpOlmhdjvUTX/mBuaKemp0oeDIBBLFiU5Fnqxh1/DZ4JPZi4evEH7TKoSBFOSOV3J7iEmmBaw/8dpiUvRKlQ==", + "version": "1.30.1", + "resolved": "https://registry.npmjs.org/lightningcss-linux-arm64-gnu/-/lightningcss-linux-arm64-gnu-1.30.1.tgz", + "integrity": "sha512-gB72maP8rmrKsnKYy8XUuXi/4OctJiuQjcuqWNlJQ6jZiWqtPvqFziskH3hnajfvKB27ynbVCucKSm2rkQp4Bw==", "cpu": [ "arm64" ], @@ -10091,9 +10473,9 @@ } }, "node_modules/lightningcss-linux-arm64-musl": { - "version": "1.29.2", - "resolved": "https://registry.npmjs.org/lightningcss-linux-arm64-musl/-/lightningcss-linux-arm64-musl-1.29.2.tgz", - "integrity": "sha512-Q64eM1bPlOOUgxFmoPUefqzY1yV3ctFPE6d/Vt7WzLW4rKTv7MyYNky+FWxRpLkNASTnKQUaiMJ87zNODIrrKQ==", + "version": "1.30.1", + "resolved": "https://registry.npmjs.org/lightningcss-linux-arm64-musl/-/lightningcss-linux-arm64-musl-1.30.1.tgz", + "integrity": "sha512-jmUQVx4331m6LIX+0wUhBbmMX7TCfjF5FoOH6SD1CttzuYlGNVpA7QnrmLxrsub43ClTINfGSYyHe2HWeLl5CQ==", "cpu": [ "arm64" ], @@ -10112,9 +10494,9 @@ } }, "node_modules/lightningcss-linux-x64-gnu": { - "version": "1.29.2", - "resolved": "https://registry.npmjs.org/lightningcss-linux-x64-gnu/-/lightningcss-linux-x64-gnu-1.29.2.tgz", - "integrity": "sha512-0v6idDCPG6epLXtBH/RPkHvYx74CVziHo6TMYga8O2EiQApnUPZsbR9nFNrg2cgBzk1AYqEd95TlrsL7nYABQg==", + "version": "1.30.1", + "resolved": "https://registry.npmjs.org/lightningcss-linux-x64-gnu/-/lightningcss-linux-x64-gnu-1.30.1.tgz", + "integrity": "sha512-piWx3z4wN8J8z3+O5kO74+yr6ze/dKmPnI7vLqfSqI8bccaTGY5xiSGVIJBDd5K5BHlvVLpUB3S2YCfelyJ1bw==", "cpu": [ "x64" ], @@ -10133,9 +10515,9 @@ } }, "node_modules/lightningcss-linux-x64-musl": { - "version": "1.29.2", - "resolved": "https://registry.npmjs.org/lightningcss-linux-x64-musl/-/lightningcss-linux-x64-musl-1.29.2.tgz", - "integrity": "sha512-rMpz2yawkgGT8RULc5S4WiZopVMOFWjiItBT7aSfDX4NQav6M44rhn5hjtkKzB+wMTRlLLqxkeYEtQ3dd9696w==", + "version": "1.30.1", + "resolved": "https://registry.npmjs.org/lightningcss-linux-x64-musl/-/lightningcss-linux-x64-musl-1.30.1.tgz", + "integrity": "sha512-rRomAK7eIkL+tHY0YPxbc5Dra2gXlI63HL+v1Pdi1a3sC+tJTcFrHX+E86sulgAXeI7rSzDYhPSeHHjqFhqfeQ==", "cpu": [ "x64" ], @@ -10154,9 +10536,9 @@ } }, "node_modules/lightningcss-win32-arm64-msvc": { - "version": "1.29.2", - "resolved": "https://registry.npmjs.org/lightningcss-win32-arm64-msvc/-/lightningcss-win32-arm64-msvc-1.29.2.tgz", - "integrity": "sha512-nL7zRW6evGQqYVu/bKGK+zShyz8OVzsCotFgc7judbt6wnB2KbiKKJwBE4SGoDBQ1O94RjW4asrCjQL4i8Fhbw==", + "version": "1.30.1", + "resolved": "https://registry.npmjs.org/lightningcss-win32-arm64-msvc/-/lightningcss-win32-arm64-msvc-1.30.1.tgz", + "integrity": "sha512-mSL4rqPi4iXq5YVqzSsJgMVFENoa4nGTT/GjO2c0Yl9OuQfPsIfncvLrEW6RbbB24WtZ3xP/2CCmI3tNkNV4oA==", "cpu": [ "arm64" ], @@ -10175,9 +10557,9 @@ } }, "node_modules/lightningcss-win32-x64-msvc": { - "version": "1.29.2", - "resolved": "https://registry.npmjs.org/lightningcss-win32-x64-msvc/-/lightningcss-win32-x64-msvc-1.29.2.tgz", - "integrity": "sha512-EdIUW3B2vLuHmv7urfzMI/h2fmlnOQBk1xlsDxkN1tCWKjNFjfLhGxYk8C8mzpSfr+A6jFFIi8fU6LbQGsRWjA==", + "version": "1.30.1", + "resolved": "https://registry.npmjs.org/lightningcss-win32-x64-msvc/-/lightningcss-win32-x64-msvc-1.30.1.tgz", + "integrity": "sha512-PVqXh48wh4T53F/1CCu8PIPCxLzWyCnn/9T5W1Jpmdy5h9Cwd+0YQS6/LwhHXSafuc61/xg9Lv5OrCby6a++jg==", "cpu": [ "x64" ], @@ -10259,17 +10641,17 @@ "license": "MIT" }, "node_modules/log-symbols": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/log-symbols/-/log-symbols-4.1.0.tgz", - "integrity": "sha512-8XPvpAA8uyhfteu8pIvQxpJZ7SYYdpUivZpGy6sFsBuKRY/7rQGavedeB8aK+Zkyq6upMFVL/9AW6vOYzfRyLg==", + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/log-symbols/-/log-symbols-7.0.1.tgz", + "integrity": "sha512-ja1E3yCr9i/0hmBVaM0bfwDjnGy8I/s6PP4DFp+yP+a+mrHO4Rm7DtmnqROTUkHIkqffC84YY7AeqX6oFk0WFg==", "dev": true, "license": "MIT", "dependencies": { - "chalk": "^4.1.0", - "is-unicode-supported": "^0.1.0" + "is-unicode-supported": "^2.0.0", + "yoctocolors": "^2.1.1" }, "engines": { - "node": ">=10" + "node": ">=18" }, "funding": { "url": "https://github.com/sponsors/sindresorhus" @@ -10314,9 +10696,9 @@ } }, "node_modules/lucide-react": { - "version": "0.469.0", - "resolved": "https://registry.npmjs.org/lucide-react/-/lucide-react-0.469.0.tgz", - "integrity": "sha512-28vvUnnKQ/dBwiCQtwJw7QauYnE7yd2Cyp4tTTJpvglX4EMpbflcdBgrgToX2j71B3YvugK/NH3BGUk+E/p/Fw==", + "version": "0.511.0", + "resolved": "https://registry.npmjs.org/lucide-react/-/lucide-react-0.511.0.tgz", + "integrity": "sha512-VK5a2ydJ7xm8GvBeKLS9mu1pVK6ucef9780JVUjw6bAjJL/QXnd4Y0p7SPeOUMC27YhzNCZvm5d/QX0Tp3rc0w==", "license": "ISC", "peerDependencies": { "react": "^16.5.1 || ^17.0.0 || ^18.0.0 || ^19.0.0" @@ -10499,6 +10881,19 @@ "node": ">=6" } }, + "node_modules/mimic-function": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/mimic-function/-/mimic-function-5.0.1.tgz", + "integrity": "sha512-VP79XUPxV2CigYP3jWwAUFSku2aKqBH7uTAapFWCBqutsbmDo96KY5o8uh6U+/YSIn5OxJnXp73beVkpqMIGhA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/mimic-response": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/mimic-response/-/mimic-response-3.1.0.tgz", @@ -10554,6 +10949,10 @@ "version": "3.0.2", "resolved": "https://registry.npmjs.org/minizlib/-/minizlib-3.0.2.tgz", "integrity": "sha512-oG62iEk+CYt5Xj2YqI5Xi9xWUeZhDI8jjQmC5oThVH5JGCTgIjr7ciJDzC7MBzYd//WvR1OTmP5Q38Q8ShQtVA==", +<<<<<<< HEAD +======= + "dev": true, +>>>>>>> dev "license": "MIT", "dependencies": { "minipass": "^7.1.2" @@ -10566,6 +10965,10 @@ "version": "3.0.1", "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-3.0.1.tgz", "integrity": "sha512-+NsyUUAZDmo6YVHzL/stxSu3t9YS1iljliy3BSDrXJ/dkn1KYdmtZODGGjLcc9XLgVVpH4KshHB8XmZgMhaBXg==", +<<<<<<< HEAD +======= + "dev": true, +>>>>>>> dev "license": "MIT", "bin": { "mkdirp": "dist/cjs/src/bin.js" @@ -10637,9 +11040,15 @@ "license": "MIT" }, "node_modules/napi-postinstall": { +<<<<<<< HEAD "version": "0.2.3", "resolved": "https://registry.npmjs.org/napi-postinstall/-/napi-postinstall-0.2.3.tgz", "integrity": "sha512-Mi7JISo/4Ij2tDZ2xBE2WH+/KvVlkhA6juEjpEeRAVPNCpN3nxJo/5FhDNKgBcdmcmhaH6JjgST4xY/23ZYK0w==", +======= + "version": "0.2.4", + "resolved": "https://registry.npmjs.org/napi-postinstall/-/napi-postinstall-0.2.4.tgz", + "integrity": "sha512-ZEzHJwBhZ8qQSbknHqYcdtQVr8zUgGyM/q6h6qAyhtyVMNrSgDhrC4disf03dYW0e+czXyLnZINnCTEkWy0eJg==", +>>>>>>> dev "license": "MIT", "bin": { "napi-postinstall": "lib/cli.js" @@ -10667,12 +11076,12 @@ } }, "node_modules/next": { - "version": "15.2.4", - "resolved": "https://registry.npmjs.org/next/-/next-15.2.4.tgz", - "integrity": "sha512-VwL+LAaPSxEkd3lU2xWbgEOtrM8oedmyhBqaVNmgKB+GvZlCy9rgaEc+y2on0wv+l0oSFqLtYD6dcC1eAedUaQ==", + "version": "15.3.3", + "resolved": "https://registry.npmjs.org/next/-/next-15.3.3.tgz", + "integrity": "sha512-JqNj29hHNmCLtNvd090SyRbXJiivQ+58XjCcrC50Crb5g5u2zi7Y2YivbsEfzk6AtVI80akdOQbaMZwWB1Hthw==", "license": "MIT", "dependencies": { - "@next/env": "15.2.4", + "@next/env": "15.3.3", "@swc/counter": "0.1.3", "@swc/helpers": "0.5.15", "busboy": "1.6.0", @@ -10687,15 +11096,15 @@ "node": "^18.18.0 || ^19.8.0 || >= 20.0.0" }, "optionalDependencies": { - "@next/swc-darwin-arm64": "15.2.4", - "@next/swc-darwin-x64": "15.2.4", - "@next/swc-linux-arm64-gnu": "15.2.4", - "@next/swc-linux-arm64-musl": "15.2.4", - "@next/swc-linux-x64-gnu": "15.2.4", - "@next/swc-linux-x64-musl": "15.2.4", - "@next/swc-win32-arm64-msvc": "15.2.4", - "@next/swc-win32-x64-msvc": "15.2.4", - "sharp": "^0.33.5" + "@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", + "sharp": "^0.34.1" }, "peerDependencies": { "@opentelemetry/api": "^1.1.0", @@ -10721,9 +11130,9 @@ } }, "node_modules/next-themes": { - "version": "0.4.4", - "resolved": "https://registry.npmjs.org/next-themes/-/next-themes-0.4.4.tgz", - "integrity": "sha512-LDQ2qIOJF0VnuVrrMSMLrWGjRMkq+0mpgl6e0juCLqdJ+oo8Q84JRWT6Wh11VDQKkMMe+dVzDKLWs5n87T+PkQ==", + "version": "0.4.6", + "resolved": "https://registry.npmjs.org/next-themes/-/next-themes-0.4.6.tgz", + "integrity": "sha512-pZvgD5L0IEvX5/9GWyHMf3m8BKiVQwsCMHfoFosXtXBMnaS0ZnIJ9ST4b4NqLVKDEm8QBxoNNGNaBv2JNF6XNA==", "license": "MIT", "peerDependencies": { "react": "^16.8 || ^17 || ^18 || ^19 || ^19.0.0-rc", @@ -10840,9 +11249,15 @@ } }, "node_modules/npm": { +<<<<<<< HEAD "version": "11.3.0", "resolved": "https://registry.npmjs.org/npm/-/npm-11.3.0.tgz", "integrity": "sha512-luthFIP0nFX3+nTfYbWI3p4hP4CiVnKOZ5jdxnF2x7B+Shz8feiSJCLLzgJUNxQ2cDdTaVUiH6RRsMT++vIMZg==", +======= + "version": "11.4.1", + "resolved": "https://registry.npmjs.org/npm/-/npm-11.4.1.tgz", + "integrity": "sha512-/O5DiEFmtvnF0EU1+5VlDpcItpSKH3l+3fQOl3hkZ3ilGN+jJlGxxi/zb0rEK+zxd8pGyifVPyS1ORkMjZGAKw==", +>>>>>>> dev "bundleDependencies": [ "@isaacs/string-locale-compare", "@npmcli/arborist", @@ -10921,16 +11336,26 @@ ], "dependencies": { "@isaacs/string-locale-compare": "^1.1.0", +<<<<<<< HEAD "@npmcli/arborist": "^9.0.2", "@npmcli/config": "^10.2.0", +======= + "@npmcli/arborist": "^9.1.1", + "@npmcli/config": "^10.3.0", +>>>>>>> dev "@npmcli/fs": "^4.0.0", "@npmcli/map-workspaces": "^4.0.2", "@npmcli/package-json": "^6.1.1", "@npmcli/promise-spawn": "^8.0.2", "@npmcli/redact": "^3.1.1", "@npmcli/run-script": "^9.1.0", +<<<<<<< HEAD "@sigstore/tuf": "^3.0.0", "abbrev": "^3.0.0", +======= + "@sigstore/tuf": "^3.1.1", + "abbrev": "^3.0.1", +>>>>>>> dev "archy": "~1.0.0", "cacache": "^19.0.1", "chalk": "^5.4.1", @@ -10940,21 +11365,30 @@ "fs-minipass": "^3.0.3", "glob": "^10.4.5", "graceful-fs": "^4.2.11", - "hosted-git-info": "^8.0.2", + "hosted-git-info": "^8.1.0", "ini": "^5.0.0", - "init-package-json": "^8.0.0", + "init-package-json": "^8.2.1", "is-cidr": "^5.1.1", "json-parse-even-better-errors": "^4.0.0", +<<<<<<< HEAD "libnpmaccess": "^10.0.0", "libnpmdiff": "^8.0.2", "libnpmexec": "^10.1.1", "libnpmfund": "^7.0.2", "libnpmorg": "^8.0.0", "libnpmpack": "^9.0.2", +======= + "libnpmaccess": "^10.0.1", + "libnpmdiff": "^8.0.4", + "libnpmexec": "^10.1.3", + "libnpmfund": "^7.0.4", + "libnpmorg": "^8.0.0", + "libnpmpack": "^9.0.4", +>>>>>>> dev "libnpmpublish": "^11.0.0", "libnpmsearch": "^9.0.0", - "libnpmteam": "^8.0.0", - "libnpmversion": "^8.0.0", + "libnpmteam": "^8.0.1", + "libnpmversion": "^8.0.1", "make-fetch-happen": "^14.0.3", "minimatch": "^9.0.5", "minipass": "^7.1.1", @@ -10976,7 +11410,7 @@ "proc-log": "^5.0.0", "qrcode-terminal": "^0.12.0", "read": "^4.1.0", - "semver": "^7.7.1", + "semver": "^7.7.2", "spdx-expression-parse": "^4.0.0", "ssri": "^12.0.0", "supports-color": "^10.0.0", @@ -11102,7 +11536,11 @@ } }, "node_modules/npm/node_modules/@npmcli/arborist": { +<<<<<<< HEAD "version": "9.0.2", +======= + "version": "9.1.1", +>>>>>>> dev "inBundle": true, "license": "ISC", "dependencies": { @@ -11149,7 +11587,11 @@ } }, "node_modules/npm/node_modules/@npmcli/config": { +<<<<<<< HEAD "version": "10.2.0", +======= + "version": "10.3.0", +>>>>>>> dev "inBundle": true, "license": "ISC", "dependencies": { @@ -11256,7 +11698,7 @@ } }, "node_modules/npm/node_modules/@npmcli/package-json": { - "version": "6.1.1", + "version": "6.2.0", "inBundle": true, "license": "ISC", "dependencies": { @@ -11284,11 +11726,11 @@ } }, "node_modules/npm/node_modules/@npmcli/query": { - "version": "4.0.0", + "version": "4.0.1", "inBundle": true, "license": "ISC", "dependencies": { - "postcss-selector-parser": "^6.1.2" + "postcss-selector-parser": "^7.0.0" }, "engines": { "node": "^18.17.0 || >=20.5.0" @@ -11347,7 +11789,7 @@ } }, "node_modules/npm/node_modules/@sigstore/protobuf-specs": { - "version": "0.4.0", + "version": "0.4.1", "inBundle": true, "license": "Apache-2.0", "engines": { @@ -11371,11 +11813,11 @@ } }, "node_modules/npm/node_modules/@sigstore/tuf": { - "version": "3.1.0", + "version": "3.1.1", "inBundle": true, "license": "Apache-2.0", "dependencies": { - "@sigstore/protobuf-specs": "^0.4.0", + "@sigstore/protobuf-specs": "^0.4.1", "tuf-js": "^3.0.1" }, "engines": { @@ -11383,13 +11825,13 @@ } }, "node_modules/npm/node_modules/@sigstore/verify": { - "version": "2.1.0", + "version": "2.1.1", "inBundle": true, "license": "Apache-2.0", "dependencies": { "@sigstore/bundle": "^3.1.0", "@sigstore/core": "^2.0.0", - "@sigstore/protobuf-specs": "^0.4.0" + "@sigstore/protobuf-specs": "^0.4.1" }, "engines": { "node": "^18.17.0 || >=20.5.0" @@ -11416,7 +11858,7 @@ } }, "node_modules/npm/node_modules/abbrev": { - "version": "3.0.0", + "version": "3.0.1", "inBundle": true, "license": "ISC", "engines": { @@ -11481,7 +11923,7 @@ } }, "node_modules/npm/node_modules/binary-extensions": { - "version": "3.0.0", + "version": "3.1.0", "inBundle": true, "license": "MIT", "engines": { @@ -11821,7 +12263,7 @@ "license": "ISC" }, "node_modules/npm/node_modules/hosted-git-info": { - "version": "8.0.2", + "version": "8.1.0", "inBundle": true, "license": "ISC", "dependencies": { @@ -11832,7 +12274,7 @@ } }, "node_modules/npm/node_modules/http-cache-semantics": { - "version": "4.1.1", + "version": "4.2.0", "inBundle": true, "license": "BSD-2-Clause" }, @@ -11900,7 +12342,7 @@ } }, "node_modules/npm/node_modules/init-package-json": { - "version": "8.0.0", + "version": "8.2.1", "inBundle": true, "license": "ISC", "dependencies": { @@ -12017,7 +12459,7 @@ "license": "MIT" }, "node_modules/npm/node_modules/libnpmaccess": { - "version": "10.0.0", + "version": "10.0.1", "inBundle": true, "license": "ISC", "dependencies": { @@ -12029,11 +12471,19 @@ } }, "node_modules/npm/node_modules/libnpmdiff": { +<<<<<<< HEAD "version": "8.0.2", "inBundle": true, "license": "ISC", "dependencies": { "@npmcli/arborist": "^9.0.2", +======= + "version": "8.0.4", + "inBundle": true, + "license": "ISC", + "dependencies": { + "@npmcli/arborist": "^9.1.1", +>>>>>>> dev "@npmcli/installed-package-contents": "^3.0.0", "binary-extensions": "^3.0.0", "diff": "^7.0.0", @@ -12047,11 +12497,19 @@ } }, "node_modules/npm/node_modules/libnpmexec": { +<<<<<<< HEAD "version": "10.1.1", "inBundle": true, "license": "ISC", "dependencies": { "@npmcli/arborist": "^9.0.2", +======= + "version": "10.1.3", + "inBundle": true, + "license": "ISC", + "dependencies": { + "@npmcli/arborist": "^9.1.1", +>>>>>>> dev "@npmcli/package-json": "^6.1.1", "@npmcli/run-script": "^9.0.1", "ci-info": "^4.0.0", @@ -12068,11 +12526,19 @@ } }, "node_modules/npm/node_modules/libnpmfund": { +<<<<<<< HEAD "version": "7.0.2", "inBundle": true, "license": "ISC", "dependencies": { "@npmcli/arborist": "^9.0.2" +======= + "version": "7.0.4", + "inBundle": true, + "license": "ISC", + "dependencies": { + "@npmcli/arborist": "^9.1.1" +>>>>>>> dev }, "engines": { "node": "^20.17.0 || >=22.9.0" @@ -12091,11 +12557,19 @@ } }, "node_modules/npm/node_modules/libnpmpack": { +<<<<<<< HEAD "version": "9.0.2", "inBundle": true, "license": "ISC", "dependencies": { "@npmcli/arborist": "^9.0.2", +======= + "version": "9.0.4", + "inBundle": true, + "license": "ISC", + "dependencies": { + "@npmcli/arborist": "^9.1.1", +>>>>>>> dev "@npmcli/run-script": "^9.0.1", "npm-package-arg": "^12.0.0", "pacote": "^21.0.0" @@ -12134,7 +12608,7 @@ } }, "node_modules/npm/node_modules/libnpmteam": { - "version": "8.0.0", + "version": "8.0.1", "inBundle": true, "license": "ISC", "dependencies": { @@ -12146,7 +12620,7 @@ } }, "node_modules/npm/node_modules/libnpmversion": { - "version": "8.0.0", + "version": "8.0.1", "inBundle": true, "license": "ISC", "dependencies": { @@ -12683,7 +13157,7 @@ } }, "node_modules/npm/node_modules/postcss-selector-parser": { - "version": "6.1.2", + "version": "7.1.0", "inBundle": true, "license": "MIT", "dependencies": { @@ -12802,7 +13276,7 @@ "optional": true }, "node_modules/npm/node_modules/semver": { - "version": "7.7.1", + "version": "7.7.2", "inBundle": true, "license": "ISC", "bin": { @@ -13064,11 +13538,19 @@ "license": "MIT" }, "node_modules/npm/node_modules/tinyglobby": { +<<<<<<< HEAD "version": "0.2.12", "inBundle": true, "license": "MIT", "dependencies": { "fdir": "^6.4.3", +======= + "version": "0.2.13", + "inBundle": true, + "license": "MIT", + "dependencies": { + "fdir": "^6.4.4", +>>>>>>> dev "picomatch": "^4.0.2" }, "engines": { @@ -13079,7 +13561,11 @@ } }, "node_modules/npm/node_modules/tinyglobby/node_modules/fdir": { +<<<<<<< HEAD "version": "6.4.3", +======= + "version": "6.4.4", +>>>>>>> dev "inBundle": true, "license": "MIT", "peerDependencies": { @@ -13532,50 +14018,95 @@ } }, "node_modules/ora": { - "version": "5.4.1", - "resolved": "https://registry.npmjs.org/ora/-/ora-5.4.1.tgz", - "integrity": "sha512-5b6Y85tPxZZ7QytO+BQzysW31HJku27cRIlkbAXaNx+BdcVi+LlRFmVXzeF6a7JCwJpyw5c4b+YSVImQIrBpuQ==", + "version": "8.2.0", + "resolved": "https://registry.npmjs.org/ora/-/ora-8.2.0.tgz", + "integrity": "sha512-weP+BZ8MVNnlCm8c0Qdc1WSWq4Qn7I+9CJGm7Qali6g44e/PUzbjNqJX5NJ9ljlNMosfJvg1fKEGILklK9cwnw==", "dev": true, "license": "MIT", "dependencies": { - "bl": "^4.1.0", - "chalk": "^4.1.0", - "cli-cursor": "^3.1.0", - "cli-spinners": "^2.5.0", - "is-interactive": "^1.0.0", - "is-unicode-supported": "^0.1.0", - "log-symbols": "^4.1.0", - "strip-ansi": "^6.0.0", - "wcwidth": "^1.0.1" + "chalk": "^5.3.0", + "cli-cursor": "^5.0.0", + "cli-spinners": "^2.9.2", + "is-interactive": "^2.0.0", + "is-unicode-supported": "^2.0.0", + "log-symbols": "^6.0.0", + "stdin-discarder": "^0.2.2", + "string-width": "^7.2.0", + "strip-ansi": "^7.1.0" }, "engines": { - "node": ">=10" + "node": ">=18" }, "funding": { "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/ora/node_modules/ansi-regex": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", - "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", + "node_modules/ora/node_modules/chalk": { + "version": "5.4.1", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-5.4.1.tgz", + "integrity": "sha512-zgVZuo2WcZgfUEmsn6eO3kINexW8RAE4maiQ8QNs8CtpPCSyMiYsULR3HQYkm3w8FIA3SberyMJMSldGsW+U3w==", "dev": true, "license": "MIT", "engines": { - "node": ">=8" + "node": "^12.17.0 || ^14.13 || >=16.0.0" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" } }, - "node_modules/ora/node_modules/strip-ansi": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", - "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "node_modules/ora/node_modules/emoji-regex": { + "version": "10.4.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-10.4.0.tgz", + "integrity": "sha512-EC+0oUMY1Rqm4O6LLrgjtYDvcVYTy7chDnM4Q7030tP4Kwj3u/pR6gP9ygnp2CJMK5Gq+9Q2oqmrFJAz01DXjw==", + "dev": true, + "license": "MIT" + }, + "node_modules/ora/node_modules/log-symbols": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/log-symbols/-/log-symbols-6.0.0.tgz", + "integrity": "sha512-i24m8rpwhmPIS4zscNzK6MSEhk0DUWa/8iYQWxhffV8jkI4Phvs3F+quL5xvS0gdQR0FyTCMMH33Y78dDTzzIw==", "dev": true, "license": "MIT", "dependencies": { - "ansi-regex": "^5.0.1" + "chalk": "^5.3.0", + "is-unicode-supported": "^1.3.0" }, "engines": { - "node": ">=8" + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/ora/node_modules/log-symbols/node_modules/is-unicode-supported": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/is-unicode-supported/-/is-unicode-supported-1.3.0.tgz", + "integrity": "sha512-43r2mRvz+8JRIKnWJ+3j8JtjRKZ6GmjzfaE/qiBJnikNnYv/6bagRJ1kUhNk8R5EX/GkobD+r+sfxCPJsiKBLQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/ora/node_modules/string-width": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-7.2.0.tgz", + "integrity": "sha512-tsaTIkKW9b4N+AEj+SVA+WhJzV7/zMhcSu78mLKWSk7cXMOSHsBKFWUs0fWwq8QyK3MgJBQRX6Gbi4kYbdvGkQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "emoji-regex": "^10.3.0", + "get-east-asian-width": "^1.0.0", + "strip-ansi": "^7.1.0" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, "node_modules/oslo": { @@ -14023,6 +14554,95 @@ "url": "https://ko-fi.com/killymxi" } }, + "node_modules/pg": { + "version": "8.16.0", + "resolved": "https://registry.npmjs.org/pg/-/pg-8.16.0.tgz", + "integrity": "sha512-7SKfdvP8CTNXjMUzfcVTaI+TDzBEeaUnVwiVGZQD1Hh33Kpev7liQba9uLd4CfN8r9mCVsD0JIpq03+Unpz+kg==", + "license": "MIT", + "dependencies": { + "pg-connection-string": "^2.9.0", + "pg-pool": "^3.10.0", + "pg-protocol": "^1.10.0", + "pg-types": "2.2.0", + "pgpass": "1.0.5" + }, + "engines": { + "node": ">= 8.0.0" + }, + "optionalDependencies": { + "pg-cloudflare": "^1.2.5" + }, + "peerDependencies": { + "pg-native": ">=3.0.1" + }, + "peerDependenciesMeta": { + "pg-native": { + "optional": true + } + } + }, + "node_modules/pg-cloudflare": { + "version": "1.2.5", + "resolved": "https://registry.npmjs.org/pg-cloudflare/-/pg-cloudflare-1.2.5.tgz", + "integrity": "sha512-OOX22Vt0vOSRrdoUPKJ8Wi2OpE/o/h9T8X1s4qSkCedbNah9ei2W2765be8iMVxQUsvgT7zIAT2eIa9fs5+vtg==", + "license": "MIT", + "optional": true + }, + "node_modules/pg-connection-string": { + "version": "2.9.0", + "resolved": "https://registry.npmjs.org/pg-connection-string/-/pg-connection-string-2.9.0.tgz", + "integrity": "sha512-P2DEBKuvh5RClafLngkAuGe9OUlFV7ebu8w1kmaaOgPcpJd1RIFh7otETfI6hAR8YupOLFTY7nuvvIn7PLciUQ==", + "license": "MIT" + }, + "node_modules/pg-int8": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/pg-int8/-/pg-int8-1.0.1.tgz", + "integrity": "sha512-WCtabS6t3c8SkpDBUlb1kjOs7l66xsGdKpIPZsg4wR+B3+u9UAum2odSsF9tnvxg80h4ZxLWMy4pRjOsFIqQpw==", + "license": "ISC", + "engines": { + "node": ">=4.0.0" + } + }, + "node_modules/pg-pool": { + "version": "3.10.0", + "resolved": "https://registry.npmjs.org/pg-pool/-/pg-pool-3.10.0.tgz", + "integrity": "sha512-DzZ26On4sQ0KmqnO34muPcmKbhrjmyiO4lCCR0VwEd7MjmiKf5NTg/6+apUEu0NF7ESa37CGzFxH513CoUmWnA==", + "license": "MIT", + "peerDependencies": { + "pg": ">=8.0" + } + }, + "node_modules/pg-protocol": { + "version": "1.10.0", + "resolved": "https://registry.npmjs.org/pg-protocol/-/pg-protocol-1.10.0.tgz", + "integrity": "sha512-IpdytjudNuLv8nhlHs/UrVBhU0e78J0oIS/0AVdTbWxSOkFUVdsHC/NrorO6nXsQNDTT1kzDSOMJubBQviX18Q==", + "license": "MIT" + }, + "node_modules/pg-types": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/pg-types/-/pg-types-2.2.0.tgz", + "integrity": "sha512-qTAAlrEsl8s4OiEQY69wDvcMIdQN6wdz5ojQiOy6YRMuynxenON0O5oCpJI6lshc6scgAY8qvJ2On/p+CXY0GA==", + "license": "MIT", + "dependencies": { + "pg-int8": "1.0.1", + "postgres-array": "~2.0.0", + "postgres-bytea": "~1.0.0", + "postgres-date": "~1.0.4", + "postgres-interval": "^1.1.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/pgpass": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/pgpass/-/pgpass-1.0.5.tgz", + "integrity": "sha512-FdW9r/jQZhSeohs1Z3sI1yxFQNFvMcnmfuj4WBMUTxOrAyLMaTcE1aAMBiTlbMNaXvBCQuVi0R7hd8udDSP7ug==", + "license": "MIT", + "dependencies": { + "split2": "^4.1.0" + } + }, "node_modules/picocolors": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.1.1.tgz", @@ -14064,9 +14684,15 @@ } }, "node_modules/postcss": { +<<<<<<< HEAD "version": "8.5.3", "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.5.3.tgz", "integrity": "sha512-dle9A3yYxlBSrt8Fu+IpjGT8SY8hN0mlaA6GY8t0P5PjIOZemULz/E2Bnm/2dcUOena75OTNkHI76uZBNUUq3A==", +======= + "version": "8.5.4", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.5.4.tgz", + "integrity": "sha512-QSa9EBe+uwlGTFmHsPKokv3B/oEMQZxfqW0QqNCyhpa6mB1afzulwn8hihglqAb2pOw+BJgNlmXQ8la2VeHB7w==", +>>>>>>> dev "dev": true, "funding": [ { @@ -14084,7 +14710,7 @@ ], "license": "MIT", "dependencies": { - "nanoid": "^3.3.8", + "nanoid": "^3.3.11", "picocolors": "^1.1.1", "source-map-js": "^1.2.1" }, @@ -14092,6 +14718,45 @@ "node": "^10 || ^12 || >=14" } }, + "node_modules/postgres-array": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/postgres-array/-/postgres-array-2.0.0.tgz", + "integrity": "sha512-VpZrUqU5A69eQyW2c5CA1jtLecCsN2U/bD6VilrFDWq5+5UIEVO7nazS3TEcHf1zuPYO/sqGvUvW62g86RXZuA==", + "license": "MIT", + "engines": { + "node": ">=4" + } + }, + "node_modules/postgres-bytea": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/postgres-bytea/-/postgres-bytea-1.0.0.tgz", + "integrity": "sha512-xy3pmLuQqRBZBXDULy7KbaitYqLcmxigw14Q5sj8QBVLqEwXfeybIKVWiqAXTlcvdvb0+xkOtDbfQMOf4lST1w==", + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/postgres-date": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/postgres-date/-/postgres-date-1.0.7.tgz", + "integrity": "sha512-suDmjLVQg78nMK2UZ454hAG+OAW+HQPZ6n++TNDUX+L0+uUlLywnoxJKDou51Zm+zTCjrCl0Nq6J9C5hP9vK/Q==", + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/postgres-interval": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/postgres-interval/-/postgres-interval-1.2.0.tgz", + "integrity": "sha512-9ZhXKM/rw350N1ovuWHbGxnGh/SNJ4cnxHiM0rxE4VN41wsg8P8zWn9hv/buK00RP4WvlOyr/RBDiptyxVbkZQ==", + "license": "MIT", + "dependencies": { + "xtend": "^4.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, "node_modules/prebuild-install": { "version": "7.1.3", "resolved": "https://registry.npmjs.org/prebuild-install/-/prebuild-install-7.1.3.tgz", @@ -14303,24 +14968,24 @@ } }, "node_modules/react": { - "version": "19.0.0", - "resolved": "https://registry.npmjs.org/react/-/react-19.0.0.tgz", - "integrity": "sha512-V8AVnmPIICiWpGfm6GLzCR/W5FXLchHop40W4nXBmdlEceh16rCN8O8LNWm5bh5XUX91fh7KpA+W0TgMKmgTpQ==", + "version": "19.1.0", + "resolved": "https://registry.npmjs.org/react/-/react-19.1.0.tgz", + "integrity": "sha512-FS+XFBNvn3GTAWq26joslQgWNoFu08F4kl0J4CgdNKADkdSGXQyTCnKteIAJy96Br6YbpEU1LSzV5dYtjMkMDg==", "license": "MIT", "engines": { "node": ">=0.10.0" } }, "node_modules/react-dom": { - "version": "19.0.0", - "resolved": "https://registry.npmjs.org/react-dom/-/react-dom-19.0.0.tgz", - "integrity": "sha512-4GV5sHFG0e/0AD4X+ySy6UJd3jVl1iNsNHdpad0qhABJ11twS3TTBnseqsKurKcsNqCEFeGL3uLpVChpIO3QfQ==", + "version": "19.1.0", + "resolved": "https://registry.npmjs.org/react-dom/-/react-dom-19.1.0.tgz", + "integrity": "sha512-Xs1hdnE+DyKgeHJeJznQmYMIBG3TKIHJJT95Q58nHLSrElKlGQqDTR2HQ9fx5CN/Gk6Vh/kupBTDLU11/nDk/g==", "license": "MIT", "dependencies": { - "scheduler": "^0.25.0" + "scheduler": "^0.26.0" }, "peerDependencies": { - "react": "^19.0.0" + "react": "^19.1.0" } }, "node_modules/react-easy-sort": { @@ -14347,596 +15012,84 @@ "license": "0BSD" }, "node_modules/react-email": { - "version": "4.0.6", - "resolved": "https://registry.npmjs.org/react-email/-/react-email-4.0.6.tgz", - "integrity": "sha512-RzMDZCRd2JFFkGljhBWNWGH2ti4Qnhcx03nR1uPW1vNBptqDJx/fxSJqzCDYEEpTkWPaEe2unHM4CdzRAI7awg==", + "version": "4.0.16", + "resolved": "https://registry.npmjs.org/react-email/-/react-email-4.0.16.tgz", + "integrity": "sha512-auhFU+nQxAkKkP6lQhPyGsa9exwfUEzp2BwZnjHokCwphZlg30tu4t1LgdKRwGPYsi7XNGy6asbVLAUhOVpzzg==", "dev": true, "license": "MIT", "dependencies": { - "@babel/parser": "7.24.5", - "@babel/traverse": "7.25.6", - "chalk": "4.1.2", - "chokidar": "4.0.3", - "commander": "11.1.0", - "debounce": "2.0.0", - "esbuild": "0.25.0", - "glob": "10.3.4", - "log-symbols": "4.1.0", - "mime-types": "2.1.35", - "next": "15.2.4", - "normalize-path": "3.0.0", - "ora": "5.4.1", - "socket.io": "4.8.1" + "@babel/parser": "^7.27.0", + "@babel/traverse": "^7.27.0", + "chalk": "^5.0.0", + "chokidar": "^4.0.3", + "commander": "^13.0.0", + "debounce": "^2.0.0", + "esbuild": "^0.25.0", + "glob": "^11.0.0", + "log-symbols": "^7.0.0", + "mime-types": "^3.0.0", + "next": "^15.3.1", + "normalize-path": "^3.0.0", + "ora": "^8.0.0", + "socket.io": "^4.8.1" }, "bin": { - "email": "dist/cli/index.js" + "email": "dist/cli/index.mjs" }, "engines": { "node": ">=18.0.0" } }, - "node_modules/react-email/node_modules/@esbuild/aix-ppc64": { - "version": "0.25.0", - "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.25.0.tgz", - "integrity": "sha512-O7vun9Sf8DFjH2UtqK8Ku3LkquL9SZL8OLY1T5NZkA34+wG3OQF7cl4Ql8vdNzM6fzBbYfLaiRLIOZ+2FOCgBQ==", - "cpu": [ - "ppc64" - ], + "node_modules/react-email/node_modules/chalk": { + "version": "5.4.1", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-5.4.1.tgz", + "integrity": "sha512-zgVZuo2WcZgfUEmsn6eO3kINexW8RAE4maiQ8QNs8CtpPCSyMiYsULR3HQYkm3w8FIA3SberyMJMSldGsW+U3w==", "dev": true, "license": "MIT", - "optional": true, - "os": [ - "aix" - ], "engines": { - "node": ">=18" - } - }, - "node_modules/react-email/node_modules/@esbuild/android-arm": { - "version": "0.25.0", - "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.25.0.tgz", - "integrity": "sha512-PTyWCYYiU0+1eJKmw21lWtC+d08JDZPQ5g+kFyxP0V+es6VPPSUhM6zk8iImp2jbV6GwjX4pap0JFbUQN65X1g==", - "cpu": [ - "arm" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "android" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/react-email/node_modules/@esbuild/android-arm64": { - "version": "0.25.0", - "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.25.0.tgz", - "integrity": "sha512-grvv8WncGjDSyUBjN9yHXNt+cq0snxXbDxy5pJtzMKGmmpPxeAmAhWxXI+01lU5rwZomDgD3kJwulEnhTRUd6g==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "android" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/react-email/node_modules/@esbuild/android-x64": { - "version": "0.25.0", - "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.25.0.tgz", - "integrity": "sha512-m/ix7SfKG5buCnxasr52+LI78SQ+wgdENi9CqyCXwjVR2X4Jkz+BpC3le3AoBPYTC9NHklwngVXvbJ9/Akhrfg==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "android" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/react-email/node_modules/@esbuild/darwin-arm64": { - "version": "0.25.0", - "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.25.0.tgz", - "integrity": "sha512-mVwdUb5SRkPayVadIOI78K7aAnPamoeFR2bT5nszFUZ9P8UpK4ratOdYbZZXYSqPKMHfS1wdHCJk1P1EZpRdvw==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "darwin" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/react-email/node_modules/@esbuild/darwin-x64": { - "version": "0.25.0", - "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.25.0.tgz", - "integrity": "sha512-DgDaYsPWFTS4S3nWpFcMn/33ZZwAAeAFKNHNa1QN0rI4pUjgqf0f7ONmXf6d22tqTY+H9FNdgeaAa+YIFUn2Rg==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "darwin" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/react-email/node_modules/@esbuild/freebsd-arm64": { - "version": "0.25.0", - "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.25.0.tgz", - "integrity": "sha512-VN4ocxy6dxefN1MepBx/iD1dH5K8qNtNe227I0mnTRjry8tj5MRk4zprLEdG8WPyAPb93/e4pSgi1SoHdgOa4w==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "freebsd" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/react-email/node_modules/@esbuild/freebsd-x64": { - "version": "0.25.0", - "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.25.0.tgz", - "integrity": "sha512-mrSgt7lCh07FY+hDD1TxiTyIHyttn6vnjesnPoVDNmDfOmggTLXRv8Id5fNZey1gl/V2dyVK1VXXqVsQIiAk+A==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "freebsd" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/react-email/node_modules/@esbuild/linux-arm": { - "version": "0.25.0", - "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.25.0.tgz", - "integrity": "sha512-vkB3IYj2IDo3g9xX7HqhPYxVkNQe8qTK55fraQyTzTX/fxaDtXiEnavv9geOsonh2Fd2RMB+i5cbhu2zMNWJwg==", - "cpu": [ - "arm" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/react-email/node_modules/@esbuild/linux-arm64": { - "version": "0.25.0", - "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.25.0.tgz", - "integrity": "sha512-9QAQjTWNDM/Vk2bgBl17yWuZxZNQIF0OUUuPZRKoDtqF2k4EtYbpyiG5/Dk7nqeK6kIJWPYldkOcBqjXjrUlmg==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/react-email/node_modules/@esbuild/linux-ia32": { - "version": "0.25.0", - "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.25.0.tgz", - "integrity": "sha512-43ET5bHbphBegyeqLb7I1eYn2P/JYGNmzzdidq/w0T8E2SsYL1U6un2NFROFRg1JZLTzdCoRomg8Rvf9M6W6Gg==", - "cpu": [ - "ia32" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/react-email/node_modules/@esbuild/linux-loong64": { - "version": "0.25.0", - "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.25.0.tgz", - "integrity": "sha512-fC95c/xyNFueMhClxJmeRIj2yrSMdDfmqJnyOY4ZqsALkDrrKJfIg5NTMSzVBr5YW1jf+l7/cndBfP3MSDpoHw==", - "cpu": [ - "loong64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/react-email/node_modules/@esbuild/linux-mips64el": { - "version": "0.25.0", - "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.25.0.tgz", - "integrity": "sha512-nkAMFju7KDW73T1DdH7glcyIptm95a7Le8irTQNO/qtkoyypZAnjchQgooFUDQhNAy4iu08N79W4T4pMBwhPwQ==", - "cpu": [ - "mips64el" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/react-email/node_modules/@esbuild/linux-ppc64": { - "version": "0.25.0", - "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.25.0.tgz", - "integrity": "sha512-NhyOejdhRGS8Iwv+KKR2zTq2PpysF9XqY+Zk77vQHqNbo/PwZCzB5/h7VGuREZm1fixhs4Q/qWRSi5zmAiO4Fw==", - "cpu": [ - "ppc64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/react-email/node_modules/@esbuild/linux-riscv64": { - "version": "0.25.0", - "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.25.0.tgz", - "integrity": "sha512-5S/rbP5OY+GHLC5qXp1y/Mx//e92L1YDqkiBbO9TQOvuFXM+iDqUNG5XopAnXoRH3FjIUDkeGcY1cgNvnXp/kA==", - "cpu": [ - "riscv64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/react-email/node_modules/@esbuild/linux-s390x": { - "version": "0.25.0", - "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.25.0.tgz", - "integrity": "sha512-XM2BFsEBz0Fw37V0zU4CXfcfuACMrppsMFKdYY2WuTS3yi8O1nFOhil/xhKTmE1nPmVyvQJjJivgDT+xh8pXJA==", - "cpu": [ - "s390x" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/react-email/node_modules/@esbuild/linux-x64": { - "version": "0.25.0", - "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.25.0.tgz", - "integrity": "sha512-9yl91rHw/cpwMCNytUDxwj2XjFpxML0y9HAOH9pNVQDpQrBxHy01Dx+vaMu0N1CKa/RzBD2hB4u//nfc+Sd3Cw==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/react-email/node_modules/@esbuild/netbsd-arm64": { - "version": "0.25.0", - "resolved": "https://registry.npmjs.org/@esbuild/netbsd-arm64/-/netbsd-arm64-0.25.0.tgz", - "integrity": "sha512-RuG4PSMPFfrkH6UwCAqBzauBWTygTvb1nxWasEJooGSJ/NwRw7b2HOwyRTQIU97Hq37l3npXoZGYMy3b3xYvPw==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "netbsd" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/react-email/node_modules/@esbuild/netbsd-x64": { - "version": "0.25.0", - "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.25.0.tgz", - "integrity": "sha512-jl+qisSB5jk01N5f7sPCsBENCOlPiS/xptD5yxOx2oqQfyourJwIKLRA2yqWdifj3owQZCL2sn6o08dBzZGQzA==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "netbsd" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/react-email/node_modules/@esbuild/openbsd-arm64": { - "version": "0.25.0", - "resolved": "https://registry.npmjs.org/@esbuild/openbsd-arm64/-/openbsd-arm64-0.25.0.tgz", - "integrity": "sha512-21sUNbq2r84YE+SJDfaQRvdgznTD8Xc0oc3p3iW/a1EVWeNj/SdUCbm5U0itZPQYRuRTW20fPMWMpcrciH2EJw==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "openbsd" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/react-email/node_modules/@esbuild/openbsd-x64": { - "version": "0.25.0", - "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.25.0.tgz", - "integrity": "sha512-2gwwriSMPcCFRlPlKx3zLQhfN/2WjJ2NSlg5TKLQOJdV0mSxIcYNTMhk3H3ulL/cak+Xj0lY1Ym9ysDV1igceg==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "openbsd" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/react-email/node_modules/@esbuild/sunos-x64": { - "version": "0.25.0", - "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.25.0.tgz", - "integrity": "sha512-bxI7ThgLzPrPz484/S9jLlvUAHYMzy6I0XiU1ZMeAEOBcS0VePBFxh1JjTQt3Xiat5b6Oh4x7UC7IwKQKIJRIg==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "sunos" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/react-email/node_modules/@esbuild/win32-arm64": { - "version": "0.25.0", - "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.25.0.tgz", - "integrity": "sha512-ZUAc2YK6JW89xTbXvftxdnYy3m4iHIkDtK3CLce8wg8M2L+YZhIvO1DKpxrd0Yr59AeNNkTiic9YLf6FTtXWMw==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "win32" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/react-email/node_modules/@esbuild/win32-ia32": { - "version": "0.25.0", - "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.25.0.tgz", - "integrity": "sha512-eSNxISBu8XweVEWG31/JzjkIGbGIJN/TrRoiSVZwZ6pkC6VX4Im/WV2cz559/TXLcYbcrDN8JtKgd9DJVIo8GA==", - "cpu": [ - "ia32" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "win32" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/react-email/node_modules/@esbuild/win32-x64": { - "version": "0.25.0", - "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.25.0.tgz", - "integrity": "sha512-ZENoHJBxA20C2zFzh6AI4fT6RraMzjYw4xKWemRTRmRVtN9c5DcH9r/f2ihEkMjOW5eGgrwCslG/+Y/3bL+DHQ==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "win32" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/react-email/node_modules/brace-expansion": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", - "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", - "dev": true, - "license": "MIT", - "dependencies": { - "balanced-match": "^1.0.0" - } - }, - "node_modules/react-email/node_modules/esbuild": { - "version": "0.25.0", - "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.25.0.tgz", - "integrity": "sha512-BXq5mqc8ltbaN34cDqWuYKyNhX8D/Z0J1xdtdQ8UcIIIyJyz+ZMKUt58tF3SrZ85jcfN/PZYhjR5uDQAYNVbuw==", - "dev": true, - "hasInstallScript": true, - "license": "MIT", - "bin": { - "esbuild": "bin/esbuild" - }, - "engines": { - "node": ">=18" - }, - "optionalDependencies": { - "@esbuild/aix-ppc64": "0.25.0", - "@esbuild/android-arm": "0.25.0", - "@esbuild/android-arm64": "0.25.0", - "@esbuild/android-x64": "0.25.0", - "@esbuild/darwin-arm64": "0.25.0", - "@esbuild/darwin-x64": "0.25.0", - "@esbuild/freebsd-arm64": "0.25.0", - "@esbuild/freebsd-x64": "0.25.0", - "@esbuild/linux-arm": "0.25.0", - "@esbuild/linux-arm64": "0.25.0", - "@esbuild/linux-ia32": "0.25.0", - "@esbuild/linux-loong64": "0.25.0", - "@esbuild/linux-mips64el": "0.25.0", - "@esbuild/linux-ppc64": "0.25.0", - "@esbuild/linux-riscv64": "0.25.0", - "@esbuild/linux-s390x": "0.25.0", - "@esbuild/linux-x64": "0.25.0", - "@esbuild/netbsd-arm64": "0.25.0", - "@esbuild/netbsd-x64": "0.25.0", - "@esbuild/openbsd-arm64": "0.25.0", - "@esbuild/openbsd-x64": "0.25.0", - "@esbuild/sunos-x64": "0.25.0", - "@esbuild/win32-arm64": "0.25.0", - "@esbuild/win32-ia32": "0.25.0", - "@esbuild/win32-x64": "0.25.0" - } - }, - "node_modules/react-email/node_modules/glob": { - "version": "10.3.4", - "resolved": "https://registry.npmjs.org/glob/-/glob-10.3.4.tgz", - "integrity": "sha512-6LFElP3A+i/Q8XQKEvZjkEWEOTgAIALR9AO2rwT8bgPhDd1anmqDJDZ6lLddI4ehxxxR1S5RIqKe1uapMQfYaQ==", - "dev": true, - "license": "ISC", - "dependencies": { - "foreground-child": "^3.1.0", - "jackspeak": "^2.0.3", - "minimatch": "^9.0.1", - "minipass": "^5.0.0 || ^6.0.2 || ^7.0.0", - "path-scurry": "^1.10.1" - }, - "bin": { - "glob": "dist/cjs/src/bin.js" - }, - "engines": { - "node": ">=16 || 14 >=14.17" + "node": "^12.17.0 || ^14.13 || >=16.0.0" }, "funding": { - "url": "https://github.com/sponsors/isaacs" + "url": "https://github.com/chalk/chalk?sponsor=1" } }, - "node_modules/react-email/node_modules/jackspeak": { - "version": "2.3.6", - "resolved": "https://registry.npmjs.org/jackspeak/-/jackspeak-2.3.6.tgz", - "integrity": "sha512-N3yCS/NegsOBokc8GAdM8UcmfsKiSS8cipheD/nivzr700H+nsMOxJjQnvwOcRYVuFkdH0wGUvW2WbXGmrZGbQ==", + "node_modules/react-email/node_modules/commander": { + "version": "13.1.0", + "resolved": "https://registry.npmjs.org/commander/-/commander-13.1.0.tgz", + "integrity": "sha512-/rFeCpNJQbhSZjGVwO9RFV3xPqbnERS8MmIQzCtD/zl6gpJuV/bMLuN92oG3F7d8oDEHHRrujSXNUr8fpjntKw==", "dev": true, - "license": "BlueOak-1.0.0", - "dependencies": { - "@isaacs/cliui": "^8.0.2" - }, + "license": "MIT", "engines": { - "node": ">=14" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - }, - "optionalDependencies": { - "@pkgjs/parseargs": "^0.11.0" + "node": ">=18" } }, - "node_modules/react-email/node_modules/lru-cache": { - "version": "10.4.3", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-10.4.3.tgz", - "integrity": "sha512-JNAzZcXrCt42VGLuYz0zfAzDfAvJWW6AfYlDBQyDV5DClI2m5sAmK+OIO7s59XfsRsWHp02jAJrRadPRGTt6SQ==", + "node_modules/react-email/node_modules/mime-db": { + "version": "1.54.0", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.54.0.tgz", + "integrity": "sha512-aU5EJuIN2WDemCcAp2vFBfp/m4EAhWJnUNSSw0ixs7/kXbd6Pg64EmwJkNdFhB8aWt1sH2CTXrLxo/iAGV3oPQ==", "dev": true, - "license": "ISC" - }, - "node_modules/react-email/node_modules/minimatch": { - "version": "9.0.5", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.5.tgz", - "integrity": "sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow==", - "dev": true, - "license": "ISC", - "dependencies": { - "brace-expansion": "^2.0.1" - }, + "license": "MIT", "engines": { - "node": ">=16 || 14 >=14.17" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" + "node": ">= 0.6" } }, - "node_modules/react-email/node_modules/path-scurry": { - "version": "1.11.1", - "resolved": "https://registry.npmjs.org/path-scurry/-/path-scurry-1.11.1.tgz", - "integrity": "sha512-Xa4Nw17FS9ApQFJ9umLiJS4orGjm7ZzwUrwamcGQuHSzDyth9boKDaycYdDcZDuqYATXw4HFXgaqWTctW/v1HA==", + "node_modules/react-email/node_modules/mime-types": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-3.0.1.tgz", + "integrity": "sha512-xRc4oEhT6eaBpU1XF7AjpOFD+xQmXNB5OVKwp4tqCuBpHLS/ZbBDrc07mYTDqVMg6PfxUjjNp85O6Cd2Z/5HWA==", "dev": true, - "license": "BlueOak-1.0.0", + "license": "MIT", "dependencies": { - "lru-cache": "^10.2.0", - "minipass": "^5.0.0 || ^6.0.2 || ^7.0.0" + "mime-db": "^1.54.0" }, "engines": { - "node": ">=16 || 14 >=14.18" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" + "node": ">= 0.6" } }, "node_modules/react-hook-form": { - "version": "7.54.2", - "resolved": "https://registry.npmjs.org/react-hook-form/-/react-hook-form-7.54.2.tgz", - "integrity": "sha512-eHpAUgUjWbZocoQYUHposymRb4ZP6d0uwUnooL2uOybA9/3tPUvoAKqEWK1WaSiTxxOfTpffNZP7QwlnM3/gEg==", + "version": "7.56.4", + "resolved": "https://registry.npmjs.org/react-hook-form/-/react-hook-form-7.56.4.tgz", + "integrity": "sha512-Rob7Ftz2vyZ/ZGsQZPaRdIefkgOSrQSPXfqBdvOPwJfoGnjwRJUs7EM7Kc1mcoDv3NOtqBzPGbcMB8CGn9CKgw==", "license": "MIT", "engines": { "node": ">=18.0.0" @@ -14980,9 +15133,9 @@ "license": "MIT" }, "node_modules/react-remove-scroll": { - "version": "2.6.3", - "resolved": "https://registry.npmjs.org/react-remove-scroll/-/react-remove-scroll-2.6.3.tgz", - "integrity": "sha512-pnAi91oOk8g8ABQKGF5/M9qxmmOPxaAnopyTHYfqYEwJhyFrbbBtHuSgtKEoH0jpcxx5o3hXqH1mNd9/Oi+8iQ==", + "version": "2.7.1", + "resolved": "https://registry.npmjs.org/react-remove-scroll/-/react-remove-scroll-2.7.1.tgz", + "integrity": "sha512-HpMh8+oahmIdOuS5aFKKY6Pyog+FNaZV/XyJOq7b4YFwsFHe5yYfdbIalI4k3vU2nSDql7YskmUseHsRrJqIPA==", "license": "MIT", "dependencies": { "react-remove-scroll-bar": "^2.3.7", @@ -15132,16 +15285,6 @@ "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/require-directory": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz", - "integrity": "sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=0.10.0" - } - }, "node_modules/resolve": { "version": "1.22.10", "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.10.tgz", @@ -15181,17 +15324,49 @@ } }, "node_modules/restore-cursor": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/restore-cursor/-/restore-cursor-3.1.0.tgz", - "integrity": "sha512-l+sSefzHpj5qimhFSE5a8nufZYAM3sBSVMAPtYkmC+4EH2anSGaEMXSD0izRQbu9nfyQ9y5JrVmp7E8oZrUjvA==", + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/restore-cursor/-/restore-cursor-5.1.0.tgz", + "integrity": "sha512-oMA2dcrw6u0YfxJQXm342bFKX/E4sG9rbTzO9ptUcR/e8A33cHuvStiYOwH7fszkZlZ1z/ta9AAoPk2F4qIOHA==", "dev": true, "license": "MIT", "dependencies": { - "onetime": "^5.1.0", - "signal-exit": "^3.0.2" + "onetime": "^7.0.0", + "signal-exit": "^4.1.0" }, "engines": { - "node": ">=8" + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/restore-cursor/node_modules/onetime": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/onetime/-/onetime-7.0.0.tgz", + "integrity": "sha512-VXJjc87FScF88uafS3JllDgvAm+c/Slfz06lorj2uAY34rlUu0Nt+v8wreiImcrgAjjIHp1rXpTDlLOGw29WwQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "mimic-function": "^5.0.0" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/restore-cursor/node_modules/signal-exit": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-4.1.0.tgz", + "integrity": "sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==", + "dev": true, + "license": "ISC", + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" } }, "node_modules/reusify": { @@ -15315,9 +15490,9 @@ "license": "MIT" }, "node_modules/scheduler": { - "version": "0.25.0", - "resolved": "https://registry.npmjs.org/scheduler/-/scheduler-0.25.0.tgz", - "integrity": "sha512-xFVuu11jh+xcO7JOAGJNOXld8/TcEHK/4CituBUeUb5hqxJLj9YuemAEuvm9gQ/+pgXYfbQuqAkiYu+u7YEsNA==", + "version": "0.26.0", + "resolved": "https://registry.npmjs.org/scheduler/-/scheduler-0.26.0.tgz", + "integrity": "sha512-NlHwttCI/l5gCPR3D1nNXtWABUmBwvZpEQiD4IXSbIDq8BzLIK/7Ir5gTFSGZDUu37K5cMNp0hFtzO38sC7gWA==", "license": "MIT" }, "node_modules/selderee": { @@ -15333,9 +15508,9 @@ } }, "node_modules/semver": { - "version": "7.6.3", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.3.tgz", - "integrity": "sha512-oVekP1cKtI+CTDvHWYFUcMtsK/00wmAEfyqKfNdARm8u1wNVhSgaX7A8d4UuIlUI5e84iEwOhs7ZPYRmzU9U6A==", + "version": "7.7.2", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.7.2.tgz", + "integrity": "sha512-RF0Fw+rO5AMf9MAyaRXI4AV0Ulj5lMHqVxxdSgiVbixSCXoEmmX/jk0CuJw4+3SqroYO9VoUh+HcuJivvtJemA==", "license": "ISC", "bin": { "semver": "bin/semver.js" @@ -15460,16 +15635,16 @@ "license": "ISC" }, "node_modules/sharp": { - "version": "0.33.5", - "resolved": "https://registry.npmjs.org/sharp/-/sharp-0.33.5.tgz", - "integrity": "sha512-haPVm1EkS9pgvHrQ/F3Xy+hgcuMV0Wm9vfIBSiwZ05k+xgb0PkBQpGsAA/oWdDobNaZTH5ppvHtzCFbnSEwHVw==", + "version": "0.34.2", + "resolved": "https://registry.npmjs.org/sharp/-/sharp-0.34.2.tgz", + "integrity": "sha512-lszvBmB9QURERtyKT2bNmsgxXK0ShJrL/fvqlonCo7e6xBF8nT8xU6pW+PMIbLsz0RxQk3rgH9kd8UmvOzlMJg==", "hasInstallScript": true, "license": "Apache-2.0", "optional": true, "dependencies": { "color": "^4.2.3", - "detect-libc": "^2.0.3", - "semver": "^7.6.3" + "detect-libc": "^2.0.4", + "semver": "^7.7.2" }, "engines": { "node": "^18.17.0 || ^20.3.0 || >=21.0.0" @@ -15478,25 +15653,27 @@ "url": "https://opencollective.com/libvips" }, "optionalDependencies": { - "@img/sharp-darwin-arm64": "0.33.5", - "@img/sharp-darwin-x64": "0.33.5", - "@img/sharp-libvips-darwin-arm64": "1.0.4", - "@img/sharp-libvips-darwin-x64": "1.0.4", - "@img/sharp-libvips-linux-arm": "1.0.5", - "@img/sharp-libvips-linux-arm64": "1.0.4", - "@img/sharp-libvips-linux-s390x": "1.0.4", - "@img/sharp-libvips-linux-x64": "1.0.4", - "@img/sharp-libvips-linuxmusl-arm64": "1.0.4", - "@img/sharp-libvips-linuxmusl-x64": "1.0.4", - "@img/sharp-linux-arm": "0.33.5", - "@img/sharp-linux-arm64": "0.33.5", - "@img/sharp-linux-s390x": "0.33.5", - "@img/sharp-linux-x64": "0.33.5", - "@img/sharp-linuxmusl-arm64": "0.33.5", - "@img/sharp-linuxmusl-x64": "0.33.5", - "@img/sharp-wasm32": "0.33.5", - "@img/sharp-win32-ia32": "0.33.5", - "@img/sharp-win32-x64": "0.33.5" + "@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" } }, "node_modules/shebang-command": { @@ -15520,19 +15697,6 @@ "node": ">=8" } }, - "node_modules/shell-quote": { - "version": "1.8.2", - "resolved": "https://registry.npmjs.org/shell-quote/-/shell-quote-1.8.2.tgz", - "integrity": "sha512-AzqKpGKjrj7EM6rKVQEPpB288oCfnrEIuyoT9cyF4nmGa7V8Zk6f7RRqYisX8X9m+Q7bd632aZW4ky7EhbQztA==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, "node_modules/side-channel": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.1.0.tgz", @@ -15826,6 +15990,15 @@ "source-map": "^0.6.0" } }, + "node_modules/split2": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/split2/-/split2-4.2.0.tgz", + "integrity": "sha512-UcjcJOWknrNkF6PLX83qcHM6KHgVKNkV62Y8a5uYDVv9ydGQVwAHMKqHdJje1VTWpljG0WYpCDhrCdAOYH4TWg==", + "license": "ISC", + "engines": { + "node": ">= 10.x" + } + }, "node_modules/stable-hash": { "version": "0.0.5", "resolved": "https://registry.npmjs.org/stable-hash/-/stable-hash-0.0.5.tgz", @@ -15850,6 +16023,32 @@ "node": ">= 0.8" } }, + "node_modules/stdin-discarder": { + "version": "0.2.2", + "resolved": "https://registry.npmjs.org/stdin-discarder/-/stdin-discarder-0.2.2.tgz", + "integrity": "sha512-UhDfHmA92YAlNnCfhmq0VeNL5bDbiZGg7sZ2IvPsXubGkiNa9EC+tUTsjBRsYUAz87btI6/1wf4XoVvQ3uRnmQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/stop-iteration-iterator": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/stop-iteration-iterator/-/stop-iteration-iterator-1.1.0.tgz", + "integrity": "sha512-eLoXW/DHyl62zxY4SCaIgnRhuMr6ri4juEYARS8E6sCEqzKpOiE521Ucofdx+KnDZl5xmvGYaaKCk5FEOxJCoQ==", + "license": "MIT", + "dependencies": { + "es-errors": "^1.3.0", + "internal-slot": "^1.1.0" + }, + "engines": { + "node": ">= 0.4" + } + }, "node_modules/streamsearch": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/streamsearch/-/streamsearch-1.1.0.tgz", @@ -16149,9 +16348,9 @@ } }, "node_modules/swagger-ui-dist": { - "version": "5.21.0", - "resolved": "https://registry.npmjs.org/swagger-ui-dist/-/swagger-ui-dist-5.21.0.tgz", - "integrity": "sha512-E0K3AB6HvQd8yQNSMR7eE5bk+323AUxjtCz/4ZNKiahOlPhPJxqn3UPIGs00cyY/dhrTDJ61L7C/a8u6zhGrZg==", + "version": "5.24.0", + "resolved": "https://registry.npmjs.org/swagger-ui-dist/-/swagger-ui-dist-5.24.0.tgz", + "integrity": "sha512-okwN8vf14TOgBTUyGgCXEAoHnrwwp/042dC00B3kPu2OAe9zD75BtSbLlgAK1Y5e3csJhs+AdnIxJYZN9uvptg==", "license": "Apache-2.0", "dependencies": { "@scarf/scarf": "=1.4.0" @@ -16183,6 +16382,7 @@ } }, "node_modules/tailwindcss": { +<<<<<<< HEAD "version": "4.1.6", "resolved": "https://registry.npmjs.org/tailwindcss/-/tailwindcss-4.1.6.tgz", "integrity": "sha512-j0cGLTreM6u4OWzBeLBpycK0WIh8w7kSwcUsQZoGLHZ7xDTdM69lN64AgoIEEwFi0tnhs4wSykUa5YWxAzgFYg==", @@ -16192,6 +16392,17 @@ "version": "2.2.1", "resolved": "https://registry.npmjs.org/tapable/-/tapable-2.2.1.tgz", "integrity": "sha512-GNzQvQTOIP6RyTfE2Qxb8ZVlNmw0n88vp1szwWRimP02mnTsx3Wtn5qRdqY9w2XduFNUgvOwhNnQsjwCp+kqaQ==", +======= + "version": "4.1.8", + "resolved": "https://registry.npmjs.org/tailwindcss/-/tailwindcss-4.1.8.tgz", + "integrity": "sha512-kjeW8gjdxasbmFKpVGrGd5T4i40mV5J2Rasw48QARfYeQ8YS9x02ON9SFWax3Qf616rt4Cp3nVNIj6Hd1mP3og==", + "license": "MIT" + }, + "node_modules/tapable": { + "version": "2.2.2", + "resolved": "https://registry.npmjs.org/tapable/-/tapable-2.2.2.tgz", + "integrity": "sha512-Re10+NauLTMCudc7T5WLFLAwDhQ0JWdrMK+9B2M8zR5hRExKmsRDCBA7/aV/pNJFltmBFO5BAMlQFi/vq3nKOg==", +>>>>>>> dev "dev": true, "license": "MIT", "engines": { @@ -16202,6 +16413,10 @@ "version": "7.4.3", "resolved": "https://registry.npmjs.org/tar/-/tar-7.4.3.tgz", "integrity": "sha512-5S7Va8hKfV7W5U6g3aYxXmlPoZVAwUMy9AOKyF2fVuZa2UD3qZjg578OrLRt8PcNN1PleVaL/5/yYATNL0ICUw==", +<<<<<<< HEAD +======= + "dev": true, +>>>>>>> dev "license": "ISC", "dependencies": { "@isaacs/fs-minipass": "^4.0.0", @@ -16216,9 +16431,9 @@ } }, "node_modules/tar-fs": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/tar-fs/-/tar-fs-2.1.2.tgz", - "integrity": "sha512-EsaAXwxmx8UB7FRKqeozqEPop69DXcmYwTQwXvyAPF352HJsPdkVhvTaDPYqfNgruveJIJy3TA2l+2zj8LJIJA==", + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/tar-fs/-/tar-fs-2.1.3.tgz", + "integrity": "sha512-090nwYJDmlhwFwEW3QQl+vaNnxsO2yVsd45eTKRBzSzu+hlb1w2K9inVq5b0ngXuLVqQ4ApvsUHHnu/zQNkWAg==", "license": "MIT", "dependencies": { "chownr": "^1.1.1", @@ -16256,9 +16471,15 @@ "license": "MIT" }, "node_modules/tinyglobby": { +<<<<<<< HEAD "version": "0.2.13", "resolved": "https://registry.npmjs.org/tinyglobby/-/tinyglobby-0.2.13.tgz", "integrity": "sha512-mEwzpUgrLySlveBwEVDMKk5B57bhLPYovRfPAXD5gA/98Opn0rCDj3GtLwFvCvH5RK9uPCExUROW5NjDwvqkxw==", +======= + "version": "0.2.14", + "resolved": "https://registry.npmjs.org/tinyglobby/-/tinyglobby-0.2.14.tgz", + "integrity": "sha512-tX5e7OM1HnYr2+a2C/4V0htOcSQcoSTH9KgJnVvNm5zm/cyEWKJ7j7YutsH9CxMdtOkkLFy2AHrMci9IM8IPZQ==", +>>>>>>> dev "license": "MIT", "dependencies": { "fdir": "^6.4.4", @@ -16314,14 +16535,15 @@ } }, "node_modules/tsc-alias": { - "version": "1.8.10", - "resolved": "https://registry.npmjs.org/tsc-alias/-/tsc-alias-1.8.10.tgz", - "integrity": "sha512-Ibv4KAWfFkFdKJxnWfVtdOmB0Zi1RJVxcbPGiCDsFpCQSsmpWyuzHG3rQyI5YkobWwxFPEyQfu1hdo4qLG2zPw==", + "version": "1.8.16", + "resolved": "https://registry.npmjs.org/tsc-alias/-/tsc-alias-1.8.16.tgz", + "integrity": "sha512-QjCyu55NFyRSBAl6+MTFwplpFcnm2Pq01rR/uxfqJoLMm6X3O14KEGtaSDZpJYaE1bJBGDjD0eSuiIWPe2T58g==", "dev": true, "license": "MIT", "dependencies": { "chokidar": "^3.5.3", "commander": "^9.0.0", + "get-tsconfig": "^4.10.0", "globby": "^11.0.4", "mylas": "^2.1.9", "normalize-path": "^3.0.0", @@ -16329,6 +16551,9 @@ }, "bin": { "tsc-alias": "dist/bin/index.js" + }, + "engines": { + "node": ">=16.20.2" } }, "node_modules/tsc-alias/node_modules/chokidar": { @@ -16433,9 +16658,9 @@ } }, "node_modules/tsx": { - "version": "4.19.3", - "resolved": "https://registry.npmjs.org/tsx/-/tsx-4.19.3.tgz", - "integrity": "sha512-4H8vUNGNjQ4V2EOoGw005+c+dGuPSnhpPBPHBtsZdGZBk/iJb4kguGlPWaZTZ3q5nMtFOEsY0nRDlh9PJyd6SQ==", + "version": "4.19.4", + "resolved": "https://registry.npmjs.org/tsx/-/tsx-4.19.4.tgz", + "integrity": "sha512-gK5GVzDkJK1SI1zwHf32Mqxf2tSJkNx+eYcNly5+nHvWqXUJYUkWBQtKauoESz3ymezAI++ZwT855x5p5eop+Q==", "dev": true, "license": "MIT", "dependencies": { @@ -16465,9 +16690,15 @@ } }, "node_modules/tw-animate-css": { +<<<<<<< HEAD "version": "1.2.9", "resolved": "https://registry.npmjs.org/tw-animate-css/-/tw-animate-css-1.2.9.tgz", "integrity": "sha512-9O4k1at9pMQff9EAcCEuy1UNO43JmaPQvq+0lwza9Y0BQ6LB38NiMj+qHqjoQf40355MX+gs6wtlR6H9WsSXFg==", +======= + "version": "1.3.4", + "resolved": "https://registry.npmjs.org/tw-animate-css/-/tw-animate-css-1.3.4.tgz", + "integrity": "sha512-dd1Ht6/YQHcNbq0znIT6dG8uhO7Ce+VIIhZUhjsryXsMPJQz3bZg7Q2eNzLwipb25bRZslGb2myio5mScd1TFg==", +>>>>>>> dev "license": "MIT", "funding": { "url": "https://github.com/sponsors/Wombosvideo" @@ -16585,6 +16816,29 @@ "node": ">=14.17" } }, + "node_modules/typescript-eslint": { + "version": "8.34.0", + "resolved": "https://registry.npmjs.org/typescript-eslint/-/typescript-eslint-8.34.0.tgz", + "integrity": "sha512-MRpfN7uYjTrTGigFCt8sRyNqJFhjN0WwZecldaqhWm+wy0gaRt8Edb/3cuUy0zdq2opJWT6iXINKAtewnDOltQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@typescript-eslint/eslint-plugin": "8.34.0", + "@typescript-eslint/parser": "8.34.0", + "@typescript-eslint/utils": "8.34.0" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "eslint": "^8.57.0 || ^9.0.0", + "typescript": ">=4.8.4 <5.9.0" + } + }, "node_modules/unbox-primitive": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/unbox-primitive/-/unbox-primitive-1.1.0.tgz", @@ -16620,15 +16874,22 @@ } }, "node_modules/unrs-resolver": { +<<<<<<< HEAD "version": "1.7.2", "resolved": "https://registry.npmjs.org/unrs-resolver/-/unrs-resolver-1.7.2.tgz", "integrity": "sha512-BBKpaylOW8KbHsu378Zky/dGh4ckT/4NW/0SHRABdqRLcQJ2dAOjDo9g97p04sWflm0kqPqpUatxReNV/dqI5A==", +======= + "version": "1.7.11", + "resolved": "https://registry.npmjs.org/unrs-resolver/-/unrs-resolver-1.7.11.tgz", + "integrity": "sha512-OhuAzBImFPjKNgZ2JwHMfGFUA6NSbRegd1+BPjC1Y0E6X9Y/vJ4zKeGmIMqmlYboj6cMNEwKI+xQisrg4J0HaQ==", +>>>>>>> dev "hasInstallScript": true, "license": "MIT", "dependencies": { "napi-postinstall": "^0.2.2" }, "funding": { +<<<<<<< HEAD "url": "https://github.com/sponsors/JounQin" }, "optionalDependencies": { @@ -16649,6 +16910,28 @@ "@unrs/resolver-binding-win32-arm64-msvc": "1.7.2", "@unrs/resolver-binding-win32-ia32-msvc": "1.7.2", "@unrs/resolver-binding-win32-x64-msvc": "1.7.2" +======= + "url": "https://opencollective.com/unrs-resolver" + }, + "optionalDependencies": { + "@unrs/resolver-binding-darwin-arm64": "1.7.11", + "@unrs/resolver-binding-darwin-x64": "1.7.11", + "@unrs/resolver-binding-freebsd-x64": "1.7.11", + "@unrs/resolver-binding-linux-arm-gnueabihf": "1.7.11", + "@unrs/resolver-binding-linux-arm-musleabihf": "1.7.11", + "@unrs/resolver-binding-linux-arm64-gnu": "1.7.11", + "@unrs/resolver-binding-linux-arm64-musl": "1.7.11", + "@unrs/resolver-binding-linux-ppc64-gnu": "1.7.11", + "@unrs/resolver-binding-linux-riscv64-gnu": "1.7.11", + "@unrs/resolver-binding-linux-riscv64-musl": "1.7.11", + "@unrs/resolver-binding-linux-s390x-gnu": "1.7.11", + "@unrs/resolver-binding-linux-x64-gnu": "1.7.11", + "@unrs/resolver-binding-linux-x64-musl": "1.7.11", + "@unrs/resolver-binding-wasm32-wasi": "1.7.11", + "@unrs/resolver-binding-win32-arm64-msvc": "1.7.11", + "@unrs/resolver-binding-win32-ia32-msvc": "1.7.11", + "@unrs/resolver-binding-win32-x64-msvc": "1.7.11" +>>>>>>> dev } }, "node_modules/uri-js": { @@ -16762,16 +17045,6 @@ "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0.0 || ^19.0.0-rc" } }, - "node_modules/wcwidth": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/wcwidth/-/wcwidth-1.0.1.tgz", - "integrity": "sha512-XHPEwS0q6TaxcvG85+8EYkbiCux2XtWG2mkc47Ng2A77BQu9+DqIOJldST4HgPkuea7dvKSj5VgX3P1d4rW8Tg==", - "dev": true, - "license": "MIT", - "dependencies": { - "defaults": "^1.0.3" - } - }, "node_modules/web-streams-polyfill": { "version": "3.3.3", "resolved": "https://registry.npmjs.org/web-streams-polyfill/-/web-streams-polyfill-3.3.3.tgz", @@ -17048,9 +17321,9 @@ "license": "ISC" }, "node_modules/ws": { - "version": "8.18.0", - "resolved": "https://registry.npmjs.org/ws/-/ws-8.18.0.tgz", - "integrity": "sha512-8VbfWfHLbbwu3+N6OKsOMpBdT4kXPDDB9cJk2bJ6mh9ucxdlnNvH1e+roYkKmN9Nxw2yjz7VzeO9oOz2zJ04Pw==", + "version": "8.18.2", + "resolved": "https://registry.npmjs.org/ws/-/ws-8.18.2.tgz", + "integrity": "sha512-DMricUmwGZUVr++AEAe2uiVM7UoO9MAVZMDu05UQOaUII0lp+zOzLLU4Xqh/JvTqklB1T4uELaaPBKyjE1r4fQ==", "license": "MIT", "engines": { "node": ">=10.0.0" @@ -17068,6 +17341,15 @@ } } }, + "node_modules/xtend": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.2.tgz", + "integrity": "sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ==", + "license": "MIT", + "engines": { + "node": ">=0.4" + } + }, "node_modules/y18n": { "version": "5.0.8", "resolved": "https://registry.npmjs.org/y18n/-/y18n-5.0.8.tgz", @@ -17082,95 +17364,78 @@ "version": "5.0.0", "resolved": "https://registry.npmjs.org/yallist/-/yallist-5.0.0.tgz", "integrity": "sha512-YgvUTfwqyc7UXVMrB+SImsVYSmTS8X/tSrtdNZMImM+n7+QTriRXyXim0mBrTXNeqzVF0KWGgHPeiyViFFrNDw==", +<<<<<<< HEAD +======= + "dev": true, +>>>>>>> dev "license": "BlueOak-1.0.0", "engines": { "node": ">=18" } }, "node_modules/yaml": { - "version": "2.7.1", - "resolved": "https://registry.npmjs.org/yaml/-/yaml-2.7.1.tgz", - "integrity": "sha512-10ULxpnOCQXxJvBgxsn9ptjq6uviG/htZKk9veJGhlqn3w/DxQ631zFF+nlQXLwmImeS5amR2dl2U8sg6U9jsQ==", + "version": "2.8.0", + "resolved": "https://registry.npmjs.org/yaml/-/yaml-2.8.0.tgz", + "integrity": "sha512-4lLa/EcQCB0cJkyts+FpIRx5G/llPxfP6VQU5KByHEhLxY3IJCH0f0Hy1MHI8sClTvsIb8qwRJ6R/ZdlDJ/leQ==", "license": "ISC", "bin": { "yaml": "bin.mjs" }, "engines": { - "node": ">= 14" + "node": ">= 14.6" } }, "node_modules/yargs": { - "version": "17.7.2", - "resolved": "https://registry.npmjs.org/yargs/-/yargs-17.7.2.tgz", - "integrity": "sha512-7dSzzRQ++CKnNI/krKnYRV7JKKPUXMEh61soaHKg9mrWEhzFWhFnxPxGl+69cD1Ou63C13NUPCnmIcrvqCuM6w==", + "version": "18.0.0", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-18.0.0.tgz", + "integrity": "sha512-4UEqdc2RYGHZc7Doyqkrqiln3p9X2DZVxaGbwhn2pi7MrRagKaOcIKe8L3OxYcbhXLgLFUS3zAYuQjKBQgmuNg==", "dev": true, "license": "MIT", "dependencies": { - "cliui": "^8.0.1", + "cliui": "^9.0.1", "escalade": "^3.1.1", "get-caller-file": "^2.0.5", - "require-directory": "^2.1.1", - "string-width": "^4.2.3", + "string-width": "^7.2.0", "y18n": "^5.0.5", - "yargs-parser": "^21.1.1" + "yargs-parser": "^22.0.0" }, "engines": { - "node": ">=12" + "node": "^20.19.0 || ^22.12.0 || >=23" } }, "node_modules/yargs-parser": { - "version": "21.1.1", - "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-21.1.1.tgz", - "integrity": "sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw==", + "version": "22.0.0", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-22.0.0.tgz", + "integrity": "sha512-rwu/ClNdSMpkSrUb+d6BRsSkLUq1fmfsY6TOpYzTwvwkg1/NRG85KBy3kq++A8LKQwX6lsu+aWad+2khvuXrqw==", "dev": true, "license": "ISC", "engines": { - "node": ">=12" - } - }, - "node_modules/yargs/node_modules/ansi-regex": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", - "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=8" + "node": "^20.19.0 || ^22.12.0 || >=23" } }, "node_modules/yargs/node_modules/emoji-regex": { - "version": "8.0.0", - "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", - "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", + "version": "10.4.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-10.4.0.tgz", + "integrity": "sha512-EC+0oUMY1Rqm4O6LLrgjtYDvcVYTy7chDnM4Q7030tP4Kwj3u/pR6gP9ygnp2CJMK5Gq+9Q2oqmrFJAz01DXjw==", "dev": true, "license": "MIT" }, "node_modules/yargs/node_modules/string-width": { - "version": "4.2.3", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", - "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-7.2.0.tgz", + "integrity": "sha512-tsaTIkKW9b4N+AEj+SVA+WhJzV7/zMhcSu78mLKWSk7cXMOSHsBKFWUs0fWwq8QyK3MgJBQRX6Gbi4kYbdvGkQ==", "dev": true, "license": "MIT", "dependencies": { - "emoji-regex": "^8.0.0", - "is-fullwidth-code-point": "^3.0.0", - "strip-ansi": "^6.0.1" + "emoji-regex": "^10.3.0", + "get-east-asian-width": "^1.0.0", + "strip-ansi": "^7.1.0" }, "engines": { - "node": ">=8" - } - }, - "node_modules/yargs/node_modules/strip-ansi": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", - "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", - "dev": true, - "license": "MIT", - "dependencies": { - "ansi-regex": "^5.0.1" + "node": ">=18" }, - "engines": { - "node": ">=8" + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, "node_modules/yocto-queue": { @@ -17185,25 +17450,38 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/yoctocolors": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/yoctocolors/-/yoctocolors-2.1.1.tgz", + "integrity": "sha512-GQHQqAopRhwU8Kt1DDM8NjibDXHC8eoh1erhGAJPEyveY9qqVeXvVikNKrDz69sHowPMorbPUrH/mx8c50eiBQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/zod": { - "version": "3.24.1", - "resolved": "https://registry.npmjs.org/zod/-/zod-3.24.1.tgz", - "integrity": "sha512-muH7gBL9sI1nciMZV67X5fTKKBLtwpZ5VBp1vsOQzj1MhrBZ4wlVCm3gedKZWLp0Oyel8sIGfeiz54Su+OVT+A==", + "version": "3.25.56", + "resolved": "https://registry.npmjs.org/zod/-/zod-3.25.56.tgz", + "integrity": "sha512-rd6eEF3BTNvQnR2e2wwolfTmUTnp70aUTqr0oaGbHifzC3BKJsoV+Gat8vxUMR1hwOKBs6El+qWehrHbCpW6SQ==", "license": "MIT", "funding": { "url": "https://github.com/sponsors/colinhacks" } }, "node_modules/zod-validation-error": { - "version": "3.4.0", - "resolved": "https://registry.npmjs.org/zod-validation-error/-/zod-validation-error-3.4.0.tgz", - "integrity": "sha512-ZOPR9SVY6Pb2qqO5XHt+MkkTRxGXb4EVtnjc9JpXUOtUB1T9Ru7mZOT361AN3MsetVe7R0a1KZshJDZdgp9miQ==", + "version": "3.4.1", + "resolved": "https://registry.npmjs.org/zod-validation-error/-/zod-validation-error-3.4.1.tgz", + "integrity": "sha512-1KP64yqDPQ3rupxNv7oXhf7KdhHHgaqbKuspVoiN93TT0xrBjql+Svjkdjq/Qh/7GSMmgQs3AfvBT0heE35thw==", "license": "MIT", "engines": { "node": ">=18.0.0" }, "peerDependencies": { - "zod": "^3.18.0" + "zod": "^3.24.4" } } } diff --git a/package.json b/package.json index d30658b3..5b0ff4b9 100644 --- a/package.json +++ b/package.json @@ -12,101 +12,108 @@ "license": "SEE LICENSE IN LICENSE AND README.md", "scripts": { "dev": "NODE_ENV=development ENVIRONMENT=dev tsx watch server/index.ts", - "db:generate": "drizzle-kit generate", - "db:push": "npx tsx server/db/migrate.ts", - "db:studio": "drizzle-kit studio", - "build": "mkdir -p dist && next build && node esbuild.mjs -e server/index.ts -o dist/server.mjs && node esbuild.mjs -e server/setup/migrations.ts -o dist/migrations.mjs", - "start": "NODE_OPTIONS=--enable-source-maps NODE_ENV=development ENVIRONMENT=prod sh -c 'node dist/migrations.mjs && node dist/server.mjs'", + "db:pg:generate": "drizzle-kit generate --config=./drizzle.pg.config.ts", + "db:sqlite:generate": "drizzle-kit generate --config=./drizzle.sqlite.config.ts", + "db:pg:push": "npx tsx server/db/pg/migrate.ts", + "db:sqlite:push": "npx tsx server/db/sqlite/migrate.ts", + "db:sqlite:studio": "drizzle-kit studio --config=./drizzle.sqlite.config.ts", + "db:pg:studio": "drizzle-kit studio --config=./drizzle.pg.config.ts", + "db:clear-migrations": "rm -rf server/migrations", + "build:sqlite": "mkdir -p dist && next build && node esbuild.mjs -e server/index.ts -o dist/server.mjs && node esbuild.mjs -e server/setup/migrationsSqlite.ts -o dist/migrations.mjs", + "build:pg": "mkdir -p dist && next build && node esbuild.mjs -e server/index.ts -o dist/server.mjs && node esbuild.mjs -e server/setup/migrationsPg.ts -o dist/migrations.mjs", + "start:sqlite": "DB_TYPE=sqlite NODE_OPTIONS=--enable-source-maps NODE_ENV=development ENVIRONMENT=prod sh -c 'node dist/migrations.mjs && node dist/server.mjs'", + "start:pg": "DB_TYPE=pg NODE_OPTIONS=--enable-source-maps NODE_ENV=development ENVIRONMENT=prod sh -c 'node dist/migrations.mjs && node dist/server.mjs'", "email": "email dev --dir server/emails/templates --port 3005" }, "dependencies": { - "@asteasolutions/zod-to-openapi": "^7.3.0", + "@asteasolutions/zod-to-openapi": "^7.3.2", "@hookform/resolvers": "3.9.1", - "@node-rs/argon2": "2.0.2", + "@node-rs/argon2": "^2.0.2", "@oslojs/crypto": "1.0.1", "@oslojs/encoding": "1.1.0", - "@radix-ui/react-avatar": "1.1.2", - "@radix-ui/react-checkbox": "1.1.3", - "@radix-ui/react-collapsible": "1.1.2", - "@radix-ui/react-dialog": "1.1.4", - "@radix-ui/react-dropdown-menu": "2.1.4", + "@radix-ui/react-avatar": "1.1.10", + "@radix-ui/react-checkbox": "1.3.2", + "@radix-ui/react-collapsible": "1.1.11", + "@radix-ui/react-dialog": "1.1.14", + "@radix-ui/react-dropdown-menu": "2.1.15", "@radix-ui/react-icons": "1.3.2", - "@radix-ui/react-label": "2.1.1", - "@radix-ui/react-popover": "1.1.4", - "@radix-ui/react-progress": "^1.1.4", - "@radix-ui/react-radio-group": "1.2.2", - "@radix-ui/react-scroll-area": "1.2.3", - "@radix-ui/react-select": "2.1.4", - "@radix-ui/react-separator": "1.1.1", - "@radix-ui/react-slot": "1.1.1", - "@radix-ui/react-switch": "1.1.2", - "@radix-ui/react-tabs": "1.1.2", - "@radix-ui/react-toast": "1.2.4", - "@react-email/components": "0.0.36", - "@react-email/render": "^1.0.6", - "@react-email/tailwind": "1.0.4", + "@radix-ui/react-label": "2.1.7", + "@radix-ui/react-popover": "1.1.14", + "@radix-ui/react-progress": "^1.1.7", + "@radix-ui/react-radio-group": "1.3.7", + "@radix-ui/react-scroll-area": "^1.2.9", + "@radix-ui/react-select": "2.2.5", + "@radix-ui/react-separator": "1.1.7", + "@radix-ui/react-slot": "1.2.3", + "@radix-ui/react-switch": "1.2.5", + "@radix-ui/react-tabs": "1.1.12", + "@radix-ui/react-toast": "1.2.14", + "@react-email/components": "0.0.41", + "@react-email/render": "^1.1.2", + "@react-email/tailwind": "1.0.5", "@tailwindcss/forms": "^0.5.10", - "@tanstack/react-table": "8.20.6", - "arctic": "^3.6.0", - "axios": "1.8.4", + "@tanstack/react-table": "8.21.3", + "arctic": "^3.7.0", + "axios": "1.9.0", "better-sqlite3": "11.7.0", "canvas-confetti": "1.9.3", "class-variance-authority": "0.7.1", "clsx": "2.1.1", - "cmdk": "1.0.4", + "cmdk": "1.1.1", "cookie": "^1.0.2", "cookie-parser": "1.4.7", "cookies": "^0.9.1", "cors": "2.8.5", "crypto-js": "^4.2.0", "drizzle-orm": "0.38.3", - "eslint": "9.17.0", - "eslint-config-next": "15.1.3", + "eslint": "9.28.0", + "eslint-config-next": "15.3.3", "express": "4.21.2", "express-rate-limit": "7.5.0", - "glob": "11.0.0", - "helmet": "8.0.0", + "glob": "11.0.2", + "helmet": "8.1.0", "http-errors": "2.0.0", "i": "^0.3.7", - "input-otp": "1.4.1", + "input-otp": "1.4.2", "jmespath": "^0.16.0", "js-yaml": "4.1.0", "jsonwebtoken": "^9.0.2", - "lucide-react": "0.469.0", + "lucide-react": "0.511.0", "moment": "2.30.1", - "next": "15.2.4", - "next-themes": "0.4.4", + "next": "15.3.3", + "next-themes": "0.4.6", "node-cache": "5.1.2", "node-fetch": "3.3.2", "nodemailer": "6.9.16", - "npm": "^11.2.0", + "npm": "^11.4.1", "oslo": "1.2.1", + "pg": "^8.16.0", "qrcode.react": "4.2.0", - "react": "19.0.0", - "react-dom": "19.0.0", + "react": "19.1.0", + "react-dom": "19.1.0", "react-easy-sort": "^1.6.0", - "react-hook-form": "7.54.2", + "react-hook-form": "7.56.4", "react-icons": "^5.5.0", "rebuild": "0.1.2", - "semver": "7.6.3", + "semver": "7.7.2", "swagger-ui-express": "^5.0.1", "tailwind-merge": "2.6.0", - "tw-animate-css": "^1.2.5", + "tw-animate-css": "^1.3.3", "uuid": "^11.1.0", "vaul": "1.1.2", "winston": "3.17.0", "winston-daily-rotate-file": "5.0.0", - "ws": "8.18.0", - "zod": "3.24.1", - "zod-validation-error": "3.4.0" + "ws": "8.18.2", + "zod": "3.25.56", + "zod-validation-error": "3.4.1" }, "devDependencies": { - "@dotenvx/dotenvx": "1.32.0", + "@dotenvx/dotenvx": "1.44.1", "@esbuild-plugins/tsconfig-paths": "0.1.2", - "@tailwindcss/postcss": "^4.1.3", + "@tailwindcss/postcss": "^4.1.8", "@types/better-sqlite3": "7.6.12", - "@types/cookie-parser": "1.4.8", - "@types/cors": "2.8.17", + "@types/cookie-parser": "1.4.9", + "@types/cors": "2.8.19", "@types/crypto-js": "^4.2.2", "@types/express": "5.0.0", "@types/jmespath": "^0.15.2", @@ -114,22 +121,23 @@ "@types/jsonwebtoken": "^9.0.9", "@types/node": "^22", "@types/nodemailer": "6.4.17", - "@types/react": "19.1.1", - "@types/react-dom": "19.1.2", - "@types/semver": "7.5.8", + "@types/react": "19.1.7", + "@types/react-dom": "19.1.6", + "@types/semver": "7.7.0", "@types/swagger-ui-express": "^4.1.8", - "@types/ws": "8.5.13", + "@types/ws": "8.18.1", "@types/yargs": "17.0.33", - "drizzle-kit": "0.30.6", - "esbuild": "0.25.2", + "drizzle-kit": "0.31.1", + "esbuild": "0.25.5", "esbuild-node-externals": "1.18.0", "postcss": "^8", - "react-email": "4.0.6", + "react-email": "4.0.16", "tailwindcss": "^4.1.4", - "tsc-alias": "1.8.10", - "tsx": "4.19.3", + "tsc-alias": "1.8.16", + "tsx": "4.19.4", "typescript": "^5", - "yargs": "17.7.2" + "typescript-eslint": "^8.34.0", + "yargs": "18.0.0" }, "overrides": { "emblor": { diff --git a/public/logo/pangolin_black.svg b/public/logo/pangolin_black.svg index fd2b02ac..89f5a622 100644 --- a/public/logo/pangolin_black.svg +++ b/public/logo/pangolin_black.svg @@ -1,22 +1,21 @@ + + + + inkscape:document-units="mm" + showgrid="false" /> + + + + + diff --git a/public/logo/pangolin_orange.svg b/public/logo/pangolin_orange.svg index a8823c9d..5e81a57f 100644 --- a/public/logo/pangolin_orange.svg +++ b/public/logo/pangolin_orange.svg @@ -1,39 +1,22 @@ + + + xmlns:svg="http://www.w3.org/2000/svg"> + + + + + diff --git a/public/logo/pangolin_orange_192x192.png b/public/logo/pangolin_orange_192x192.png index 52e8659b..33fbf7b0 100644 Binary files a/public/logo/pangolin_orange_192x192.png and b/public/logo/pangolin_orange_192x192.png differ diff --git a/public/logo/pangolin_orange_512x512.png b/public/logo/pangolin_orange_512x512.png index 21f27644..ceed7e55 100644 Binary files a/public/logo/pangolin_orange_512x512.png and b/public/logo/pangolin_orange_512x512.png differ diff --git a/public/logo/pangolin_orange_96x96.png b/public/logo/pangolin_orange_96x96.png index 6d3821c2..76f23b9d 100644 Binary files a/public/logo/pangolin_orange_96x96.png and b/public/logo/pangolin_orange_96x96.png differ diff --git a/public/logo/pangolin_profile_picture.png b/public/logo/pangolin_profile_picture.png new file mode 100644 index 00000000..20c5f72b Binary files /dev/null and b/public/logo/pangolin_profile_picture.png differ diff --git a/public/logo/word_mark.png b/public/logo/word_mark.png index d75a047c..27944d9c 100644 Binary files a/public/logo/word_mark.png and b/public/logo/word_mark.png differ diff --git a/public/logo/word_mark_black.png b/public/logo/word_mark_black.png new file mode 100644 index 00000000..ba6fb84e Binary files /dev/null and b/public/logo/word_mark_black.png differ diff --git a/public/logo/word_mark_white.png b/public/logo/word_mark_white.png new file mode 100644 index 00000000..fb7a252d Binary files /dev/null and b/public/logo/word_mark_white.png differ diff --git a/server/auth/actions.ts b/server/auth/actions.ts index 5df1f467..f5a7f5da 100644 --- a/server/auth/actions.ts +++ b/server/auth/actions.ts @@ -1,6 +1,6 @@ import { Request } from "express"; import { db } from "@server/db"; -import { userActions, roleActions, userOrgs } from "@server/db/schemas"; +import { userActions, roleActions, userOrgs } from "@server/db"; import { and, eq } from "drizzle-orm"; import createHttpError from "http-errors"; import HttpCode from "@server/types/HttpCode"; diff --git a/server/auth/canUserAccessResource.ts b/server/auth/canUserAccessResource.ts index 0d618255..161a0bee 100644 --- a/server/auth/canUserAccessResource.ts +++ b/server/auth/canUserAccessResource.ts @@ -1,6 +1,6 @@ -import db from "@server/db"; +import { db } from "@server/db"; import { and, eq } from "drizzle-orm"; -import { roleResources, userResources } from "@server/db/schemas"; +import { roleResources, userResources } from "@server/db"; export async function canUserAccessResource({ userId, diff --git a/server/auth/checkValidInvite.ts b/server/auth/checkValidInvite.ts index bda12c9f..e8dee8a8 100644 --- a/server/auth/checkValidInvite.ts +++ b/server/auth/checkValidInvite.ts @@ -1,5 +1,5 @@ -import db from "@server/db"; -import { UserInvite, userInvites } from "@server/db/schemas"; +import { db } from "@server/db"; +import { UserInvite, userInvites } from "@server/db"; import { isWithinExpirationDate } from "oslo"; import { verifyPassword } from "./password"; import { eq } from "drizzle-orm"; diff --git a/server/auth/limits.ts b/server/auth/limits.ts index c7c19398..5d0b14e4 100644 --- a/server/auth/limits.ts +++ b/server/auth/limits.ts @@ -1,5 +1,5 @@ import { db } from '@server/db'; -import { limitsTable } from '@server/db/schemas'; +import { limitsTable } from '@server/db'; import { and, eq } from 'drizzle-orm'; import createHttpError from 'http-errors'; import HttpCode from '@server/types/HttpCode'; diff --git a/server/auth/resourceOtp.ts b/server/auth/resourceOtp.ts index 2539bf38..3a0753e0 100644 --- a/server/auth/resourceOtp.ts +++ b/server/auth/resourceOtp.ts @@ -1,5 +1,5 @@ -import db from "@server/db"; -import { resourceOtp } from "@server/db/schemas"; +import { db } from "@server/db"; +import { resourceOtp } from "@server/db"; import { and, eq } from "drizzle-orm"; import { createDate, isWithinExpirationDate, TimeSpan } from "oslo"; import { alphabet, generateRandomString, sha256 } from "oslo/crypto"; diff --git a/server/auth/sendEmailVerificationCode.ts b/server/auth/sendEmailVerificationCode.ts index 788c1358..71112922 100644 --- a/server/auth/sendEmailVerificationCode.ts +++ b/server/auth/sendEmailVerificationCode.ts @@ -1,7 +1,7 @@ import { TimeSpan, createDate } from "oslo"; import { generateRandomString, alphabet } from "oslo/crypto"; -import db from "@server/db"; -import { users, emailVerificationCodes } from "@server/db/schemas"; +import { db } from "@server/db"; +import { users, emailVerificationCodes } from "@server/db"; import { eq } from "drizzle-orm"; import { sendEmail } from "@server/emails"; import config from "@server/lib/config"; diff --git a/server/auth/sessions/app.ts b/server/auth/sessions/app.ts index be43d7a8..34d584f6 100644 --- a/server/auth/sessions/app.ts +++ b/server/auth/sessions/app.ts @@ -9,8 +9,8 @@ import { sessions, User, users -} from "@server/db/schemas"; -import db from "@server/db"; +} from "@server/db"; +import { db } from "@server/db"; import { eq, inArray } from "drizzle-orm"; import config from "@server/lib/config"; import type { RandomReader } from "@oslojs/crypto/random"; diff --git a/server/auth/sessions/newt.ts b/server/auth/sessions/newt.ts index 7d2ef8ab..5e55c491 100644 --- a/server/auth/sessions/newt.ts +++ b/server/auth/sessions/newt.ts @@ -2,8 +2,8 @@ import { encodeHexLowerCase, } from "@oslojs/encoding"; import { sha256 } from "@oslojs/crypto/sha2"; -import { Newt, newts, newtSessions, NewtSession } from "@server/db/schemas"; -import db from "@server/db"; +import { Newt, newts, newtSessions, NewtSession } from "@server/db"; +import { db } from "@server/db"; import { eq } from "drizzle-orm"; export const EXPIRES = 1000 * 60 * 60 * 24 * 30; diff --git a/server/auth/sessions/resource.ts b/server/auth/sessions/resource.ts index b95bece3..f29a8b75 100644 --- a/server/auth/sessions/resource.ts +++ b/server/auth/sessions/resource.ts @@ -1,7 +1,7 @@ import { encodeHexLowerCase } from "@oslojs/encoding"; import { sha256 } from "@oslojs/crypto/sha2"; -import { resourceSessions, ResourceSession } from "@server/db/schemas"; -import db from "@server/db"; +import { resourceSessions, ResourceSession } from "@server/db"; +import { db } from "@server/db"; import { eq, and } from "drizzle-orm"; import config from "@server/lib/config"; diff --git a/server/auth/totp.ts b/server/auth/totp.ts index 3ca183a0..efe2b64b 100644 --- a/server/auth/totp.ts +++ b/server/auth/totp.ts @@ -1,6 +1,6 @@ import { verify } from "@node-rs/argon2"; -import db from "@server/db"; -import { twoFactorBackupCodes } from "@server/db/schemas"; +import { db } from "@server/db"; +import { twoFactorBackupCodes } from "@server/db"; import { eq } from "drizzle-orm"; import { decodeHex } from "oslo/encoding"; import { TOTPController } from "oslo/otp"; diff --git a/server/auth/verifyResourceAccessToken.ts b/server/auth/verifyResourceAccessToken.ts index 8ddb5018..f1b587b7 100644 --- a/server/auth/verifyResourceAccessToken.ts +++ b/server/auth/verifyResourceAccessToken.ts @@ -1,10 +1,10 @@ -import db from "@server/db"; +import { db } from "@server/db"; import { Resource, ResourceAccessToken, resourceAccessToken, resources -} from "@server/db/schemas"; +} from "@server/db"; import { and, eq } from "drizzle-orm"; import { isWithinExpirationDate } from "oslo"; import { verifyPassword } from "./password"; diff --git a/server/db/README.md b/server/db/README.md new file mode 100644 index 00000000..36c3730b --- /dev/null +++ b/server/db/README.md @@ -0,0 +1,72 @@ +# Database + +Pangolin can use a Postgres or SQLite database to store its data. + +## Development + +### Postgres + +To use Postgres, edit `server/db/index.ts` to export all from `server/db/pg/index.ts`: + +```typescript +export * from "./pg"; +``` + +Make sure you have a valid config file with a connection string: + +```yaml +postgres: + connection_string: postgresql://postgres:postgres@localhost:5432 +``` + +You can run an ephemeral Postgres database for local development using Docker: + +```bash +docker run -d \ + --name postgres \ + --rm \ + -p 5432:5432 \ + -e POSTGRES_PASSWORD=postgres \ + -v $(mktemp -d):/var/lib/postgresql/data \ + postgres:17 +``` + +### Schema + +`server/db/pg/schema.ts` and `server/db/sqlite/schema.ts` contain the database schema definitions. These need to be kept in sync with with each other. + +Stick to common data types and avoid Postgres-specific features to ensure compatibility with SQLite. + +### SQLite + +To use SQLite, edit `server/db/index.ts` to export all from `server/db/sqlite/index.ts`: + +```typescript +export * from "./sqlite"; +``` + +No edits to the config are needed. If you keep the Postgres config, it will be ignored. + +## Generate and Push Migrations + +Ensure drizzle-kit is installed. + +### Postgres + +You must have a connection string in your config file, as shown above. + +```bash +npm run db:pg:generate +npm run db:pg:push +``` + +### SQLite + +```bash +npm run db:sqlite:generate +npm run db:sqlite:push +``` + +## Build Time + +There is a dockerfile for each database type. The dockerfile swaps out the `server/db/index.ts` file to use the correct database type. diff --git a/server/db/index.ts b/server/db/index.ts index 6cf40fec..826c950f 100644 --- a/server/db/index.ts +++ b/server/db/index.ts @@ -1,52 +1,2 @@ -import { drizzle } from "drizzle-orm/better-sqlite3"; -import Database from "better-sqlite3"; -import * as schema from "@server/db/schemas"; -import path from "path"; -import fs from "fs/promises"; -import { APP_PATH } from "@server/lib/consts"; -import { existsSync, mkdirSync } from "fs"; - -export const location = path.join(APP_PATH, "db", "db.sqlite"); -export const exists = await checkFileExists(location); - -bootstrapVolume(); - -const sqlite = new Database(location); -export const db = drizzle(sqlite, { schema }); - -export default db; - -async function checkFileExists(filePath: string): Promise { - try { - await fs.access(filePath); - return true; - } catch { - return false; - } -} - -function bootstrapVolume() { - const appPath = APP_PATH; - - const dbDir = path.join(appPath, "db"); - const logsDir = path.join(appPath, "logs"); - - // check if the db directory exists and create it if it doesn't - if (!existsSync(dbDir)) { - mkdirSync(dbDir, { recursive: true }); - } - - // check if the logs directory exists and create it if it doesn't - if (!existsSync(logsDir)) { - mkdirSync(logsDir, { recursive: true }); - } - - // THIS IS FOR TRAEFIK; NOT REALLY NEEDED, BUT JUST IN CASE - - const traefikDir = path.join(appPath, "traefik"); - - // check if the traefik directory exists and create it if it doesn't - if (!existsSync(traefikDir)) { - mkdirSync(traefikDir, { recursive: true }); - } -} +export * from "./sqlite"; +// export * from "./pg"; diff --git a/server/db/names.ts b/server/db/names.ts index 21a37c9a..56d62373 100644 --- a/server/db/names.ts +++ b/server/db/names.ts @@ -1,7 +1,7 @@ import { join } from "path"; import { readFileSync } from "fs"; import { db } from "@server/db"; -import { exitNodes, sites } from "./schemas/schema"; +import { exitNodes, sites } from "@server/db"; import { eq, and } from "drizzle-orm"; import { __DIRNAME } from "@server/lib/consts"; diff --git a/server/db/pg/driver.ts b/server/db/pg/driver.ts new file mode 100644 index 00000000..999b6827 --- /dev/null +++ b/server/db/pg/driver.ts @@ -0,0 +1,17 @@ +import { drizzle as DrizzlePostgres } from "drizzle-orm/node-postgres"; +import { readConfigFile } from "@server/lib/readConfigFile"; + +function createDb() { + const config = readConfigFile(); + + const connectionString = config.postgres?.connection_string; + + if (!connectionString) { + throw new Error("Postgres connection string is not defined in the configuration file."); + } + + return DrizzlePostgres(connectionString); +} + +export const db = createDb(); +export default db; diff --git a/server/db/schemas/index.ts b/server/db/pg/index.ts similarity index 50% rename from server/db/schemas/index.ts rename to server/db/pg/index.ts index 686fbd9e..9ad4678c 100644 --- a/server/db/schemas/index.ts +++ b/server/db/pg/index.ts @@ -1 +1,2 @@ +export * from "./driver"; export * from "./schema"; diff --git a/server/db/pg/migrate.ts b/server/db/pg/migrate.ts new file mode 100644 index 00000000..b9463dd4 --- /dev/null +++ b/server/db/pg/migrate.ts @@ -0,0 +1,20 @@ +import { migrate } from "drizzle-orm/node-postgres/migrator"; +import db from "./driver"; +import path from "path"; + +const migrationsFolder = path.join("server/migrations"); + +const runMigrations = async () => { + console.log("Running migrations..."); + try { + await migrate(db as any, { + migrationsFolder: migrationsFolder + }); + console.log("Migrations completed successfully."); + } catch (error) { + console.error("Error running migrations:", error); + process.exit(1); + } +}; + +runMigrations(); diff --git a/server/db/pg/schema.ts b/server/db/pg/schema.ts new file mode 100644 index 00000000..cb641974 --- /dev/null +++ b/server/db/pg/schema.ts @@ -0,0 +1,532 @@ +import { + pgTable, + serial, + varchar, + boolean, + integer, + bigint, + real +} from "drizzle-orm/pg-core"; +import { InferSelectModel } from "drizzle-orm"; + +export const domains = pgTable("domains", { + domainId: varchar("domainId").primaryKey(), + baseDomain: varchar("baseDomain").notNull(), + configManaged: boolean("configManaged").notNull().default(false) +}); + +export const orgs = pgTable("orgs", { + orgId: varchar("orgId").primaryKey(), + name: varchar("name").notNull() +}); + +export const orgDomains = pgTable("orgDomains", { + orgId: varchar("orgId") + .notNull() + .references(() => orgs.orgId, { onDelete: "cascade" }), + domainId: varchar("domainId") + .notNull() + .references(() => domains.domainId, { onDelete: "cascade" }) +}); + +export const sites = pgTable("sites", { + siteId: serial("siteId").primaryKey(), + orgId: varchar("orgId") + .references(() => orgs.orgId, { + onDelete: "cascade" + }) + .notNull(), + niceId: varchar("niceId").notNull(), + exitNodeId: integer("exitNode").references(() => exitNodes.exitNodeId, { + onDelete: "set null" + }), + name: varchar("name").notNull(), + pubKey: varchar("pubKey"), + subnet: varchar("subnet").notNull(), + megabytesIn: real("bytesIn"), + megabytesOut: real("bytesOut"), + lastBandwidthUpdate: varchar("lastBandwidthUpdate"), + type: varchar("type").notNull(), // "newt" or "wireguard" + online: boolean("online").notNull().default(false), + dockerSocketEnabled: boolean("dockerSocketEnabled").notNull().default(true) +}); + +export const resources = pgTable("resources", { + resourceId: serial("resourceId").primaryKey(), + siteId: integer("siteId") + .references(() => sites.siteId, { + onDelete: "cascade" + }) + .notNull(), + orgId: varchar("orgId") + .references(() => orgs.orgId, { + onDelete: "cascade" + }) + .notNull(), + name: varchar("name").notNull(), + subdomain: varchar("subdomain"), + fullDomain: varchar("fullDomain"), + domainId: varchar("domainId").references(() => domains.domainId, { + onDelete: "set null" + }), + ssl: boolean("ssl").notNull().default(false), + blockAccess: boolean("blockAccess").notNull().default(false), + sso: boolean("sso").notNull().default(true), + http: boolean("http").notNull().default(true), + protocol: varchar("protocol").notNull(), + proxyPort: integer("proxyPort"), + emailWhitelistEnabled: boolean("emailWhitelistEnabled") + .notNull() + .default(false), + isBaseDomain: boolean("isBaseDomain"), + applyRules: boolean("applyRules").notNull().default(false), + enabled: boolean("enabled").notNull().default(true), + stickySession: boolean("stickySession").notNull().default(false), + tlsServerName: varchar("tlsServerName"), + setHostHeader: varchar("setHostHeader") +}); + +export const targets = pgTable("targets", { + targetId: serial("targetId").primaryKey(), + resourceId: integer("resourceId") + .references(() => resources.resourceId, { + onDelete: "cascade" + }) + .notNull(), + ip: varchar("ip").notNull(), + method: varchar("method"), + port: integer("port").notNull(), + internalPort: integer("internalPort"), + enabled: boolean("enabled").notNull().default(true) +}); + +export const exitNodes = pgTable("exitNodes", { + exitNodeId: serial("exitNodeId").primaryKey(), + name: varchar("name").notNull(), + address: varchar("address").notNull(), + endpoint: varchar("endpoint").notNull(), + publicKey: varchar("publicKey").notNull(), + listenPort: integer("listenPort").notNull(), + reachableAt: varchar("reachableAt") +}); + +export const users = pgTable("user", { + userId: varchar("id").primaryKey(), + email: varchar("email"), + username: varchar("username").notNull(), + name: varchar("name"), + type: varchar("type").notNull(), // "internal", "oidc" + idpId: integer("idpId").references(() => idp.idpId, { + onDelete: "cascade" + }), + passwordHash: varchar("passwordHash"), + twoFactorEnabled: boolean("twoFactorEnabled").notNull().default(false), + twoFactorSecret: varchar("twoFactorSecret"), + emailVerified: boolean("emailVerified").notNull().default(false), + dateCreated: varchar("dateCreated").notNull(), + serverAdmin: boolean("serverAdmin").notNull().default(false) +}); + +export const newts = pgTable("newt", { + newtId: varchar("id").primaryKey(), + secretHash: varchar("secretHash").notNull(), + dateCreated: varchar("dateCreated").notNull(), + siteId: integer("siteId").references(() => sites.siteId, { + onDelete: "cascade" + }) +}); + +export const twoFactorBackupCodes = pgTable("twoFactorBackupCodes", { + codeId: serial("id").primaryKey(), + userId: varchar("userId") + .notNull() + .references(() => users.userId, { onDelete: "cascade" }), + codeHash: varchar("codeHash").notNull() +}); + +export const sessions = pgTable("session", { + sessionId: varchar("id").primaryKey(), + userId: varchar("userId") + .notNull() + .references(() => users.userId, { onDelete: "cascade" }), + expiresAt: bigint("expiresAt", { mode: "number" }).notNull() +}); + +export const newtSessions = pgTable("newtSession", { + sessionId: varchar("id").primaryKey(), + newtId: varchar("newtId") + .notNull() + .references(() => newts.newtId, { onDelete: "cascade" }), + expiresAt: bigint("expiresAt", { mode: "number" }).notNull() +}); + +export const userOrgs = pgTable("userOrgs", { + userId: varchar("userId") + .notNull() + .references(() => users.userId, { onDelete: "cascade" }), + orgId: varchar("orgId") + .references(() => orgs.orgId, { + onDelete: "cascade" + }) + .notNull(), + roleId: integer("roleId") + .notNull() + .references(() => roles.roleId), + isOwner: boolean("isOwner").notNull().default(false) +}); + +export const emailVerificationCodes = pgTable("emailVerificationCodes", { + codeId: serial("id").primaryKey(), + userId: varchar("userId") + .notNull() + .references(() => users.userId, { onDelete: "cascade" }), + email: varchar("email").notNull(), + code: varchar("code").notNull(), + expiresAt: bigint("expiresAt", { mode: "number" }).notNull() +}); + +export const passwordResetTokens = pgTable("passwordResetTokens", { + tokenId: serial("id").primaryKey(), + email: varchar("email").notNull(), + userId: varchar("userId") + .notNull() + .references(() => users.userId, { onDelete: "cascade" }), + tokenHash: varchar("tokenHash").notNull(), + expiresAt: bigint("expiresAt", { mode: "number" }).notNull() +}); + +export const actions = pgTable("actions", { + actionId: varchar("actionId").primaryKey(), + name: varchar("name"), + description: varchar("description") +}); + +export const roles = pgTable("roles", { + roleId: serial("roleId").primaryKey(), + orgId: varchar("orgId") + .references(() => orgs.orgId, { + onDelete: "cascade" + }) + .notNull(), + isAdmin: boolean("isAdmin"), + name: varchar("name").notNull(), + description: varchar("description") +}); + +export const roleActions = pgTable("roleActions", { + roleId: integer("roleId") + .notNull() + .references(() => roles.roleId, { onDelete: "cascade" }), + actionId: varchar("actionId") + .notNull() + .references(() => actions.actionId, { onDelete: "cascade" }), + orgId: varchar("orgId") + .notNull() + .references(() => orgs.orgId, { onDelete: "cascade" }) +}); + +export const userActions = pgTable("userActions", { + userId: varchar("userId") + .notNull() + .references(() => users.userId, { onDelete: "cascade" }), + actionId: varchar("actionId") + .notNull() + .references(() => actions.actionId, { onDelete: "cascade" }), + orgId: varchar("orgId") + .notNull() + .references(() => orgs.orgId, { onDelete: "cascade" }) +}); + +export const roleSites = pgTable("roleSites", { + roleId: integer("roleId") + .notNull() + .references(() => roles.roleId, { onDelete: "cascade" }), + siteId: integer("siteId") + .notNull() + .references(() => sites.siteId, { onDelete: "cascade" }) +}); + +export const userSites = pgTable("userSites", { + userId: varchar("userId") + .notNull() + .references(() => users.userId, { onDelete: "cascade" }), + siteId: integer("siteId") + .notNull() + .references(() => sites.siteId, { onDelete: "cascade" }) +}); + +export const roleResources = pgTable("roleResources", { + roleId: integer("roleId") + .notNull() + .references(() => roles.roleId, { onDelete: "cascade" }), + resourceId: integer("resourceId") + .notNull() + .references(() => resources.resourceId, { onDelete: "cascade" }) +}); + +export const userResources = pgTable("userResources", { + userId: varchar("userId") + .notNull() + .references(() => users.userId, { onDelete: "cascade" }), + resourceId: integer("resourceId") + .notNull() + .references(() => resources.resourceId, { onDelete: "cascade" }) +}); + +export const limitsTable = pgTable("limits", { + limitId: serial("limitId").primaryKey(), + orgId: varchar("orgId") + .references(() => orgs.orgId, { + onDelete: "cascade" + }) + .notNull(), + name: varchar("name").notNull(), + value: bigint("value", { mode: "number" }).notNull(), + description: varchar("description") +}); + +export const userInvites = pgTable("userInvites", { + inviteId: varchar("inviteId").primaryKey(), + orgId: varchar("orgId") + .notNull() + .references(() => orgs.orgId, { onDelete: "cascade" }), + email: varchar("email").notNull(), + expiresAt: bigint("expiresAt", { mode: "number" }).notNull(), + tokenHash: varchar("token").notNull(), + roleId: integer("roleId") + .notNull() + .references(() => roles.roleId, { onDelete: "cascade" }) +}); + +export const resourcePincode = pgTable("resourcePincode", { + pincodeId: serial("pincodeId").primaryKey(), + resourceId: integer("resourceId") + .notNull() + .references(() => resources.resourceId, { onDelete: "cascade" }), + pincodeHash: varchar("pincodeHash").notNull(), + digitLength: integer("digitLength").notNull() +}); + +export const resourcePassword = pgTable("resourcePassword", { + passwordId: serial("passwordId").primaryKey(), + resourceId: integer("resourceId") + .notNull() + .references(() => resources.resourceId, { onDelete: "cascade" }), + passwordHash: varchar("passwordHash").notNull() +}); + +export const resourceAccessToken = pgTable("resourceAccessToken", { + accessTokenId: varchar("accessTokenId").primaryKey(), + orgId: varchar("orgId") + .notNull() + .references(() => orgs.orgId, { onDelete: "cascade" }), + resourceId: integer("resourceId") + .notNull() + .references(() => resources.resourceId, { onDelete: "cascade" }), + tokenHash: varchar("tokenHash").notNull(), + sessionLength: bigint("sessionLength", { mode: "number" }).notNull(), + expiresAt: bigint("expiresAt", { mode: "number" }), + title: varchar("title"), + description: varchar("description"), + createdAt: bigint("createdAt", { mode: "number" }).notNull() +}); + +export const resourceSessions = pgTable("resourceSessions", { + sessionId: varchar("id").primaryKey(), + resourceId: integer("resourceId") + .notNull() + .references(() => resources.resourceId, { onDelete: "cascade" }), + expiresAt: bigint("expiresAt", { mode: "number" }).notNull(), + sessionLength: bigint("sessionLength", { mode: "number" }).notNull(), + doNotExtend: boolean("doNotExtend").notNull().default(false), + isRequestToken: boolean("isRequestToken"), + userSessionId: varchar("userSessionId").references( + () => sessions.sessionId, + { + onDelete: "cascade" + } + ), + passwordId: integer("passwordId").references( + () => resourcePassword.passwordId, + { + onDelete: "cascade" + } + ), + pincodeId: integer("pincodeId").references( + () => resourcePincode.pincodeId, + { + onDelete: "cascade" + } + ), + whitelistId: integer("whitelistId").references( + () => resourceWhitelist.whitelistId, + { + onDelete: "cascade" + } + ), + accessTokenId: varchar("accessTokenId").references( + () => resourceAccessToken.accessTokenId, + { + onDelete: "cascade" + } + ) +}); + +export const resourceWhitelist = pgTable("resourceWhitelist", { + whitelistId: serial("id").primaryKey(), + email: varchar("email").notNull(), + resourceId: integer("resourceId") + .notNull() + .references(() => resources.resourceId, { onDelete: "cascade" }) +}); + +export const resourceOtp = pgTable("resourceOtp", { + otpId: serial("otpId").primaryKey(), + resourceId: integer("resourceId") + .notNull() + .references(() => resources.resourceId, { onDelete: "cascade" }), + email: varchar("email").notNull(), + otpHash: varchar("otpHash").notNull(), + expiresAt: bigint("expiresAt", { mode: "number" }).notNull() +}); + +export const versionMigrations = pgTable("versionMigrations", { + version: varchar("version").primaryKey(), + executedAt: bigint("executedAt", { mode: "number" }).notNull() +}); + +export const resourceRules = pgTable("resourceRules", { + ruleId: serial("ruleId").primaryKey(), + resourceId: integer("resourceId") + .notNull() + .references(() => resources.resourceId, { onDelete: "cascade" }), + enabled: boolean("enabled").notNull().default(true), + priority: integer("priority").notNull(), + action: varchar("action").notNull(), // ACCEPT, DROP + match: varchar("match").notNull(), // CIDR, PATH, IP + value: varchar("value").notNull() +}); + +export const supporterKey = pgTable("supporterKey", { + keyId: serial("keyId").primaryKey(), + key: varchar("key").notNull(), + githubUsername: varchar("githubUsername").notNull(), + phrase: varchar("phrase"), + tier: varchar("tier"), + valid: boolean("valid").notNull().default(false) +}); + +export const idp = pgTable("idp", { + idpId: serial("idpId").primaryKey(), + name: varchar("name").notNull(), + type: varchar("type").notNull(), + defaultRoleMapping: varchar("defaultRoleMapping"), + defaultOrgMapping: varchar("defaultOrgMapping"), + autoProvision: boolean("autoProvision").notNull().default(false) +}); + +export const idpOidcConfig = pgTable("idpOidcConfig", { + idpOauthConfigId: serial("idpOauthConfigId").primaryKey(), + idpId: integer("idpId") + .notNull() + .references(() => idp.idpId, { onDelete: "cascade" }), + clientId: varchar("clientId").notNull(), + clientSecret: varchar("clientSecret").notNull(), + authUrl: varchar("authUrl").notNull(), + tokenUrl: varchar("tokenUrl").notNull(), + identifierPath: varchar("identifierPath").notNull(), + emailPath: varchar("emailPath"), + namePath: varchar("namePath"), + scopes: varchar("scopes").notNull() +}); + +export const licenseKey = pgTable("licenseKey", { + licenseKeyId: varchar("licenseKeyId").primaryKey().notNull(), + instanceId: varchar("instanceId").notNull(), + token: varchar("token").notNull() +}); + +export const hostMeta = pgTable("hostMeta", { + hostMetaId: varchar("hostMetaId").primaryKey().notNull(), + createdAt: bigint("createdAt", { mode: "number" }).notNull() +}); + +export const apiKeys = pgTable("apiKeys", { + apiKeyId: varchar("apiKeyId").primaryKey(), + name: varchar("name").notNull(), + apiKeyHash: varchar("apiKeyHash").notNull(), + lastChars: varchar("lastChars").notNull(), + createdAt: varchar("dateCreated").notNull(), + isRoot: boolean("isRoot").notNull().default(false) +}); + +export const apiKeyActions = pgTable("apiKeyActions", { + apiKeyId: varchar("apiKeyId") + .notNull() + .references(() => apiKeys.apiKeyId, { onDelete: "cascade" }), + actionId: varchar("actionId") + .notNull() + .references(() => actions.actionId, { onDelete: "cascade" }) +}); + +export const apiKeyOrg = pgTable("apiKeyOrg", { + apiKeyId: varchar("apiKeyId") + .notNull() + .references(() => apiKeys.apiKeyId, { onDelete: "cascade" }), + orgId: varchar("orgId") + .references(() => orgs.orgId, { + onDelete: "cascade" + }) + .notNull() +}); + +export const idpOrg = pgTable("idpOrg", { + idpId: integer("idpId") + .notNull() + .references(() => idp.idpId, { onDelete: "cascade" }), + orgId: varchar("orgId") + .notNull() + .references(() => orgs.orgId, { onDelete: "cascade" }), + roleMapping: varchar("roleMapping"), + orgMapping: varchar("orgMapping") +}); + +export type Org = InferSelectModel; +export type User = InferSelectModel; +export type Site = InferSelectModel; +export type Resource = InferSelectModel; +export type ExitNode = InferSelectModel; +export type Target = InferSelectModel; +export type Session = InferSelectModel; +export type Newt = InferSelectModel; +export type NewtSession = InferSelectModel; +export type EmailVerificationCode = InferSelectModel< + typeof emailVerificationCodes +>; +export type TwoFactorBackupCode = InferSelectModel; +export type PasswordResetToken = InferSelectModel; +export type Role = InferSelectModel; +export type Action = InferSelectModel; +export type RoleAction = InferSelectModel; +export type UserAction = InferSelectModel; +export type RoleSite = InferSelectModel; +export type UserSite = InferSelectModel; +export type RoleResource = InferSelectModel; +export type UserResource = InferSelectModel; +export type Limit = InferSelectModel; +export type UserInvite = InferSelectModel; +export type UserOrg = InferSelectModel; +export type ResourceSession = InferSelectModel; +export type ResourcePincode = InferSelectModel; +export type ResourcePassword = InferSelectModel; +export type ResourceOtp = InferSelectModel; +export type ResourceAccessToken = InferSelectModel; +export type ResourceWhitelist = InferSelectModel; +export type VersionMigration = InferSelectModel; +export type ResourceRule = InferSelectModel; +export type Domain = InferSelectModel; +export type SupporterKey = InferSelectModel; +export type Idp = InferSelectModel; +export type ApiKey = InferSelectModel; +export type ApiKeyAction = InferSelectModel; +export type ApiKeyOrg = InferSelectModel; diff --git a/server/db/schemas/hostMeta.ts b/server/db/schemas/hostMeta.ts deleted file mode 100644 index e69de29b..00000000 diff --git a/server/db/sqlite/driver.ts b/server/db/sqlite/driver.ts new file mode 100644 index 00000000..a83ca7dd --- /dev/null +++ b/server/db/sqlite/driver.ts @@ -0,0 +1,58 @@ +import { drizzle as DrizzleSqlite } from "drizzle-orm/better-sqlite3"; +import Database from "better-sqlite3"; +import * as schema from "./schema"; +import path from "path"; +import fs from "fs/promises"; +import { APP_PATH } from "@server/lib/consts"; +import { existsSync, mkdirSync } from "fs"; +import { readConfigFile } from "@server/lib/readConfigFile"; + +export const location = path.join(APP_PATH, "db", "db.sqlite"); +export const exists = await checkFileExists(location); + +bootstrapVolume(); + +function createDb() { + const config = readConfigFile(); + + const sqlite = new Database(location); + return DrizzleSqlite(sqlite, { schema }); +} + +export const db = createDb(); +export default db; + +async function checkFileExists(filePath: string): Promise { + try { + await fs.access(filePath); + return true; + } catch { + return false; + } +} + +function bootstrapVolume() { + const appPath = APP_PATH; + + const dbDir = path.join(appPath, "db"); + const logsDir = path.join(appPath, "logs"); + + // check if the db directory exists and create it if it doesn't + if (!existsSync(dbDir)) { + mkdirSync(dbDir, { recursive: true }); + } + + // check if the logs directory exists and create it if it doesn't + if (!existsSync(logsDir)) { + mkdirSync(logsDir, { recursive: true }); + } + + // THIS IS FOR TRAEFIK; NOT REALLY NEEDED, BUT JUST IN CASE + + const traefikDir = path.join(appPath, "traefik"); + + // check if the traefik directory exists and create it if it doesn't + if (!existsSync(traefikDir)) { + mkdirSync(traefikDir, { recursive: true }); + } +} diff --git a/server/db/sqlite/index.ts b/server/db/sqlite/index.ts new file mode 100644 index 00000000..9ad4678c --- /dev/null +++ b/server/db/sqlite/index.ts @@ -0,0 +1,2 @@ +export * from "./driver"; +export * from "./schema"; diff --git a/server/db/migrate.ts b/server/db/sqlite/migrate.ts similarity index 89% rename from server/db/migrate.ts rename to server/db/sqlite/migrate.ts index d39f4ae9..20b9043f 100644 --- a/server/db/migrate.ts +++ b/server/db/sqlite/migrate.ts @@ -1,5 +1,5 @@ import { migrate } from "drizzle-orm/better-sqlite3/migrator"; -import db from "@server/db"; +import db from "./driver"; import path from "path"; const migrationsFolder = path.join("server/migrations"); @@ -7,7 +7,7 @@ const migrationsFolder = path.join("server/migrations"); const runMigrations = async () => { console.log("Running migrations..."); try { - migrate(db, { + migrate(db as any, { migrationsFolder: migrationsFolder, }); console.log("Migrations completed successfully."); diff --git a/server/db/schemas/schema.ts b/server/db/sqlite/schema.ts similarity index 99% rename from server/db/schemas/schema.ts rename to server/db/sqlite/schema.ts index 9d44be35..a771c4a2 100644 --- a/server/db/schemas/schema.ts +++ b/server/db/sqlite/schema.ts @@ -49,7 +49,10 @@ export const sites = sqliteTable("sites", { endpoint: text("endpoint"), // this is how to reach gerbil externally - gets put into the wireguard config publicKey: text("pubicKey"), lastHolePunch: integer("lastHolePunch"), - listenPort: integer("listenPort") + listenPort: integer("listenPort"), + dockerSocketEnabled: integer("dockerSocketEnabled", { mode: "boolean" }) + .notNull() + .default(true) }); export const resources = sqliteTable("resources", { diff --git a/server/index.ts b/server/index.ts index 33502609..4daeb711 100644 --- a/server/index.ts +++ b/server/index.ts @@ -4,7 +4,7 @@ import { runSetupFunctions } from "./setup"; import { createApiServer } from "./apiServer"; import { createNextServer } from "./nextServer"; import { createInternalServer } from "./internalServer"; -import { ApiKey, ApiKeyOrg, Session, User, UserOrg } from "./db/schemas"; +import { ApiKey, ApiKeyOrg, Session, User, UserOrg } from "@server/db"; import { createIntegrationApiServer } from "./integrationApiServer"; import config from "@server/lib/config"; diff --git a/server/lib/canUserAccessResource.ts b/server/lib/canUserAccessResource.ts index 0d618255..161a0bee 100644 --- a/server/lib/canUserAccessResource.ts +++ b/server/lib/canUserAccessResource.ts @@ -1,6 +1,6 @@ -import db from "@server/db"; +import { db } from "@server/db"; import { and, eq } from "drizzle-orm"; -import { roleResources, userResources } from "@server/db/schemas"; +import { roleResources, userResources } from "@server/db"; export async function canUserAccessResource({ userId, diff --git a/server/lib/config.ts b/server/lib/config.ts index 5214c29d..d83bb5b2 100644 --- a/server/lib/config.ts +++ b/server/lib/config.ts @@ -1,204 +1,10 @@ -import fs from "fs"; -import yaml from "js-yaml"; import { z } from "zod"; -import { fromError } from "zod-validation-error"; -import { - __DIRNAME, - APP_VERSION, - configFilePath1, - configFilePath2 -} from "@server/lib/consts"; -import { passwordSchema } from "@server/auth/passwordSchema"; -import stoi from "./stoi"; -import db from "@server/db"; -import { SupporterKey, supporterKey } from "@server/db/schemas"; +import { __DIRNAME, APP_VERSION } from "@server/lib/consts"; +import { db } from "@server/db"; +import { SupporterKey, supporterKey } from "@server/db"; import { eq } from "drizzle-orm"; import { license } from "@server/license/license"; - -const portSchema = z.number().positive().gt(0).lte(65535); - -const getEnvOrYaml = (envVar: string) => (valFromYaml: any) => { - return process.env[envVar] ?? valFromYaml; -}; - -const configSchema = z.object({ - app: z.object({ - dashboard_url: z - .string() - .url() - .optional() - .pipe(z.string().url()) - .transform((url) => url.toLowerCase()), - log_level: z - .enum(["debug", "info", "warn", "error"]) - .optional() - .default("info"), - save_logs: z.boolean().optional().default(false), - log_failed_attempts: z.boolean().optional().default(false) - }), - domains: z - .record( - z.string(), - z.object({ - base_domain: z - .string() - .nonempty("base_domain must not be empty") - .transform((url) => url.toLowerCase()), - cert_resolver: z.string().optional().default("letsencrypt"), - prefer_wildcard_cert: z.boolean().optional().default(false) - }) - ) - .refine( - (domains) => { - const keys = Object.keys(domains); - - if (keys.length === 0) { - return false; - } - - return true; - }, - { - message: "At least one domain must be defined" - } - ), - server: z.object({ - integration_port: portSchema - .optional() - .default(3003) - .transform(stoi) - .pipe(portSchema.optional()), - external_port: portSchema - .optional() - .default(3000) - .transform(stoi) - .pipe(portSchema), - internal_port: portSchema - .optional() - .default(3001) - .transform(stoi) - .pipe(portSchema), - next_port: portSchema - .optional() - .default(3002) - .transform(stoi) - .pipe(portSchema), - internal_hostname: z - .string() - .optional() - .default("pangolin") - .transform((url) => url.toLowerCase()), - session_cookie_name: z.string().optional().default("p_session_token"), - resource_access_token_param: z.string().optional().default("p_token"), - resource_access_token_headers: z - .object({ - id: z.string().optional().default("P-Access-Token-Id"), - token: z.string().optional().default("P-Access-Token") - }) - .optional() - .default({}), - resource_session_request_param: z - .string() - .optional() - .default("resource_session_request_param"), - dashboard_session_length_hours: z - .number() - .positive() - .gt(0) - .optional() - .default(720), - resource_session_length_hours: z - .number() - .positive() - .gt(0) - .optional() - .default(720), - cors: z - .object({ - origins: z.array(z.string()).optional(), - methods: z.array(z.string()).optional(), - allowed_headers: z.array(z.string()).optional(), - credentials: z.boolean().optional() - }) - .optional(), - trust_proxy: z.boolean().optional().default(true), - secret: z - .string() - .optional() - .transform(getEnvOrYaml("SERVER_SECRET")) - .pipe(z.string().min(8)) - }), - traefik: z.object({ - http_entrypoint: z.string(), - https_entrypoint: z.string().optional(), - additional_middlewares: z.array(z.string()).optional() - }), - gerbil: z.object({ - start_port: portSchema.optional().transform(stoi).pipe(portSchema), - base_endpoint: z - .string() - .optional() - .pipe(z.string()) - .transform((url) => url.toLowerCase()), - use_subdomain: z.boolean(), - subnet_group: z.string(), - block_size: z.number().positive().gt(0), - site_block_size: z.number().positive().gt(0) - }), - orgs: z.object({ - block_size: z.number().positive().gt(0), - subnet_group: z.string(), - }), - rate_limits: z.object({ - global: z.object({ - window_minutes: z.number().positive().gt(0), - max_requests: z.number().positive().gt(0) - }), - auth: z - .object({ - window_minutes: z.number().positive().gt(0), - max_requests: z.number().positive().gt(0) - }) - .optional() - }), - email: z - .object({ - smtp_host: z.string().optional(), - smtp_port: portSchema.optional(), - smtp_user: z.string().optional(), - smtp_pass: z.string().optional(), - smtp_secure: z.boolean().optional(), - smtp_tls_reject_unauthorized: z.boolean().optional(), - no_reply: z.string().email().optional() - }) - .optional(), - users: z.object({ - server_admin: z.object({ - email: z - .string() - .email() - .optional() - .transform(getEnvOrYaml("USERS_SERVERADMIN_EMAIL")) - .pipe(z.string().email()) - .transform((v) => v.toLowerCase()), - password: passwordSchema - .optional() - .transform(getEnvOrYaml("USERS_SERVERADMIN_PASSWORD")) - .pipe(passwordSchema) - }) - }), - flags: z - .object({ - require_email_verification: z.boolean().optional(), - disable_signup_without_invite: z.boolean().optional(), - disable_user_create_org: z.boolean().optional(), - allow_raw_resources: z.boolean().optional(), - allow_base_domain_resources: z.boolean().optional(), - allow_local_sites: z.boolean().optional(), - enable_integration_api: z.boolean().optional() - }) - .optional() -}); +import { configSchema, readConfigFile } from "./readConfigFile"; export class Config { private rawConfig!: z.infer; @@ -210,96 +16,57 @@ export class Config { isDev: boolean = process.env.ENVIRONMENT !== "prod"; constructor() { - this.loadConfig(); + this.load(); } - public loadConfig() { - const loadConfig = (configPath: string) => { - try { - const yamlContent = fs.readFileSync(configPath, "utf8"); - const config = yaml.load(yamlContent); - return config; - } catch (error) { - if (error instanceof Error) { - throw new Error( - `Error loading configuration file: ${error.message}` - ); - } - throw error; - } - }; - - let environment: any; - if (fs.existsSync(configFilePath1)) { - environment = loadConfig(configFilePath1); - } else if (fs.existsSync(configFilePath2)) { - environment = loadConfig(configFilePath2); - } - - if (process.env.APP_BASE_DOMAIN) { - console.log( - "You're using deprecated environment variables. Transition to the configuration file. https://docs.fossorial.io/" - ); - } - - if (!environment) { - throw new Error( - "No configuration file found. Please create one. https://docs.fossorial.io/" - ); - } - - const parsedConfig = configSchema.safeParse(environment); - - if (!parsedConfig.success) { - const errors = fromError(parsedConfig.error); - throw new Error(`Invalid configuration file: ${errors}`); - } + public load() { + const parsedConfig = readConfigFile(); process.env.APP_VERSION = APP_VERSION; - process.env.NEXT_PORT = parsedConfig.data.server.next_port.toString(); + process.env.NEXT_PORT = parsedConfig.server.next_port.toString(); process.env.SERVER_EXTERNAL_PORT = - parsedConfig.data.server.external_port.toString(); + parsedConfig.server.external_port.toString(); process.env.SERVER_INTERNAL_PORT = - parsedConfig.data.server.internal_port.toString(); - process.env.FLAGS_EMAIL_VERIFICATION_REQUIRED = parsedConfig.data.flags + parsedConfig.server.internal_port.toString(); + process.env.FLAGS_EMAIL_VERIFICATION_REQUIRED = parsedConfig.flags ?.require_email_verification ? "true" : "false"; - process.env.FLAGS_ALLOW_RAW_RESOURCES = parsedConfig.data.flags + process.env.FLAGS_ALLOW_RAW_RESOURCES = parsedConfig.flags ?.allow_raw_resources ? "true" : "false"; process.env.SESSION_COOKIE_NAME = - parsedConfig.data.server.session_cookie_name; - process.env.EMAIL_ENABLED = parsedConfig.data.email ? "true" : "false"; - process.env.DISABLE_SIGNUP_WITHOUT_INVITE = parsedConfig.data.flags + parsedConfig.server.session_cookie_name; + process.env.EMAIL_ENABLED = parsedConfig.email ? "true" : "false"; + process.env.DISABLE_SIGNUP_WITHOUT_INVITE = parsedConfig.flags ?.disable_signup_without_invite ? "true" : "false"; - process.env.DISABLE_USER_CREATE_ORG = parsedConfig.data.flags + process.env.DISABLE_USER_CREATE_ORG = parsedConfig.flags ?.disable_user_create_org ? "true" : "false"; process.env.RESOURCE_ACCESS_TOKEN_PARAM = - parsedConfig.data.server.resource_access_token_param; + parsedConfig.server.resource_access_token_param; process.env.RESOURCE_ACCESS_TOKEN_HEADERS_ID = - parsedConfig.data.server.resource_access_token_headers.id; + parsedConfig.server.resource_access_token_headers.id; process.env.RESOURCE_ACCESS_TOKEN_HEADERS_TOKEN = - parsedConfig.data.server.resource_access_token_headers.token; + parsedConfig.server.resource_access_token_headers.token; process.env.RESOURCE_SESSION_REQUEST_PARAM = - parsedConfig.data.server.resource_session_request_param; - process.env.FLAGS_ALLOW_BASE_DOMAIN_RESOURCES = parsedConfig.data.flags + parsedConfig.server.resource_session_request_param; + process.env.FLAGS_ALLOW_BASE_DOMAIN_RESOURCES = parsedConfig.flags ?.allow_base_domain_resources ? "true" : "false"; - process.env.DASHBOARD_URL = parsedConfig.data.app.dashboard_url; + process.env.DASHBOARD_URL = parsedConfig.app.dashboard_url; - license.setServerSecret(parsedConfig.data.server.secret); + license.setServerSecret(parsedConfig.server.secret); this.checkKeyStatus(); - this.rawConfig = parsedConfig.data; + this.rawConfig = parsedConfig; } private async checkKeyStatus() { diff --git a/server/lib/consts.ts b/server/lib/consts.ts index ed61e8ca..1dc46d2b 100644 --- a/server/lib/consts.ts +++ b/server/lib/consts.ts @@ -2,7 +2,7 @@ import path from "path"; import { fileURLToPath } from "url"; // This is a placeholder value replaced by the build process -export const APP_VERSION = "1.4.0"; +export const APP_VERSION = "1.5.1"; export const __FILENAME = fileURLToPath(import.meta.url); export const __DIRNAME = path.dirname(__FILENAME); diff --git a/server/lib/readConfigFile.ts b/server/lib/readConfigFile.ts new file mode 100644 index 00000000..58c383d2 --- /dev/null +++ b/server/lib/readConfigFile.ts @@ -0,0 +1,268 @@ +import fs from "fs"; +import yaml from "js-yaml"; +import { configFilePath1, configFilePath2 } from "./consts"; +import { z } from "zod"; +import stoi from "./stoi"; +import { passwordSchema } from "@server/auth/passwordSchema"; +import { fromError } from "zod-validation-error"; + +const portSchema = z.number().positive().gt(0).lte(65535); + +const getEnvOrYaml = (envVar: string) => (valFromYaml: any) => { + return process.env[envVar] ?? valFromYaml; +}; + +export const configSchema = z.object({ + app: z.object({ + dashboard_url: z + .string() + .url() + .optional() + .pipe(z.string().url()) + .transform((url) => url.toLowerCase()), + log_level: z + .enum(["debug", "info", "warn", "error"]) + .optional() + .default("info"), + save_logs: z.boolean().optional().default(false), + log_failed_attempts: z.boolean().optional().default(false) + }), + domains: z + .record( + z.string(), + z.object({ + base_domain: z + .string() + .nonempty("base_domain must not be empty") + .transform((url) => url.toLowerCase()), + cert_resolver: z.string().optional().default("letsencrypt"), + prefer_wildcard_cert: z.boolean().optional().default(false) + }) + ) + .refine( + (domains) => { + const keys = Object.keys(domains); + + if (keys.length === 0) { + return false; + } + + return true; + }, + { + message: "At least one domain must be defined" + } + ), + server: z.object({ + integration_port: portSchema + .optional() + .default(3003) + .transform(stoi) + .pipe(portSchema.optional()), + external_port: portSchema + .optional() + .default(3000) + .transform(stoi) + .pipe(portSchema), + internal_port: portSchema + .optional() + .default(3001) + .transform(stoi) + .pipe(portSchema), + next_port: portSchema + .optional() + .default(3002) + .transform(stoi) + .pipe(portSchema), + internal_hostname: z + .string() + .optional() + .default("pangolin") + .transform((url) => url.toLowerCase()), + session_cookie_name: z.string().optional().default("p_session_token"), + resource_access_token_param: z.string().optional().default("p_token"), + resource_access_token_headers: z + .object({ + id: z.string().optional().default("P-Access-Token-Id"), + token: z.string().optional().default("P-Access-Token") + }) + .optional() + .default({}), + resource_session_request_param: z + .string() + .optional() + .default("resource_session_request_param"), + dashboard_session_length_hours: z + .number() + .positive() + .gt(0) + .optional() + .default(720), + resource_session_length_hours: z + .number() + .positive() + .gt(0) + .optional() + .default(720), + cors: z + .object({ + origins: z.array(z.string()).optional(), + methods: z.array(z.string()).optional(), + allowed_headers: z.array(z.string()).optional(), + credentials: z.boolean().optional() + }) + .optional(), + trust_proxy: z.boolean().optional().default(true), + secret: z + .string() + .optional() + .transform(getEnvOrYaml("SERVER_SECRET")) + .pipe(z.string().min(8)) + }), + postgres: z + .object({ + connection_string: z.string().optional() + }) + .default({}), + traefik: z + .object({ + http_entrypoint: z.string().optional().default("web"), + https_entrypoint: z.string().optional().default("websecure"), + additional_middlewares: z.array(z.string()).optional() + }) + .optional() + .default({}), + gerbil: z + .object({ + start_port: portSchema + .optional() + .default(51820) + .transform(stoi) + .pipe(portSchema), + base_endpoint: z + .string() + .optional() + .pipe(z.string()) + .transform((url) => url.toLowerCase()), + use_subdomain: z.boolean().optional().default(false), + subnet_group: z.string().optional().default("100.89.137.0/20"), + block_size: z.number().positive().gt(0).optional().default(24), + site_block_size: z.number().positive().gt(0).optional().default(30) + }) + .optional() + .default({}), + orgs: z.object({ + block_size: z.number().positive().gt(0), + subnet_group: z.string(), + }), + rate_limits: z + .object({ + global: z + .object({ + window_minutes: z + .number() + .positive() + .gt(0) + .optional() + .default(1), + max_requests: z + .number() + .positive() + .gt(0) + .optional() + .default(500) + }) + .optional() + .default({}), + auth: z + .object({ + window_minutes: z.number().positive().gt(0), + max_requests: z.number().positive().gt(0) + }) + .optional() + }) + .optional() + .default({}), + email: z + .object({ + smtp_host: z.string().optional(), + smtp_port: portSchema.optional(), + smtp_user: z.string().optional(), + smtp_pass: z.string().optional(), + smtp_secure: z.boolean().optional(), + smtp_tls_reject_unauthorized: z.boolean().optional(), + no_reply: z.string().email().optional() + }) + .optional(), + users: z.object({ + server_admin: z.object({ + email: z + .string() + .email() + .optional() + .transform(getEnvOrYaml("USERS_SERVERADMIN_EMAIL")) + .pipe(z.string().email()) + .transform((v) => v.toLowerCase()), + password: passwordSchema + .optional() + .transform(getEnvOrYaml("USERS_SERVERADMIN_PASSWORD")) + .pipe(passwordSchema) + }) + }), + flags: z + .object({ + require_email_verification: z.boolean().optional(), + disable_signup_without_invite: z.boolean().optional(), + disable_user_create_org: z.boolean().optional(), + allow_raw_resources: z.boolean().optional(), + allow_base_domain_resources: z.boolean().optional(), + allow_local_sites: z.boolean().optional(), + enable_integration_api: z.boolean().optional() + }) + .optional() +}); + +export function readConfigFile() { + const loadConfig = (configPath: string) => { + try { + const yamlContent = fs.readFileSync(configPath, "utf8"); + const config = yaml.load(yamlContent); + return config; + } catch (error) { + if (error instanceof Error) { + throw new Error( + `Error loading configuration file: ${error.message}` + ); + } + throw error; + } + }; + + let environment: any; + if (fs.existsSync(configFilePath1)) { + environment = loadConfig(configFilePath1); + } else if (fs.existsSync(configFilePath2)) { + environment = loadConfig(configFilePath2); + } + + if (process.env.APP_BASE_DOMAIN) { + console.log( + "You're using deprecated environment variables. Transition to the configuration file. https://docs.fossorial.io/" + ); + } + + if (!environment) { + throw new Error( + "No configuration file found. Please create one. https://docs.fossorial.io/" + ); + } + + const parsedConfig = configSchema.safeParse(environment); + + if (!parsedConfig.success) { + const errors = fromError(parsedConfig.error); + throw new Error(`Invalid configuration file: ${errors}`); + } + + return parsedConfig.data; +} diff --git a/server/lib/stoi.ts b/server/lib/stoi.ts index 8fa42b54..ebc789e6 100644 --- a/server/lib/stoi.ts +++ b/server/lib/stoi.ts @@ -1,6 +1,6 @@ export default function stoi(val: any) { if (typeof val === "string") { - return parseInt(val) + return parseInt(val); } else { return val; diff --git a/server/license/license.ts b/server/license/license.ts index bd596e4b..0adc54fd 100644 --- a/server/license/license.ts +++ b/server/license/license.ts @@ -1,5 +1,5 @@ -import db from "@server/db"; -import { hostMeta, licenseKey, sites } from "@server/db/schemas"; +import { db } from "@server/db"; +import { hostMeta, licenseKey, sites } from "@server/db"; import logger from "@server/logger"; import NodeCache from "node-cache"; import { validateJWT } from "./licenseJwt"; diff --git a/server/middlewares/getUserOrgs.ts b/server/middlewares/getUserOrgs.ts index 7d5c08f7..4d042307 100644 --- a/server/middlewares/getUserOrgs.ts +++ b/server/middlewares/getUserOrgs.ts @@ -1,6 +1,6 @@ import { Request, Response, NextFunction } from "express"; import { db } from "@server/db"; -import { userOrgs, orgs } from "@server/db/schemas"; +import { userOrgs, orgs } from "@server/db"; import { eq } from "drizzle-orm"; import createHttpError from "http-errors"; import HttpCode from "@server/types/HttpCode"; diff --git a/server/middlewares/integration/verifyAccessTokenAccess.ts b/server/middlewares/integration/verifyAccessTokenAccess.ts index e9069ba4..f5ae8746 100644 --- a/server/middlewares/integration/verifyAccessTokenAccess.ts +++ b/server/middlewares/integration/verifyAccessTokenAccess.ts @@ -1,6 +1,6 @@ import { Request, Response, NextFunction } from "express"; import { db } from "@server/db"; -import { resourceAccessToken, resources, apiKeyOrg } from "@server/db/schemas"; +import { resourceAccessToken, resources, apiKeyOrg } from "@server/db"; import { and, eq } from "drizzle-orm"; import createHttpError from "http-errors"; import HttpCode from "@server/types/HttpCode"; diff --git a/server/middlewares/integration/verifyApiKey.ts b/server/middlewares/integration/verifyApiKey.ts index 0b0602ea..719b609f 100644 --- a/server/middlewares/integration/verifyApiKey.ts +++ b/server/middlewares/integration/verifyApiKey.ts @@ -1,6 +1,6 @@ import { verifyPassword } from "@server/auth/password"; -import db from "@server/db"; -import { apiKeys } from "@server/db/schemas"; +import { db } from "@server/db"; +import { apiKeys } from "@server/db"; import logger from "@server/logger"; import HttpCode from "@server/types/HttpCode"; import { eq } from "drizzle-orm"; diff --git a/server/middlewares/integration/verifyApiKeyApiKeyAccess.ts b/server/middlewares/integration/verifyApiKeyApiKeyAccess.ts index 435f01d0..1441589d 100644 --- a/server/middlewares/integration/verifyApiKeyApiKeyAccess.ts +++ b/server/middlewares/integration/verifyApiKeyApiKeyAccess.ts @@ -1,6 +1,6 @@ import { Request, Response, NextFunction } from "express"; import { db } from "@server/db"; -import { apiKeys, apiKeyOrg } from "@server/db/schemas"; +import { apiKeys, apiKeyOrg } from "@server/db"; import { and, eq, or } from "drizzle-orm"; import createHttpError from "http-errors"; import HttpCode from "@server/types/HttpCode"; diff --git a/server/middlewares/integration/verifyApiKeyHasAction.ts b/server/middlewares/integration/verifyApiKeyHasAction.ts index 35f4398e..428aeed2 100644 --- a/server/middlewares/integration/verifyApiKeyHasAction.ts +++ b/server/middlewares/integration/verifyApiKeyHasAction.ts @@ -3,8 +3,8 @@ import createHttpError from "http-errors"; import HttpCode from "@server/types/HttpCode"; import logger from "@server/logger"; import { ActionsEnum } from "@server/auth/actions"; -import db from "@server/db"; -import { apiKeyActions } from "@server/db/schemas"; +import { db } from "@server/db"; +import { apiKeyActions } from "@server/db"; import { and, eq } from "drizzle-orm"; export function verifyApiKeyHasAction(action: ActionsEnum) { diff --git a/server/middlewares/integration/verifyApiKeyOrgAccess.ts b/server/middlewares/integration/verifyApiKeyOrgAccess.ts index 902ccf5e..84ba7fe9 100644 --- a/server/middlewares/integration/verifyApiKeyOrgAccess.ts +++ b/server/middlewares/integration/verifyApiKeyOrgAccess.ts @@ -1,6 +1,6 @@ import { Request, Response, NextFunction } from "express"; import { db } from "@server/db"; -import { apiKeyOrg } from "@server/db/schemas"; +import { apiKeyOrg } from "@server/db"; import { and, eq } from "drizzle-orm"; import createHttpError from "http-errors"; import HttpCode from "@server/types/HttpCode"; diff --git a/server/middlewares/integration/verifyApiKeyResourceAccess.ts b/server/middlewares/integration/verifyApiKeyResourceAccess.ts index f4e3ed0f..2473c814 100644 --- a/server/middlewares/integration/verifyApiKeyResourceAccess.ts +++ b/server/middlewares/integration/verifyApiKeyResourceAccess.ts @@ -1,6 +1,6 @@ import { Request, Response, NextFunction } from "express"; import { db } from "@server/db"; -import { resources, apiKeyOrg } from "@server/db/schemas"; +import { resources, apiKeyOrg } from "@server/db"; import { eq, and } from "drizzle-orm"; import createHttpError from "http-errors"; import HttpCode from "@server/types/HttpCode"; diff --git a/server/middlewares/integration/verifyApiKeyRoleAccess.ts b/server/middlewares/integration/verifyApiKeyRoleAccess.ts index 4d769413..0df10913 100644 --- a/server/middlewares/integration/verifyApiKeyRoleAccess.ts +++ b/server/middlewares/integration/verifyApiKeyRoleAccess.ts @@ -1,6 +1,6 @@ import { Request, Response, NextFunction } from "express"; import { db } from "@server/db"; -import { roles, apiKeyOrg } from "@server/db/schemas"; +import { roles, apiKeyOrg } from "@server/db"; import { and, eq, inArray } from "drizzle-orm"; import createHttpError from "http-errors"; import HttpCode from "@server/types/HttpCode"; diff --git a/server/middlewares/integration/verifyApiKeySetResourceUsers.ts b/server/middlewares/integration/verifyApiKeySetResourceUsers.ts index 1c3b5b12..cbb2b598 100644 --- a/server/middlewares/integration/verifyApiKeySetResourceUsers.ts +++ b/server/middlewares/integration/verifyApiKeySetResourceUsers.ts @@ -1,6 +1,6 @@ import { Request, Response, NextFunction } from "express"; import { db } from "@server/db"; -import { userOrgs } from "@server/db/schemas"; +import { userOrgs } from "@server/db"; import { and, eq, inArray } from "drizzle-orm"; import createHttpError from "http-errors"; import HttpCode from "@server/types/HttpCode"; diff --git a/server/middlewares/integration/verifyApiKeySiteAccess.ts b/server/middlewares/integration/verifyApiKeySiteAccess.ts index 2c83eadd..35ec3b6a 100644 --- a/server/middlewares/integration/verifyApiKeySiteAccess.ts +++ b/server/middlewares/integration/verifyApiKeySiteAccess.ts @@ -3,7 +3,7 @@ import { db } from "@server/db"; import { sites, apiKeyOrg -} from "@server/db/schemas"; +} from "@server/db"; import { and, eq, or } from "drizzle-orm"; import createHttpError from "http-errors"; import HttpCode from "@server/types/HttpCode"; diff --git a/server/middlewares/integration/verifyApiKeyTargetAccess.ts b/server/middlewares/integration/verifyApiKeyTargetAccess.ts index 7da1f29f..f810e4a2 100644 --- a/server/middlewares/integration/verifyApiKeyTargetAccess.ts +++ b/server/middlewares/integration/verifyApiKeyTargetAccess.ts @@ -1,6 +1,6 @@ import { Request, Response, NextFunction } from "express"; import { db } from "@server/db"; -import { resources, targets, apiKeyOrg } from "@server/db/schemas"; +import { resources, targets, apiKeyOrg } from "@server/db"; import { and, eq } from "drizzle-orm"; import createHttpError from "http-errors"; import HttpCode from "@server/types/HttpCode"; diff --git a/server/middlewares/integration/verifyApiKeyUserAccess.ts b/server/middlewares/integration/verifyApiKeyUserAccess.ts index 69f27e9a..070ae5ac 100644 --- a/server/middlewares/integration/verifyApiKeyUserAccess.ts +++ b/server/middlewares/integration/verifyApiKeyUserAccess.ts @@ -1,6 +1,6 @@ import { Request, Response, NextFunction } from "express"; import { db } from "@server/db"; -import { userOrgs } from "@server/db/schemas"; +import { userOrgs } from "@server/db"; import { and, eq } from "drizzle-orm"; import createHttpError from "http-errors"; import HttpCode from "@server/types/HttpCode"; diff --git a/server/middlewares/verifyAccessTokenAccess.ts b/server/middlewares/verifyAccessTokenAccess.ts index a437a8a2..92873524 100644 --- a/server/middlewares/verifyAccessTokenAccess.ts +++ b/server/middlewares/verifyAccessTokenAccess.ts @@ -1,6 +1,6 @@ import { Request, Response, NextFunction } from "express"; import { db } from "@server/db"; -import { resourceAccessToken, resources, userOrgs } from "@server/db/schemas"; +import { resourceAccessToken, resources, userOrgs } from "@server/db"; import { and, eq } from "drizzle-orm"; import createHttpError from "http-errors"; import HttpCode from "@server/types/HttpCode"; diff --git a/server/middlewares/verifyAdmin.ts b/server/middlewares/verifyAdmin.ts index b53f238f..60f7334c 100644 --- a/server/middlewares/verifyAdmin.ts +++ b/server/middlewares/verifyAdmin.ts @@ -1,6 +1,6 @@ import { Request, Response, NextFunction } from "express"; import { db } from "@server/db"; -import { roles, userOrgs } from "@server/db/schemas"; +import { roles, userOrgs } from "@server/db"; import { and, eq } from "drizzle-orm"; import createHttpError from "http-errors"; import HttpCode from "@server/types/HttpCode"; diff --git a/server/middlewares/verifyApiKeyAccess.ts b/server/middlewares/verifyApiKeyAccess.ts index ad21b37e..8ab709b6 100644 --- a/server/middlewares/verifyApiKeyAccess.ts +++ b/server/middlewares/verifyApiKeyAccess.ts @@ -1,6 +1,6 @@ import { Request, Response, NextFunction } from "express"; import { db } from "@server/db"; -import { userOrgs, apiKeys, apiKeyOrg } from "@server/db/schemas"; +import { userOrgs, apiKeys, apiKeyOrg } from "@server/db"; import { and, eq, or } from "drizzle-orm"; import createHttpError from "http-errors"; import HttpCode from "@server/types/HttpCode"; diff --git a/server/middlewares/verifyOrgAccess.ts b/server/middlewares/verifyOrgAccess.ts index 20018e06..a2cc44f2 100644 --- a/server/middlewares/verifyOrgAccess.ts +++ b/server/middlewares/verifyOrgAccess.ts @@ -1,6 +1,6 @@ import { Request, Response, NextFunction } from "express"; import { db } from "@server/db"; -import { userOrgs } from "@server/db/schemas"; +import { userOrgs } from "@server/db"; import { and, eq } from "drizzle-orm"; import createHttpError from "http-errors"; import HttpCode from "@server/types/HttpCode"; diff --git a/server/middlewares/verifyResourceAccess.ts b/server/middlewares/verifyResourceAccess.ts index dc5fcc24..5c88139d 100644 --- a/server/middlewares/verifyResourceAccess.ts +++ b/server/middlewares/verifyResourceAccess.ts @@ -5,7 +5,7 @@ import { userOrgs, userResources, roleResources, -} from "@server/db/schemas"; +} from "@server/db"; import { and, eq } from "drizzle-orm"; import createHttpError from "http-errors"; import HttpCode from "@server/types/HttpCode"; diff --git a/server/middlewares/verifyRoleAccess.ts b/server/middlewares/verifyRoleAccess.ts index 54917044..cfcbd475 100644 --- a/server/middlewares/verifyRoleAccess.ts +++ b/server/middlewares/verifyRoleAccess.ts @@ -1,6 +1,6 @@ import { Request, Response, NextFunction } from "express"; import { db } from "@server/db"; -import { roles, userOrgs } from "@server/db/schemas"; +import { roles, userOrgs } from "@server/db"; import { and, eq, inArray } from "drizzle-orm"; import createHttpError from "http-errors"; import HttpCode from "@server/types/HttpCode"; diff --git a/server/middlewares/verifySession.ts b/server/middlewares/verifySession.ts index 9d284394..6af34e4c 100644 --- a/server/middlewares/verifySession.ts +++ b/server/middlewares/verifySession.ts @@ -1,7 +1,7 @@ import { NextFunction, Response } from "express"; import ErrorResponse from "@server/types/ErrorResponse"; import { db } from "@server/db"; -import { users } from "@server/db/schemas"; +import { users } from "@server/db"; import { eq } from "drizzle-orm"; import createHttpError from "http-errors"; import HttpCode from "@server/types/HttpCode"; diff --git a/server/middlewares/verifySetResourceUsers.ts b/server/middlewares/verifySetResourceUsers.ts index 0f351069..be6d21fc 100644 --- a/server/middlewares/verifySetResourceUsers.ts +++ b/server/middlewares/verifySetResourceUsers.ts @@ -1,6 +1,6 @@ import { Request, Response, NextFunction } from "express"; import { db } from "@server/db"; -import { userOrgs } from "@server/db/schemas"; +import { userOrgs } from "@server/db"; import { and, eq, inArray, or } from "drizzle-orm"; import createHttpError from "http-errors"; import HttpCode from "@server/types/HttpCode"; diff --git a/server/middlewares/verifySiteAccess.ts b/server/middlewares/verifySiteAccess.ts index b741e3ae..6d01392f 100644 --- a/server/middlewares/verifySiteAccess.ts +++ b/server/middlewares/verifySiteAccess.ts @@ -6,7 +6,7 @@ import { userSites, roleSites, roles, -} from "@server/db/schemas"; +} from "@server/db"; import { and, eq, or } from "drizzle-orm"; import createHttpError from "http-errors"; import HttpCode from "@server/types/HttpCode"; diff --git a/server/middlewares/verifyTargetAccess.ts b/server/middlewares/verifyTargetAccess.ts index f57ba474..50563d6e 100644 --- a/server/middlewares/verifyTargetAccess.ts +++ b/server/middlewares/verifyTargetAccess.ts @@ -1,6 +1,6 @@ import { Request, Response, NextFunction } from "express"; import { db } from "@server/db"; -import { resources, targets, userOrgs } from "@server/db/schemas"; +import { resources, targets, userOrgs } from "@server/db"; import { and, eq } from "drizzle-orm"; import createHttpError from "http-errors"; import HttpCode from "@server/types/HttpCode"; diff --git a/server/middlewares/verifyUser.ts b/server/middlewares/verifyUser.ts index 06b08601..8fd38b24 100644 --- a/server/middlewares/verifyUser.ts +++ b/server/middlewares/verifyUser.ts @@ -1,7 +1,7 @@ import { NextFunction, Response } from "express"; import ErrorResponse from "@server/types/ErrorResponse"; import { db } from "@server/db"; -import { users } from "@server/db/schemas"; +import { users } from "@server/db"; import { eq } from "drizzle-orm"; import createHttpError from "http-errors"; import HttpCode from "@server/types/HttpCode"; diff --git a/server/middlewares/verifyUserAccess.ts b/server/middlewares/verifyUserAccess.ts index 43ec9cff..3ef0f0ba 100644 --- a/server/middlewares/verifyUserAccess.ts +++ b/server/middlewares/verifyUserAccess.ts @@ -1,6 +1,6 @@ import { Request, Response, NextFunction } from "express"; import { db } from "@server/db"; -import { userOrgs } from "@server/db/schemas"; +import { userOrgs } from "@server/db"; import { and, eq, or } from "drizzle-orm"; import createHttpError from "http-errors"; import HttpCode from "@server/types/HttpCode"; diff --git a/server/middlewares/verifyUserIsOrgOwner.ts b/server/middlewares/verifyUserIsOrgOwner.ts index ac96f379..25ccf047 100644 --- a/server/middlewares/verifyUserIsOrgOwner.ts +++ b/server/middlewares/verifyUserIsOrgOwner.ts @@ -1,6 +1,6 @@ import { Request, Response, NextFunction } from "express"; import { db } from "@server/db"; -import { userOrgs } from "@server/db/schemas"; +import { userOrgs } from "@server/db"; import { and, eq } from "drizzle-orm"; import createHttpError from "http-errors"; import HttpCode from "@server/types/HttpCode"; diff --git a/server/routers/accessToken/deleteAccessToken.ts b/server/routers/accessToken/deleteAccessToken.ts index 783c5fc8..60d8789e 100644 --- a/server/routers/accessToken/deleteAccessToken.ts +++ b/server/routers/accessToken/deleteAccessToken.ts @@ -5,9 +5,9 @@ import HttpCode from "@server/types/HttpCode"; import createHttpError from "http-errors"; import logger from "@server/logger"; import { fromError } from "zod-validation-error"; -import { resourceAccessToken } from "@server/db/schemas"; +import { resourceAccessToken } from "@server/db"; import { and, eq } from "drizzle-orm"; -import db from "@server/db"; +import { db } from "@server/db"; import { OpenAPITags, registry } from "@server/openApi"; const deleteAccessTokenParamsSchema = z diff --git a/server/routers/accessToken/generateAccessToken.ts b/server/routers/accessToken/generateAccessToken.ts index 738c230e..631b5924 100644 --- a/server/routers/accessToken/generateAccessToken.ts +++ b/server/routers/accessToken/generateAccessToken.ts @@ -4,12 +4,12 @@ import { generateIdFromEntropySize, SESSION_COOKIE_EXPIRES } from "@server/auth/sessions/app"; -import db from "@server/db"; +import { db } from "@server/db"; import { ResourceAccessToken, resourceAccessToken, resources -} from "@server/db/schemas"; +} from "@server/db"; import HttpCode from "@server/types/HttpCode"; import response from "@server/lib/response"; import { eq } from "drizzle-orm"; diff --git a/server/routers/accessToken/listAccessTokens.ts b/server/routers/accessToken/listAccessTokens.ts index 07ef9aa3..d021c79d 100644 --- a/server/routers/accessToken/listAccessTokens.ts +++ b/server/routers/accessToken/listAccessTokens.ts @@ -7,7 +7,7 @@ import { roleResources, resourceAccessToken, sites -} from "@server/db/schemas"; +} from "@server/db"; import response from "@server/lib/response"; import HttpCode from "@server/types/HttpCode"; import createHttpError from "http-errors"; diff --git a/server/routers/apiKeys/createOrgApiKey.ts b/server/routers/apiKeys/createOrgApiKey.ts index bf8ff8c3..d61a364b 100644 --- a/server/routers/apiKeys/createOrgApiKey.ts +++ b/server/routers/apiKeys/createOrgApiKey.ts @@ -1,8 +1,8 @@ import { NextFunction, Request, Response } from "express"; -import db from "@server/db"; +import { db } from "@server/db"; import HttpCode from "@server/types/HttpCode"; import { z } from "zod"; -import { apiKeyOrg, apiKeys } from "@server/db/schemas"; +import { apiKeyOrg, apiKeys } from "@server/db"; import { fromError } from "zod-validation-error"; import createHttpError from "http-errors"; import response from "@server/lib/response"; diff --git a/server/routers/apiKeys/createRootApiKey.ts b/server/routers/apiKeys/createRootApiKey.ts index 7a5d2d81..095d952b 100644 --- a/server/routers/apiKeys/createRootApiKey.ts +++ b/server/routers/apiKeys/createRootApiKey.ts @@ -1,8 +1,8 @@ import { NextFunction, Request, Response } from "express"; -import db from "@server/db"; +import { db } from "@server/db"; import HttpCode from "@server/types/HttpCode"; import { z } from "zod"; -import { apiKeyOrg, apiKeys, orgs } from "@server/db/schemas"; +import { apiKeyOrg, apiKeys, orgs } from "@server/db"; import { fromError } from "zod-validation-error"; import createHttpError from "http-errors"; import response from "@server/lib/response"; diff --git a/server/routers/apiKeys/deleteApiKey.ts b/server/routers/apiKeys/deleteApiKey.ts index e1a74a45..4b97b353 100644 --- a/server/routers/apiKeys/deleteApiKey.ts +++ b/server/routers/apiKeys/deleteApiKey.ts @@ -1,7 +1,7 @@ import { Request, Response, NextFunction } from "express"; import { z } from "zod"; import { db } from "@server/db"; -import { apiKeys } from "@server/db/schemas"; +import { apiKeys } from "@server/db"; import { eq } from "drizzle-orm"; import response from "@server/lib/response"; import HttpCode from "@server/types/HttpCode"; diff --git a/server/routers/apiKeys/deleteOrgApiKey.ts b/server/routers/apiKeys/deleteOrgApiKey.ts index dbaf47fe..22e776ca 100644 --- a/server/routers/apiKeys/deleteOrgApiKey.ts +++ b/server/routers/apiKeys/deleteOrgApiKey.ts @@ -1,7 +1,7 @@ import { Request, Response, NextFunction } from "express"; import { z } from "zod"; import { db } from "@server/db"; -import { apiKeyOrg, apiKeys } from "@server/db/schemas"; +import { apiKeyOrg, apiKeys } from "@server/db"; import { and, eq } from "drizzle-orm"; import response from "@server/lib/response"; import HttpCode from "@server/types/HttpCode"; diff --git a/server/routers/apiKeys/getApiKey.ts b/server/routers/apiKeys/getApiKey.ts index e0354cf1..2bb3b65c 100644 --- a/server/routers/apiKeys/getApiKey.ts +++ b/server/routers/apiKeys/getApiKey.ts @@ -1,7 +1,7 @@ import { Request, Response, NextFunction } from "express"; import { z } from "zod"; import { db } from "@server/db"; -import { apiKeys } from "@server/db/schemas"; +import { apiKeys } from "@server/db"; import { eq } from "drizzle-orm"; import response from "@server/lib/response"; import HttpCode from "@server/types/HttpCode"; diff --git a/server/routers/apiKeys/listApiKeyActions.ts b/server/routers/apiKeys/listApiKeyActions.ts index 5bd14411..51d20b24 100644 --- a/server/routers/apiKeys/listApiKeyActions.ts +++ b/server/routers/apiKeys/listApiKeyActions.ts @@ -1,5 +1,5 @@ import { db } from "@server/db"; -import { actions, apiKeyActions, apiKeyOrg, apiKeys } from "@server/db/schemas"; +import { actions, apiKeyActions, apiKeyOrg, apiKeys } from "@server/db"; import logger from "@server/logger"; import HttpCode from "@server/types/HttpCode"; import response from "@server/lib/response"; diff --git a/server/routers/apiKeys/listOrgApiKeys.ts b/server/routers/apiKeys/listOrgApiKeys.ts index 9833ef0f..e8c8bc1c 100644 --- a/server/routers/apiKeys/listOrgApiKeys.ts +++ b/server/routers/apiKeys/listOrgApiKeys.ts @@ -1,5 +1,5 @@ import { db } from "@server/db"; -import { apiKeyOrg, apiKeys } from "@server/db/schemas"; +import { apiKeyOrg, apiKeys } from "@server/db"; import logger from "@server/logger"; import HttpCode from "@server/types/HttpCode"; import response from "@server/lib/response"; diff --git a/server/routers/apiKeys/listRootApiKeys.ts b/server/routers/apiKeys/listRootApiKeys.ts index c639ce51..ddfade3c 100644 --- a/server/routers/apiKeys/listRootApiKeys.ts +++ b/server/routers/apiKeys/listRootApiKeys.ts @@ -1,5 +1,5 @@ import { db } from "@server/db"; -import { apiKeys } from "@server/db/schemas"; +import { apiKeys } from "@server/db"; import logger from "@server/logger"; import HttpCode from "@server/types/HttpCode"; import response from "@server/lib/response"; diff --git a/server/routers/apiKeys/setApiKeyActions.ts b/server/routers/apiKeys/setApiKeyActions.ts index 602c7798..bb16deb5 100644 --- a/server/routers/apiKeys/setApiKeyActions.ts +++ b/server/routers/apiKeys/setApiKeyActions.ts @@ -1,7 +1,7 @@ import { Request, Response, NextFunction } from "express"; import { z } from "zod"; import { db } from "@server/db"; -import { actions, apiKeyActions } from "@server/db/schemas"; +import { actions, apiKeyActions } from "@server/db"; import response from "@server/lib/response"; import HttpCode from "@server/types/HttpCode"; import createHttpError from "http-errors"; diff --git a/server/routers/apiKeys/setApiKeyOrgs.ts b/server/routers/apiKeys/setApiKeyOrgs.ts index c42046de..f03eec18 100644 --- a/server/routers/apiKeys/setApiKeyOrgs.ts +++ b/server/routers/apiKeys/setApiKeyOrgs.ts @@ -1,7 +1,7 @@ import { Request, Response, NextFunction } from "express"; import { z } from "zod"; import { db } from "@server/db"; -import { apiKeyOrg, orgs } from "@server/db/schemas"; +import { apiKeyOrg, orgs } from "@server/db"; import response from "@server/lib/response"; import HttpCode from "@server/types/HttpCode"; import createHttpError from "http-errors"; diff --git a/server/routers/auth/changePassword.ts b/server/routers/auth/changePassword.ts index 3b1e4c2f..3a9120e3 100644 --- a/server/routers/auth/changePassword.ts +++ b/server/routers/auth/changePassword.ts @@ -4,7 +4,7 @@ import HttpCode from "@server/types/HttpCode"; import { fromError } from "zod-validation-error"; import { z } from "zod"; import { db } from "@server/db"; -import { User, users } from "@server/db/schemas"; +import { User, users } from "@server/db"; import { eq } from "drizzle-orm"; import { response } from "@server/lib"; import { diff --git a/server/routers/auth/disable2fa.ts b/server/routers/auth/disable2fa.ts index b10dd9b2..7fbea2e5 100644 --- a/server/routers/auth/disable2fa.ts +++ b/server/routers/auth/disable2fa.ts @@ -4,7 +4,7 @@ import HttpCode from "@server/types/HttpCode"; import { fromError } from "zod-validation-error"; import { z } from "zod"; import { db } from "@server/db"; -import { User, users } from "@server/db/schemas"; +import { User, users } from "@server/db"; import { eq } from "drizzle-orm"; import { response } from "@server/lib"; import { verifyPassword } from "@server/auth/password"; diff --git a/server/routers/auth/login.ts b/server/routers/auth/login.ts index eda637fa..5558a9c7 100644 --- a/server/routers/auth/login.ts +++ b/server/routers/auth/login.ts @@ -3,8 +3,8 @@ import { generateSessionToken, serializeSessionCookie } from "@server/auth/sessions/app"; -import db from "@server/db"; -import { users } from "@server/db/schemas"; +import { db } from "@server/db"; +import { users } from "@server/db"; import HttpCode from "@server/types/HttpCode"; import response from "@server/lib/response"; import { eq, and } from "drizzle-orm"; @@ -37,6 +37,8 @@ export type LoginResponse = { emailVerificationRequired?: boolean; }; +export const dynamic = "force-dynamic"; + export async function login( req: Request, res: Response, diff --git a/server/routers/auth/logout.ts b/server/routers/auth/logout.ts index db95c2e6..b9a1431a 100644 --- a/server/routers/auth/logout.ts +++ b/server/routers/auth/logout.ts @@ -34,7 +34,7 @@ export async function logout( try { await invalidateSession(session.sessionId); } catch (error) { - logger.error("Failed to invalidate session", error) + logger.error("Failed to invalidate session", error); } const isSecure = req.protocol === "https"; diff --git a/server/routers/auth/requestEmailVerificationCode.ts b/server/routers/auth/requestEmailVerificationCode.ts index 0cc8825c..eeabedf2 100644 --- a/server/routers/auth/requestEmailVerificationCode.ts +++ b/server/routers/auth/requestEmailVerificationCode.ts @@ -2,7 +2,7 @@ import { Request, Response, NextFunction } from "express"; import createHttpError from "http-errors"; import HttpCode from "@server/types/HttpCode"; import { response } from "@server/lib"; -import { User } from "@server/db/schemas"; +import { User } from "@server/db"; import { sendEmailVerificationCode } from "../../auth/sendEmailVerificationCode"; import config from "@server/lib/config"; import logger from "@server/logger"; diff --git a/server/routers/auth/requestPasswordReset.ts b/server/routers/auth/requestPasswordReset.ts index 087352f0..4127533f 100644 --- a/server/routers/auth/requestPasswordReset.ts +++ b/server/routers/auth/requestPasswordReset.ts @@ -5,7 +5,7 @@ import { fromError } from "zod-validation-error"; import HttpCode from "@server/types/HttpCode"; import { response } from "@server/lib"; import { db } from "@server/db"; -import { passwordResetTokens, users } from "@server/db/schemas"; +import { passwordResetTokens, users } from "@server/db"; import { eq } from "drizzle-orm"; import { alphabet, generateRandomString, sha256 } from "oslo/crypto"; import { createDate } from "oslo"; diff --git a/server/routers/auth/requestTotpSecret.ts b/server/routers/auth/requestTotpSecret.ts index a4f8bc4a..2de35412 100644 --- a/server/routers/auth/requestTotpSecret.ts +++ b/server/routers/auth/requestTotpSecret.ts @@ -6,7 +6,7 @@ import { encodeHex } from "oslo/encoding"; import HttpCode from "@server/types/HttpCode"; import { response } from "@server/lib"; import { db } from "@server/db"; -import { User, users } from "@server/db/schemas"; +import { User, users } from "@server/db"; import { eq } from "drizzle-orm"; import { createTOTPKeyURI } from "oslo/otp"; import logger from "@server/logger"; diff --git a/server/routers/auth/resetPassword.ts b/server/routers/auth/resetPassword.ts index 967ddc66..d99b8718 100644 --- a/server/routers/auth/resetPassword.ts +++ b/server/routers/auth/resetPassword.ts @@ -6,7 +6,7 @@ import { fromError } from "zod-validation-error"; import HttpCode from "@server/types/HttpCode"; import { response } from "@server/lib"; import { db } from "@server/db"; -import { passwordResetTokens, users } from "@server/db/schemas"; +import { passwordResetTokens, users } from "@server/db"; import { eq } from "drizzle-orm"; import { hashPassword, verifyPassword } from "@server/auth/password"; import { verifyTotpCode } from "@server/auth/totp"; diff --git a/server/routers/auth/signup.ts b/server/routers/auth/signup.ts index 564a1378..d2a1e730 100644 --- a/server/routers/auth/signup.ts +++ b/server/routers/auth/signup.ts @@ -1,8 +1,8 @@ import { NextFunction, Request, Response } from "express"; -import db from "@server/db"; +import { db } from "@server/db"; import HttpCode from "@server/types/HttpCode"; import { z } from "zod"; -import { users } from "@server/db/schemas"; +import { users } from "@server/db"; import { fromError } from "zod-validation-error"; import createHttpError from "http-errors"; import response from "@server/lib/response"; diff --git a/server/routers/auth/verifyEmail.ts b/server/routers/auth/verifyEmail.ts index fd7aa138..f707de22 100644 --- a/server/routers/auth/verifyEmail.ts +++ b/server/routers/auth/verifyEmail.ts @@ -5,7 +5,7 @@ import { fromError } from "zod-validation-error"; import HttpCode from "@server/types/HttpCode"; import { response } from "@server/lib"; import { db } from "@server/db"; -import { User, emailVerificationCodes, users } from "@server/db/schemas"; +import { User, emailVerificationCodes, users } from "@server/db"; import { eq } from "drizzle-orm"; import { isWithinExpirationDate } from "oslo"; import config from "@server/lib/config"; diff --git a/server/routers/auth/verifyTotp.ts b/server/routers/auth/verifyTotp.ts index db4ec1a1..70018a7d 100644 --- a/server/routers/auth/verifyTotp.ts +++ b/server/routers/auth/verifyTotp.ts @@ -5,7 +5,7 @@ import { fromError } from "zod-validation-error"; import HttpCode from "@server/types/HttpCode"; import { response } from "@server/lib"; import { db } from "@server/db"; -import { twoFactorBackupCodes, User, users } from "@server/db/schemas"; +import { twoFactorBackupCodes, User, users } from "@server/db"; import { eq } from "drizzle-orm"; import { alphabet, generateRandomString } from "oslo/crypto"; import { hashPassword } from "@server/auth/password"; diff --git a/server/routers/badger/exchangeSession.ts b/server/routers/badger/exchangeSession.ts index a9208423..8139694a 100644 --- a/server/routers/badger/exchangeSession.ts +++ b/server/routers/badger/exchangeSession.ts @@ -4,8 +4,8 @@ import createHttpError from "http-errors"; import { z } from "zod"; import { fromError } from "zod-validation-error"; import logger from "@server/logger"; -import { resourceAccessToken, resources, sessions } from "@server/db/schemas"; -import db from "@server/db"; +import { resourceAccessToken, resources, sessions } from "@server/db"; +import { db } from "@server/db"; import { eq } from "drizzle-orm"; import { createResourceSession, diff --git a/server/routers/badger/verifySession.ts b/server/routers/badger/verifySession.ts index 0c2e6493..7ee431d6 100644 --- a/server/routers/badger/verifySession.ts +++ b/server/routers/badger/verifySession.ts @@ -5,7 +5,7 @@ import { validateResourceSessionToken } from "@server/auth/sessions/resource"; import { verifyResourceAccessToken } from "@server/auth/verifyResourceAccessToken"; -import db from "@server/db"; +import { db } from "@server/db"; import { Resource, ResourceAccessToken, @@ -21,7 +21,7 @@ import { userOrgs, userResources, users -} from "@server/db/schemas"; +} from "@server/db"; import config from "@server/lib/config"; import { isIpInCidr } from "@server/lib/ip"; import { response } from "@server/lib/response"; @@ -56,9 +56,16 @@ export type VerifyResourceSessionSchema = z.infer< typeof verifyResourceSessionSchema >; +type BasicUserData = { + username: string; + email: string | null; + name: string | null; +}; + export type VerifyUserResponse = { valid: boolean; redirectUrl?: string; + userData?: BasicUserData; }; export async function verifyResourceSession( @@ -90,7 +97,28 @@ export async function verifyResourceSession( query } = parsedBody.data; - const clientIp = requestIp?.split(":")[0]; + const clientIp = requestIp + ? (() => { + logger.debug("Request IP:", { requestIp }); + if (requestIp.startsWith("[") && requestIp.includes("]")) { + // if brackets are found, extract the IPv6 address from between the brackets + const ipv6Match = requestIp.match(/\[(.*?)\]/); + if (ipv6Match) { + return ipv6Match[1]; + } + } + + // ivp4 + // split at last colon + const lastColonIndex = requestIp.lastIndexOf(":"); + if (lastColonIndex !== -1) { + return requestIp.substring(0, lastColonIndex); + } + return requestIp; + })() + : undefined; + + logger.debug("Client IP:", { clientIp }); let cleanHost = host; // if the host ends with :443 or :80 remove it @@ -350,23 +378,26 @@ export async function verifyResourceSession( resourceSession.userSessionId }:${resource.resourceId}`; - let isAllowed: boolean | undefined = + let allowedUserData: BasicUserData | null | undefined = cache.get(userAccessCacheKey); - if (isAllowed === undefined) { - isAllowed = await isUserAllowedToAccessResource( + if (allowedUserData === undefined) { + allowedUserData = await isUserAllowedToAccessResource( resourceSession.userSessionId, resource ); - cache.set(userAccessCacheKey, isAllowed); + cache.set(userAccessCacheKey, allowedUserData); } - if (isAllowed) { + if ( + allowedUserData !== null && + allowedUserData !== undefined + ) { logger.debug( "Resource allowed because user session is valid" ); - return allowed(res); + return allowed(res, allowedUserData); } } } @@ -448,15 +479,17 @@ function notAllowed(res: Response, redirectUrl?: string) { return response(res, data); } -function allowed(res: Response) { +function allowed(res: Response, userData?: BasicUserData) { const data = { - data: { valid: true }, + data: + userData !== undefined && userData !== null + ? { valid: true, ...userData } + : { valid: true }, success: true, error: false, message: "Access allowed", status: HttpCode.OK }; - logger.debug(JSON.stringify(data)); return response(res, data); } @@ -496,7 +529,7 @@ async function createAccessTokenSession( async function isUserAllowedToAccessResource( userSessionId: string, resource: Resource -): Promise { +): Promise { const [res] = await db .select() .from(sessions) @@ -507,14 +540,14 @@ async function isUserAllowedToAccessResource( const session = res.session; if (!user || !session) { - return false; + return null; } if ( config.getRawConfig().flags?.require_email_verification && !user.emailVerified ) { - return false; + return null; } const userOrgRole = await db @@ -529,7 +562,7 @@ async function isUserAllowedToAccessResource( .limit(1); if (userOrgRole.length === 0) { - return false; + return null; } const roleResourceAccess = await db @@ -544,7 +577,11 @@ async function isUserAllowedToAccessResource( .limit(1); if (roleResourceAccess.length > 0) { - return true; + return { + username: user.username, + email: user.email, + name: user.name + }; } const userResourceAccess = await db @@ -559,10 +596,14 @@ async function isUserAllowedToAccessResource( .limit(1); if (userResourceAccess.length > 0) { - return true; + return { + username: user.username, + email: user.email, + name: user.name + }; } - return false; + return null; } async function checkRules( diff --git a/server/routers/domain/listDomains.ts b/server/routers/domain/listDomains.ts index c525e1d8..a8216c5f 100644 --- a/server/routers/domain/listDomains.ts +++ b/server/routers/domain/listDomains.ts @@ -1,7 +1,7 @@ import { Request, Response, NextFunction } from "express"; import { z } from "zod"; import { db } from "@server/db"; -import { domains, orgDomains, users } from "@server/db/schemas"; +import { domains, orgDomains, users } from "@server/db"; import response from "@server/lib/response"; import HttpCode from "@server/types/HttpCode"; import createHttpError from "http-errors"; diff --git a/server/routers/external.ts b/server/routers/external.ts index 5ff4629e..8950fc22 100644 --- a/server/routers/external.ts +++ b/server/routers/external.ts @@ -174,6 +174,37 @@ authenticated.delete( site.deleteSite ); +authenticated.get( + "/site/:siteId/docker/status", + verifySiteAccess, + verifyUserHasAction(ActionsEnum.getSite), + site.dockerStatus +); +authenticated.get( + "/site/:siteId/docker/online", + verifySiteAccess, + verifyUserHasAction(ActionsEnum.getSite), + site.dockerOnline +); +authenticated.post( + "/site/:siteId/docker/check", + verifySiteAccess, + verifyUserHasAction(ActionsEnum.getSite), + site.checkDockerSocket +); +authenticated.post( + "/site/:siteId/docker/trigger", + verifySiteAccess, + verifyUserHasAction(ActionsEnum.getSite), + site.triggerFetchContainers +); +authenticated.get( + "/site/:siteId/docker/containers", + verifySiteAccess, + verifyUserHasAction(ActionsEnum.getSite), + site.listContainers +); + authenticated.put( "/org/:orgId/site/:siteId/resource", verifyOrgAccess, diff --git a/server/routers/gerbil/getConfig.ts b/server/routers/gerbil/getConfig.ts index e0461d66..de3da171 100644 --- a/server/routers/gerbil/getConfig.ts +++ b/server/routers/gerbil/getConfig.ts @@ -1,21 +1,21 @@ -import { Request, Response, NextFunction } from 'express'; -import { z } from 'zod'; -import { sites, resources, targets, exitNodes } from '@server/db/schemas'; -import { db } from '@server/db'; -import { eq } from 'drizzle-orm'; +import { Request, Response, NextFunction } from "express"; +import { z } from "zod"; +import { sites, resources, targets, exitNodes } from "@server/db"; +import { db } from "@server/db"; +import { eq } from "drizzle-orm"; import response from "@server/lib/response"; -import HttpCode from '@server/types/HttpCode'; -import createHttpError from 'http-errors'; -import logger from '@server/logger'; +import HttpCode from "@server/types/HttpCode"; +import createHttpError from "http-errors"; +import logger from "@server/logger"; import config from "@server/lib/config"; -import { getUniqueExitNodeEndpointName } from '@server/db/names'; +import { getUniqueExitNodeEndpointName } from "../../db/names"; import { findNextAvailableCidr } from "@server/lib/ip"; -import { fromError } from 'zod-validation-error'; -import { getAllowedIps } from '../target/helpers'; +import { fromError } from "zod-validation-error"; +import { getAllowedIps } from "../target/helpers"; // Define Zod schema for request validation const getConfigSchema = z.object({ publicKey: z.string(), - reachableAt: z.string().optional(), + reachableAt: z.string().optional() }); export type GetConfigResponse = { @@ -25,9 +25,13 @@ export type GetConfigResponse = { publicKey: string | null; allowedIps: string[]; }[]; -} +}; -export async function getConfig(req: Request, res: Response, next: NextFunction): Promise { +export async function getConfig( + req: Request, + res: Response, + next: NextFunction +): Promise { try { // Validate request parameters const parsedParams = getConfigSchema.safeParse(req.body); @@ -43,11 +47,16 @@ export async function getConfig(req: Request, res: Response, next: NextFunction) const { publicKey, reachableAt } = parsedParams.data; if (!publicKey) { - return next(createHttpError(HttpCode.BAD_REQUEST, 'publicKey is required')); + return next( + createHttpError(HttpCode.BAD_REQUEST, "publicKey is required") + ); } // Fetch exit node - let exitNodeQuery = await db.select().from(exitNodes).where(eq(exitNodes.publicKey, publicKey)); + let exitNodeQuery = await db + .select() + .from(exitNodes) + .where(eq(exitNodes.publicKey, publicKey)); let exitNode; if (exitNodeQuery.length === 0) { const address = await getNextAvailableSubnet(); @@ -60,38 +69,53 @@ export async function getConfig(req: Request, res: Response, next: NextFunction) } // create a new exit node - exitNode = await db.insert(exitNodes).values({ - publicKey, - endpoint: `${subEndpoint}${subEndpoint != "" ? "." : ""}${config.getRawConfig().gerbil.base_endpoint}`, - address, - listenPort, - reachableAt, - name: `Exit Node ${publicKey.slice(0, 8)}`, - }).returning().execute(); + exitNode = await db + .insert(exitNodes) + .values({ + publicKey, + endpoint: `${subEndpoint}${subEndpoint != "" ? "." : ""}${config.getRawConfig().gerbil.base_endpoint}`, + address, + listenPort, + reachableAt, + name: `Exit Node ${publicKey.slice(0, 8)}` + }) + .returning() + .execute(); - logger.info(`Created new exit node ${exitNode[0].name} with address ${exitNode[0].address} and port ${exitNode[0].listenPort}`); + logger.info( + `Created new exit node ${exitNode[0].name} with address ${exitNode[0].address} and port ${exitNode[0].listenPort}` + ); } else { exitNode = exitNodeQuery; } if (!exitNode) { - return next(createHttpError(HttpCode.INTERNAL_SERVER_ERROR, "Failed to create exit node")); + return next( + createHttpError( + HttpCode.INTERNAL_SERVER_ERROR, + "Failed to create exit node" + ) + ); } - // Fetch sites for this exit node - const sitesRes = await db.select().from(sites).where(eq(sites.exitNodeId, exitNode[0].exitNodeId)); + const sitesRes = await db + .select() + .from(sites) + .where(eq(sites.exitNodeId, exitNode[0].exitNodeId)); - const peers = await Promise.all(sitesRes.map(async (site) => { - return { - publicKey: site.pubKey, - allowedIps: await getAllowedIps(site.siteId) // put 0.0.0.0/0 for now - }; - })); + const peers = await Promise.all( + sitesRes.map(async (site) => { + return { + publicKey: site.pubKey, + allowedIps: await getAllowedIps(site.siteId) + }; + }) + ); const configResponse: GetConfigResponse = { listenPort: exitNode[0].listenPort || 51820, ipAddress: exitNode[0].address, - peers, + peers }; logger.debug("Sending config: ", configResponse); @@ -99,32 +123,49 @@ export async function getConfig(req: Request, res: Response, next: NextFunction) return res.status(HttpCode.OK).send(configResponse); } catch (error) { logger.error(error); - return next(createHttpError(HttpCode.INTERNAL_SERVER_ERROR, "An error occurred...")); + return next( + createHttpError( + HttpCode.INTERNAL_SERVER_ERROR, + "An error occurred..." + ) + ); } } async function getNextAvailableSubnet(): Promise { // Get all existing subnets from routes table - const existingAddresses = await db.select({ - address: exitNodes.address, - }).from(exitNodes); + const existingAddresses = await db + .select({ + address: exitNodes.address + }) + .from(exitNodes); - const addresses = existingAddresses.map(a => a.address); - let subnet = findNextAvailableCidr(addresses, config.getRawConfig().gerbil.block_size, config.getRawConfig().gerbil.subnet_group); + const addresses = existingAddresses.map((a) => a.address); + let subnet = findNextAvailableCidr( + addresses, + config.getRawConfig().gerbil.block_size, + config.getRawConfig().gerbil.subnet_group + ); if (!subnet) { - throw new Error('No available subnets remaining in space'); + throw new Error("No available subnets remaining in space"); } // replace the last octet with 1 - subnet = subnet.split('.').slice(0, 3).join('.') + '.1' + '/' + subnet.split('/')[1]; + subnet = + subnet.split(".").slice(0, 3).join(".") + + ".1" + + "/" + + subnet.split("/")[1]; return subnet; } async function getNextAvailablePort(): Promise { // Get all existing ports from exitNodes table - const existingPorts = await db.select({ - listenPort: exitNodes.listenPort, - }).from(exitNodes); + const existingPorts = await db + .select({ + listenPort: exitNodes.listenPort + }) + .from(exitNodes); // Find the first available port between 1024 and 65535 let nextPort = config.getRawConfig().gerbil.start_port; @@ -134,7 +175,7 @@ async function getNextAvailablePort(): Promise { } nextPort++; if (nextPort > 65535) { - throw new Error('No available ports remaining in space'); + throw new Error("No available ports remaining in space"); } } diff --git a/server/routers/gerbil/peers.ts b/server/routers/gerbil/peers.ts index 47527ea0..4bc9ce7f 100644 --- a/server/routers/gerbil/peers.ts +++ b/server/routers/gerbil/peers.ts @@ -1,7 +1,7 @@ import axios from 'axios'; import logger from '@server/logger'; -import db from '@server/db'; -import { exitNodes } from '@server/db/schemas'; +import { db } from "@server/db"; +import { exitNodes } from '@server/db'; import { eq } from 'drizzle-orm'; export async function addPeer(exitNodeId: number, peer: { @@ -24,7 +24,7 @@ export async function addPeer(exitNodeId: number, peer: { } }); - logger.info('Peer added successfully:', response.data.status); + logger.info('Peer added successfully:', { peer: response.data.status }); return response.data; } catch (error) { if (axios.isAxiosError(error)) { diff --git a/server/routers/gerbil/receiveBandwidth.ts b/server/routers/gerbil/receiveBandwidth.ts index 9fdb9438..66556c32 100644 --- a/server/routers/gerbil/receiveBandwidth.ts +++ b/server/routers/gerbil/receiveBandwidth.ts @@ -1,7 +1,7 @@ import { Request, Response, NextFunction } from "express"; -import { DrizzleError, eq } from "drizzle-orm"; -import { sites, resources, targets, exitNodes } from "@server/db/schemas"; -import db from "@server/db"; +import { eq } from "drizzle-orm"; +import { sites, } from "@server/db"; +import { db } from "@server/db"; import logger from "@server/logger"; import createHttpError from "http-errors"; import HttpCode from "@server/types/HttpCode"; @@ -29,7 +29,6 @@ export const receiveBandwidth = async ( for (const peer of bandwidthData) { const { publicKey, bytesIn, bytesOut } = peer; - // Find the site by public key const [site] = await trx .select() .from(sites) @@ -85,10 +84,4 @@ export const receiveBandwidth = async ( ) ); } -}; - -function calculateSubnet(index: number): string { - const baseIp = 10 << 24; - const subnetSize = 16; - return `${(baseIp | (index * subnetSize)).toString()}/28`; -} +}; \ No newline at end of file diff --git a/server/routers/idp/createIdpOrgPolicy.ts b/server/routers/idp/createIdpOrgPolicy.ts index 808c7ca7..448b39cd 100644 --- a/server/routers/idp/createIdpOrgPolicy.ts +++ b/server/routers/idp/createIdpOrgPolicy.ts @@ -9,7 +9,7 @@ import { fromError } from "zod-validation-error"; import { OpenAPITags, registry } from "@server/openApi"; import config from "@server/lib/config"; import { eq, and } from "drizzle-orm"; -import { idp, idpOrg } from "@server/db/schemas"; +import { idp, idpOrg } from "@server/db"; const paramsSchema = z .object({ diff --git a/server/routers/idp/createOidcIdp.ts b/server/routers/idp/createOidcIdp.ts index 22c569f2..51700701 100644 --- a/server/routers/idp/createOidcIdp.ts +++ b/server/routers/idp/createOidcIdp.ts @@ -7,7 +7,7 @@ import createHttpError from "http-errors"; import logger from "@server/logger"; import { fromError } from "zod-validation-error"; import { OpenAPITags, registry } from "@server/openApi"; -import { idp, idpOidcConfig, idpOrg, orgs } from "@server/db/schemas"; +import { idp, idpOidcConfig, idpOrg, orgs } from "@server/db"; import { generateOidcRedirectUrl } from "@server/lib/idp/generateRedirectUrl"; import { encrypt } from "@server/lib/crypto"; import config from "@server/lib/config"; diff --git a/server/routers/idp/deleteIdp.ts b/server/routers/idp/deleteIdp.ts index ac84c4f7..e862c81c 100644 --- a/server/routers/idp/deleteIdp.ts +++ b/server/routers/idp/deleteIdp.ts @@ -6,7 +6,7 @@ import HttpCode from "@server/types/HttpCode"; import createHttpError from "http-errors"; import logger from "@server/logger"; import { fromError } from "zod-validation-error"; -import { idp, idpOidcConfig, idpOrg } from "@server/db/schemas"; +import { idp, idpOidcConfig, idpOrg } from "@server/db"; import { eq } from "drizzle-orm"; import { OpenAPITags, registry } from "@server/openApi"; diff --git a/server/routers/idp/deleteIdpOrgPolicy.ts b/server/routers/idp/deleteIdpOrgPolicy.ts index 9a6f6e72..8314a6d5 100644 --- a/server/routers/idp/deleteIdpOrgPolicy.ts +++ b/server/routers/idp/deleteIdpOrgPolicy.ts @@ -6,7 +6,7 @@ import HttpCode from "@server/types/HttpCode"; import createHttpError from "http-errors"; import logger from "@server/logger"; import { fromError } from "zod-validation-error"; -import { idp, idpOrg } from "@server/db/schemas"; +import { idp, idpOrg } from "@server/db"; import { eq, and } from "drizzle-orm"; import { OpenAPITags, registry } from "@server/openApi"; diff --git a/server/routers/idp/generateOidcUrl.ts b/server/routers/idp/generateOidcUrl.ts index 371a2c21..36c55dcb 100644 --- a/server/routers/idp/generateOidcUrl.ts +++ b/server/routers/idp/generateOidcUrl.ts @@ -6,7 +6,7 @@ import HttpCode from "@server/types/HttpCode"; import createHttpError from "http-errors"; import logger from "@server/logger"; import { fromError } from "zod-validation-error"; -import { idp, idpOidcConfig, idpOrg } from "@server/db/schemas"; +import { idp, idpOidcConfig, idpOrg } from "@server/db"; import { and, eq } from "drizzle-orm"; import * as arctic from "arctic"; import { generateOidcRedirectUrl } from "@server/lib/idp/generateRedirectUrl"; diff --git a/server/routers/idp/getIdp.ts b/server/routers/idp/getIdp.ts index 794daade..227a2429 100644 --- a/server/routers/idp/getIdp.ts +++ b/server/routers/idp/getIdp.ts @@ -1,7 +1,7 @@ import { Request, Response, NextFunction } from "express"; import { z } from "zod"; import { db } from "@server/db"; -import { idp, idpOidcConfig } from "@server/db/schemas"; +import { idp, idpOidcConfig } from "@server/db"; import { eq } from "drizzle-orm"; import response from "@server/lib/response"; import HttpCode from "@server/types/HttpCode"; diff --git a/server/routers/idp/listIdpOrgPolicies.ts b/server/routers/idp/listIdpOrgPolicies.ts index 08ad110c..bd288837 100644 --- a/server/routers/idp/listIdpOrgPolicies.ts +++ b/server/routers/idp/listIdpOrgPolicies.ts @@ -1,7 +1,7 @@ import { Request, Response, NextFunction } from "express"; import { z } from "zod"; import { db } from "@server/db"; -import { idpOrg } from "@server/db/schemas"; +import { idpOrg } from "@server/db"; import response from "@server/lib/response"; import HttpCode from "@server/types/HttpCode"; import createHttpError from "http-errors"; diff --git a/server/routers/idp/listIdps.ts b/server/routers/idp/listIdps.ts index a723ee05..2a0e5809 100644 --- a/server/routers/idp/listIdps.ts +++ b/server/routers/idp/listIdps.ts @@ -1,7 +1,7 @@ import { Request, Response, NextFunction } from "express"; import { z } from "zod"; import { db } from "@server/db"; -import { domains, idp, orgDomains, users, idpOrg } from "@server/db/schemas"; +import { domains, idp, orgDomains, users, idpOrg } from "@server/db"; import response from "@server/lib/response"; import HttpCode from "@server/types/HttpCode"; import createHttpError from "http-errors"; diff --git a/server/routers/idp/updateIdpOrgPolicy.ts b/server/routers/idp/updateIdpOrgPolicy.ts index a5898943..ecbc6dbd 100644 --- a/server/routers/idp/updateIdpOrgPolicy.ts +++ b/server/routers/idp/updateIdpOrgPolicy.ts @@ -8,7 +8,7 @@ import logger from "@server/logger"; import { fromError } from "zod-validation-error"; import { OpenAPITags, registry } from "@server/openApi"; import { eq, and } from "drizzle-orm"; -import { idp, idpOrg } from "@server/db/schemas"; +import { idp, idpOrg } from "@server/db"; const paramsSchema = z .object({ diff --git a/server/routers/idp/updateOidcIdp.ts b/server/routers/idp/updateOidcIdp.ts index 11040679..2f4e3c66 100644 --- a/server/routers/idp/updateOidcIdp.ts +++ b/server/routers/idp/updateOidcIdp.ts @@ -7,7 +7,7 @@ import createHttpError from "http-errors"; import logger from "@server/logger"; import { fromError } from "zod-validation-error"; import { OpenAPITags, registry } from "@server/openApi"; -import { idp, idpOidcConfig } from "@server/db/schemas"; +import { idp, idpOidcConfig } from "@server/db"; import { eq } from "drizzle-orm"; import { encrypt } from "@server/lib/crypto"; import config from "@server/lib/config"; diff --git a/server/routers/idp/validateOidcCallback.ts b/server/routers/idp/validateOidcCallback.ts index d0c847da..0066693f 100644 --- a/server/routers/idp/validateOidcCallback.ts +++ b/server/routers/idp/validateOidcCallback.ts @@ -14,7 +14,7 @@ import { roles, userOrgs, users -} from "@server/db/schemas"; +} from "@server/db"; import { and, eq, inArray } from "drizzle-orm"; import * as arctic from "arctic"; import { generateOidcRedirectUrl } from "@server/lib/idp/generateRedirectUrl"; diff --git a/server/routers/integration.ts b/server/routers/integration.ts index 8fa5c25c..fc66a88d 100644 --- a/server/routers/integration.ts +++ b/server/routers/integration.ts @@ -280,6 +280,13 @@ authenticated.delete( role.deleteRole ); +authenticated.get( + "/role/:roleId", + verifyApiKeyRoleAccess, + verifyApiKeyHasAction(ActionsEnum.getRole), + role.getRole +); + authenticated.post( "/role/:roleId/add/:userId", verifyApiKeyRoleAccess, diff --git a/server/routers/internal.ts b/server/routers/internal.ts index e7e5647f..118c8ae3 100644 --- a/server/routers/internal.ts +++ b/server/routers/internal.ts @@ -6,6 +6,7 @@ import * as badger from "./badger"; import * as auth from "@server/routers/auth"; import * as supporterKey from "@server/routers/supporterKey"; import * as license from "@server/routers/license"; +import * as idp from "@server/routers/idp"; import HttpCode from "@server/types/HttpCode"; import { verifyResourceAccess, @@ -38,10 +39,11 @@ internalRouter.get( supporterKey.isSupporterKeyVisible ); -internalRouter.get( - `/license/status`, - license.getLicenseStatus -); +internalRouter.get(`/license/status`, license.getLicenseStatus); + +internalRouter.get("/idp", idp.listIdps); + +internalRouter.get("/idp/:idpId", idp.getIdp); // Gerbil routes const gerbilRouter = Router(); diff --git a/server/routers/license/deleteLicenseKey.ts b/server/routers/license/deleteLicenseKey.ts index 6ae5ca24..2663308e 100644 --- a/server/routers/license/deleteLicenseKey.ts +++ b/server/routers/license/deleteLicenseKey.ts @@ -5,9 +5,9 @@ import logger from "@server/logger"; import { response as sendResponse } from "@server/lib"; import { z } from "zod"; import { fromError } from "zod-validation-error"; -import db from "@server/db"; +import { db } from "@server/db"; import { eq } from "drizzle-orm"; -import { licenseKey } from "@server/db/schemas"; +import { licenseKey } from "@server/db"; import license, { LicenseStatus } from "@server/license/license"; import { encrypt } from "@server/lib/crypto"; import config from "@server/lib/config"; diff --git a/server/routers/messageHandlers.ts b/server/routers/messageHandlers.ts index 074cd4e2..2f4cd660 100644 --- a/server/routers/messageHandlers.ts +++ b/server/routers/messageHandlers.ts @@ -1,5 +1,16 @@ -import { handleNewtRegisterMessage, handleReceiveBandwidthMessage, handleGetConfigMessage } from "./newt"; -import { handleOlmRegisterMessage, handleOlmRelayMessage, handleOlmPingMessage, startOfflineChecker } from "./olm"; +import { + handleNewtRegisterMessage, + handleReceiveBandwidthMessage, + handleGetConfigMessage, + handleDockerStatusMessage, + handleDockerContainersMessage +} from "./newt"; +import { + handleOlmRegisterMessage, + handleOlmRelayMessage, + handleOlmPingMessage, + startOfflineChecker +} from "./olm"; import { MessageHandler } from "./ws"; export const messageHandlers: Record = { @@ -8,7 +19,9 @@ export const messageHandlers: Record = { "newt/wg/get-config": handleGetConfigMessage, "newt/receive-bandwidth": handleReceiveBandwidthMessage, "olm/wg/relay": handleOlmRelayMessage, - "olm/ping": handleOlmPingMessage + "olm/ping": handleOlmPingMessage, + "newt/socket/status": handleDockerStatusMessage, + "newt/socket/containers": handleDockerContainersMessage }; -startOfflineChecker(); // this is to handle the offline check for olms \ No newline at end of file +startOfflineChecker(); // this is to handle the offline check for olms diff --git a/server/routers/newt/createNewt.ts b/server/routers/newt/createNewt.ts index 02517db5..3066e4ea 100644 --- a/server/routers/newt/createNewt.ts +++ b/server/routers/newt/createNewt.ts @@ -1,9 +1,9 @@ import { NextFunction, Request, Response } from "express"; -import db from "@server/db"; +import { db } from "@server/db"; import { hash } from "@node-rs/argon2"; import HttpCode from "@server/types/HttpCode"; import { z } from "zod"; -import { newts } from "@server/db/schemas"; +import { newts } from "@server/db"; import createHttpError from "http-errors"; import response from "@server/lib/response"; import { SqliteError } from "better-sqlite3"; diff --git a/server/routers/newt/dockerSocket.ts b/server/routers/newt/dockerSocket.ts new file mode 100644 index 00000000..0c59d354 --- /dev/null +++ b/server/routers/newt/dockerSocket.ts @@ -0,0 +1,22 @@ +import NodeCache from "node-cache"; +import { sendToClient } from "../ws"; + +export const dockerSocketCache = new NodeCache({ + stdTTL: 3600 // seconds +}); + +export function fetchContainers(newtId: string) { + const payload = { + type: `newt/socket/fetch`, + data: {} + }; + sendToClient(newtId, payload); +} + +export function dockerSocket(newtId: string) { + const payload = { + type: `newt/socket/check`, + data: {} + }; + sendToClient(newtId, payload); +} diff --git a/server/routers/newt/getNewtToken.ts b/server/routers/newt/getNewtToken.ts index ab8ab9d3..3bf45dcf 100644 --- a/server/routers/newt/getNewtToken.ts +++ b/server/routers/newt/getNewtToken.ts @@ -1,6 +1,6 @@ import { generateSessionToken } from "@server/auth/sessions/app"; -import db from "@server/db"; -import { newts } from "@server/db/schemas"; +import { db } from "@server/db"; +import { newts } from "@server/db"; import HttpCode from "@server/types/HttpCode"; import response from "@server/lib/response"; import { eq } from "drizzle-orm"; diff --git a/server/routers/newt/handleNewtRegisterMessage.ts b/server/routers/newt/handleNewtRegisterMessage.ts index 7e43b2e8..a8396554 100644 --- a/server/routers/newt/handleNewtRegisterMessage.ts +++ b/server/routers/newt/handleNewtRegisterMessage.ts @@ -1,4 +1,4 @@ -import db from "@server/db"; +import { db } from "@server/db"; import { MessageHandler } from "../ws"; import { exitNodes, @@ -7,7 +7,7 @@ import { sites, Target, targets -} from "@server/db/schemas"; +} from "@server/db"; import { eq, and, sql, inArray } from "drizzle-orm"; import { addPeer, deletePeer } from "../gerbil/peers"; import logger from "@server/logger"; diff --git a/server/routers/newt/handleSocketMessages.ts b/server/routers/newt/handleSocketMessages.ts new file mode 100644 index 00000000..0a217c52 --- /dev/null +++ b/server/routers/newt/handleSocketMessages.ts @@ -0,0 +1,57 @@ +import { MessageHandler } from "../ws"; +import logger from "@server/logger"; +import { dockerSocketCache } from "./dockerSocket"; + +export const handleDockerStatusMessage: MessageHandler = async (context) => { + const { message, newt } = context; + + logger.info("Handling Docker socket check response"); + + if (!newt) { + logger.warn("Newt not found"); + return; + } + + logger.info(`Newt ID: ${newt.newtId}, Site ID: ${newt.siteId}`); + const { available, socketPath } = message.data; + + logger.info( + `Docker socket availability for Newt ${newt.newtId}: available=${available}, socketPath=${socketPath}` + ); + + if (available) { + logger.info(`Newt ${newt.newtId} has Docker socket access`); + dockerSocketCache.set(`${newt.newtId}:socketPath`, socketPath, 0); + dockerSocketCache.set(`${newt.newtId}:isAvailable`, available, 0); + } else { + logger.warn(`Newt ${newt.newtId} does not have Docker socket access`); + } + + return; +}; + +export const handleDockerContainersMessage: MessageHandler = async ( + context +) => { + const { message, newt } = context; + + logger.info("Handling Docker containers response"); + + if (!newt) { + logger.warn("Newt not found"); + return; + } + + logger.info(`Newt ID: ${newt.newtId}, Site ID: ${newt.siteId}`); + const { containers } = message.data; + + logger.info( + `Docker containers for Newt ${newt.newtId}: ${containers ? containers.length : 0}` + ); + + if (containers && containers.length > 0) { + dockerSocketCache.set(`${newt.newtId}:dockerContainers`, containers, 0); + } else { + logger.warn(`Newt ${newt.newtId} does not have Docker containers`); + } +}; diff --git a/server/routers/newt/index.ts b/server/routers/newt/index.ts index 700f3c37..e51ef93d 100644 --- a/server/routers/newt/index.ts +++ b/server/routers/newt/index.ts @@ -2,4 +2,5 @@ export * from "./createNewt"; export * from "./getNewtToken"; export * from "./handleNewtRegisterMessage"; export * from "./handleReceiveBandwidthMessage"; -export * from "./handleGetConfigMessage"; \ No newline at end of file +export * from "./handleGetConfigMessage"; +export * from "./handleSocketMessages"; diff --git a/server/routers/newt/targets.ts b/server/routers/newt/targets.ts index f2f5dc45..d3c541a6 100644 --- a/server/routers/newt/targets.ts +++ b/server/routers/newt/targets.ts @@ -1,4 +1,4 @@ -import { Target } from "@server/db/schemas"; +import { Target } from "@server/db"; import { sendToClient } from "../ws"; export function addTargets( diff --git a/server/routers/org/checkId.ts b/server/routers/org/checkId.ts index 40a347aa..c5d00002 100644 --- a/server/routers/org/checkId.ts +++ b/server/routers/org/checkId.ts @@ -1,7 +1,7 @@ import { Request, Response, NextFunction } from "express"; import { z } from "zod"; import { db } from "@server/db"; -import { orgs } from "@server/db/schemas"; +import { orgs } from "@server/db"; import { eq } from "drizzle-orm"; import response from "@server/lib/response"; import HttpCode from "@server/types/HttpCode"; diff --git a/server/routers/org/createOrg.ts b/server/routers/org/createOrg.ts index 576a46fa..98b4d592 100644 --- a/server/routers/org/createOrg.ts +++ b/server/routers/org/createOrg.ts @@ -12,13 +12,13 @@ import { roleActions, roles, userOrgs, - users -} from "@server/db/schemas"; + users, + actions +} from "@server/db"; import response from "@server/lib/response"; import HttpCode from "@server/types/HttpCode"; import createHttpError from "http-errors"; import logger from "@server/logger"; -import { createAdminRole } from "@server/setup/ensureActions"; import config from "@server/lib/config"; import { fromError } from "zod-validation-error"; import { defaultRoleAllowedActions } from "../role"; @@ -159,14 +159,40 @@ export async function createOrg( org = newOrg[0]; - const roleId = await createAdminRole(newOrg[0].orgId); + // Create admin role within the same transaction + const [insertedRole] = await trx + .insert(roles) + .values({ + orgId: newOrg[0].orgId, + isAdmin: true, + name: "Admin", + description: "Admin role with the most permissions" + }) + .returning({ roleId: roles.roleId }); - if (!roleId) { + if (!insertedRole || !insertedRole.roleId) { error = "Failed to create Admin role"; trx.rollback(); return; } + const roleId = insertedRole.roleId; + + // Get all actions and create role actions + const actionIds = await trx.select().from(actions).execute(); + + if (actionIds.length > 0) { + await trx + .insert(roleActions) + .values( + actionIds.map((action) => ({ + roleId, + actionId: action.actionId, + orgId: newOrg[0].orgId + })) + ); + } + await trx.insert(orgDomains).values( allDomains.map((domain) => ({ orgId: newOrg[0].orgId, @@ -236,7 +262,7 @@ export async function createOrg( return next( createHttpError( HttpCode.INTERNAL_SERVER_ERROR, - "Failed to createo org" + "Failed to create org" ) ); } diff --git a/server/routers/org/deleteOrg.ts b/server/routers/org/deleteOrg.ts index 030588c5..5b2accce 100644 --- a/server/routers/org/deleteOrg.ts +++ b/server/routers/org/deleteOrg.ts @@ -7,7 +7,7 @@ import { orgs, sites, userActions -} from "@server/db/schemas"; +} from "@server/db"; import { eq } from "drizzle-orm"; import response from "@server/lib/response"; import HttpCode from "@server/types/HttpCode"; diff --git a/server/routers/org/getOrg.ts b/server/routers/org/getOrg.ts index c112ab7a..35c1a5f7 100644 --- a/server/routers/org/getOrg.ts +++ b/server/routers/org/getOrg.ts @@ -1,7 +1,7 @@ import { Request, Response, NextFunction } from "express"; import { z } from "zod"; import { db } from "@server/db"; -import { Org, orgs } from "@server/db/schemas"; +import { Org, orgs } from "@server/db"; import { eq } from "drizzle-orm"; import response from "@server/lib/response"; import HttpCode from "@server/types/HttpCode"; diff --git a/server/routers/org/getOrgOverview.ts b/server/routers/org/getOrgOverview.ts index dcde292d..67a14464 100644 --- a/server/routers/org/getOrgOverview.ts +++ b/server/routers/org/getOrgOverview.ts @@ -10,7 +10,7 @@ import { userResources, users, userSites -} from "@server/db/schemas"; +} from "@server/db"; import { and, count, eq, inArray } from "drizzle-orm"; import response from "@server/lib/response"; import HttpCode from "@server/types/HttpCode"; diff --git a/server/routers/org/listOrgs.ts b/server/routers/org/listOrgs.ts index 27114104..07705e48 100644 --- a/server/routers/org/listOrgs.ts +++ b/server/routers/org/listOrgs.ts @@ -1,7 +1,7 @@ import { Request, Response, NextFunction } from "express"; import { z } from "zod"; import { db } from "@server/db"; -import { Org, orgs, userOrgs } from "@server/db/schemas"; +import { Org, orgs, userOrgs } from "@server/db"; import response from "@server/lib/response"; import HttpCode from "@server/types/HttpCode"; import createHttpError from "http-errors"; diff --git a/server/routers/org/listUserOrgs.ts b/server/routers/org/listUserOrgs.ts index fa33d2cb..694a4fb2 100644 --- a/server/routers/org/listUserOrgs.ts +++ b/server/routers/org/listUserOrgs.ts @@ -1,7 +1,7 @@ import { Request, Response, NextFunction } from "express"; import { z } from "zod"; import { db } from "@server/db"; -import { Org, orgs, userOrgs } from "@server/db/schemas"; +import { Org, orgs, userOrgs } from "@server/db"; import response from "@server/lib/response"; import HttpCode from "@server/types/HttpCode"; import createHttpError from "http-errors"; diff --git a/server/routers/org/updateOrg.ts b/server/routers/org/updateOrg.ts index 0f0aa89a..06c92fad 100644 --- a/server/routers/org/updateOrg.ts +++ b/server/routers/org/updateOrg.ts @@ -1,7 +1,7 @@ import { Request, Response, NextFunction } from "express"; import { z } from "zod"; import { db } from "@server/db"; -import { orgs } from "@server/db/schemas"; +import { orgs } from "@server/db"; import { eq } from "drizzle-orm"; import response from "@server/lib/response"; import HttpCode from "@server/types/HttpCode"; diff --git a/server/routers/resource/authWithAccessToken.ts b/server/routers/resource/authWithAccessToken.ts index 961b2d8a..2d7fdf93 100644 --- a/server/routers/resource/authWithAccessToken.ts +++ b/server/routers/resource/authWithAccessToken.ts @@ -1,6 +1,6 @@ import { generateSessionToken } from "@server/auth/sessions/app"; -import db from "@server/db"; -import { Resource, resources } from "@server/db/schemas"; +import { db } from "@server/db"; +import { Resource, resources } from "@server/db"; import HttpCode from "@server/types/HttpCode"; import response from "@server/lib/response"; import { eq } from "drizzle-orm"; diff --git a/server/routers/resource/authWithPassword.ts b/server/routers/resource/authWithPassword.ts index 602ddccd..652c4e86 100644 --- a/server/routers/resource/authWithPassword.ts +++ b/server/routers/resource/authWithPassword.ts @@ -1,7 +1,7 @@ import { verify } from "@node-rs/argon2"; import { generateSessionToken } from "@server/auth/sessions/app"; -import db from "@server/db"; -import { orgs, resourcePassword, resources } from "@server/db/schemas"; +import { db } from "@server/db"; +import { orgs, resourcePassword, resources } from "@server/db"; import HttpCode from "@server/types/HttpCode"; import response from "@server/lib/response"; import { eq } from "drizzle-orm"; diff --git a/server/routers/resource/authWithPincode.ts b/server/routers/resource/authWithPincode.ts index 21640942..d8733c18 100644 --- a/server/routers/resource/authWithPincode.ts +++ b/server/routers/resource/authWithPincode.ts @@ -1,6 +1,6 @@ import { generateSessionToken } from "@server/auth/sessions/app"; -import db from "@server/db"; -import { orgs, resourcePincode, resources } from "@server/db/schemas"; +import { db } from "@server/db"; +import { orgs, resourcePincode, resources } from "@server/db"; import HttpCode from "@server/types/HttpCode"; import response from "@server/lib/response"; import { eq } from "drizzle-orm"; diff --git a/server/routers/resource/authWithWhitelist.ts b/server/routers/resource/authWithWhitelist.ts index 01c9909c..ba0d36d3 100644 --- a/server/routers/resource/authWithWhitelist.ts +++ b/server/routers/resource/authWithWhitelist.ts @@ -1,11 +1,11 @@ import { generateSessionToken } from "@server/auth/sessions/app"; -import db from "@server/db"; +import { db } from "@server/db"; import { orgs, resourceOtp, resources, resourceWhitelist -} from "@server/db/schemas"; +} from "@server/db"; import HttpCode from "@server/types/HttpCode"; import response from "@server/lib/response"; import { eq, and } from "drizzle-orm"; diff --git a/server/routers/resource/createResource.ts b/server/routers/resource/createResource.ts index e899530b..ba115f71 100644 --- a/server/routers/resource/createResource.ts +++ b/server/routers/resource/createResource.ts @@ -10,7 +10,7 @@ import { roleResources, roles, userResources -} from "@server/db/schemas"; +} from "@server/db"; import response from "@server/lib/response"; import HttpCode from "@server/types/HttpCode"; import createHttpError from "http-errors"; diff --git a/server/routers/resource/createResourceRule.ts b/server/routers/resource/createResourceRule.ts index b52713d1..6651eee2 100644 --- a/server/routers/resource/createResourceRule.ts +++ b/server/routers/resource/createResourceRule.ts @@ -1,7 +1,7 @@ import { Request, Response, NextFunction } from "express"; import { z } from "zod"; import { db } from "@server/db"; -import { resourceRules, resources } from "@server/db/schemas"; +import { resourceRules, resources } from "@server/db"; import { eq } from "drizzle-orm"; import response from "@server/lib/response"; import HttpCode from "@server/types/HttpCode"; diff --git a/server/routers/resource/deleteResource.ts b/server/routers/resource/deleteResource.ts index 8b58f688..bb9a6f32 100644 --- a/server/routers/resource/deleteResource.ts +++ b/server/routers/resource/deleteResource.ts @@ -1,7 +1,7 @@ import { Request, Response, NextFunction } from "express"; import { z } from "zod"; import { db } from "@server/db"; -import { newts, resources, sites, targets } from "@server/db/schemas"; +import { newts, resources, sites, targets } from "@server/db"; import { eq } from "drizzle-orm"; import response from "@server/lib/response"; import HttpCode from "@server/types/HttpCode"; diff --git a/server/routers/resource/deleteResourceRule.ts b/server/routers/resource/deleteResourceRule.ts index 573825b0..6b404651 100644 --- a/server/routers/resource/deleteResourceRule.ts +++ b/server/routers/resource/deleteResourceRule.ts @@ -1,7 +1,7 @@ import { Request, Response, NextFunction } from "express"; import { z } from "zod"; import { db } from "@server/db"; -import { resourceRules, resources } from "@server/db/schemas"; +import { resourceRules, resources } from "@server/db"; import { eq } from "drizzle-orm"; import response from "@server/lib/response"; import HttpCode from "@server/types/HttpCode"; diff --git a/server/routers/resource/getExchangeToken.ts b/server/routers/resource/getExchangeToken.ts index f9579433..ba01f63b 100644 --- a/server/routers/resource/getExchangeToken.ts +++ b/server/routers/resource/getExchangeToken.ts @@ -1,7 +1,7 @@ import { Request, Response, NextFunction } from "express"; import { z } from "zod"; import { db } from "@server/db"; -import { resources } from "@server/db/schemas"; +import { resources } from "@server/db"; import { eq } from "drizzle-orm"; import { createResourceSession } from "@server/auth/sessions/resource"; import HttpCode from "@server/types/HttpCode"; diff --git a/server/routers/resource/getResource.ts b/server/routers/resource/getResource.ts index ae3c87d3..0cffb1cf 100644 --- a/server/routers/resource/getResource.ts +++ b/server/routers/resource/getResource.ts @@ -1,7 +1,7 @@ import { Request, Response, NextFunction } from "express"; import { z } from "zod"; import { db } from "@server/db"; -import { Resource, resources, sites } from "@server/db/schemas"; +import { Resource, resources, sites } from "@server/db"; import { eq } from "drizzle-orm"; import response from "@server/lib/response"; import HttpCode from "@server/types/HttpCode"; diff --git a/server/routers/resource/getResourceAuthInfo.ts b/server/routers/resource/getResourceAuthInfo.ts index 5f74b637..64fade89 100644 --- a/server/routers/resource/getResourceAuthInfo.ts +++ b/server/routers/resource/getResourceAuthInfo.ts @@ -5,7 +5,7 @@ import { resourcePassword, resourcePincode, resources -} from "@server/db/schemas"; +} from "@server/db"; import { eq } from "drizzle-orm"; import response from "@server/lib/response"; import HttpCode from "@server/types/HttpCode"; diff --git a/server/routers/resource/getResourceWhitelist.ts b/server/routers/resource/getResourceWhitelist.ts index 321fd331..415cb714 100644 --- a/server/routers/resource/getResourceWhitelist.ts +++ b/server/routers/resource/getResourceWhitelist.ts @@ -1,7 +1,7 @@ import { Request, Response, NextFunction } from "express"; import { z } from "zod"; import { db } from "@server/db"; -import { resourceWhitelist, users } from "@server/db/schemas"; // Assuming these are the correct tables +import { resourceWhitelist, users } from "@server/db"; // Assuming these are the correct tables import { eq } from "drizzle-orm"; import response from "@server/lib/response"; import HttpCode from "@server/types/HttpCode"; diff --git a/server/routers/resource/listResourceRoles.ts b/server/routers/resource/listResourceRoles.ts index c173cacb..4676b01e 100644 --- a/server/routers/resource/listResourceRoles.ts +++ b/server/routers/resource/listResourceRoles.ts @@ -1,7 +1,7 @@ import { Request, Response, NextFunction } from "express"; import { z } from "zod"; import { db } from "@server/db"; -import { roleResources, roles } from "@server/db/schemas"; +import { roleResources, roles } from "@server/db"; import { eq } from "drizzle-orm"; import response from "@server/lib/response"; import HttpCode from "@server/types/HttpCode"; diff --git a/server/routers/resource/listResourceRules.ts b/server/routers/resource/listResourceRules.ts index f0a0d84c..ff96afea 100644 --- a/server/routers/resource/listResourceRules.ts +++ b/server/routers/resource/listResourceRules.ts @@ -1,5 +1,5 @@ import { db } from "@server/db"; -import { resourceRules, resources } from "@server/db/schemas"; +import { resourceRules, resources } from "@server/db"; import HttpCode from "@server/types/HttpCode"; import response from "@server/lib/response"; import { eq, sql } from "drizzle-orm"; diff --git a/server/routers/resource/listResourceUsers.ts b/server/routers/resource/listResourceUsers.ts index 4699ec8b..0d96ac0d 100644 --- a/server/routers/resource/listResourceUsers.ts +++ b/server/routers/resource/listResourceUsers.ts @@ -1,7 +1,7 @@ import { Request, Response, NextFunction } from "express"; import { z } from "zod"; import { db } from "@server/db"; -import { idp, userResources, users } from "@server/db/schemas"; // Assuming these are the correct tables +import { idp, userResources, users } from "@server/db"; // Assuming these are the correct tables import { eq } from "drizzle-orm"; import response from "@server/lib/response"; import HttpCode from "@server/types/HttpCode"; diff --git a/server/routers/resource/listResources.ts b/server/routers/resource/listResources.ts index 9af24740..6dc852e4 100644 --- a/server/routers/resource/listResources.ts +++ b/server/routers/resource/listResources.ts @@ -8,7 +8,7 @@ import { roleResources, resourcePassword, resourcePincode -} from "@server/db/schemas"; +} from "@server/db"; import response from "@server/lib/response"; import HttpCode from "@server/types/HttpCode"; import createHttpError from "http-errors"; diff --git a/server/routers/resource/setResourcePassword.ts b/server/routers/resource/setResourcePassword.ts index 29eb89cb..d1d4a655 100644 --- a/server/routers/resource/setResourcePassword.ts +++ b/server/routers/resource/setResourcePassword.ts @@ -1,7 +1,7 @@ import { Request, Response, NextFunction } from "express"; import { z } from "zod"; import { db } from "@server/db"; -import { resourcePassword } from "@server/db/schemas"; +import { resourcePassword } from "@server/db"; import { eq } from "drizzle-orm"; import HttpCode from "@server/types/HttpCode"; import createHttpError from "http-errors"; diff --git a/server/routers/resource/setResourcePincode.ts b/server/routers/resource/setResourcePincode.ts index 2a1b7c1f..d8553c8c 100644 --- a/server/routers/resource/setResourcePincode.ts +++ b/server/routers/resource/setResourcePincode.ts @@ -1,7 +1,7 @@ import { Request, Response, NextFunction } from "express"; import { z } from "zod"; import { db } from "@server/db"; -import { resourcePincode } from "@server/db/schemas"; +import { resourcePincode } from "@server/db"; import { eq } from "drizzle-orm"; import HttpCode from "@server/types/HttpCode"; import createHttpError from "http-errors"; diff --git a/server/routers/resource/setResourceRoles.ts b/server/routers/resource/setResourceRoles.ts index 0f0b3df2..01991763 100644 --- a/server/routers/resource/setResourceRoles.ts +++ b/server/routers/resource/setResourceRoles.ts @@ -1,7 +1,7 @@ import { Request, Response, NextFunction } from "express"; import { z } from "zod"; import { db } from "@server/db"; -import { apiKeys, roleResources, roles } from "@server/db/schemas"; +import { apiKeys, roleResources, roles } from "@server/db"; import response from "@server/lib/response"; import HttpCode from "@server/types/HttpCode"; import createHttpError from "http-errors"; diff --git a/server/routers/resource/setResourceUsers.ts b/server/routers/resource/setResourceUsers.ts index 3080ae45..152c0f88 100644 --- a/server/routers/resource/setResourceUsers.ts +++ b/server/routers/resource/setResourceUsers.ts @@ -1,7 +1,7 @@ import { Request, Response, NextFunction } from "express"; import { z } from "zod"; import { db } from "@server/db"; -import { userResources } from "@server/db/schemas"; +import { userResources } from "@server/db"; import response from "@server/lib/response"; import HttpCode from "@server/types/HttpCode"; import createHttpError from "http-errors"; diff --git a/server/routers/resource/setResourceWhitelist.ts b/server/routers/resource/setResourceWhitelist.ts index ceec816c..16c9150b 100644 --- a/server/routers/resource/setResourceWhitelist.ts +++ b/server/routers/resource/setResourceWhitelist.ts @@ -1,7 +1,7 @@ import { Request, Response, NextFunction } from "express"; import { z } from "zod"; import { db } from "@server/db"; -import { resources, resourceWhitelist } from "@server/db/schemas"; +import { resources, resourceWhitelist } from "@server/db"; import response from "@server/lib/response"; import HttpCode from "@server/types/HttpCode"; import createHttpError from "http-errors"; diff --git a/server/routers/resource/transferResource.ts b/server/routers/resource/transferResource.ts index 9b21abb2..e0fce278 100644 --- a/server/routers/resource/transferResource.ts +++ b/server/routers/resource/transferResource.ts @@ -1,7 +1,7 @@ import { Request, Response, NextFunction } from "express"; import { z } from "zod"; import { db } from "@server/db"; -import { newts, resources, sites, targets } from "@server/db/schemas"; +import { newts, resources, sites, targets } from "@server/db"; import { eq } from "drizzle-orm"; import response from "@server/lib/response"; import HttpCode from "@server/types/HttpCode"; diff --git a/server/routers/resource/updateResource.ts b/server/routers/resource/updateResource.ts index 9198bb8d..68e38a3e 100644 --- a/server/routers/resource/updateResource.ts +++ b/server/routers/resource/updateResource.ts @@ -8,7 +8,7 @@ import { orgs, Resource, resources -} from "@server/db/schemas"; +} from "@server/db"; import { eq, and } from "drizzle-orm"; import response from "@server/lib/response"; import HttpCode from "@server/types/HttpCode"; diff --git a/server/routers/resource/updateResourceRule.ts b/server/routers/resource/updateResourceRule.ts index 9a953500..449a92ef 100644 --- a/server/routers/resource/updateResourceRule.ts +++ b/server/routers/resource/updateResourceRule.ts @@ -1,7 +1,7 @@ import { Request, Response, NextFunction } from "express"; import { z } from "zod"; import { db } from "@server/db"; -import { resourceRules, resources } from "@server/db/schemas"; +import { resourceRules, resources } from "@server/db"; import { eq } from "drizzle-orm"; import response from "@server/lib/response"; import HttpCode from "@server/types/HttpCode"; diff --git a/server/routers/role/addRoleAction.ts b/server/routers/role/addRoleAction.ts index 9f364a55..62ab87b5 100644 --- a/server/routers/role/addRoleAction.ts +++ b/server/routers/role/addRoleAction.ts @@ -1,7 +1,7 @@ import { Request, Response, NextFunction } from "express"; import { z } from "zod"; import { db } from "@server/db"; -import { roleActions, roles } from "@server/db/schemas"; +import { roleActions, roles } from "@server/db"; import response from "@server/lib/response"; import HttpCode from "@server/types/HttpCode"; import createHttpError from "http-errors"; diff --git a/server/routers/role/addRoleSite.ts b/server/routers/role/addRoleSite.ts index 0db6ac4e..58da9879 100644 --- a/server/routers/role/addRoleSite.ts +++ b/server/routers/role/addRoleSite.ts @@ -1,7 +1,7 @@ import { Request, Response, NextFunction } from "express"; import { z } from "zod"; import { db } from "@server/db"; -import { resources, roleResources, roleSites } from "@server/db/schemas"; +import { resources, roleResources, roleSites } from "@server/db"; import response from "@server/lib/response"; import HttpCode from "@server/types/HttpCode"; import createHttpError from "http-errors"; diff --git a/server/routers/role/createRole.ts b/server/routers/role/createRole.ts index 3bc363f6..f66c95e2 100644 --- a/server/routers/role/createRole.ts +++ b/server/routers/role/createRole.ts @@ -1,7 +1,7 @@ import { Request, Response, NextFunction } from "express"; import { z } from "zod"; import { db } from "@server/db"; -import { orgs, Role, roleActions, roles } from "@server/db/schemas"; +import { orgs, Role, roleActions, roles } from "@server/db"; import response from "@server/lib/response"; import HttpCode from "@server/types/HttpCode"; import createHttpError from "http-errors"; diff --git a/server/routers/role/deleteRole.ts b/server/routers/role/deleteRole.ts index a89428d5..6806386e 100644 --- a/server/routers/role/deleteRole.ts +++ b/server/routers/role/deleteRole.ts @@ -1,7 +1,7 @@ import { Request, Response, NextFunction } from "express"; import { z } from "zod"; import { db } from "@server/db"; -import { roles, userOrgs } from "@server/db/schemas"; +import { roles, userOrgs } from "@server/db"; import { eq } from "drizzle-orm"; import response from "@server/lib/response"; import HttpCode from "@server/types/HttpCode"; diff --git a/server/routers/role/getRole.ts b/server/routers/role/getRole.ts index 20f93bf4..66dbb68f 100644 --- a/server/routers/role/getRole.ts +++ b/server/routers/role/getRole.ts @@ -1,13 +1,14 @@ import { Request, Response, NextFunction } from "express"; import { z } from "zod"; import { db } from "@server/db"; -import { roles } from "@server/db/schemas"; +import { roles } from "@server/db"; import { eq } from "drizzle-orm"; import response from "@server/lib/response"; import HttpCode from "@server/types/HttpCode"; import createHttpError from "http-errors"; import logger from "@server/logger"; import { fromError } from "zod-validation-error"; +import { OpenAPITags, registry } from "@server/openApi"; const getRoleSchema = z .object({ @@ -15,6 +16,17 @@ const getRoleSchema = z }) .strict(); +registry.registerPath({ + method: "get", + path: "/role/{roleId}", + description: "Get a role.", + tags: [OpenAPITags.Role], + request: { + params: getRoleSchema + }, + responses: {} +}); + export async function getRole( req: Request, res: Response, diff --git a/server/routers/role/listRoleActions.ts b/server/routers/role/listRoleActions.ts index d4637092..cdf1391b 100644 --- a/server/routers/role/listRoleActions.ts +++ b/server/routers/role/listRoleActions.ts @@ -1,7 +1,7 @@ import { Request, Response, NextFunction } from "express"; import { z } from "zod"; import { db } from "@server/db"; -import { roleActions, actions } from "@server/db/schemas"; +import { roleActions, actions } from "@server/db"; import { eq } from "drizzle-orm"; import response from "@server/lib/response"; import HttpCode from "@server/types/HttpCode"; diff --git a/server/routers/role/listRoleResources.ts b/server/routers/role/listRoleResources.ts index 7239f6f7..ba254f1d 100644 --- a/server/routers/role/listRoleResources.ts +++ b/server/routers/role/listRoleResources.ts @@ -1,7 +1,7 @@ import { Request, Response, NextFunction } from "express"; import { z } from "zod"; import { db } from "@server/db"; -import { roleResources, resources } from "@server/db/schemas"; +import { roleResources, resources } from "@server/db"; import { eq } from "drizzle-orm"; import response from "@server/lib/response"; import HttpCode from "@server/types/HttpCode"; diff --git a/server/routers/role/listRoleSites.ts b/server/routers/role/listRoleSites.ts index f6594545..72f49e3a 100644 --- a/server/routers/role/listRoleSites.ts +++ b/server/routers/role/listRoleSites.ts @@ -1,7 +1,7 @@ import { Request, Response, NextFunction } from "express"; import { z } from "zod"; import { db } from "@server/db"; -import { roleSites, sites } from "@server/db/schemas"; +import { roleSites, sites } from "@server/db"; import { eq } from "drizzle-orm"; import response from "@server/lib/response"; import HttpCode from "@server/types/HttpCode"; diff --git a/server/routers/role/listRoles.ts b/server/routers/role/listRoles.ts index 73834b53..7e838956 100644 --- a/server/routers/role/listRoles.ts +++ b/server/routers/role/listRoles.ts @@ -1,7 +1,7 @@ import { Request, Response, NextFunction } from "express"; import { z } from "zod"; import { db } from "@server/db"; -import { roles, orgs } from "@server/db/schemas"; +import { roles, orgs } from "@server/db"; import response from "@server/lib/response"; import HttpCode from "@server/types/HttpCode"; import createHttpError from "http-errors"; diff --git a/server/routers/role/removeRoleAction.ts b/server/routers/role/removeRoleAction.ts index 72d9be53..e643ae04 100644 --- a/server/routers/role/removeRoleAction.ts +++ b/server/routers/role/removeRoleAction.ts @@ -1,7 +1,7 @@ import { Request, Response, NextFunction } from "express"; import { z } from "zod"; import { db } from "@server/db"; -import { roleActions } from "@server/db/schemas"; +import { roleActions } from "@server/db"; import { and, eq } from "drizzle-orm"; import response from "@server/lib/response"; import HttpCode from "@server/types/HttpCode"; diff --git a/server/routers/role/removeRoleResource.ts b/server/routers/role/removeRoleResource.ts index ca068e05..4068b0bd 100644 --- a/server/routers/role/removeRoleResource.ts +++ b/server/routers/role/removeRoleResource.ts @@ -1,7 +1,7 @@ import { Request, Response, NextFunction } from "express"; import { z } from "zod"; import { db } from "@server/db"; -import { roleResources } from "@server/db/schemas"; +import { roleResources } from "@server/db"; import { and, eq } from "drizzle-orm"; import response from "@server/lib/response"; import HttpCode from "@server/types/HttpCode"; diff --git a/server/routers/role/removeRoleSite.ts b/server/routers/role/removeRoleSite.ts index a99adf5c..c88e4711 100644 --- a/server/routers/role/removeRoleSite.ts +++ b/server/routers/role/removeRoleSite.ts @@ -1,7 +1,7 @@ import { Request, Response, NextFunction } from "express"; import { z } from "zod"; import { db } from "@server/db"; -import { resources, roleResources, roleSites } from "@server/db/schemas"; +import { resources, roleResources, roleSites } from "@server/db"; import { and, eq } from "drizzle-orm"; import response from "@server/lib/response"; import HttpCode from "@server/types/HttpCode"; diff --git a/server/routers/role/updateRole.ts b/server/routers/role/updateRole.ts index bf029eb1..793be6eb 100644 --- a/server/routers/role/updateRole.ts +++ b/server/routers/role/updateRole.ts @@ -1,7 +1,7 @@ import { Request, Response, NextFunction } from "express"; import { z } from "zod"; import { db } from "@server/db"; -import { roles } from "@server/db/schemas"; +import { roles } from "@server/db"; import { eq } from "drizzle-orm"; import response from "@server/lib/response"; import HttpCode from "@server/types/HttpCode"; diff --git a/server/routers/site/createSite.ts b/server/routers/site/createSite.ts index 1e673ee5..2a907e1c 100644 --- a/server/routers/site/createSite.ts +++ b/server/routers/site/createSite.ts @@ -1,16 +1,16 @@ import { Request, Response, NextFunction } from "express"; import { z } from "zod"; import { db } from "@server/db"; -import { roles, userSites, sites, roleSites, Site, orgs } from "@server/db/schemas"; +import { roles, userSites, sites, roleSites, Site, orgs } from "@server/db"; import response from "@server/lib/response"; import HttpCode from "@server/types/HttpCode"; import createHttpError from "http-errors"; import logger from "@server/logger"; import { eq, and } from "drizzle-orm"; -import { getUniqueSiteName } from "@server/db/names"; +import { getUniqueSiteName } from "../../db/names"; import { addPeer } from "../gerbil/peers"; import { fromError } from "zod-validation-error"; -import { newts } from "@server/db/schemas"; +import { newts } from "@server/db"; import moment from "moment"; import { OpenAPITags, registry } from "@server/openApi"; import { hashPassword } from "@server/auth/password"; @@ -199,6 +199,7 @@ export async function createSite( address: updatedAddress || null, subnet, type, + dockerSocketEnabled: type == "newt", ...(pubKey && type == "wireguard" && { pubKey }) }) .returning(); @@ -213,6 +214,7 @@ export async function createSite( niceId, address: updatedAddress || null, type, + dockerSocketEnabled: type == "newt", subnet: "0.0.0.0/0" }) .returning(); diff --git a/server/routers/site/deleteSite.ts b/server/routers/site/deleteSite.ts index 667ab5c8..1554ad2b 100644 --- a/server/routers/site/deleteSite.ts +++ b/server/routers/site/deleteSite.ts @@ -1,7 +1,7 @@ import { Request, Response, NextFunction } from "express"; import { z } from "zod"; import { db } from "@server/db"; -import { newts, newtSessions, sites } from "@server/db/schemas"; +import { newts, newtSessions, sites } from "@server/db"; import { eq } from "drizzle-orm"; import response from "@server/lib/response"; import HttpCode from "@server/types/HttpCode"; diff --git a/server/routers/site/getSite.ts b/server/routers/site/getSite.ts index 4baa85cc..a9785fa4 100644 --- a/server/routers/site/getSite.ts +++ b/server/routers/site/getSite.ts @@ -1,7 +1,7 @@ import { Request, Response, NextFunction } from "express"; import { z } from "zod"; import { db } from "@server/db"; -import { sites } from "@server/db/schemas"; +import { sites } from "@server/db"; import { eq, and } from "drizzle-orm"; import response from "@server/lib/response"; import HttpCode from "@server/types/HttpCode"; diff --git a/server/routers/site/index.ts b/server/routers/site/index.ts index 63505991..3edf67c1 100644 --- a/server/routers/site/index.ts +++ b/server/routers/site/index.ts @@ -3,5 +3,6 @@ export * from "./createSite"; export * from "./deleteSite"; export * from "./updateSite"; export * from "./listSites"; -export * from "./listSiteRoles" -export * from "./pickSiteDefaults"; \ No newline at end of file +export * from "./listSiteRoles"; +export * from "./pickSiteDefaults"; +export * from "./socketIntegration"; diff --git a/server/routers/site/listSiteRoles.ts b/server/routers/site/listSiteRoles.ts index 13c8dd41..009e0907 100644 --- a/server/routers/site/listSiteRoles.ts +++ b/server/routers/site/listSiteRoles.ts @@ -1,7 +1,7 @@ import { Request, Response, NextFunction } from "express"; import { z } from "zod"; import { db } from "@server/db"; -import { roleSites, roles } from "@server/db/schemas"; +import { roleSites, roles } from "@server/db"; import { eq } from "drizzle-orm"; import response from "@server/lib/response"; import HttpCode from "@server/types/HttpCode"; diff --git a/server/routers/site/listSites.ts b/server/routers/site/listSites.ts index 829f8375..ddbe7d43 100644 --- a/server/routers/site/listSites.ts +++ b/server/routers/site/listSites.ts @@ -1,5 +1,5 @@ import { db } from "@server/db"; -import { orgs, roleSites, sites, userSites } from "@server/db/schemas"; +import { orgs, roleSites, sites, userSites } from "@server/db"; import logger from "@server/logger"; import HttpCode from "@server/types/HttpCode"; import response from "@server/lib/response"; diff --git a/server/routers/site/pickSiteDefaults.ts b/server/routers/site/pickSiteDefaults.ts index a8cf3a39..68107d95 100644 --- a/server/routers/site/pickSiteDefaults.ts +++ b/server/routers/site/pickSiteDefaults.ts @@ -1,6 +1,6 @@ import { Request, Response, NextFunction } from "express"; import { db } from "@server/db"; -import { exitNodes, sites } from "@server/db/schemas"; +import { exitNodes, sites } from "@server/db"; import { eq } from "drizzle-orm"; import response from "@server/lib/response"; import HttpCode from "@server/types/HttpCode"; diff --git a/server/routers/site/socketIntegration.ts b/server/routers/site/socketIntegration.ts new file mode 100644 index 00000000..34084a0a --- /dev/null +++ b/server/routers/site/socketIntegration.ts @@ -0,0 +1,283 @@ +import { db } from "@server/db"; +import { newts, sites } from "@server/db"; +import logger from "@server/logger"; +import HttpCode from "@server/types/HttpCode"; +import response from "@server/lib/response"; +import { eq } from "drizzle-orm"; +import { NextFunction, Request, Response } from "express"; +import createHttpError from "http-errors"; +import { z } from "zod"; +import { fromError } from "zod-validation-error"; +import stoi from "@server/lib/stoi"; +import { sendToClient } from "../ws"; +import { + fetchContainers, + dockerSocketCache, + dockerSocket +} from "../newt/dockerSocket"; + +export interface ContainerNetwork { + networkId: string; + endpointId: string; + gateway?: string; + ipAddress?: string; + ipPrefixLen?: number; + macAddress?: string; + aliases?: string[]; + dnsNames?: string[]; +} + +export interface ContainerPort { + privatePort: number; + publicPort?: number; + type: "tcp" | "udp"; + ip?: string; +} + +export interface Container { + id: string; + name: string; + image: string; + state: "running" | "exited" | "paused" | "created"; + status: string; + ports?: ContainerPort[]; + labels: Record; + created: number; + networks: Record; +} + +const siteIdParamsSchema = z + .object({ + siteId: z.string().transform(stoi).pipe(z.number().int().positive()) + }) + .strict(); + +const DockerStatusSchema = z + .object({ + isAvailable: z.boolean(), + socketPath: z.string().optional() + }) + .strict(); + +function validateSiteIdParams(params: any) { + const parsedParams = siteIdParamsSchema.safeParse(params); + if (!parsedParams.success) { + throw createHttpError( + HttpCode.BAD_REQUEST, + fromError(parsedParams.error) + ); + } + return parsedParams.data; +} + +async function getSiteAndValidateNewt(siteId: number) { + const [site] = await db + .select() + .from(sites) + .where(eq(sites.siteId, siteId)) + .limit(1); + + if (!site) { + throw createHttpError(HttpCode.NOT_FOUND, "Site not found"); + } + + if (site.type !== "newt") { + throw createHttpError( + HttpCode.BAD_REQUEST, + "This endpoint is only for Newt sites" + ); + } + + return site; +} + +async function getNewtBySiteId(siteId: number) { + const [newt] = await db + .select() + .from(newts) + .where(eq(newts.siteId, siteId)) + .limit(1); + + if (!newt) { + throw createHttpError(HttpCode.NOT_FOUND, "Newt not found for site"); + } + + return newt; +} + +async function getSiteAndNewt(siteId: number) { + const site = await getSiteAndValidateNewt(siteId); + const newt = await getNewtBySiteId(siteId); + return { site, newt }; +} + +function asyncHandler( + operation: (siteId: number) => Promise, + successMessage: string +) { + return async ( + req: Request, + res: Response, + next: NextFunction + ): Promise => { + try { + const { siteId } = validateSiteIdParams(req.params); + const result = await operation(siteId); + + return response(res, { + data: result, + success: true, + error: false, + message: successMessage, + status: HttpCode.OK + }); + } catch (error) { + if (createHttpError.isHttpError(error)) { + return next(error); + } + logger.error(error); + return next( + createHttpError( + HttpCode.INTERNAL_SERVER_ERROR, + "An error occurred" + ) + ); + } + }; +} + +// Core business logic functions +async function triggerFetch(siteId: number) { + const { newt } = await getSiteAndNewt(siteId); + + logger.info( + `Triggering fetch containers for site ${siteId} with Newt ${newt.newtId}` + ); + fetchContainers(newt.newtId); + + // clear the cache for this Newt ID so that the site has to keep asking for the containers + // this is to ensure that the site always gets the latest data + dockerSocketCache.del(`${newt.newtId}:dockerContainers`); + + return { siteId, newtId: newt.newtId }; +} + +async function queryContainers(siteId: number) { + const { newt } = await getSiteAndNewt(siteId); + + const result = dockerSocketCache.get( + `${newt.newtId}:dockerContainers` + ) as Container[]; + if (!result) { + throw createHttpError( + HttpCode.TOO_EARLY, + "Nothing found yet. Perhaps the fetch is still in progress? Wait a bit and try again." + ); + } + + return result; +} + +async function isDockerAvailable(siteId: number): Promise { + const { newt } = await getSiteAndNewt(siteId); + + const key = `${newt.newtId}:isAvailable`; + const isAvailable = dockerSocketCache.get(key); + + return !!isAvailable; +} + +async function getDockerStatus( + siteId: number +): Promise> { + const { newt } = await getSiteAndNewt(siteId); + + const keys = ["isAvailable", "socketPath"]; + const mappedKeys = keys.map((x) => `${newt.newtId}:${x}`); + + const result = { + isAvailable: dockerSocketCache.get(mappedKeys[0]) as boolean, + socketPath: dockerSocketCache.get(mappedKeys[1]) as string | undefined + }; + + return result; +} + +async function checkSocket( + siteId: number +): Promise<{ siteId: number; newtId: string }> { + const { newt } = await getSiteAndNewt(siteId); + + logger.info( + `Checking Docker socket for site ${siteId} with Newt ${newt.newtId}` + ); + + // Trigger the Docker socket check + dockerSocket(newt.newtId); + return { siteId, newtId: newt.newtId }; +} + +// Export types +export type GetDockerStatusResponse = NonNullable< + Awaited> +>; + +export type ListContainersResponse = Awaited< + ReturnType +>; + +export type TriggerFetchResponse = Awaited>; + +// Route handlers +export const triggerFetchContainers = asyncHandler( + triggerFetch, + "Fetch containers triggered successfully" +); + +export const listContainers = asyncHandler( + queryContainers, + "Containers retrieved successfully" +); + +export const dockerOnline = asyncHandler(async (siteId: number) => { + const isAvailable = await isDockerAvailable(siteId); + return { isAvailable }; +}, "Docker availability checked successfully"); + +export const dockerStatus = asyncHandler( + getDockerStatus, + "Docker status retrieved successfully" +); + +export async function checkDockerSocket( + req: Request, + res: Response, + next: NextFunction +): Promise { + try { + const { siteId } = validateSiteIdParams(req.params); + const result = await checkSocket(siteId); + + // Notify the Newt client about the Docker socket check + sendToClient(result.newtId, { + type: "newt/socket/check", + data: {} + }); + + return response(res, { + data: result, + success: true, + error: false, + message: "Docker socket checked successfully", + status: HttpCode.OK + }); + } catch (error) { + if (createHttpError.isHttpError(error)) { + return next(error); + } + logger.error(error); + return next( + createHttpError(HttpCode.INTERNAL_SERVER_ERROR, "An error occurred") + ); + } +} diff --git a/server/routers/site/updateSite.ts b/server/routers/site/updateSite.ts index 43cd848a..a5a5f7c0 100644 --- a/server/routers/site/updateSite.ts +++ b/server/routers/site/updateSite.ts @@ -1,7 +1,7 @@ import { Request, Response, NextFunction } from "express"; import { z } from "zod"; import { db } from "@server/db"; -import { sites } from "@server/db/schemas"; +import { sites } from "@server/db"; import { eq } from "drizzle-orm"; import response from "@server/lib/response"; import HttpCode from "@server/types/HttpCode"; @@ -19,6 +19,7 @@ const updateSiteParamsSchema = z const updateSiteBodySchema = z .object({ name: z.string().min(1).max(255).optional(), + dockerSocketEnabled: z.boolean().optional(), // subdomain: z // .string() // .min(1) diff --git a/server/routers/supporterKey/isSupporterKeyVisible.ts b/server/routers/supporterKey/isSupporterKeyVisible.ts index 15e313de..94d0815b 100644 --- a/server/routers/supporterKey/isSupporterKeyVisible.ts +++ b/server/routers/supporterKey/isSupporterKeyVisible.ts @@ -4,9 +4,9 @@ import createHttpError from "http-errors"; import logger from "@server/logger"; import { response as sendResponse } from "@server/lib"; import config from "@server/lib/config"; -import db from "@server/db"; +import { db } from "@server/db"; import { count } from "drizzle-orm"; -import { users } from "@server/db/schemas"; +import { users } from "@server/db"; import license from "@server/license/license"; export type IsSupporterKeyVisibleResponse = { diff --git a/server/routers/supporterKey/validateSupporterKey.ts b/server/routers/supporterKey/validateSupporterKey.ts index fadcdc39..a365030a 100644 --- a/server/routers/supporterKey/validateSupporterKey.ts +++ b/server/routers/supporterKey/validateSupporterKey.ts @@ -6,8 +6,8 @@ import logger from "@server/logger"; import { fromError } from "zod-validation-error"; import { response as sendResponse } from "@server/lib"; import { suppressDeprecationWarnings } from "moment"; -import { supporterKey } from "@server/db/schemas"; -import db from "@server/db"; +import { supporterKey } from "@server/db"; +import { db } from "@server/db"; import { eq } from "drizzle-orm"; import config from "@server/lib/config"; diff --git a/server/routers/target/createTarget.ts b/server/routers/target/createTarget.ts index 810ee409..52bd0417 100644 --- a/server/routers/target/createTarget.ts +++ b/server/routers/target/createTarget.ts @@ -1,7 +1,7 @@ import { Request, Response, NextFunction } from "express"; import { z } from "zod"; import { db } from "@server/db"; -import { newts, resources, sites, Target, targets } from "@server/db/schemas"; +import { newts, resources, sites, Target, targets } from "@server/db"; import response from "@server/lib/response"; import HttpCode from "@server/types/HttpCode"; import createHttpError from "http-errors"; diff --git a/server/routers/target/deleteTarget.ts b/server/routers/target/deleteTarget.ts index 979740dd..17a9c5ee 100644 --- a/server/routers/target/deleteTarget.ts +++ b/server/routers/target/deleteTarget.ts @@ -1,7 +1,7 @@ import { Request, Response, NextFunction } from "express"; import { z } from "zod"; import { db } from "@server/db"; -import { newts, resources, sites, targets } from "@server/db/schemas"; +import { newts, resources, sites, targets } from "@server/db"; import { eq } from "drizzle-orm"; import response from "@server/lib/response"; import HttpCode from "@server/types/HttpCode"; diff --git a/server/routers/target/getTarget.ts b/server/routers/target/getTarget.ts index a268629c..071ec8a6 100644 --- a/server/routers/target/getTarget.ts +++ b/server/routers/target/getTarget.ts @@ -1,7 +1,7 @@ import { Request, Response, NextFunction } from "express"; import { z } from "zod"; import { db } from "@server/db"; -import { targets } from "@server/db/schemas"; +import { targets } from "@server/db"; import { eq } from "drizzle-orm"; import response from "@server/lib/response"; import HttpCode from "@server/types/HttpCode"; diff --git a/server/routers/target/helpers.ts b/server/routers/target/helpers.ts index 8fc8797f..5b65feb7 100644 --- a/server/routers/target/helpers.ts +++ b/server/routers/target/helpers.ts @@ -1,5 +1,5 @@ import { db } from "@server/db"; -import { resources, targets } from "@server/db/schemas"; +import { resources, targets } from "@server/db"; import { eq } from "drizzle-orm"; let currentBannedPorts: number[] = []; @@ -8,10 +8,10 @@ export async function pickPort(siteId: number): Promise<{ internalPort: number; targetIps: string[]; }> { - // Fetch resources for this site - const resourcesRes = await db.query.resources.findMany({ - where: eq(resources.siteId, siteId) - }); + const resourcesRes = await db + .select() + .from(resources) + .where(eq(resources.siteId, siteId)); // TODO: is this all inefficient? // Fetch targets for all resources of this site @@ -19,9 +19,10 @@ export async function pickPort(siteId: number): Promise<{ let targetInternalPorts: number[] = []; await Promise.all( resourcesRes.map(async (resource) => { - const targetsRes = await db.query.targets.findMany({ - where: eq(targets.resourceId, resource.resourceId) - }); + const targetsRes = await db + .select() + .from(targets) + .where(eq(targets.resourceId, resource.resourceId)); targetsRes.forEach((target) => { targetIps.push(`${target.ip}/32`); if (target.internalPort) { @@ -49,16 +50,19 @@ export async function pickPort(siteId: number): Promise<{ export async function getAllowedIps(siteId: number) { // TODO: is this all inefficient? - const resourcesRes = await db.query.resources.findMany({ - where: eq(resources.siteId, siteId) - }); + + const resourcesRes = await db + .select() + .from(resources) + .where(eq(resources.siteId, siteId)); // Fetch targets for all resources of this site const targetIps = await Promise.all( resourcesRes.map(async (resource) => { - const targetsRes = await db.query.targets.findMany({ - where: eq(targets.resourceId, resource.resourceId) - }); + const targetsRes = await db + .select() + .from(targets) + .where(eq(targets.resourceId, resource.resourceId)); return targetsRes.map((target) => `${target.ip}/32`); }) ); diff --git a/server/routers/target/listTargets.ts b/server/routers/target/listTargets.ts index 3d4c573b..86599fa1 100644 --- a/server/routers/target/listTargets.ts +++ b/server/routers/target/listTargets.ts @@ -1,5 +1,5 @@ import { db } from "@server/db"; -import { targets } from "@server/db/schemas"; +import { targets } from "@server/db"; import HttpCode from "@server/types/HttpCode"; import response from "@server/lib/response"; import { eq, sql } from "drizzle-orm"; diff --git a/server/routers/target/updateTarget.ts b/server/routers/target/updateTarget.ts index 284b1a31..0138520b 100644 --- a/server/routers/target/updateTarget.ts +++ b/server/routers/target/updateTarget.ts @@ -1,7 +1,7 @@ import { Request, Response, NextFunction } from "express"; import { z } from "zod"; import { db } from "@server/db"; -import { newts, resources, sites, targets } from "@server/db/schemas"; +import { newts, resources, sites, targets } from "@server/db"; import { eq } from "drizzle-orm"; import response from "@server/lib/response"; import HttpCode from "@server/types/HttpCode"; diff --git a/server/routers/traefik/getTraefikConfig.ts b/server/routers/traefik/getTraefikConfig.ts index 2fd656ba..7f70dbc7 100644 --- a/server/routers/traefik/getTraefikConfig.ts +++ b/server/routers/traefik/getTraefikConfig.ts @@ -1,10 +1,10 @@ import { Request, Response } from "express"; -import db from "@server/db"; +import { db } from "@server/db"; import { and, eq, inArray } from "drizzle-orm"; import logger from "@server/logger"; import HttpCode from "@server/types/HttpCode"; import config from "@server/lib/config"; -import { orgs, resources, sites, Target, targets } from "@server/db/schemas"; +import { orgs, resources, sites, Target, targets } from "@server/db"; import { sql } from "drizzle-orm"; export async function traefikConfigProvider( diff --git a/server/routers/user/acceptInvite.ts b/server/routers/user/acceptInvite.ts index cc483b16..115168b9 100644 --- a/server/routers/user/acceptInvite.ts +++ b/server/routers/user/acceptInvite.ts @@ -1,7 +1,7 @@ import { Request, Response, NextFunction } from "express"; import { z } from "zod"; import { db } from "@server/db"; -import { roles, userInvites, userOrgs, users } from "@server/db/schemas"; +import { roles, userInvites, userOrgs, users } from "@server/db"; import { eq } from "drizzle-orm"; import response from "@server/lib/response"; import HttpCode from "@server/types/HttpCode"; diff --git a/server/routers/user/addUserAction.ts b/server/routers/user/addUserAction.ts index 472f4298..074ebe9b 100644 --- a/server/routers/user/addUserAction.ts +++ b/server/routers/user/addUserAction.ts @@ -1,7 +1,7 @@ import { Request, Response, NextFunction } from "express"; import { z } from "zod"; import { db } from "@server/db"; -import { userActions, users } from "@server/db/schemas"; +import { userActions, users } from "@server/db"; import response from "@server/lib/response"; import HttpCode from "@server/types/HttpCode"; import createHttpError from "http-errors"; diff --git a/server/routers/user/addUserRole.ts b/server/routers/user/addUserRole.ts index c0ac31bc..bd6d9901 100644 --- a/server/routers/user/addUserRole.ts +++ b/server/routers/user/addUserRole.ts @@ -1,7 +1,7 @@ import { Request, Response, NextFunction } from "express"; import { z } from "zod"; import { db } from "@server/db"; -import { userOrgs, roles } from "@server/db/schemas"; +import { userOrgs, roles } from "@server/db"; import { eq, and } from "drizzle-orm"; import response from "@server/lib/response"; import HttpCode from "@server/types/HttpCode"; diff --git a/server/routers/user/addUserSite.ts b/server/routers/user/addUserSite.ts index 5b20ed8d..c55d5463 100644 --- a/server/routers/user/addUserSite.ts +++ b/server/routers/user/addUserSite.ts @@ -1,7 +1,7 @@ import { Request, Response, NextFunction } from "express"; import { z } from "zod"; import { db } from "@server/db"; -import { resources, userResources, userSites } from "@server/db/schemas"; +import { resources, userResources, userSites } from "@server/db"; import response from "@server/lib/response"; import HttpCode from "@server/types/HttpCode"; import createHttpError from "http-errors"; diff --git a/server/routers/user/adminListUsers.ts b/server/routers/user/adminListUsers.ts index 6de12be9..cb1e21fb 100644 --- a/server/routers/user/adminListUsers.ts +++ b/server/routers/user/adminListUsers.ts @@ -6,7 +6,7 @@ import HttpCode from "@server/types/HttpCode"; import createHttpError from "http-errors"; import { sql, eq } from "drizzle-orm"; import logger from "@server/logger"; -import { idp, users } from "@server/db/schemas"; +import { idp, users } from "@server/db"; import { fromZodError } from "zod-validation-error"; const listUsersSchema = z diff --git a/server/routers/user/adminRemoveUser.ts b/server/routers/user/adminRemoveUser.ts index fa31c52f..14916ab9 100644 --- a/server/routers/user/adminRemoveUser.ts +++ b/server/routers/user/adminRemoveUser.ts @@ -1,7 +1,7 @@ import { Request, Response, NextFunction } from "express"; import { z } from "zod"; import { db } from "@server/db"; -import { users } from "@server/db/schemas"; +import { users } from "@server/db"; import { eq } from "drizzle-orm"; import response from "@server/lib/response"; import HttpCode from "@server/types/HttpCode"; diff --git a/server/routers/user/createOrgUser.ts b/server/routers/user/createOrgUser.ts index a198db5d..f6fcb619 100644 --- a/server/routers/user/createOrgUser.ts +++ b/server/routers/user/createOrgUser.ts @@ -6,9 +6,9 @@ import createHttpError from "http-errors"; import logger from "@server/logger"; import { fromError } from "zod-validation-error"; import { OpenAPITags, registry } from "@server/openApi"; -import db from "@server/db"; +import { db } from "@server/db"; import { and, eq } from "drizzle-orm"; -import { idp, idpOidcConfig, roles, userOrgs, users } from "@server/db/schemas"; +import { idp, idpOidcConfig, roles, userOrgs, users } from "@server/db"; import { generateId } from "@server/auth/sessions/app"; const paramsSchema = z diff --git a/server/routers/user/getOrgUser.ts b/server/routers/user/getOrgUser.ts index 6ebd33c0..562ef34e 100644 --- a/server/routers/user/getOrgUser.ts +++ b/server/routers/user/getOrgUser.ts @@ -1,7 +1,7 @@ import { Request, Response, NextFunction } from "express"; import { z } from "zod"; import { db } from "@server/db"; -import { roles, userOrgs, users } from "@server/db/schemas"; +import { roles, userOrgs, users } from "@server/db"; import { and, eq } from "drizzle-orm"; import response from "@server/lib/response"; import HttpCode from "@server/types/HttpCode"; diff --git a/server/routers/user/getUser.ts b/server/routers/user/getUser.ts index 2f80be90..e33daab6 100644 --- a/server/routers/user/getUser.ts +++ b/server/routers/user/getUser.ts @@ -1,7 +1,7 @@ import { Request, Response, NextFunction } from "express"; import { z } from "zod"; import { db } from "@server/db"; -import { idp, users } from "@server/db/schemas"; +import { idp, users } from "@server/db"; import { eq } from "drizzle-orm"; import response from "@server/lib/response"; import HttpCode from "@server/types/HttpCode"; diff --git a/server/routers/user/inviteUser.ts b/server/routers/user/inviteUser.ts index 042942ab..6b47338a 100644 --- a/server/routers/user/inviteUser.ts +++ b/server/routers/user/inviteUser.ts @@ -2,7 +2,7 @@ import NodeCache from "node-cache"; import { Request, Response, NextFunction } from "express"; import { z } from "zod"; import { db } from "@server/db"; -import { orgs, userInvites, userOrgs, users } from "@server/db/schemas"; +import { orgs, userInvites, userOrgs, users } from "@server/db"; import { and, eq } from "drizzle-orm"; import response from "@server/lib/response"; import HttpCode from "@server/types/HttpCode"; diff --git a/server/routers/user/listInvitations.ts b/server/routers/user/listInvitations.ts index 76e82db5..c91a136d 100644 --- a/server/routers/user/listInvitations.ts +++ b/server/routers/user/listInvitations.ts @@ -1,7 +1,7 @@ import { Request, Response, NextFunction } from "express"; import { z } from "zod"; import { db } from "@server/db"; -import { userInvites, roles } from "@server/db/schemas"; +import { userInvites, roles } from "@server/db"; import response from "@server/lib/response"; import HttpCode from "@server/types/HttpCode"; import createHttpError from "http-errors"; diff --git a/server/routers/user/listUsers.ts b/server/routers/user/listUsers.ts index fd2291d5..2e23f401 100644 --- a/server/routers/user/listUsers.ts +++ b/server/routers/user/listUsers.ts @@ -1,7 +1,7 @@ import { Request, Response, NextFunction } from "express"; import { z } from "zod"; import { db } from "@server/db"; -import { idp, roles, userOrgs, users } from "@server/db/schemas"; +import { idp, roles, userOrgs, users } from "@server/db"; import response from "@server/lib/response"; import HttpCode from "@server/types/HttpCode"; import createHttpError from "http-errors"; diff --git a/server/routers/user/removeInvitation.ts b/server/routers/user/removeInvitation.ts index c825df6d..e3ee40d0 100644 --- a/server/routers/user/removeInvitation.ts +++ b/server/routers/user/removeInvitation.ts @@ -1,7 +1,7 @@ import { Request, Response, NextFunction } from "express"; import { z } from "zod"; import { db } from "@server/db"; -import { userInvites } from "@server/db/schemas"; +import { userInvites } from "@server/db"; import { eq, and } from "drizzle-orm"; import response from "@server/lib/response"; import HttpCode from "@server/types/HttpCode"; diff --git a/server/routers/user/removeUserAction.ts b/server/routers/user/removeUserAction.ts index 9364f406..f0bd7d92 100644 --- a/server/routers/user/removeUserAction.ts +++ b/server/routers/user/removeUserAction.ts @@ -1,7 +1,7 @@ import { Request, Response, NextFunction } from "express"; import { z } from "zod"; import { db } from "@server/db"; -import { userActions } from "@server/db/schemas"; +import { userActions } from "@server/db"; import { and, eq } from "drizzle-orm"; import response from "@server/lib/response"; import HttpCode from "@server/types/HttpCode"; diff --git a/server/routers/user/removeUserOrg.ts b/server/routers/user/removeUserOrg.ts index b344978c..a406e5ac 100644 --- a/server/routers/user/removeUserOrg.ts +++ b/server/routers/user/removeUserOrg.ts @@ -1,7 +1,7 @@ import { Request, Response, NextFunction } from "express"; import { z } from "zod"; import { db } from "@server/db"; -import { userOrgs, userResources, users, userSites } from "@server/db/schemas"; +import { userOrgs, userResources, users, userSites } from "@server/db"; import { and, eq } from "drizzle-orm"; import response from "@server/lib/response"; import HttpCode from "@server/types/HttpCode"; diff --git a/server/routers/user/removeUserResource.ts b/server/routers/user/removeUserResource.ts index be5acab9..186e8032 100644 --- a/server/routers/user/removeUserResource.ts +++ b/server/routers/user/removeUserResource.ts @@ -1,7 +1,7 @@ import { Request, Response, NextFunction } from "express"; import { z } from "zod"; import { db } from "@server/db"; -import { userResources } from "@server/db/schemas"; +import { userResources } from "@server/db"; import { and, eq } from "drizzle-orm"; import response from "@server/lib/response"; import HttpCode from "@server/types/HttpCode"; diff --git a/server/routers/user/removeUserSite.ts b/server/routers/user/removeUserSite.ts index 6142f45c..200999fd 100644 --- a/server/routers/user/removeUserSite.ts +++ b/server/routers/user/removeUserSite.ts @@ -1,7 +1,7 @@ import { Request, Response, NextFunction } from "express"; import { z } from "zod"; import { db } from "@server/db"; -import { resources, userResources, userSites } from "@server/db/schemas"; +import { resources, userResources, userSites } from "@server/db"; import { and, eq } from "drizzle-orm"; import response from "@server/lib/response"; import HttpCode from "@server/types/HttpCode"; diff --git a/server/routers/ws.ts b/server/routers/ws.ts index d6a601c3..1459e79c 100644 --- a/server/routers/ws.ts +++ b/server/routers/ws.ts @@ -3,9 +3,9 @@ import { Server as HttpServer } from "http"; import { WebSocket, WebSocketServer } from "ws"; import { IncomingMessage } from "http"; import { Socket } from "net"; -import { Newt, newts, NewtSession, olms, Olm, OlmSession } from "@server/db/schemas"; +import { Newt, newts, NewtSession, olms, Olm, OlmSession } from "@server/db"; import { eq } from "drizzle-orm"; -import db from "@server/db"; +import { db } from "@server/db"; import { validateNewtSessionToken } from "@server/auth/sessions/newt"; import { validateOlmSessionToken } from "@server/auth/sessions/olm"; import { messageHandlers } from "./messageHandlers"; diff --git a/server/setup/clearStaleData.ts b/server/setup/clearStaleData.ts index 4d95107e..220a64f5 100644 --- a/server/setup/clearStaleData.ts +++ b/server/setup/clearStaleData.ts @@ -8,7 +8,7 @@ import { resourceSessions, sessions, userInvites -} from "@server/db/schemas"; +} from "@server/db"; import logger from "@server/logger"; import { lt } from "drizzle-orm"; diff --git a/server/setup/copyInConfig.ts b/server/setup/copyInConfig.ts index ec5a137b..6ab8d446 100644 --- a/server/setup/copyInConfig.ts +++ b/server/setup/copyInConfig.ts @@ -1,5 +1,5 @@ import { db } from "@server/db"; -import { domains, exitNodes, orgDomains, orgs, resources } from "../db/schemas/schema"; +import { domains, exitNodes, orgDomains, orgs, resources } from "@server/db"; import config from "@server/lib/config"; import { eq, ne } from "drizzle-orm"; import logger from "@server/logger"; diff --git a/server/setup/ensureActions.ts b/server/setup/ensureActions.ts index 0d789e1d..7fd5384a 100644 --- a/server/setup/ensureActions.ts +++ b/server/setup/ensureActions.ts @@ -1,6 +1,6 @@ import { ActionsEnum } from "@server/auth/actions"; import { db } from "@server/db"; -import { actions, roles, roleActions } from "../db/schemas/schema"; +import { actions, roles, roleActions } from "@server/db"; import { eq, inArray } from "drizzle-orm"; import logger from "@server/logger"; @@ -22,85 +22,37 @@ export async function ensureActions() { .where(eq(roles.isAdmin, true)) .execute(); - await db.transaction(async (trx) => { + await db.transaction(async (trx) => { + // Add new actions + for (const actionId of actionsToAdd) { + logger.debug(`Adding action: ${actionId}`); + await trx.insert(actions).values({ actionId }).execute(); + // Add new actions to the Default role + if (defaultRoles.length != 0) { + await trx + .insert(roleActions) + .values( + defaultRoles.map((role) => ({ + roleId: role.roleId!, + actionId, + orgId: role.orgId! + })) + ) + .execute(); + } + } - // Add new actions - for (const actionId of actionsToAdd) { - logger.debug(`Adding action: ${actionId}`); - await trx.insert(actions).values({ actionId }).execute(); - // Add new actions to the Default role - if (defaultRoles.length != 0) { + // Remove deprecated actions + if (actionsToRemove.length > 0) { + logger.debug(`Removing actions: ${actionsToRemove.join(", ")}`); await trx - .insert(roleActions) - .values( - defaultRoles.map((role) => ({ - roleId: role.roleId!, - actionId, - orgId: role.orgId! - })) - ) + .delete(actions) + .where(inArray(actions.actionId, actionsToRemove)) + .execute(); + await trx + .delete(roleActions) + .where(inArray(roleActions.actionId, actionsToRemove)) .execute(); } - } - - // Remove deprecated actions - if (actionsToRemove.length > 0) { - logger.debug(`Removing actions: ${actionsToRemove.join(", ")}`); - await trx - .delete(actions) - .where(inArray(actions.actionId, actionsToRemove)) - .execute(); - await trx - .delete(roleActions) - .where(inArray(roleActions.actionId, actionsToRemove)) - .execute(); - } -}); -} - -export async function createAdminRole(orgId: string) { - let roleId: any; - await db.transaction(async (trx) => { - - const [insertedRole] = await trx - .insert(roles) - .values({ - orgId, - isAdmin: true, - name: "Admin", - description: "Admin role with the most permissions" - }) - .returning({ roleId: roles.roleId }) - .execute(); - - if (!insertedRole || !insertedRole.roleId) { - throw new Error("Failed to create Admin role"); - } - - roleId = insertedRole.roleId; - - const actionIds = await trx.select().from(actions).execute(); - - if (actionIds.length === 0) { - logger.info("No actions to assign to the Admin role"); - return; - } - - await trx - .insert(roleActions) - .values( - actionIds.map((action) => ({ - roleId, - actionId: action.actionId, - orgId - })) - ) - .execute(); }); - - if (!roleId) { - throw new Error("Failed to create Admin role"); - } - - return roleId; } diff --git a/server/setup/migrationsPg.ts b/server/setup/migrationsPg.ts new file mode 100644 index 00000000..a3dc6499 --- /dev/null +++ b/server/setup/migrationsPg.ts @@ -0,0 +1,133 @@ +import { migrate } from "drizzle-orm/node-postgres/migrator"; +import { db } from "../db/pg"; +import semver from "semver"; +import { versionMigrations } from "../db/pg"; +import { __DIRNAME, APP_PATH, APP_VERSION } from "@server/lib/consts"; +import path from "path"; + +// THIS CANNOT IMPORT ANYTHING FROM THE SERVER +// EXCEPT FOR THE DATABASE AND THE SCHEMA + +// Define the migration list with versions and their corresponding functions +const migrations = [ + // Add new migrations here as they are created +] as { + version: string; + run: () => Promise; +}[]; + +await run(); + +async function run() { + // run the migrations + await runMigrations(); +} + +export async function runMigrations() { + try { + const appVersion = APP_VERSION; + + // determine if the migrations table exists + const exists = await db + .select() + .from(versionMigrations) + .limit(1) + .execute() + .then((res) => res.length > 0) + .catch(() => false); + + if (exists) { + console.log("Migrations table exists, running scripts..."); + await executeScripts(); + } else { + console.log("Migrations table does not exist, creating it..."); + console.log("Running migrations..."); + try { + await migrate(db, { + migrationsFolder: path.join(__DIRNAME, "init") // put here during the docker build + }); + console.log("Migrations completed successfully."); + } catch (error) { + console.error("Error running migrations:", error); + } + + await db + .insert(versionMigrations) + .values({ + version: appVersion, + executedAt: Date.now() + }) + .execute(); + } + } catch (e) { + console.error("Error running migrations:", e); + await new Promise((resolve) => + setTimeout(resolve, 1000 * 60 * 60 * 24 * 1) + ); + } +} + +async function executeScripts() { + try { + // Get the last executed version from the database + const lastExecuted = await db.select().from(versionMigrations); + + // Filter and sort migrations + const pendingMigrations = lastExecuted + .map((m) => m) + .sort((a, b) => semver.compare(b.version, a.version)); + const startVersion = pendingMigrations[0]?.version ?? "0.0.0"; + console.log(`Starting migrations from version ${startVersion}`); + + const migrationsToRun = migrations.filter((migration) => + semver.gt(migration.version, startVersion) + ); + + console.log( + "Migrations to run:", + migrationsToRun.map((m) => m.version).join(", ") + ); + + // Run migrations in order + for (const migration of migrationsToRun) { + console.log(`Running migration ${migration.version}`); + + try { + await migration.run(); + + // Update version in database + await db + .insert(versionMigrations) + .values({ + version: migration.version, + executedAt: Date.now() + }) + .execute(); + + console.log( + `Successfully completed migration ${migration.version}` + ); + } catch (e) { + if ( + e instanceof Error && + typeof (e as any).code === "string" && + (e as any).code === "23505" + ) { + console.error("Migration has already run! Skipping..."); + continue; // or return, depending on context + } + + console.error( + `Failed to run migration ${migration.version}:`, + e + ); + throw e; + } + } + + console.log("All migrations completed successfully"); + } catch (error) { + console.error("Migration process failed:", error); + throw error; + } +} diff --git a/server/setup/migrations.ts b/server/setup/migrationsSqlite.ts similarity index 86% rename from server/setup/migrations.ts rename to server/setup/migrationsSqlite.ts index 753ed6a7..36b87de2 100644 --- a/server/setup/migrations.ts +++ b/server/setup/migrationsSqlite.ts @@ -1,26 +1,26 @@ import { migrate } from "drizzle-orm/better-sqlite3/migrator"; -import db, { exists } from "@server/db"; +import { db, exists } from "../db/sqlite"; import path from "path"; import semver from "semver"; -import { versionMigrations } from "@server/db/schemas"; +import { versionMigrations } from "../db/sqlite"; import { __DIRNAME, APP_PATH, APP_VERSION } from "@server/lib/consts"; import { SqliteError } from "better-sqlite3"; import fs from "fs"; -import m1 from "./scripts/1.0.0-beta1"; -import m2 from "./scripts/1.0.0-beta2"; -import m3 from "./scripts/1.0.0-beta3"; -import m4 from "./scripts/1.0.0-beta5"; -import m5 from "./scripts/1.0.0-beta6"; -import m6 from "./scripts/1.0.0-beta9"; -import m7 from "./scripts/1.0.0-beta10"; -import m8 from "./scripts/1.0.0-beta12"; -import m13 from "./scripts/1.0.0-beta13"; -import m15 from "./scripts/1.0.0-beta15"; -import m16 from "./scripts/1.0.0"; -import m17 from "./scripts/1.1.0"; -import m18 from "./scripts/1.2.0"; -import m19 from "./scripts/1.3.0"; -import { setHostMeta } from "./setHostMeta"; +import m1 from "./scriptsSqlite/1.0.0-beta1"; +import m2 from "./scriptsSqlite/1.0.0-beta2"; +import m3 from "./scriptsSqlite/1.0.0-beta3"; +import m4 from "./scriptsSqlite/1.0.0-beta5"; +import m5 from "./scriptsSqlite/1.0.0-beta6"; +import m6 from "./scriptsSqlite/1.0.0-beta9"; +import m7 from "./scriptsSqlite/1.0.0-beta10"; +import m8 from "./scriptsSqlite/1.0.0-beta12"; +import m13 from "./scriptsSqlite/1.0.0-beta13"; +import m15 from "./scriptsSqlite/1.0.0-beta15"; +import m16 from "./scriptsSqlite/1.0.0"; +import m17 from "./scriptsSqlite/1.1.0"; +import m18 from "./scriptsSqlite/1.2.0"; +import m19 from "./scriptsSqlite/1.3.0"; +import m20 from "./scriptsSqlite/1.5.0"; // THIS CANNOT IMPORT ANYTHING FROM THE SERVER // EXCEPT FOR THE DATABASE AND THE SCHEMA @@ -40,7 +40,8 @@ const migrations = [ { version: "1.0.0", run: m16 }, { version: "1.1.0", run: m17 }, { version: "1.2.0", run: m18 }, - { version: "1.3.0", run: m19 } + { version: "1.3.0", run: m19 }, + { version: "1.5.0", run: m20 }, // Add new migrations here as they are created ] as const; diff --git a/server/setup/scripts/1.0.0-beta1.ts b/server/setup/scriptsSqlite/1.0.0-beta1.ts similarity index 100% rename from server/setup/scripts/1.0.0-beta1.ts rename to server/setup/scriptsSqlite/1.0.0-beta1.ts diff --git a/server/setup/scripts/1.0.0-beta10.ts b/server/setup/scriptsSqlite/1.0.0-beta10.ts similarity index 100% rename from server/setup/scripts/1.0.0-beta10.ts rename to server/setup/scriptsSqlite/1.0.0-beta10.ts diff --git a/server/setup/scripts/1.0.0-beta12.ts b/server/setup/scriptsSqlite/1.0.0-beta12.ts similarity index 97% rename from server/setup/scripts/1.0.0-beta12.ts rename to server/setup/scriptsSqlite/1.0.0-beta12.ts index 0632b5e1..a400b3a6 100644 --- a/server/setup/scripts/1.0.0-beta12.ts +++ b/server/setup/scriptsSqlite/1.0.0-beta12.ts @@ -1,4 +1,4 @@ -import db from "@server/db"; +import { db } from "../../db/sqlite"; import { configFilePath1, configFilePath2 } from "@server/lib/consts"; import { sql } from "drizzle-orm"; import fs from "fs"; diff --git a/server/setup/scripts/1.0.0-beta13.ts b/server/setup/scriptsSqlite/1.0.0-beta13.ts similarity index 96% rename from server/setup/scripts/1.0.0-beta13.ts rename to server/setup/scriptsSqlite/1.0.0-beta13.ts index 48b68cec..9ced727f 100644 --- a/server/setup/scripts/1.0.0-beta13.ts +++ b/server/setup/scriptsSqlite/1.0.0-beta13.ts @@ -1,4 +1,4 @@ -import db from "@server/db"; +import { db } from "../../db/sqlite"; import { sql } from "drizzle-orm"; const version = "1.0.0-beta.13"; diff --git a/server/setup/scripts/1.0.0-beta15.ts b/server/setup/scriptsSqlite/1.0.0-beta15.ts similarity index 97% rename from server/setup/scripts/1.0.0-beta15.ts rename to server/setup/scriptsSqlite/1.0.0-beta15.ts index a087c5c6..e50558a5 100644 --- a/server/setup/scripts/1.0.0-beta15.ts +++ b/server/setup/scriptsSqlite/1.0.0-beta15.ts @@ -1,9 +1,9 @@ -import db from "@server/db"; +import { db } from "../../db/sqlite"; import { configFilePath1, configFilePath2 } from "@server/lib/consts"; import fs from "fs"; import yaml from "js-yaml"; import { sql } from "drizzle-orm"; -import { domains, orgDomains, resources } from "@server/db/schemas"; +import { domains, orgDomains, resources } from "@server/db"; const version = "1.0.0-beta.15"; diff --git a/server/setup/scripts/1.0.0-beta2.ts b/server/setup/scriptsSqlite/1.0.0-beta2.ts similarity index 100% rename from server/setup/scripts/1.0.0-beta2.ts rename to server/setup/scriptsSqlite/1.0.0-beta2.ts diff --git a/server/setup/scripts/1.0.0-beta3.ts b/server/setup/scriptsSqlite/1.0.0-beta3.ts similarity index 100% rename from server/setup/scripts/1.0.0-beta3.ts rename to server/setup/scriptsSqlite/1.0.0-beta3.ts diff --git a/server/setup/scripts/1.0.0-beta5.ts b/server/setup/scriptsSqlite/1.0.0-beta5.ts similarity index 100% rename from server/setup/scripts/1.0.0-beta5.ts rename to server/setup/scriptsSqlite/1.0.0-beta5.ts diff --git a/server/setup/scripts/1.0.0-beta6.ts b/server/setup/scriptsSqlite/1.0.0-beta6.ts similarity index 96% rename from server/setup/scripts/1.0.0-beta6.ts rename to server/setup/scriptsSqlite/1.0.0-beta6.ts index 4fcfb114..8fbb1387 100644 --- a/server/setup/scripts/1.0.0-beta6.ts +++ b/server/setup/scriptsSqlite/1.0.0-beta6.ts @@ -44,8 +44,8 @@ export default async function migration() { const updatedYaml = yaml.dump(rawConfig); fs.writeFileSync(filePath, updatedYaml, "utf8"); } catch (error) { - console.log("We were unable to add CORS to your config file. Please add it manually.") - console.error(error) + console.log("We were unable to add CORS to your config file. Please add it manually."); + console.error(error); } console.log("Done."); diff --git a/server/setup/scripts/1.0.0-beta9.ts b/server/setup/scriptsSqlite/1.0.0-beta9.ts similarity index 99% rename from server/setup/scripts/1.0.0-beta9.ts rename to server/setup/scriptsSqlite/1.0.0-beta9.ts index 64f2beed..c731996b 100644 --- a/server/setup/scripts/1.0.0-beta9.ts +++ b/server/setup/scriptsSqlite/1.0.0-beta9.ts @@ -1,4 +1,4 @@ -import db from "@server/db"; +import { db } from "../../db/sqlite"; import { emailVerificationCodes, passwordResetTokens, @@ -8,7 +8,7 @@ import { targets, userInvites, users -} from "@server/db/schemas"; +} from "../../db/sqlite"; import { APP_PATH, configFilePath1, configFilePath2 } from "@server/lib/consts"; import { eq, sql } from "drizzle-orm"; import fs from "fs"; diff --git a/server/setup/scripts/1.0.0.ts b/server/setup/scriptsSqlite/1.0.0.ts similarity index 100% rename from server/setup/scripts/1.0.0.ts rename to server/setup/scriptsSqlite/1.0.0.ts diff --git a/server/setup/scripts/1.1.0.ts b/server/setup/scriptsSqlite/1.1.0.ts similarity index 94% rename from server/setup/scripts/1.1.0.ts rename to server/setup/scriptsSqlite/1.1.0.ts index 8bd2cd19..4d121852 100644 --- a/server/setup/scripts/1.1.0.ts +++ b/server/setup/scriptsSqlite/1.1.0.ts @@ -1,4 +1,4 @@ -import db from "@server/db"; +import { db } from "../../db/sqlite"; import { sql } from "drizzle-orm"; const version = "1.1.0"; diff --git a/server/setup/scripts/1.2.0.ts b/server/setup/scriptsSqlite/1.2.0.ts similarity index 98% rename from server/setup/scripts/1.2.0.ts rename to server/setup/scriptsSqlite/1.2.0.ts index fdea9fab..940d38e6 100644 --- a/server/setup/scripts/1.2.0.ts +++ b/server/setup/scriptsSqlite/1.2.0.ts @@ -1,4 +1,4 @@ -import db from "@server/db"; +import { db } from "../../db/sqlite"; import { APP_PATH, configFilePath1, configFilePath2 } from "@server/lib/consts"; import { sql } from "drizzle-orm"; import fs from "fs"; diff --git a/server/setup/scripts/1.3.0.ts b/server/setup/scriptsSqlite/1.3.0.ts similarity index 100% rename from server/setup/scripts/1.3.0.ts rename to server/setup/scriptsSqlite/1.3.0.ts diff --git a/server/setup/scriptsSqlite/1.5.0.ts b/server/setup/scriptsSqlite/1.5.0.ts new file mode 100644 index 00000000..69fe7053 --- /dev/null +++ b/server/setup/scriptsSqlite/1.5.0.ts @@ -0,0 +1,71 @@ +import Database from "better-sqlite3"; +import path from "path"; +import { APP_PATH, configFilePath1, configFilePath2 } from "@server/lib/consts"; +import fs from "fs"; +import yaml from "js-yaml"; + +const version = "1.5.0"; +const location = path.join(APP_PATH, "db", "db.sqlite"); + +export default async function migration() { + console.log(`Running setup script ${version}...`); + + const db = new Database(location); + + try { + db.pragma("foreign_keys = OFF"); + db.transaction(() => { + db.exec(` + ALTER TABLE 'sites' ADD 'dockerSocketEnabled' integer DEFAULT true NOT NULL; + `); + })(); // <-- executes the transaction immediately + db.pragma("foreign_keys = ON"); + console.log(`Migrated database schema`); + } catch (e) { + console.log("Unable to migrate database schema"); + throw e; + } + + try { + // Determine which config file exists + const filePaths = [configFilePath1, configFilePath2]; + let filePath = ""; + for (const path of filePaths) { + if (fs.existsSync(path)) { + filePath = path; + break; + } + } + + if (!filePath) { + throw new Error( + `No config file found (expected config.yml or config.yaml).` + ); + } + + // Read and parse the YAML file + let rawConfig: any; + const fileContents = fs.readFileSync(filePath, "utf8"); + rawConfig = yaml.load(fileContents); + + if (rawConfig.cors?.headers) { + const headers = JSON.parse( + JSON.stringify(rawConfig.cors.headers) + ); + rawConfig.cors.allowed_headers = headers; + delete rawConfig.cors.headers; + } + + // Write the updated YAML back to the file + const updatedYaml = yaml.dump(rawConfig); + fs.writeFileSync(filePath, updatedYaml, "utf8"); + + console.log(`Migrated CORS headers to allowed_headers`); + } catch (e) { + console.log( + `Unable to migrate config file. Error: ${e}` + ); + } + + console.log(`${version} migration complete`); +} diff --git a/server/setup/setHostMeta.ts b/server/setup/setHostMeta.ts index 2a5b16a5..2223d11b 100644 --- a/server/setup/setHostMeta.ts +++ b/server/setup/setHostMeta.ts @@ -1,5 +1,5 @@ -import db from "@server/db"; -import { hostMeta } from "@server/db/schemas"; +import { db } from "@server/db"; +import { hostMeta } from "@server/db"; import { v4 as uuidv4 } from "uuid"; export async function setHostMeta() { diff --git a/server/setup/setupServerAdmin.ts b/server/setup/setupServerAdmin.ts index 9a84852a..5dcf3760 100644 --- a/server/setup/setupServerAdmin.ts +++ b/server/setup/setupServerAdmin.ts @@ -1,8 +1,8 @@ import { generateId, invalidateAllSessions } from "@server/auth/sessions/app"; import { hashPassword, verifyPassword } from "@server/auth/password"; import config from "@server/lib/config"; -import db from "@server/db"; -import { users } from "@server/db/schemas"; +import { db } from "@server/db"; +import { users } from "@server/db"; import logger from "@server/logger"; import { eq } from "drizzle-orm"; import moment from "moment"; diff --git a/server/types/Auth.ts b/server/types/Auth.ts index ce86623f..8e222987 100644 --- a/server/types/Auth.ts +++ b/server/types/Auth.ts @@ -1,6 +1,6 @@ import { Request } from "express"; -import { User } from "@server/db/schemas"; -import { Session } from "@server/db/schemas"; +import { User } from "@server/db"; +import { Session } from "@server/db"; export interface AuthenticatedRequest extends Request { user: User; diff --git a/src/app/[orgId]/settings/access/roles/RolesTable.tsx b/src/app/[orgId]/settings/access/roles/RolesTable.tsx index 7ebcfbce..5369b761 100644 --- a/src/app/[orgId]/settings/access/roles/RolesTable.tsx +++ b/src/app/[orgId]/settings/access/roles/RolesTable.tsx @@ -14,7 +14,7 @@ import ConfirmDeleteDialog from "@app/components/ConfirmDeleteDialog"; import { useOrgContext } from "@app/hooks/useOrgContext"; import { toast } from "@app/hooks/useToast"; import { RolesDataTable } from "./RolesDataTable"; -import { Role } from "@server/db/schemas"; +import { Role } from "@server/db"; import CreateRoleForm from "./CreateRoleForm"; import DeleteRoleForm from "./DeleteRoleForm"; import { createApiClient } from "@app/lib/api"; diff --git a/src/app/[orgId]/settings/api-keys/create/page.tsx b/src/app/[orgId]/settings/api-keys/create/page.tsx index d3e7e346..3493361a 100644 --- a/src/app/[orgId]/settings/api-keys/create/page.tsx +++ b/src/app/[orgId]/settings/api-keys/create/page.tsx @@ -44,7 +44,6 @@ import { CreateOrgApiKeyBody, CreateOrgApiKeyResponse } from "@server/routers/apiKeys"; -import { ApiKey } from "@server/db/schemas"; import { InfoSection, InfoSectionContent, diff --git a/src/app/[orgId]/settings/resources/[resourceId]/ResourceInfoBox.tsx b/src/app/[orgId]/settings/resources/[resourceId]/ResourceInfoBox.tsx index 86916755..a6740b3c 100644 --- a/src/app/[orgId]/settings/resources/[resourceId]/ResourceInfoBox.tsx +++ b/src/app/[orgId]/settings/resources/[resourceId]/ResourceInfoBox.tsx @@ -1,9 +1,8 @@ "use client"; import { Alert, AlertDescription, AlertTitle } from "@/components/ui/alert"; -import { ArrowRight, InfoIcon, ShieldCheck, ShieldOff } from "lucide-react"; +import { InfoIcon, ShieldCheck, ShieldOff } from "lucide-react"; import { useResourceContext } from "@app/hooks/useResourceContext"; -import { Separator } from "@app/components/ui/separator"; import CopyToClipboard from "@app/components/CopyToClipboard"; import { InfoSection, @@ -11,13 +10,17 @@ import { InfoSections, InfoSectionTitle } from "@app/components/InfoSection"; -import Link from "next/link"; -import { Switch } from "@app/components/ui/switch"; +import { createApiClient } from "@app/lib/api"; +import { useEnvContext } from "@app/hooks/useEnvContext"; +import { useDockerSocket } from "@app/hooks/useDockerSocket"; type ResourceInfoBoxType = {}; export default function ResourceInfoBox({}: ResourceInfoBoxType) { - const { resource, authInfo } = useResourceContext(); + const { resource, authInfo, site } = useResourceContext(); + const api = createApiClient(useEnvContext()); + + const { isEnabled, isAvailable } = useDockerSocket(site!); let fullUrl = `${resource.ssl ? "https" : "http"}://${resource.fullDomain}`; @@ -67,6 +70,24 @@ export default function ResourceInfoBox({}: ResourceInfoBoxType) { {resource.siteName} + {/* {isEnabled && ( + + Socket + + {isAvailable ? ( + +
+ Online +
+ ) : ( + +
+ Offline +
+ )} +
+
+ )} */} ) : ( <> @@ -92,7 +113,9 @@ export default function ResourceInfoBox({}: ResourceInfoBoxType) { Visibility - {resource.enabled ? "Enabled" : "Disabled"} + + {resource.enabled ? "Enabled" : "Disabled"} + diff --git a/src/app/[orgId]/settings/resources/[resourceId]/authentication/SetResourcePasswordForm.tsx b/src/app/[orgId]/settings/resources/[resourceId]/authentication/SetResourcePasswordForm.tsx index 3bf2966a..a0f6f9a7 100644 --- a/src/app/[orgId]/settings/resources/[resourceId]/authentication/SetResourcePasswordForm.tsx +++ b/src/app/[orgId]/settings/resources/[resourceId]/authentication/SetResourcePasswordForm.tsx @@ -28,7 +28,7 @@ import { } from "@app/components/Credenza"; import { formatAxiosError } from "@app/lib/api"; import { AxiosResponse } from "axios"; -import { Resource } from "@server/db/schemas"; +import { Resource } from "@server/db"; import { createApiClient } from "@app/lib/api"; import { useEnvContext } from "@app/hooks/useEnvContext"; diff --git a/src/app/[orgId]/settings/resources/[resourceId]/authentication/SetResourcePincodeForm.tsx b/src/app/[orgId]/settings/resources/[resourceId]/authentication/SetResourcePincodeForm.tsx index 31ccbea6..cf9d5e42 100644 --- a/src/app/[orgId]/settings/resources/[resourceId]/authentication/SetResourcePincodeForm.tsx +++ b/src/app/[orgId]/settings/resources/[resourceId]/authentication/SetResourcePincodeForm.tsx @@ -28,7 +28,7 @@ import { } from "@app/components/Credenza"; import { formatAxiosError } from "@app/lib/api"; import { AxiosResponse } from "axios"; -import { Resource } from "@server/db/schemas"; +import { Resource } from "@server/db"; import { InputOTP, InputOTPGroup, diff --git a/src/app/[orgId]/settings/resources/[resourceId]/layout.tsx b/src/app/[orgId]/settings/resources/[resourceId]/layout.tsx index edb21303..1021889e 100644 --- a/src/app/[orgId]/settings/resources/[resourceId]/layout.tsx +++ b/src/app/[orgId]/settings/resources/[resourceId]/layout.tsx @@ -13,15 +13,7 @@ import { GetOrgResponse } from "@server/routers/org"; import OrgProvider from "@app/providers/OrgProvider"; import { cache } from "react"; import ResourceInfoBox from "./ResourceInfoBox"; -import { - Breadcrumb, - BreadcrumbItem, - BreadcrumbLink, - BreadcrumbList, - BreadcrumbPage, - BreadcrumbSeparator -} from "@app/components/ui/breadcrumb"; -import Link from "next/link"; +import { GetSiteResponse } from "@server/routers/site"; interface ResourceLayoutProps { children: React.ReactNode; @@ -35,6 +27,7 @@ export default async function ResourceLayout(props: ResourceLayoutProps) { let authInfo = null; let resource = null; + let site = null; try { const res = await internal.get>( `/resource/${params.resourceId}`, @@ -49,6 +42,19 @@ export default async function ResourceLayout(props: ResourceLayoutProps) { redirect(`/${params.orgId}/settings/resources`); } + // Fetch site info + if (resource.siteId) { + try { + const res = await internal.get>( + `/site/${resource.siteId}`, + await authCookieHeader() + ); + site = res.data.data; + } catch { + redirect(`/${params.orgId}/settings/resources`); + } + } + try { const res = await internal.get< AxiosResponse @@ -110,7 +116,11 @@ export default async function ResourceLayout(props: ResourceLayoutProps) { /> - +
diff --git a/src/app/[orgId]/settings/resources/[resourceId]/proxy/page.tsx b/src/app/[orgId]/settings/resources/[resourceId]/proxy/page.tsx index ddf255e0..c9419865 100644 --- a/src/app/[orgId]/settings/resources/[resourceId]/proxy/page.tsx +++ b/src/app/[orgId]/settings/resources/[resourceId]/proxy/page.tsx @@ -41,7 +41,6 @@ import { TableBody, TableCaption, TableCell, - TableContainer, TableHead, TableHeader, TableRow @@ -61,7 +60,8 @@ import { SettingsSectionDescription, SettingsSectionBody, SettingsSectionFooter, - SettingsSectionForm + SettingsSectionForm, + SettingsSectionGrid } from "@app/components/Settings"; import { SwitchInput } from "@app/components/SwitchInput"; import { useRouter } from "next/navigation"; @@ -73,6 +73,8 @@ import { CollapsibleContent, CollapsibleTrigger } from "@app/components/ui/collapsible"; +import { ContainersSelector } from "@app/components/ContainersSelector"; +import { FaDocker } from "react-icons/fa"; const addTargetSchema = z.object({ ip: z.string().refine(isTargetValid), @@ -163,6 +165,9 @@ export default function ReverseProxyTargets(props: { } as z.infer }); + const watchedIp = addTargetForm.watch("ip"); + const watchedPort = addTargetForm.watch("port"); + const tlsSettingsForm = useForm({ resolver: zodResolver(tlsSettingsSchema), defaultValues: { @@ -556,115 +561,6 @@ export default function ReverseProxyTargets(props: { return ( - {resource.http && ( - - - - HTTPS & TLS Settings - - - Configure TLS settings for your resource - - - - -
- - ( - - - { - field.onChange(val); - }} - /> - - - )} - /> - -
- - - -
- - ( - - - TLS Server Name - (SNI) - - - - - - The TLS Server Name - to use for SNI. - Leave empty to use - the default. - - - - )} - /> - -
- - -
-
- - - -
- )} - @@ -767,11 +663,31 @@ export default function ReverseProxyTargets(props: { control={addTargetForm.control} name="ip" render={({ field }) => ( - + IP / Hostname + {site && site.type == "newt" && ( + { + addTargetForm.setValue( + "ip", + hostname + ); + if (port) { + addTargetForm.setValue( + "port", + port + ); + } + }} + /> + )} )} @@ -798,12 +714,7 @@ export default function ReverseProxyTargets(props: { type="submit" variant="outlinePrimary" className="mt-6" - disabled={ - !( - addTargetForm.getValues("ip") && - addTargetForm.getValues("port") - ) - } + disabled={!(watchedIp && watchedPort)} > Add Target @@ -873,59 +784,175 @@ export default function ReverseProxyTargets(props: { {resource.http && ( - - - - Additional Proxy Settings - - - Configure how your resource handles proxy settings - - - - -
- - ( - - - Custom Host Header - - - - - - The host header to set when - proxying requests. Leave - empty to use the default. - - - + + + + + Secure Connection Configuration + + + Configure SSL/TLS settings for your resource + + + + + + - - - - - - - - + className="space-y-4" + id="tls-settings-form" + > + ( + + + { + field.onChange( + val + ); + }} + /> + + + )} + /> + +
+ + + +
+ + ( + + + TLS Server Name + (SNI) + + + + + + The TLS Server + Name to use for + SNI. Leave empty + to use the + default. + + + + )} + /> + +
+ + +
+
+ + + +
+ + + + Additional Proxy Settings + + + Configure how your resource handles proxy + settings + + + + +
+ + ( + + + Custom Host Header + + + + + + The host header to set + when proxying requests. + Leave empty to use the + default. + + + + )} + /> + + +
+
+ + + +
+ )}
); diff --git a/src/app/[orgId]/settings/resources/create/page.tsx b/src/app/[orgId]/settings/resources/create/page.tsx index c1be6353..7bd90349 100644 --- a/src/app/[orgId]/settings/resources/create/page.tsx +++ b/src/app/[orgId]/settings/resources/create/page.tsx @@ -32,7 +32,7 @@ import { createApiClient } from "@app/lib/api"; import { useEnvContext } from "@app/hooks/useEnvContext"; import { toast } from "@app/hooks/useToast"; import { AxiosResponse } from "axios"; -import { Resource } from "@server/db/schemas"; +import { Resource } from "@server/db"; import { StrategySelect } from "@app/components/StrategySelect"; import { Select, diff --git a/src/app/[orgId]/settings/sites/CreateSiteForm.tsx b/src/app/[orgId]/settings/sites/CreateSiteForm.tsx index b089a2c3..7588f07f 100644 --- a/src/app/[orgId]/settings/sites/CreateSiteForm.tsx +++ b/src/app/[orgId]/settings/sites/CreateSiteForm.tsx @@ -269,7 +269,7 @@ PersistentKeepalive = 5` - NEWT_ID=${siteDefaults?.newtId} - NEWT_SECRET=${siteDefaults?.newtSecret}`; - const newtConfigDockerRun = `docker run -it fosrl/newt --id ${siteDefaults?.newtId} --secret ${siteDefaults?.newtSecret} --endpoint ${env.app.dashboardUrl}`; + const newtConfigDockerRun = `docker run -dit fosrl/newt --id ${siteDefaults?.newtId} --secret ${siteDefaults?.newtSecret} --endpoint ${env.app.dashboardUrl}`; return loadingPage ? ( diff --git a/src/app/[orgId]/settings/sites/SitesTable.tsx b/src/app/[orgId]/settings/sites/SitesTable.tsx index 2b4195eb..677588a7 100644 --- a/src/app/[orgId]/settings/sites/SitesTable.tsx +++ b/src/app/[orgId]/settings/sites/SitesTable.tsx @@ -27,6 +27,7 @@ import { formatAxiosError } from "@app/lib/api"; import { createApiClient } from "@app/lib/api"; import { useEnvContext } from "@app/hooks/useEnvContext"; import CreateSiteFormModal from "./CreateSiteModal"; +import { parseDataSize } from '@app/lib/dataSize'; export type SiteRow = { id: number; @@ -198,7 +199,9 @@ export default function SitesTable({ sites, orgId }: SitesTableProps) { ); - } + }, + sortingFn: (rowA, rowB) => + parseDataSize(rowA.original.mbIn) - parseDataSize(rowB.original.mbIn) }, { accessorKey: "mbOut", @@ -214,7 +217,9 @@ export default function SitesTable({ sites, orgId }: SitesTableProps) { ); - } + }, + sortingFn: (rowA, rowB) => + parseDataSize(rowA.original.mbOut) - parseDataSize(rowB.original.mbOut), }, { accessorKey: "type", diff --git a/src/app/[orgId]/settings/sites/[niceId]/general/page.tsx b/src/app/[orgId]/settings/sites/[niceId]/general/page.tsx index f107d960..ae9de83d 100644 --- a/src/app/[orgId]/settings/sites/[niceId]/general/page.tsx +++ b/src/app/[orgId]/settings/sites/[niceId]/general/page.tsx @@ -31,9 +31,13 @@ import { formatAxiosError } from "@app/lib/api"; import { createApiClient } from "@app/lib/api"; import { useEnvContext } from "@app/hooks/useEnvContext"; import { useState } from "react"; +import { SwitchInput } from "@app/components/SwitchInput"; +import Link from "next/link"; +import { ArrowRight, ExternalLink } from "lucide-react"; const GeneralFormSchema = z.object({ - name: z.string().nonempty("Name is required") + name: z.string().nonempty("Name is required"), + dockerSocketEnabled: z.boolean().optional() }); type GeneralFormValues = z.infer; @@ -50,7 +54,8 @@ export default function GeneralPage() { const form = useForm({ resolver: zodResolver(GeneralFormSchema), defaultValues: { - name: site?.name + name: site?.name, + dockerSocketEnabled: site?.dockerSocketEnabled ?? false }, mode: "onChange" }); @@ -60,7 +65,8 @@ export default function GeneralPage() { await api .post(`/site/${site?.siteId}`, { - name: data.name + name: data.name, + dockerSocketEnabled: data.dockerSocketEnabled }) .catch((e) => { toast({ @@ -73,7 +79,10 @@ export default function GeneralPage() { }); }); - updateSite({ name: data.name }); + updateSite({ + name: data.name, + dockerSocketEnabled: data.dockerSocketEnabled + }); toast({ title: "Site updated", @@ -102,7 +111,7 @@ export default function GeneralPage() {
)} /> + {site && site.type === "newt" && ( + ( + + + + + + + Enable Docker Socket + discovery for populating + container information. + Socket path must be provided + to Newt.{" "} + + Learn more + + + + + )} + /> + )} diff --git a/src/app/[orgId]/settings/sites/create/page.tsx b/src/app/[orgId]/settings/sites/create/page.tsx index d9f1c3f7..8cf3a58b 100644 --- a/src/app/[orgId]/settings/sites/create/page.tsx +++ b/src/app/[orgId]/settings/sites/create/page.tsx @@ -258,7 +258,7 @@ PersistentKeepalive = 5`; - NEWT_SECRET=${secret}` ], "Docker Run": [ - `docker run -it fosrl/newt --id ${id} --secret ${secret} --endpoint ${endpoint}` + `docker run -dit fosrl/newt --id ${id} --secret ${secret} --endpoint ${endpoint}` ] }, podman: { @@ -281,7 +281,7 @@ Restart=always WantedBy=default.target` ], "Podman Run": [ - `podman run -it docker.io/fosrl/newt --id ${id} --secret ${secret} --endpoint ${endpoint}` + `podman run -dit docker.io/fosrl/newt --id ${id} --secret ${secret} --endpoint ${endpoint}` ] } }; diff --git a/src/app/admin/idp/[idpId]/policies/page.tsx b/src/app/admin/idp/[idpId]/policies/page.tsx index ba108064..0701e3e2 100644 --- a/src/app/admin/idp/[idpId]/policies/page.tsx +++ b/src/app/admin/idp/[idpId]/policies/page.tsx @@ -395,7 +395,7 @@ export default function PoliciesPage() { This expression must return - thr org ID or true for the + the org ID or true for the user to be allowed to access the organization. diff --git a/src/app/admin/license/page.tsx b/src/app/admin/license/page.tsx index b86c18b3..b3cc221e 100644 --- a/src/app/admin/license/page.tsx +++ b/src/app/admin/license/page.tsx @@ -289,17 +289,17 @@ export default function LicensePage() { terms corresponding to the tier associated with your license key. -
- - View Fossorial - Commercial License & - Subscription Terms - + {/*
*/} + {/* */} + {/* View Fossorial */} + {/* Commercial License & */} + {/* Subscription Terms */} + {/* */}
@@ -503,32 +503,32 @@ export default function LicensePage() { )} - - {!licenseStatus?.isHostLicensed ? ( - <> - - - ) : ( - <> - - - )} - + {/* */} + {/* {!licenseStatus?.isHostLicensed ? ( */} + {/* <> */} + {/* */} + {/* */} + {/* ) : ( */} + {/* <> */} + {/* */} + {/* */} + {/* )} */} + {/* */} ; @@ -17,13 +20,14 @@ export default async function Page(props: { const allCookies = await cookies(); const stateCookie = allCookies.get("p_oidc_state")?.value; - // query db directly in server component because just need the name - const [idpRes] = await db - .select({ name: idp.name }) - .from(idp) - .where(eq(idp.idpId, parseInt(params.idpId!))); - if (!idpRes) { + const idpRes = await cache( + async () => await priv.get>(`/idp/${params.idpId}`) + )(); + + const foundIdp = idpRes.data?.data?.idp; + + if (!foundIdp) { return
IdP not found
; } @@ -35,7 +39,7 @@ export default async function Page(props: { code={searchParams.code} expectedState={searchParams.state} stateCookie={stateCookie} - idp={{ name: idpRes.name }} + idp={{ name: foundIdp.name }} /> ); diff --git a/src/app/auth/login/DashboardLoginForm.tsx b/src/app/auth/login/DashboardLoginForm.tsx index b15dd518..0691b343 100644 --- a/src/app/auth/login/DashboardLoginForm.tsx +++ b/src/app/auth/login/DashboardLoginForm.tsx @@ -45,8 +45,8 @@ export default function DashboardLoginForm({ Pangolin Logo
diff --git a/src/app/auth/login/page.tsx b/src/app/auth/login/page.tsx index 8227c1a0..e6be3017 100644 --- a/src/app/auth/login/page.tsx +++ b/src/app/auth/login/page.tsx @@ -6,9 +6,11 @@ import DashboardLoginForm from "./DashboardLoginForm"; import { Mail } from "lucide-react"; import { pullEnv } from "@app/lib/pullEnv"; import { cleanRedirect } from "@app/lib/cleanRedirect"; -import db from "@server/db"; -import { idp } from "@server/db/schemas"; +import { idp } from "@server/db"; import { LoginFormIDP } from "@app/components/LoginForm"; +import { priv } from "@app/lib/api"; +import { AxiosResponse } from "axios"; +import { ListIdpsResponse } from "@server/routers/idp"; export const dynamic = "force-dynamic"; @@ -34,8 +36,10 @@ export default async function Page(props: { redirectUrl = cleanRedirect(searchParams.redirect as string); } - const idps = await db.select().from(idp); - const loginIdps = idps.map((idp) => ({ + const idpsRes = await cache( + async () => await priv.get>("/idp") + )(); + const loginIdps = idpsRes.data.data.idps.map((idp) => ({ idpId: idp.idpId, name: idp.name })) as LoginFormIDP[]; diff --git a/src/app/auth/resource/[resourceId]/page.tsx b/src/app/auth/resource/[resourceId]/page.tsx index af31de98..ad5afa0f 100644 --- a/src/app/auth/resource/[resourceId]/page.tsx +++ b/src/app/auth/resource/[resourceId]/page.tsx @@ -14,8 +14,9 @@ import ResourceAccessDenied from "./ResourceAccessDenied"; import AccessToken from "./AccessToken"; import { pullEnv } from "@app/lib/pullEnv"; import { LoginFormIDP } from "@app/components/LoginForm"; -import db from "@server/db"; -import { idp } from "@server/db/schemas"; +import { ListIdpsResponse } from "@server/routers/idp"; + +export const dynamic = "force-dynamic"; export default async function ResourceAuthPage(props: { params: Promise<{ resourceId: number }>; @@ -130,8 +131,10 @@ export default async function ResourceAuthPage(props: { ); } - const idps = await db.select().from(idp); - const loginIdps = idps.map((idp) => ({ + const idpsRes = await cache( + async () => await priv.get>("/idp") + )(); + const loginIdps = idpsRes.data.data.idps.map((idp) => ({ idpId: idp.idpId, name: idp.name })) as LoginFormIDP[]; diff --git a/src/app/favicon.ico b/src/app/favicon.ico index 0ffb1c54..bcaab339 100644 Binary files a/src/app/favicon.ico and b/src/app/favicon.ico differ diff --git a/src/app/setup/page.tsx b/src/app/setup/page.tsx index 76cdc36e..5dc06aa8 100644 --- a/src/app/setup/page.tsx +++ b/src/app/setup/page.tsx @@ -101,7 +101,14 @@ export default function StepperForm() { ); const generateId = (name: string) => { - return name.toLowerCase().replace(/\s+/g, "-"); + // Replace any character that is not a letter, number, space, or hyphen with a hyphen + // Also collapse multiple hyphens and trim + return name + .toLowerCase() + .replace(/[^a-z0-9\s-]/g, "-") + .replace(/\s+/g, "-") + .replace(/-+/g, "-") + .replace(/^-+|-+$/g, ""); }; async function orgSubmit(values: z.infer) { @@ -227,23 +234,22 @@ export default function StepperForm() { type="text" {...field} onChange={(e) => { - const orgId = - generateId( - e.target - .value - ); + // Prevent "/" in orgName input + const sanitizedValue = e.target.value.replace(/\//g, "-"); + const orgId = generateId(sanitizedValue); orgForm.setValue( "orgId", orgId ); orgForm.setValue( "orgName", - e.target.value + sanitizedValue ); debouncedCheckOrgIdAvailability( orgId ); }} + value={field.value.replace(/\//g, "-")} /> diff --git a/src/components/ContainersSelector.tsx b/src/components/ContainersSelector.tsx new file mode 100644 index 00000000..edc6b77c --- /dev/null +++ b/src/components/ContainersSelector.tsx @@ -0,0 +1,673 @@ +import { useEffect, useState, FC, useCallback, useMemo } from "react"; +import { + ColumnDef, + getCoreRowModel, + useReactTable, + flexRender, + getFilteredRowModel, + VisibilityState +} from "@tanstack/react-table"; +import { Button } from "@/components/ui/button"; +import { + Credenza, + CredenzaBody, + CredenzaClose, + CredenzaContent, + CredenzaDescription, + CredenzaFooter, + CredenzaHeader, + CredenzaTitle +} from "@/components/Credenza"; +import { + Table, + TableBody, + TableCell, + TableHead, + TableHeader, + TableRow +} from "@/components/ui/table"; +import { Badge } from "@/components/ui/badge"; +import { Input } from "@/components/ui/input"; +import { + Popover, + PopoverContent, + PopoverTrigger +} from "@/components/ui/popover"; +import { + DropdownMenu, + DropdownMenuContent, + DropdownMenuTrigger, + DropdownMenuLabel, + DropdownMenuSeparator, + DropdownMenuCheckboxItem +} from "@/components/ui/dropdown-menu"; +import { ScrollArea } from "@/components/ui/scroll-area"; +import { Search, RefreshCw, Filter, Columns } from "lucide-react"; +import { GetSiteResponse, Container } from "@server/routers/site"; +import { useDockerSocket } from "@app/hooks/useDockerSocket"; +import { FaDocker } from "react-icons/fa"; + +// Type definitions based on the JSON structure + +interface ContainerSelectorProps { + site: GetSiteResponse; + onContainerSelect?: (hostname: string, port?: number) => void; +} + +export const ContainersSelector: FC = ({ + site, + onContainerSelect +}) => { + const [open, setOpen] = useState(false); + + const { isAvailable, containers, fetchContainers } = useDockerSocket(site); + + useEffect(() => { + console.log("DockerSocket isAvailable:", isAvailable); + if (isAvailable) { + fetchContainers(); + } + }, [isAvailable]); + + if (!site || !isAvailable) { + return null; + } + + const handleContainerSelect = (container: Container, port?: number) => { + // Extract hostname - prefer IP address from networks, fallback to container name + const hostname = getContainerHostname(container); + onContainerSelect?.(hostname, port); + setOpen(false); + }; + + return ( + <> + setOpen(true)} + > + View Docker Containers + + + + + Containers in {site.name} + + Select any container to use as a hostname for this + target. Click a port to use a port. + + + +
+ fetchContainers()} + /> +
+
+ + + + + +
+
+ + ); +}; + +const DockerContainersTable: FC<{ + containers: Container[]; + onContainerSelect: (container: Container, port?: number) => void; + onRefresh: () => void; +}> = ({ containers, onContainerSelect, onRefresh }) => { + const [searchInput, setSearchInput] = useState(""); + const [globalFilter, setGlobalFilter] = useState(""); + const [hideContainersWithoutPorts, setHideContainersWithoutPorts] = + useState(true); + const [hideStoppedContainers, setHideStoppedContainers] = useState(false); + const [columnVisibility, setColumnVisibility] = useState({ + labels: false + }); + + useEffect(() => { + const timer = setTimeout(() => { + setGlobalFilter(searchInput); + }, 100); + + return () => clearTimeout(timer); + }, [searchInput]); + + const getExposedPorts = useCallback((container: Container): number[] => { + const ports: number[] = []; + + container.ports?.forEach((port) => { + if (port.privatePort) { + ports.push(port.privatePort); + } + }); + + return [...new Set(ports)]; // Remove duplicates + }, []); + + const globalFilterFunction = useCallback( + (row: any, columnId: string, value: string) => { + const container = row.original as Container; + const searchValue = value.toLowerCase(); + + // Search across all relevant fields + const searchableFields = [ + container.name, + container.image, + container.state, + container.status, + getContainerHostname(container), + ...Object.keys(container.networks), + ...Object.values(container.networks) + .map((n) => n.ipAddress) + .filter(Boolean), + ...getExposedPorts(container).map((p) => p.toString()), + ...Object.entries(container.labels).flat() + ]; + + return searchableFields.some((field) => + field?.toString().toLowerCase().includes(searchValue) + ); + }, + [getExposedPorts] + ); + + const columns: ColumnDef[] = [ + { + accessorKey: "name", + header: "Name", + cell: ({ row }) => ( +
{row.original.name}
+ ) + }, + { + accessorKey: "image", + header: "Image", + cell: ({ row }) => ( +
+ {row.original.image} +
+ ) + }, + { + accessorKey: "state", + header: "State", + cell: ({ row }) => ( + + {row.original.state} + + ) + }, + { + accessorKey: "networks", + header: "Networks", + cell: ({ row }) => { + const networks = Object.keys(row.original.networks); + return ( +
+ {networks.length > 0 + ? networks.map((n) => ( + + {n} + + )) + : "-"} +
+ ); + } + }, + { + accessorKey: "hostname", + header: "Hostname/IP", + enableHiding: false, + cell: ({ row }) => ( +
+ {getContainerHostname(row.original)} +
+ ) + }, + { + accessorKey: "labels", + header: "Labels", + cell: ({ row }) => { + const labels = row.original.labels || {}; + const labelEntries = Object.entries(labels); + + if (labelEntries.length === 0) { + return -; + } + + return ( + + + + + + +
+

+ Container Labels +

+
+ {labelEntries.map(([key, value]) => ( +
+
+ {key} +
+
+ {value || ""} +
+
+ ))} +
+
+
+
+
+ ); + } + }, + { + accessorKey: "ports", + header: "Ports", + enableHiding: false, + cell: ({ row }) => { + const ports = getExposedPorts(row.original); + return ( +
+ {ports.slice(0, 2).map((port) => ( + + ))} + {ports.length > 2 && ( + + + + + + {ports.slice(2).map((port) => ( + + ))} + + + )} +
+ ); + } + }, + { + id: "actions", + header: "Actions", + cell: ({ row }) => { + const ports = getExposedPorts(row.original); + return ( + + ); + } + } + ]; + + const initialFilters = useMemo(() => { + let filtered = containers; + + // Filter by port visibility + if (hideContainersWithoutPorts) { + filtered = filtered.filter((container) => { + const ports = getExposedPorts(container); + return ports.length > 0; // Show only containers WITH ports + }); + } + + // Filter by container state + if (hideStoppedContainers) { + filtered = filtered.filter((container) => { + return container.state === "running"; + }); + } + + return filtered; + }, [ + containers, + hideContainersWithoutPorts, + hideStoppedContainers, + getExposedPorts + ]); + + const table = useReactTable({ + data: initialFilters, + columns, + getCoreRowModel: getCoreRowModel(), + getFilteredRowModel: getFilteredRowModel(), + globalFilterFn: globalFilterFunction, + state: { + globalFilter, + columnVisibility + }, + onGlobalFilterChange: setGlobalFilter, + onColumnVisibilityChange: setColumnVisibility + }); + + if (initialFilters.length === 0) { + return ( +
+
+
+ {(hideContainersWithoutPorts || + hideStoppedContainers) && + containers.length > 0 ? ( + <> +

+ No containers found matching the current + filters. +

+
+ {hideContainersWithoutPorts && ( + + )} + {hideStoppedContainers && ( + + )} +
+ + ) : ( +

+ No containers found. Make sure Docker containers + are running. +

+ )} +
+
+
+ ); + } + + return ( +
+
+
+
+ + + setSearchInput(event.target.value) + } + className="pl-8" + /> + {searchInput && + table.getFilteredRowModel().rows.length > 0 && ( +
+ {table.getFilteredRowModel().rows.length}{" "} + result + {table.getFilteredRowModel().rows.length !== + 1 + ? "s" + : ""} +
+ )} +
+
+ + + + + + + Filter Options + + + + Ports + + + Stopped + + {(hideContainersWithoutPorts || + hideStoppedContainers) && ( + <> + +
+ +
+ + )} +
+
+ + + + + + + + Toggle Columns + + + {table + .getAllColumns() + .filter((column) => column.getCanHide()) + .map((column) => { + return ( + + column.toggleVisibility( + !!value + ) + } + > + {column.id === "hostname" + ? "Hostname/IP" + : column.id} + + ); + })} + + +
+ +
+
+
+ + + {table.getHeaderGroups().map((headerGroup) => ( + + {headerGroup.headers.map((header) => ( + + {header.isPlaceholder + ? null + : flexRender( + header.column.columnDef + .header, + header.getContext() + )} + + ))} + + ))} + + + {table.getRowModel().rows?.length ? ( + table.getRowModel().rows.map((row) => ( + + {row.getVisibleCells().map((cell) => ( + + {flexRender( + cell.column.columnDef.cell, + cell.getContext() + )} + + ))} + + )) + ) : ( + + + {searchInput && !globalFilter ? ( +
+
+ Searching... +
+ ) : ( + `No containers found matching "${globalFilter}".` + )} + + + )} + +
+
+
+ ); +}; + +function getContainerHostname(container: Container): string { + // First, try to get IP from networks + const networks = Object.values(container.networks); + for (const network of networks) { + if (network.ipAddress) { + return network.ipAddress; + } + } + + // Fallback to container name (works in Docker networks) + return container.name; +} diff --git a/src/components/Layout.tsx b/src/components/Layout.tsx index e0925525..b98e1886 100644 --- a/src/components/Layout.tsx +++ b/src/components/Layout.tsx @@ -1,6 +1,6 @@ "use client"; -import React, { useState } from "react"; +import React, { useEffect, useState } from "react"; import { SidebarNav } from "@app/components/SidebarNav"; import { OrgSelector } from "@app/components/OrgSelector"; import { cn } from "@app/lib/cn"; @@ -23,6 +23,7 @@ import Link from "next/link"; import { usePathname } from "next/navigation"; import { useUserContext } from "@app/hooks/useUserContext"; import { useLicenseStatusContext } from "@app/hooks/useLicenseStatusContext"; +import { useTheme } from "next-themes"; interface LayoutProps { children: React.ReactNode; @@ -61,6 +62,30 @@ export function Layout({ const { user } = useUserContext(); const { isUnlocked } = useLicenseStatusContext(); + const { theme } = useTheme(); + const [path, setPath] = useState(""); // Default logo path + + useEffect(() => { + function getPath() { + let lightOrDark = theme; + + if (theme === "system" || !theme) { + lightOrDark = window.matchMedia("(prefers-color-scheme: dark)") + .matches + ? "dark" + : "light"; + } + + if (lightOrDark === "light") { + return "/logo/word_mark_black.png"; + } + + return "/logo/word_mark_white.png"; + } + + setPath(getPath()); + }, [theme, env]); + return (
{/* Full width header */} @@ -139,12 +164,16 @@ export function Layout({ href="/" className="flex items-center hidden md:block" > - Pangolin Logo + {path && ( + Pangolin Logo + )} {showBreadcrumbs && (
diff --git a/src/components/ui/avatar.tsx b/src/components/ui/avatar.tsx index ef6e4355..44c1b5b5 100644 --- a/src/components/ui/avatar.tsx +++ b/src/components/ui/avatar.tsx @@ -1,9 +1,9 @@ -"use client" +"use client"; -import * as React from "react" -import * as AvatarPrimitive from "@radix-ui/react-avatar" +import * as React from "react"; +import * as AvatarPrimitive from "@radix-ui/react-avatar"; -import { cn } from "@app/lib/cn" +import { cn } from "@app/lib/cn"; const Avatar = React.forwardRef< React.ElementRef, @@ -17,8 +17,8 @@ const Avatar = React.forwardRef< )} {...props} /> -)) -Avatar.displayName = AvatarPrimitive.Root.displayName +)); +Avatar.displayName = AvatarPrimitive.Root.displayName; const AvatarImage = React.forwardRef< React.ElementRef, @@ -29,8 +29,8 @@ const AvatarImage = React.forwardRef< className={cn("aspect-square h-full w-full", className)} {...props} /> -)) -AvatarImage.displayName = AvatarPrimitive.Image.displayName +)); +AvatarImage.displayName = AvatarPrimitive.Image.displayName; const AvatarFallback = React.forwardRef< React.ElementRef, @@ -44,7 +44,7 @@ const AvatarFallback = React.forwardRef< )} {...props} /> -)) -AvatarFallback.displayName = AvatarPrimitive.Fallback.displayName +)); +AvatarFallback.displayName = AvatarPrimitive.Fallback.displayName; -export { Avatar, AvatarImage, AvatarFallback } +export { Avatar, AvatarImage, AvatarFallback }; diff --git a/src/components/ui/breadcrumb.tsx b/src/components/ui/breadcrumb.tsx index dd40aa55..98c13818 100644 --- a/src/components/ui/breadcrumb.tsx +++ b/src/components/ui/breadcrumb.tsx @@ -1,16 +1,16 @@ -import * as React from "react" -import { Slot } from "@radix-ui/react-slot" -import { ChevronRight, MoreHorizontal } from "lucide-react" +import * as React from "react"; +import { Slot } from "@radix-ui/react-slot"; +import { ChevronRight, MoreHorizontal } from "lucide-react"; -import { cn } from "@app/lib/cn" +import { cn } from "@app/lib/cn"; const Breadcrumb = React.forwardRef< HTMLElement, React.ComponentPropsWithoutRef<"nav"> & { separator?: React.ReactNode } ->(({ ...props }, ref) =>
-)) +)); -CommandInput.displayName = CommandPrimitive.Input.displayName +CommandInput.displayName = CommandPrimitive.Input.displayName; const CommandList = React.forwardRef< React.ElementRef, @@ -65,9 +65,9 @@ const CommandList = React.forwardRef< className={cn("max-h-[300px] overflow-y-auto overflow-x-hidden", className)} {...props} /> -)) +)); -CommandList.displayName = CommandPrimitive.List.displayName +CommandList.displayName = CommandPrimitive.List.displayName; const CommandEmpty = React.forwardRef< React.ElementRef, @@ -78,9 +78,9 @@ const CommandEmpty = React.forwardRef< className="py-6 text-center text-sm" {...props} /> -)) +)); -CommandEmpty.displayName = CommandPrimitive.Empty.displayName +CommandEmpty.displayName = CommandPrimitive.Empty.displayName; const CommandGroup = React.forwardRef< React.ElementRef, @@ -94,9 +94,9 @@ const CommandGroup = React.forwardRef< )} {...props} /> -)) +)); -CommandGroup.displayName = CommandPrimitive.Group.displayName +CommandGroup.displayName = CommandPrimitive.Group.displayName; const CommandSeparator = React.forwardRef< React.ElementRef, @@ -107,8 +107,8 @@ const CommandSeparator = React.forwardRef< className={cn("-mx-1 h-px bg-border", className)} {...props} /> -)) -CommandSeparator.displayName = CommandPrimitive.Separator.displayName +)); +CommandSeparator.displayName = CommandPrimitive.Separator.displayName; const CommandItem = React.forwardRef< React.ElementRef, @@ -122,9 +122,9 @@ const CommandItem = React.forwardRef< )} {...props} /> -)) +)); -CommandItem.displayName = CommandPrimitive.Item.displayName +CommandItem.displayName = CommandPrimitive.Item.displayName; const CommandShortcut = ({ className, @@ -138,9 +138,9 @@ const CommandShortcut = ({ )} {...props} /> - ) -} -CommandShortcut.displayName = "CommandShortcut" + ); +}; +CommandShortcut.displayName = "CommandShortcut"; export { Command, @@ -152,4 +152,4 @@ export { CommandItem, CommandShortcut, CommandSeparator, -} +}; diff --git a/src/components/ui/dropdown-menu.tsx b/src/components/ui/dropdown-menu.tsx index 8d2f4c3c..efe369d8 100644 --- a/src/components/ui/dropdown-menu.tsx +++ b/src/components/ui/dropdown-menu.tsx @@ -1,22 +1,22 @@ -"use client" +"use client"; -import * as React from "react" -import * as DropdownMenuPrimitive from "@radix-ui/react-dropdown-menu" -import { Check, ChevronRight, Circle } from "lucide-react" +import * as React from "react"; +import * as DropdownMenuPrimitive from "@radix-ui/react-dropdown-menu"; +import { Check, ChevronRight, Circle } from "lucide-react"; -import { cn } from "@app/lib/cn" +import { cn } from "@app/lib/cn"; -const DropdownMenu = DropdownMenuPrimitive.Root +const DropdownMenu = DropdownMenuPrimitive.Root; -const DropdownMenuTrigger = DropdownMenuPrimitive.Trigger +const DropdownMenuTrigger = DropdownMenuPrimitive.Trigger; -const DropdownMenuGroup = DropdownMenuPrimitive.Group +const DropdownMenuGroup = DropdownMenuPrimitive.Group; -const DropdownMenuPortal = DropdownMenuPrimitive.Portal +const DropdownMenuPortal = DropdownMenuPrimitive.Portal; -const DropdownMenuSub = DropdownMenuPrimitive.Sub +const DropdownMenuSub = DropdownMenuPrimitive.Sub; -const DropdownMenuRadioGroup = DropdownMenuPrimitive.RadioGroup +const DropdownMenuRadioGroup = DropdownMenuPrimitive.RadioGroup; const DropdownMenuSubTrigger = React.forwardRef< React.ElementRef, @@ -36,9 +36,9 @@ const DropdownMenuSubTrigger = React.forwardRef< {children} -)) +)); DropdownMenuSubTrigger.displayName = - DropdownMenuPrimitive.SubTrigger.displayName + DropdownMenuPrimitive.SubTrigger.displayName; const DropdownMenuSubContent = React.forwardRef< React.ElementRef, @@ -52,9 +52,9 @@ const DropdownMenuSubContent = React.forwardRef< )} {...props} /> -)) +)); DropdownMenuSubContent.displayName = - DropdownMenuPrimitive.SubContent.displayName + DropdownMenuPrimitive.SubContent.displayName; const DropdownMenuContent = React.forwardRef< React.ElementRef, @@ -71,8 +71,8 @@ const DropdownMenuContent = React.forwardRef< {...props} /> -)) -DropdownMenuContent.displayName = DropdownMenuPrimitive.Content.displayName +)); +DropdownMenuContent.displayName = DropdownMenuPrimitive.Content.displayName; const DropdownMenuItem = React.forwardRef< React.ElementRef, @@ -89,8 +89,8 @@ const DropdownMenuItem = React.forwardRef< )} {...props} /> -)) -DropdownMenuItem.displayName = DropdownMenuPrimitive.Item.displayName +)); +DropdownMenuItem.displayName = DropdownMenuPrimitive.Item.displayName; const DropdownMenuCheckboxItem = React.forwardRef< React.ElementRef, @@ -112,9 +112,9 @@ const DropdownMenuCheckboxItem = React.forwardRef< {children} -)) +)); DropdownMenuCheckboxItem.displayName = - DropdownMenuPrimitive.CheckboxItem.displayName + DropdownMenuPrimitive.CheckboxItem.displayName; const DropdownMenuRadioItem = React.forwardRef< React.ElementRef, @@ -135,8 +135,8 @@ const DropdownMenuRadioItem = React.forwardRef< {children} -)) -DropdownMenuRadioItem.displayName = DropdownMenuPrimitive.RadioItem.displayName +)); +DropdownMenuRadioItem.displayName = DropdownMenuPrimitive.RadioItem.displayName; const DropdownMenuLabel = React.forwardRef< React.ElementRef, @@ -153,8 +153,8 @@ const DropdownMenuLabel = React.forwardRef< )} {...props} /> -)) -DropdownMenuLabel.displayName = DropdownMenuPrimitive.Label.displayName +)); +DropdownMenuLabel.displayName = DropdownMenuPrimitive.Label.displayName; const DropdownMenuSeparator = React.forwardRef< React.ElementRef, @@ -165,8 +165,8 @@ const DropdownMenuSeparator = React.forwardRef< className={cn("-mx-1 my-1 h-px bg-muted", className)} {...props} /> -)) -DropdownMenuSeparator.displayName = DropdownMenuPrimitive.Separator.displayName +)); +DropdownMenuSeparator.displayName = DropdownMenuPrimitive.Separator.displayName; const DropdownMenuShortcut = ({ className, @@ -177,9 +177,9 @@ const DropdownMenuShortcut = ({ className={cn("ml-auto text-xs tracking-widest opacity-60", className)} {...props} /> - ) -} -DropdownMenuShortcut.displayName = "DropdownMenuShortcut" + ); +}; +DropdownMenuShortcut.displayName = "DropdownMenuShortcut"; export { DropdownMenu, @@ -197,4 +197,4 @@ export { DropdownMenuSubContent, DropdownMenuSubTrigger, DropdownMenuRadioGroup, -} +}; diff --git a/src/components/ui/input-otp.tsx b/src/components/ui/input-otp.tsx index 57cfe388..efa4141d 100644 --- a/src/components/ui/input-otp.tsx +++ b/src/components/ui/input-otp.tsx @@ -1,10 +1,10 @@ -"use client" +"use client"; -import * as React from "react" -import { OTPInput, OTPInputContext } from "input-otp" -import { Dot } from "lucide-react" +import * as React from "react"; +import { OTPInput, OTPInputContext } from "input-otp"; +import { Dot } from "lucide-react"; -import { cn } from "@app/lib/cn" +import { cn } from "@app/lib/cn"; const InputOTP = React.forwardRef< React.ElementRef, @@ -19,23 +19,23 @@ const InputOTP = React.forwardRef< className={cn("disabled:cursor-not-allowed", className)} {...props} /> -)) -InputOTP.displayName = "InputOTP" +)); +InputOTP.displayName = "InputOTP"; const InputOTPGroup = React.forwardRef< React.ElementRef<"div">, React.ComponentPropsWithoutRef<"div"> >(({ className, ...props }, ref) => (
-)) -InputOTPGroup.displayName = "InputOTPGroup" +)); +InputOTPGroup.displayName = "InputOTPGroup"; const InputOTPSlot = React.forwardRef< React.ElementRef<"div">, React.ComponentPropsWithoutRef<"div"> & { index: number; obscured?: boolean } >(({ index, className, obscured = false, ...props }, ref) => { - const inputOTPContext = React.useContext(OTPInputContext) - const { char, hasFakeCaret, isActive } = inputOTPContext.slots[index] + const inputOTPContext = React.useContext(OTPInputContext); + const { char, hasFakeCaret, isActive } = inputOTPContext.slots[index]; return (
)}
- ) -}) -InputOTPSlot.displayName = "InputOTPSlot" + ); +}); +InputOTPSlot.displayName = "InputOTPSlot"; const InputOTPSeparator = React.forwardRef< React.ElementRef<"div">, @@ -65,7 +65,7 @@ const InputOTPSeparator = React.forwardRef<
-)) -InputOTPSeparator.displayName = "InputOTPSeparator" +)); +InputOTPSeparator.displayName = "InputOTPSeparator"; -export { InputOTP, InputOTPGroup, InputOTPSlot, InputOTPSeparator } +export { InputOTP, InputOTPGroup, InputOTPSlot, InputOTPSeparator }; diff --git a/src/components/ui/label.tsx b/src/components/ui/label.tsx index 0c85b64d..c6dad5be 100644 --- a/src/components/ui/label.tsx +++ b/src/components/ui/label.tsx @@ -1,14 +1,14 @@ -"use client" +"use client"; -import * as React from "react" -import * as LabelPrimitive from "@radix-ui/react-label" -import { cva, type VariantProps } from "class-variance-authority" +import * as React from "react"; +import * as LabelPrimitive from "@radix-ui/react-label"; +import { cva, type VariantProps } from "class-variance-authority"; -import { cn } from "@app/lib/cn" +import { cn } from "@app/lib/cn"; const labelVariants = cva( "text-sm font-medium leading-none peer-disabled:cursor-not-allowed peer-disabled:opacity-70" -) +); const Label = React.forwardRef< React.ElementRef, @@ -20,7 +20,7 @@ const Label = React.forwardRef< className={cn(labelVariants(), className)} {...props} /> -)) -Label.displayName = LabelPrimitive.Root.displayName +)); +Label.displayName = LabelPrimitive.Root.displayName; -export { Label } +export { Label }; diff --git a/src/components/ui/popover.tsx b/src/components/ui/popover.tsx index d283903d..715fa61c 100644 --- a/src/components/ui/popover.tsx +++ b/src/components/ui/popover.tsx @@ -1,11 +1,11 @@ -"use client" +"use client"; -import * as React from "react" -import * as PopoverPrimitive from "@radix-ui/react-popover" +import * as React from "react"; +import * as PopoverPrimitive from "@radix-ui/react-popover"; -import { cn } from "@app/lib/cn" +import { cn } from "@app/lib/cn"; -const Popover = PopoverPrimitive.Root +const Popover = PopoverPrimitive.Root; const PopoverTrigger = React.forwardRef< React.ElementRef, @@ -16,7 +16,7 @@ const PopoverTrigger = React.forwardRef< className={cn(className, "rounded-md")} {...props} /> -)) +)); const PopoverContent = React.forwardRef< React.ElementRef, @@ -34,7 +34,7 @@ const PopoverContent = React.forwardRef< {...props} /> -)) -PopoverContent.displayName = PopoverPrimitive.Content.displayName +)); +PopoverContent.displayName = PopoverPrimitive.Content.displayName; -export { Popover, PopoverTrigger, PopoverContent } +export { Popover, PopoverTrigger, PopoverContent }; diff --git a/src/components/ui/radio-group.tsx b/src/components/ui/radio-group.tsx index f0bf50ac..edce7ce9 100644 --- a/src/components/ui/radio-group.tsx +++ b/src/components/ui/radio-group.tsx @@ -1,10 +1,10 @@ -"use client" +"use client"; -import * as React from "react" -import * as RadioGroupPrimitive from "@radix-ui/react-radio-group" -import { Circle } from "lucide-react" +import * as React from "react"; +import * as RadioGroupPrimitive from "@radix-ui/react-radio-group"; +import { Circle } from "lucide-react"; -import { cn } from "@app/lib/cn" +import { cn } from "@app/lib/cn"; const RadioGroup = React.forwardRef< React.ElementRef, @@ -16,9 +16,9 @@ const RadioGroup = React.forwardRef< {...props} ref={ref} /> - ) -}) -RadioGroup.displayName = RadioGroupPrimitive.Root.displayName + ); +}); +RadioGroup.displayName = RadioGroupPrimitive.Root.displayName; const RadioGroupItem = React.forwardRef< React.ElementRef, @@ -37,8 +37,8 @@ const RadioGroupItem = React.forwardRef< - ) -}) -RadioGroupItem.displayName = RadioGroupPrimitive.Item.displayName + ); +}); +RadioGroupItem.displayName = RadioGroupPrimitive.Item.displayName; -export { RadioGroup, RadioGroupItem } +export { RadioGroup, RadioGroupItem }; diff --git a/src/components/ui/scroll-area.tsx b/src/components/ui/scroll-area.tsx index 4f6b1fcf..2c2df285 100644 --- a/src/components/ui/scroll-area.tsx +++ b/src/components/ui/scroll-area.tsx @@ -1,48 +1,58 @@ -"use client" +"use client"; -import * as React from "react" -import * as ScrollAreaPrimitive from "@radix-ui/react-scroll-area" +import * as React from "react"; +import * as ScrollAreaPrimitive from "@radix-ui/react-scroll-area"; +import { cn } from "@app/lib/cn"; -import { cn } from "@app/lib/cn" -const ScrollArea = React.forwardRef< - React.ElementRef, - React.ComponentPropsWithoutRef ->(({ className, children, ...props }, ref) => ( - - - {children} - - - - -)) -ScrollArea.displayName = ScrollAreaPrimitive.Root.displayName +function ScrollArea({ + className, + children, + ...props +}: React.ComponentProps) { + return ( + + + {children} + + + + + ); +} -const ScrollBar = React.forwardRef< - React.ElementRef, - React.ComponentPropsWithoutRef ->(({ className, orientation = "vertical", ...props }, ref) => ( - - - -)) -ScrollBar.displayName = ScrollAreaPrimitive.ScrollAreaScrollbar.displayName +function ScrollBar({ + className, + orientation = "vertical", + ...props +}: React.ComponentProps) { + return ( + + + + ); +} -export { ScrollArea, ScrollBar } +export { ScrollArea, ScrollBar }; diff --git a/src/components/ui/select.tsx b/src/components/ui/select.tsx index cd9f6678..214e3712 100644 --- a/src/components/ui/select.tsx +++ b/src/components/ui/select.tsx @@ -1,16 +1,16 @@ -"use client" +"use client"; -import * as React from "react" -import * as SelectPrimitive from "@radix-ui/react-select" -import { Check, ChevronDown, ChevronUp } from "lucide-react" +import * as React from "react"; +import * as SelectPrimitive from "@radix-ui/react-select"; +import { Check, ChevronDown, ChevronUp } from "lucide-react"; -import { cn } from "@app/lib/cn" +import { cn } from "@app/lib/cn"; -const Select = SelectPrimitive.Root +const Select = SelectPrimitive.Root; -const SelectGroup = SelectPrimitive.Group +const SelectGroup = SelectPrimitive.Group; -const SelectValue = SelectPrimitive.Value +const SelectValue = SelectPrimitive.Value; const SelectTrigger = React.forwardRef< React.ElementRef, @@ -30,8 +30,8 @@ const SelectTrigger = React.forwardRef< -)) -SelectTrigger.displayName = SelectPrimitive.Trigger.displayName +)); +SelectTrigger.displayName = SelectPrimitive.Trigger.displayName; const SelectScrollUpButton = React.forwardRef< React.ElementRef, @@ -47,8 +47,8 @@ const SelectScrollUpButton = React.forwardRef< > -)) -SelectScrollUpButton.displayName = SelectPrimitive.ScrollUpButton.displayName +)); +SelectScrollUpButton.displayName = SelectPrimitive.ScrollUpButton.displayName; const SelectScrollDownButton = React.forwardRef< React.ElementRef, @@ -64,9 +64,9 @@ const SelectScrollDownButton = React.forwardRef< > -)) +)); SelectScrollDownButton.displayName = - SelectPrimitive.ScrollDownButton.displayName + SelectPrimitive.ScrollDownButton.displayName; const SelectContent = React.forwardRef< React.ElementRef, @@ -97,8 +97,8 @@ const SelectContent = React.forwardRef< -)) -SelectContent.displayName = SelectPrimitive.Content.displayName +)); +SelectContent.displayName = SelectPrimitive.Content.displayName; const SelectLabel = React.forwardRef< React.ElementRef, @@ -109,8 +109,8 @@ const SelectLabel = React.forwardRef< className={cn("py-1.5 pl-8 pr-2 text-sm font-semibold", className)} {...props} /> -)) -SelectLabel.displayName = SelectPrimitive.Label.displayName +)); +SelectLabel.displayName = SelectPrimitive.Label.displayName; const SelectItem = React.forwardRef< React.ElementRef, @@ -132,8 +132,8 @@ const SelectItem = React.forwardRef< {children} -)) -SelectItem.displayName = SelectPrimitive.Item.displayName +)); +SelectItem.displayName = SelectPrimitive.Item.displayName; const SelectSeparator = React.forwardRef< React.ElementRef, @@ -144,8 +144,8 @@ const SelectSeparator = React.forwardRef< className={cn("-mx-1 my-1 h-px bg-muted", className)} {...props} /> -)) -SelectSeparator.displayName = SelectPrimitive.Separator.displayName +)); +SelectSeparator.displayName = SelectPrimitive.Separator.displayName; export { Select, @@ -158,4 +158,4 @@ export { SelectSeparator, SelectScrollUpButton, SelectScrollDownButton, -} +}; diff --git a/src/components/ui/separator.tsx b/src/components/ui/separator.tsx index c59cac0d..33ae97e3 100644 --- a/src/components/ui/separator.tsx +++ b/src/components/ui/separator.tsx @@ -1,9 +1,9 @@ -"use client" +"use client"; -import * as React from "react" -import * as SeparatorPrimitive from "@radix-ui/react-separator" +import * as React from "react"; +import * as SeparatorPrimitive from "@radix-ui/react-separator"; -import { cn } from "@app/lib/cn" +import { cn } from "@app/lib/cn"; const Separator = React.forwardRef< React.ElementRef, @@ -25,7 +25,7 @@ const Separator = React.forwardRef< {...props} /> ) -) -Separator.displayName = SeparatorPrimitive.Root.displayName +); +Separator.displayName = SeparatorPrimitive.Root.displayName; -export { Separator } +export { Separator }; diff --git a/src/components/ui/sheet.tsx b/src/components/ui/sheet.tsx index 44cdf853..e3f5b4d6 100644 --- a/src/components/ui/sheet.tsx +++ b/src/components/ui/sheet.tsx @@ -1,19 +1,19 @@ -"use client" +"use client"; -import * as React from "react" -import * as SheetPrimitive from "@radix-ui/react-dialog" -import { cva, type VariantProps } from "class-variance-authority" -import { X } from "lucide-react" +import * as React from "react"; +import * as SheetPrimitive from "@radix-ui/react-dialog"; +import { cva, type VariantProps } from "class-variance-authority"; +import { X } from "lucide-react"; -import { cn } from "@app/lib/cn" +import { cn } from "@app/lib/cn"; -const Sheet = SheetPrimitive.Root +const Sheet = SheetPrimitive.Root; -const SheetTrigger = SheetPrimitive.Trigger +const SheetTrigger = SheetPrimitive.Trigger; -const SheetClose = SheetPrimitive.Close +const SheetClose = SheetPrimitive.Close; -const SheetPortal = SheetPrimitive.Portal +const SheetPortal = SheetPrimitive.Portal; const SheetOverlay = React.forwardRef< React.ElementRef, @@ -27,8 +27,8 @@ const SheetOverlay = React.forwardRef< {...props} ref={ref} /> -)) -SheetOverlay.displayName = SheetPrimitive.Overlay.displayName +)); +SheetOverlay.displayName = SheetPrimitive.Overlay.displayName; const sheetVariants = cva( "fixed z-50 gap-4 bg-card p-6 shadow-lg transition ease-in-out data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:duration-100 data-[state=open]:duration-300", @@ -47,7 +47,7 @@ const sheetVariants = cva( side: "right", }, } -) +); interface SheetContentProps extends React.ComponentPropsWithoutRef, @@ -71,8 +71,8 @@ const SheetContent = React.forwardRef< {/* */} -)) -SheetContent.displayName = SheetPrimitive.Content.displayName +)); +SheetContent.displayName = SheetPrimitive.Content.displayName; const SheetHeader = ({ className, @@ -85,8 +85,8 @@ const SheetHeader = ({ )} {...props} /> -) -SheetHeader.displayName = "SheetHeader" +); +SheetHeader.displayName = "SheetHeader"; const SheetFooter = ({ className, @@ -99,8 +99,8 @@ const SheetFooter = ({ )} {...props} /> -) -SheetFooter.displayName = "SheetFooter" +); +SheetFooter.displayName = "SheetFooter"; const SheetTitle = React.forwardRef< React.ElementRef, @@ -111,8 +111,8 @@ const SheetTitle = React.forwardRef< className={cn("text-lg font-semibold text-foreground", className)} {...props} /> -)) -SheetTitle.displayName = SheetPrimitive.Title.displayName +)); +SheetTitle.displayName = SheetPrimitive.Title.displayName; const SheetDescription = React.forwardRef< React.ElementRef, @@ -123,8 +123,8 @@ const SheetDescription = React.forwardRef< className={cn("text-sm text-muted-foreground", className)} {...props} /> -)) -SheetDescription.displayName = SheetPrimitive.Description.displayName +)); +SheetDescription.displayName = SheetPrimitive.Description.displayName; export { Sheet, @@ -137,4 +137,4 @@ export { SheetFooter, SheetTitle, SheetDescription, -} +}; diff --git a/src/components/ui/switch.tsx b/src/components/ui/switch.tsx index 18c9279c..4eecee3a 100644 --- a/src/components/ui/switch.tsx +++ b/src/components/ui/switch.tsx @@ -1,9 +1,9 @@ -"use client" +"use client"; -import * as React from "react" -import * as SwitchPrimitives from "@radix-ui/react-switch" +import * as React from "react"; +import * as SwitchPrimitives from "@radix-ui/react-switch"; -import { cn } from "@app/lib/cn" +import { cn } from "@app/lib/cn"; const Switch = React.forwardRef< React.ElementRef, @@ -23,7 +23,7 @@ const Switch = React.forwardRef< )} /> -)) -Switch.displayName = SwitchPrimitives.Root.displayName +)); +Switch.displayName = SwitchPrimitives.Root.displayName; -export { Switch } +export { Switch }; diff --git a/src/components/ui/table.tsx b/src/components/ui/table.tsx index 7bfec308..069e68b8 100644 --- a/src/components/ui/table.tsx +++ b/src/components/ui/table.tsx @@ -1,121 +1,138 @@ -import * as React from "react" +import * as React from "react"; -import { cn } from "@app/lib/cn" +import { cn } from "@app/lib/cn"; export function TableContainer({ children }: { children: React.ReactNode }) { - return
{children}
+ return
{children}
; } const Table = React.forwardRef< - HTMLTableElement, - React.HTMLAttributes ->(({ className, ...props }, ref) => ( -
- - -)) -Table.displayName = "Table" + HTMLTableElement, + React.HTMLAttributes & { sticky?: boolean } +>(({ className, sticky, ...props }, ref) => ( +
+
+ +)); +Table.displayName = "Table"; const TableHeader = React.forwardRef< - HTMLTableSectionElement, - React.HTMLAttributes ->(({ className, ...props }, ref) => ( - -)) -TableHeader.displayName = "TableHeader" + HTMLTableSectionElement, + React.HTMLAttributes & { sticky?: boolean } +>(({ className, sticky, ...props }, ref) => ( + +)); +TableHeader.displayName = "TableHeader"; const TableBody = React.forwardRef< - HTMLTableSectionElement, - React.HTMLAttributes + HTMLTableSectionElement, + React.HTMLAttributes >(({ className, ...props }, ref) => ( - -)) -TableBody.displayName = "TableBody" + +)); +TableBody.displayName = "TableBody"; const TableFooter = React.forwardRef< - HTMLTableSectionElement, - React.HTMLAttributes + HTMLTableSectionElement, + React.HTMLAttributes >(({ className, ...props }, ref) => ( - tr]:last:border-b-0", - className - )} - {...props} - /> -)) -TableFooter.displayName = "TableFooter" + tr]:last:border-b-0", + className + )} + {...props} + /> +)); +TableFooter.displayName = "TableFooter"; const TableRow = React.forwardRef< - HTMLTableRowElement, - React.HTMLAttributes + HTMLTableRowElement, + React.HTMLAttributes >(({ className, ...props }, ref) => ( - -)) -TableRow.displayName = "TableRow" + +)); +TableRow.displayName = "TableRow"; const TableHead = React.forwardRef< - HTMLTableCellElement, - React.ThHTMLAttributes + HTMLTableCellElement, + React.ThHTMLAttributes >(({ className, ...props }, ref) => ( -
-)) -TableHead.displayName = "TableHead" + +)); +TableHead.displayName = "TableHead"; const TableCell = React.forwardRef< - HTMLTableCellElement, - React.TdHTMLAttributes + HTMLTableCellElement, + React.TdHTMLAttributes >(({ className, ...props }, ref) => ( - -)) -TableCell.displayName = "TableCell" + +)); +TableCell.displayName = "TableCell"; const TableCaption = React.forwardRef< - HTMLTableCaptionElement, - React.HTMLAttributes + HTMLTableCaptionElement, + React.HTMLAttributes >(({ className, ...props }, ref) => ( -
-)) -TableCaption.displayName = "TableCaption" + +)); +TableCaption.displayName = "TableCaption"; export { - Table, - TableHeader, - TableBody, - TableFooter, - TableHead, - TableRow, - TableCell, - TableCaption, -} + Table, + TableHeader, + TableBody, + TableFooter, + TableHead, + TableRow, + TableCell, + TableCaption +}; diff --git a/src/components/ui/tabs.tsx b/src/components/ui/tabs.tsx index aa76c090..b11c16c0 100644 --- a/src/components/ui/tabs.tsx +++ b/src/components/ui/tabs.tsx @@ -1,11 +1,11 @@ -"use client" +"use client"; -import * as React from "react" -import * as TabsPrimitive from "@radix-ui/react-tabs" +import * as React from "react"; +import * as TabsPrimitive from "@radix-ui/react-tabs"; -import { cn } from "@app/lib/cn" +import { cn } from "@app/lib/cn"; -const Tabs = TabsPrimitive.Root +const Tabs = TabsPrimitive.Root; const TabsList = React.forwardRef< React.ElementRef, @@ -19,8 +19,8 @@ const TabsList = React.forwardRef< )} {...props} /> -)) -TabsList.displayName = TabsPrimitive.List.displayName +)); +TabsList.displayName = TabsPrimitive.List.displayName; const TabsTrigger = React.forwardRef< React.ElementRef, @@ -34,8 +34,8 @@ const TabsTrigger = React.forwardRef< )} {...props} /> -)) -TabsTrigger.displayName = TabsPrimitive.Trigger.displayName +)); +TabsTrigger.displayName = TabsPrimitive.Trigger.displayName; const TabsContent = React.forwardRef< React.ElementRef, @@ -49,7 +49,7 @@ const TabsContent = React.forwardRef< )} {...props} /> -)) -TabsContent.displayName = TabsPrimitive.Content.displayName +)); +TabsContent.displayName = TabsPrimitive.Content.displayName; -export { Tabs, TabsList, TabsTrigger, TabsContent } +export { Tabs, TabsList, TabsTrigger, TabsContent }; diff --git a/src/components/ui/textarea.tsx b/src/components/ui/textarea.tsx index a0e91293..9e5c16bd 100644 --- a/src/components/ui/textarea.tsx +++ b/src/components/ui/textarea.tsx @@ -1,6 +1,6 @@ -import * as React from "react" +import * as React from "react"; -import { cn } from "@app/lib/cn" +import { cn } from "@app/lib/cn"; export interface TextareaProps extends React.TextareaHTMLAttributes {} @@ -16,9 +16,9 @@ const Textarea = React.forwardRef( ref={ref} {...props} /> - ) + ); } -) -Textarea.displayName = "Textarea" +); +Textarea.displayName = "Textarea"; -export { Textarea } +export { Textarea }; diff --git a/src/components/ui/toast.tsx b/src/components/ui/toast.tsx index af5d5ed4..39615568 100644 --- a/src/components/ui/toast.tsx +++ b/src/components/ui/toast.tsx @@ -1,13 +1,13 @@ -"use client" +"use client"; -import * as React from "react" -import * as ToastPrimitives from "@radix-ui/react-toast" -import { cva, type VariantProps } from "class-variance-authority" -import { X } from "lucide-react" +import * as React from "react"; +import * as ToastPrimitives from "@radix-ui/react-toast"; +import { cva, type VariantProps } from "class-variance-authority"; +import { X } from "lucide-react"; -import { cn } from "@app/lib/cn" +import { cn } from "@app/lib/cn"; -const ToastProvider = ToastPrimitives.Provider +const ToastProvider = ToastPrimitives.Provider; const ToastViewport = React.forwardRef< React.ElementRef, @@ -21,8 +21,8 @@ const ToastViewport = React.forwardRef< )} {...props} /> -)) -ToastViewport.displayName = ToastPrimitives.Viewport.displayName +)); +ToastViewport.displayName = ToastPrimitives.Viewport.displayName; const toastVariants = cva( "group pointer-events-auto relative flex w-full items-center justify-between space-x-4 overflow-hidden rounded-md border p-3 pr-8 transition-all data-[swipe=cancel]:translate-x-0 data-[swipe=end]:translate-x-[var(--radix-toast-swipe-end-x)] data-[swipe=move]:translate-x-[var(--radix-toast-swipe-move-x)] data-[swipe=move]:transition-none data-[state=open]:animate-in data-[state=open]:fade-in data-[state=closed]:animate-out data-[state=closed]:fade-out data-[swipe=end]:animate-out", @@ -38,7 +38,7 @@ const toastVariants = cva( variant: "default", }, } -) +); const Toast = React.forwardRef< React.ElementRef, @@ -51,9 +51,9 @@ const Toast = React.forwardRef< className={cn(toastVariants({ variant }), className)} {...props} /> - ) -}) -Toast.displayName = ToastPrimitives.Root.displayName + ); +}); +Toast.displayName = ToastPrimitives.Root.displayName; const ToastAction = React.forwardRef< React.ElementRef, @@ -67,8 +67,8 @@ const ToastAction = React.forwardRef< )} {...props} /> -)) -ToastAction.displayName = ToastPrimitives.Action.displayName +)); +ToastAction.displayName = ToastPrimitives.Action.displayName; const ToastClose = React.forwardRef< React.ElementRef, @@ -85,8 +85,8 @@ const ToastClose = React.forwardRef< > -)) -ToastClose.displayName = ToastPrimitives.Close.displayName +)); +ToastClose.displayName = ToastPrimitives.Close.displayName; const ToastTitle = React.forwardRef< React.ElementRef, @@ -97,8 +97,8 @@ const ToastTitle = React.forwardRef< className={cn("text-sm font-semibold", className)} {...props} /> -)) -ToastTitle.displayName = ToastPrimitives.Title.displayName +)); +ToastTitle.displayName = ToastPrimitives.Title.displayName; const ToastDescription = React.forwardRef< React.ElementRef, @@ -109,8 +109,8 @@ const ToastDescription = React.forwardRef< className={cn("text-sm opacity-90", className)} {...props} /> -)) -ToastDescription.displayName = ToastPrimitives.Description.displayName +)); +ToastDescription.displayName = ToastPrimitives.Description.displayName; type ToastProps = React.ComponentPropsWithoutRef @@ -126,4 +126,4 @@ export { ToastDescription, ToastClose, ToastAction, -} +}; diff --git a/src/components/ui/toaster.tsx b/src/components/ui/toaster.tsx index 16c780bc..79a87d26 100644 --- a/src/components/ui/toaster.tsx +++ b/src/components/ui/toaster.tsx @@ -1,6 +1,6 @@ -"use client" +"use client"; -import { useToast } from "@/hooks/useToast" +import { useToast } from "@/hooks/useToast"; import { Toast, ToastClose, @@ -8,10 +8,10 @@ import { ToastProvider, ToastTitle, ToastViewport, -} from "@/components/ui/toast" +} from "@/components/ui/toast"; export function Toaster() { - const { toasts } = useToast() + const { toasts } = useToast(); return ( @@ -27,9 +27,9 @@ export function Toaster() { {action} - ) + ); })} - ) + ); } diff --git a/src/contexts/resourceContext.ts b/src/contexts/resourceContext.ts index bb5501a6..d24a948b 100644 --- a/src/contexts/resourceContext.ts +++ b/src/contexts/resourceContext.ts @@ -1,9 +1,11 @@ import { GetResourceAuthInfoResponse } from "@server/routers/resource"; import { GetResourceResponse } from "@server/routers/resource/getResource"; +import { GetSiteResponse } from "@server/routers/site"; import { createContext } from "react"; interface ResourceContextType { resource: GetResourceResponse; + site: GetSiteResponse | null; authInfo: GetResourceAuthInfoResponse; updateResource: (updatedResource: Partial) => void; updateAuthInfo: ( diff --git a/src/hooks/useDockerSocket.ts b/src/hooks/useDockerSocket.ts new file mode 100644 index 00000000..dc4f08f4 --- /dev/null +++ b/src/hooks/useDockerSocket.ts @@ -0,0 +1,168 @@ +import { createApiClient, formatAxiosError } from "@app/lib/api"; +import { useCallback, useEffect, useState } from "react"; +import { useEnvContext } from "./useEnvContext"; +import { + Container, + GetDockerStatusResponse, + ListContainersResponse, + TriggerFetchResponse +} from "@server/routers/site"; +import { AxiosResponse } from "axios"; +import { toast } from "./useToast"; +import { Site } from "@server/db"; + +const sleep = (ms: number) => new Promise((resolve) => setTimeout(resolve, ms)); + +export function useDockerSocket(site: Site) { + console.log(`useDockerSocket initialized for site ID: ${site.siteId}`); + + const [dockerSocket, setDockerSocket] = useState(); + const [containers, setContainers] = useState([]); + + const api = createApiClient(useEnvContext()); + + const { dockerSocketEnabled: rawIsEnabled = true, type: siteType } = site || {}; + const isEnabled = rawIsEnabled && siteType === "newt"; + const { isAvailable = false, socketPath } = dockerSocket || {}; + + const checkDockerSocket = useCallback(async () => { + if (!isEnabled) { + console.warn("Docker socket is not enabled for this site."); + return; + } + try { + const res = await api.post(`/site/${site.siteId}/docker/check`); + console.log("Docker socket check response:", res); + } catch (error) { + console.error("Failed to check Docker socket:", error); + } + }, [api, site.siteId, isEnabled]); + + const getDockerSocketStatus = useCallback(async () => { + if (!isEnabled) { + console.warn("Docker socket is not enabled for this site."); + return; + } + + try { + const res = await api.get>( + `/site/${site.siteId}/docker/status` + ); + + if (res.status === 200) { + setDockerSocket(res.data.data); + } else { + console.error("Failed to get Docker status:", res); + toast({ + variant: "destructive", + title: "Failed to get Docker status", + description: + "An error occurred while fetching Docker status." + }); + } + } catch (error) { + console.error("Failed to get Docker status:", error); + toast({ + variant: "destructive", + title: "Failed to get Docker status", + description: "An error occurred while fetching Docker status." + }); + } + }, [api, site.siteId, isEnabled]); + + const getContainers = useCallback( + async (maxRetries: number = 3) => { + if (!isEnabled || !isAvailable) { + console.warn("Docker socket is not enabled or available."); + return; + } + + const fetchContainerList = async () => { + if (!isEnabled || !isAvailable) { + return; + } + + let attempt = 0; + while (attempt < maxRetries) { + try { + const res = await api.get< + AxiosResponse + >(`/site/${site.siteId}/docker/containers`); + setContainers(res.data.data); + return res.data.data; + } catch (error: any) { + attempt++; + + // Check if the error is a 425 (Too Early) status + if (error?.response?.status === 425) { + if (attempt < maxRetries) { + console.log( + `Containers not ready yet (attempt ${attempt}/${maxRetries}). Retrying in 250ms...` + ); + await sleep(250); + continue; + } else { + console.warn( + "Max retry attempts reached. Containers may still be loading." + ); + // toast({ + // variant: "destructive", + // title: "Containers not ready", + // description: + // "Containers are still loading. Please try again in a moment." + // }); + } + } else { + console.error( + "Failed to fetch Docker containers:", + error + ); + toast({ + variant: "destructive", + title: "Failed to fetch containers", + description: formatAxiosError( + error, + "An error occurred while fetching containers" + ) + }); + } + break; + } + } + }; + + try { + const res = await api.post>( + `/site/${site.siteId}/docker/trigger` + ); + // TODO: identify a way to poll the server for latest container list periodically? + await fetchContainerList(); + return res.data.data; + } catch (error) { + console.error("Failed to trigger Docker containers:", error); + } + }, + [api, site.siteId, isEnabled, isAvailable] + ); + + // 2. Docker socket status monitoring + useEffect(() => { + if (!isEnabled || isAvailable) { + return; + } + + checkDockerSocket(); + getDockerSocketStatus(); + + }, [isEnabled, isAvailable, checkDockerSocket, getDockerSocketStatus]); + + return { + isEnabled, + isAvailable: isEnabled && isAvailable, + socketPath, + containers, + check: checkDockerSocket, + status: getDockerSocketStatus, + fetchContainers: getContainers + }; +} diff --git a/src/lib/dataSize.ts b/src/lib/dataSize.ts new file mode 100644 index 00000000..67439d31 --- /dev/null +++ b/src/lib/dataSize.ts @@ -0,0 +1,21 @@ +export function parseDataSize(sizeStr: string): number { + if (typeof sizeStr !== 'string') return 0; + + const match = /^\s*([\d.]+)\s*([KMGT]?B)\s*$/i.exec(sizeStr); + if (!match) return 0; + + const [ , numStr, unitRaw ] = match; + const num = parseFloat(numStr); + if (isNaN(num)) return 0; + + const unit = unitRaw.toUpperCase(); + const multipliers = { + B: 1, + KB: 1024, + MB: 1024 ** 2, + GB: 1024 ** 3, + TB: 1024 ** 4, + } as const; + + return num * (multipliers[unit as keyof typeof multipliers] ?? 1); +} \ No newline at end of file diff --git a/src/providers/ResourceProvider.tsx b/src/providers/ResourceProvider.tsx index cd6229a4..37e30580 100644 --- a/src/providers/ResourceProvider.tsx +++ b/src/providers/ResourceProvider.tsx @@ -3,18 +3,21 @@ import ResourceContext from "@app/contexts/resourceContext"; import { GetResourceAuthInfoResponse } from "@server/routers/resource"; import { GetResourceResponse } from "@server/routers/resource/getResource"; +import { GetSiteResponse } from "@server/routers/site"; import { useState } from "react"; interface ResourceProviderProps { children: React.ReactNode; resource: GetResourceResponse; + site: GetSiteResponse | null; authInfo: GetResourceAuthInfoResponse; } export function ResourceProvider({ children, + site, resource: serverResource, - authInfo: serverAuthInfo, + authInfo: serverAuthInfo }: ResourceProviderProps) { const [resource, setResource] = useState(serverResource); @@ -34,7 +37,7 @@ export function ResourceProvider({ return { ...prev, - ...updatedResource, + ...updatedResource }; }); }; @@ -53,14 +56,14 @@ export function ResourceProvider({ return { ...prev, - ...updatedAuthInfo, + ...updatedAuthInfo }; }); }; return ( {children}