diff --git a/.github/dependabot.yml b/.github/dependabot.yml
new file mode 100644
index 0000000..ab556e9
--- /dev/null
+++ b/.github/dependabot.yml
@@ -0,0 +1,29 @@
+version: 2
+updates:
+ # Frontend (root package.json)
+ - package-ecosystem: "npm"
+ directory: "/"
+ schedule:
+ interval: "weekly"
+ day: "monday"
+ time: "08:00"
+ open-pull-requests-limit: 10
+ groups:
+ dev-dependencies:
+ dependency-type: "development"
+ production-dependencies:
+ dependency-type: "production"
+
+ # Backend
+ - package-ecosystem: "npm"
+ directory: "/backend"
+ schedule:
+ interval: "weekly"
+ day: "monday"
+ time: "08:00"
+ open-pull-requests-limit: 10
+ groups:
+ backend-dev:
+ dependency-type: "development"
+ backend-prod:
+ dependency-type: "production"
diff --git a/.github/workflows/security.yml b/.github/workflows/security.yml
new file mode 100644
index 0000000..c030d60
--- /dev/null
+++ b/.github/workflows/security.yml
@@ -0,0 +1,76 @@
+name: Security Audit
+
+on:
+ push:
+ branches: [main, pre-deployment]
+ pull_request:
+ branches: [main]
+ schedule:
+ # Every Monday at 08:00 UTC
+ - cron: '0 8 * * 1'
+
+jobs:
+ audit-frontend:
+ name: Frontend — npm audit
+ runs-on: ubuntu-latest
+ steps:
+ - uses: actions/checkout@v4
+
+ - name: Setup Node
+ uses: actions/setup-node@v4
+ with:
+ node-version: '20'
+ cache: 'npm'
+
+ - name: Install dependencies
+ run: npm ci
+
+ - name: Run audit (fail on high+)
+ run: npm audit --audit-level=high
+
+ audit-backend:
+ name: Backend — npm audit
+ runs-on: ubuntu-latest
+ steps:
+ - uses: actions/checkout@v4
+
+ - name: Setup Node
+ uses: actions/setup-node@v4
+ with:
+ node-version: '20'
+ cache: 'npm'
+ cache-dependency-path: backend/package-lock.json
+
+ - name: Install backend dependencies
+ working-directory: backend
+ run: npm ci
+
+ - name: Run audit (fail on high+)
+ working-directory: backend
+ run: npm audit --audit-level=high
+
+ typecheck:
+ name: TypeScript — type check
+ runs-on: ubuntu-latest
+ steps:
+ - uses: actions/checkout@v4
+
+ - name: Setup Node
+ uses: actions/setup-node@v4
+ with:
+ node-version: '20'
+ cache: 'npm'
+
+ - name: Install dependencies
+ run: npm ci
+
+ - name: Type check frontend
+ run: npx tsc --noEmit
+
+ - name: Install backend deps
+ working-directory: backend
+ run: npm ci
+
+ - name: Type check backend
+ working-directory: backend
+ run: npx tsc --noEmit
diff --git a/.gitignore b/.gitignore
index 341517a..b2c79d1 100644
--- a/.gitignore
+++ b/.gitignore
@@ -3,4 +3,6 @@
node_modules
dist
.DS_Store
-backend/prisma/schema.prisma
\ No newline at end of file
+backend/prisma/schema.prisma
+backups/
+*.log
\ No newline at end of file
diff --git a/CLAUDE.md b/CLAUDE.md
new file mode 100644
index 0000000..989c87f
--- /dev/null
+++ b/CLAUDE.md
@@ -0,0 +1,150 @@
+# OpenStudbook — Dev Environment
+
+## Stack
+
+| Layer | Tool | Port |
+|---|---|---|
+| Frontend | Vite (React + TypeScript) | 3000 |
+| Backend | Express + ts-node-dev | 3001 |
+| Database | MySQL | 3306 |
+| Mail catcher | maildev | SMTP 1025 · Web UI 1080 |
+
+## Starting the dev environment
+
+### 1. Backend
+```bash
+cd backend && npm run dev
+```
+
+### 2. Frontend
+```bash
+npm run dev
+```
+
+### 3. Mail catcher (maildev)
+```bash
+maildev --smtp 1025 --web 1080
+```
+Web UI: http://localhost:1080
+All outbound emails are caught here — nothing reaches real inboxes.
+
+> maildev is installed as a global npm package:
+> `npm install -g maildev`
+
+### 4. Cloudflare tunnel (public URL)
+```bash
+npm run tunnel
+```
+Or directly:
+```bash
+"C:\Program Files (x86)\cloudflared\cloudflared.exe" tunnel --url http://localhost:3000 --no-autoupdate
+```
+The public `trycloudflare.com` URL is printed to the console on startup.
+
+## SMTP settings (stored in DB `app_config`)
+
+| Key | Value |
+|---|---|
+| smtpHost | localhost |
+| smtpPort | 1025 |
+| smtpUser | (empty) |
+| smtpPass | (empty) |
+| smtpSecure | false |
+
+These match maildev's defaults — no changes needed for local dev.
+
+## Environment variables
+
+Backend reads from `backend/.env`:
+
+```
+PORT=3001
+JWT_SECRET=...
+API_KEY=...
+DATABASE_HOST=localhost
+DATABASE_PORT=3306
+DATABASE_USER=root
+DATABASE_PASSWORD=...
+DATABASE_NAME=openstudbook
+```
+
+## Cloudflare tunnel
+
+The `npm run tunnel` script uses the locally installed `cloudflared` at:
+`C:\Program Files (x86)\cloudflared\cloudflared.exe`
+
+For ngrok instead: `npm run ngrok`
+
+---
+
+## Security Maintenance Plan
+
+### Automated (no action needed once set up)
+
+| What | How | Cadence |
+|---|---|---|
+| Dependency vulnerability PRs | GitHub Dependabot (`.github/dependabot.yml`) | Weekly — Mondays |
+| `npm audit` gate on PRs | GitHub Actions (`.github/workflows/security.yml`) | Every push to `main` / `pre-deployment` |
+| TypeScript type-check gate | GitHub Actions (same workflow) | Every push |
+| Database backup | Windows Scheduled Task → `scripts/backup-db.ps1` | Nightly at 02:00 |
+| Backup pruning | Built into `backup-db.ps1` | Nightly (keeps 30 days) |
+
+**First-time setup for the scheduled backup task:**
+```powershell
+# Run once as Administrator
+powershell -ExecutionPolicy Bypass -File scripts\register-scheduled-tasks.ps1
+```
+Backups are written to `backups/` as `.sql.gz` files (excluded from git via `.gitignore`).
+
+---
+
+### Manual — Quarterly Checklist
+
+**Credentials**
+- [ ] Rotate `JWT_SECRET` in `backend/.env` and restart backend (invalidates all sessions — users re-login)
+- [ ] Rotate `DATABASE_PASSWORD` in MariaDB and `backend/.env`
+- [ ] Rotate `API_KEY` (Gemini) if shared or potentially exposed
+- [ ] Review any per-org Gemini API keys stored in the DB
+
+**Dependencies**
+- [ ] Run `npm audit` in root and `backend/` — fix anything at high or critical severity
+- [ ] Review and merge pending Dependabot PRs
+
+**Access**
+- [ ] Audit Super Admin accounts — remove any that are no longer needed
+- [ ] Review active user sessions / tokens (no server-side session store currently — rotating JWT_SECRET covers this)
+
+**Infrastructure**
+- [ ] Verify nightly backups are succeeding (`backups/backup.log`)
+- [ ] Test a backup restore against a spare DB instance
+- [ ] Check MariaDB version — upgrade if a security release is available
+
+---
+
+### Known Hardening Items (implement before public deployment)
+
+These are not yet in the codebase and should be addressed before exposing the app to the internet:
+
+| Priority | Issue | Fix |
+|---|---|---|
+| 🔴 High | CORS is `origin: '*'` | Lock to your actual domain in `backend/src/index.ts` |
+| 🔴 High | No HTTP security headers | Add `helmet` middleware (`npm install helmet`) |
+| 🔴 High | No rate limiting on auth endpoints | Add `express-rate-limit` on `/api/login`, `/api/register`, `/api/forgot-password` |
+| 🟡 Medium | JWT secret is a static string | Use a long random secret (32+ chars) and rotate quarterly |
+| 🟡 Medium | `express.json` body limit is 50 MB | Reduce to `5mb` unless large uploads are needed |
+| 🟢 Low | Morgan logs to console only | Pipe to a file with log rotation in production |
+
+---
+
+### Backups
+
+Backups are stored in `backups/` (gitignored). The script uses MariaDB's `mysqldump` with `--single-transaction` for a consistent snapshot.
+
+To restore a backup:
+```powershell
+# Decompress
+Expand-Archive backups\openstudbook_2026-01-01_02-00-00.sql.gz -DestinationPath backups\
+
+# Restore
+& "C:\Program Files\MariaDB 12.2\bin\mysql.exe" -u root -p openstudbook < backups\openstudbook_2026-01-01_02-00-00.sql
+```
diff --git a/README.md b/README.md
index af657e3..c796a55 100644
--- a/README.md
+++ b/README.md
@@ -1,20 +1,361 @@
-
+
+
+# OpenStudbook
+
+**Open-source captive breeding and botanical collection management for zoos, aquariums, and botanical gardens.**
+
+[](https://github.com/teruselearning/openstud/actions/workflows/security.yml)
+[](LICENSE)
+
-# Run and deploy your AI Studio app
+---
+
+OpenStudbook is a self-hosted web platform for managing captive animal and plant populations. Track individuals, species, breeding events, genetic lineage, health records, and enclosures — with a global network map for inter-organisation partnerships.
+
+**Key features:**
+- 🐾 **Fauna & Flora modes** — unified management for animals and plants
+- 🧬 **Studbook & genetics** — lineage tracking, breeding recommendations, DNA records
+- 🌍 **Network map** — discover partner organisations and propose breeding loans
+- 🤖 **AI assist** — species autofill and illustration via Gemini (optional)
+- 🔒 **Multi-factor auth**, per-org user roles, and full data export
+- 🌐 **Multi-language** — 10+ languages with live AI translation
+
+---
+
+## Contents
+
+- [Requirements](#requirements)
+- [Quick Start](#quick-start)
+- [Configuration](#configuration)
+- [Running the Dev Environment](#running-the-dev-environment)
+- [First-Time Setup (Installer)](#first-time-setup-installer)
+- [Production Deployment](#production-deployment)
+- [Resetting the Database](#resetting-the-database)
+- [Optional: AI Features](#optional-ai-features)
+- [Optional: Cloudflare / ngrok Tunnel](#optional-cloudflare--ngrok-tunnel)
+- [Security](#security)
+- [Contributing](#contributing)
+
+---
+
+## Requirements
+
+| Dependency | Minimum version | Notes |
+|---|---|---|
+| Node.js | 18 LTS | 20 LTS recommended |
+| npm | 9+ | Bundled with Node |
+| MariaDB **or** MySQL | MariaDB 10.6+ / MySQL 8.0+ | Must support `utf8mb4` |
+
+> **Windows users:** [MariaDB MSI installer](https://mariadb.org/download/) is the easiest option.
+> **macOS users:** `brew install mariadb && brew services start mariadb`
+> **Linux users:** `sudo apt install mariadb-server` or equivalent.
+
+---
+
+## Quick Start
+
+```bash
+# 1. Clone
+git clone https://github.com/teruselearning/openstud.git
+cd openstud
+
+# 2. Install frontend dependencies
+npm install
+
+# 3. Install backend dependencies
+cd backend && npm install && cd ..
+
+# 4. Configure environment
+cp backend/.env.example backend/.env
+# → open backend/.env and fill in your DB credentials and JWT secret
+
+# 5. Create the database
+# (MariaDB / MySQL must be running)
+mysql -u root -p -e "CREATE DATABASE openstudbook CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;"
+
+# 6. Start the backend
+cd backend && npm run dev &
+
+# 7. Start the frontend (new terminal)
+npm run dev
+```
+
+Then open **http://localhost:3000** — the installer wizard will guide you through creating your first organisation and admin account.
+
+---
+
+## Configuration
+
+All backend configuration lives in `backend/.env`. Copy the example file and edit it:
+
+```bash
+cp backend/.env.example backend/.env
+```
+
+| Variable | Required | Description |
+|---|---|---|
+| `PORT` | No | Backend port (default: `3001`) |
+| `JWT_SECRET` | **Yes** | Long random string used to sign auth tokens. Generate one: `node -e "console.log(require('crypto').randomBytes(32).toString('hex'))"` |
+| `DATABASE_HOST` | **Yes** | DB host (usually `localhost`) |
+| `DATABASE_PORT` | No | DB port (default: `3306`) |
+| `DATABASE_USER` | **Yes** | DB username |
+| `DATABASE_PASSWORD` | **Yes** | DB password |
+| `DATABASE_NAME` | **Yes** | DB name (e.g. `openstudbook`) |
+| `API_KEY` | No | Gemini API key — enables AI species autofill and illustrations. [Get one free.](https://aistudio.google.com/) |
+
+> **Never commit `backend/.env`** — it is gitignored by default.
+
+---
+
+## Running the Dev Environment
+
+You need four processes running simultaneously. Open a separate terminal for each:
+
+### 1. Backend (Express + TypeScript)
+
+```bash
+cd backend
+npm run dev
+# Listening on http://localhost:3001
+```
+
+### 2. Frontend (Vite + React)
+
+```bash
+npm run dev
+# Listening on http://localhost:3000
+```
+
+### 3. Mail catcher (optional — catches outbound emails locally)
+
+OpenStudbook sends transactional emails (invitations, password reset, MFA codes). In development, catch them locally instead of sending to real inboxes.
+
+**Using [maildev](https://github.com/maildev/maildev)** (recommended):
+
+```bash
+# Install once
+npm install -g maildev
+
+# Run
+maildev --smtp 1025 --web 1080
+```
+
+Web UI → **http://localhost:1080**
+
+Then set these values in the Super Admin → SMTP settings panel:
+
+| Setting | Value |
+|---|---|
+| SMTP Host | `localhost` |
+| SMTP Port | `1025` |
+| SMTP User | *(empty)* |
+| SMTP Pass | *(empty)* |
+| Secure (TLS) | Off |
+
+### 4. Cloudflare tunnel (optional — gives your local app a public HTTPS URL)
+
+Useful for testing on mobile devices or sharing a preview.
+
+```bash
+npm run tunnel
+```
+
+The public `trycloudflare.com` URL is printed to the console. Requires [cloudflared](https://developers.cloudflare.com/cloudflare-one/connections/connect-networks/downloads/) installed at `C:\Program Files (x86)\cloudflared\cloudflared.exe`.
+
+---
+
+## First-Time Setup (Installer)
+
+On a **fresh database**, the app automatically shows the installation wizard at **http://localhost:3000**.
+
+The wizard will ask you to:
+
+1. **Test the database connection** — verifies the credentials in `backend/.env` are working
+2. **Create your organisation** — name and admin account details
+3. **Choose a focus** — Fauna (animals) or Flora (plants)
-This contains everything you need to run your app locally.
+After setup, you can configure SMTP, languages, branding, and feature flags under **Super Admin** (the gear icon in the sidebar).
-View your app in AI Studio: https://ai.studio/apps/drive/1X_Gb2pzUHZHt4rb716OtG_QhLJrPbSU7
+> If you need to re-run the installer (e.g. for testing), see [Resetting the Database](#resetting-the-database).
-## Run Locally
+---
-**Prerequisites:** Node.js
+## Production Deployment
+OpenStudbook is designed to run on a single Linux/Windows server behind a reverse proxy.
-1. Install dependencies:
- `npm install`
-2. Set the `GEMINI_API_KEY` in [.env.local](.env.local) to your Gemini API key
-3. Run the app:
- `npm run dev`
+### Recommended stack
+
+```
+Internet → Nginx (HTTPS/TLS) → Vite static build (port 80)
+ → Express backend (port 3001)
+```
+
+### Build steps
+
+```bash
+# Build the frontend
+npm run build
+# Output is in dist/ — serve as static files via Nginx
+
+# Build the backend
+cd backend && npm run build
+# Output is in backend/dist/ — run with: node dist/index.js
+```
+
+### Nginx example config
+
+```nginx
+server {
+ listen 443 ssl;
+ server_name yourdomain.com;
+
+ # SSL cert (e.g. Let's Encrypt)
+ ssl_certificate /etc/letsencrypt/live/yourdomain.com/fullchain.pem;
+ ssl_certificate_key /etc/letsencrypt/live/yourdomain.com/privkey.pem;
+
+ # Frontend (built static files)
+ root /var/www/openstudbook/dist;
+ index index.html;
+ try_files $uri $uri/ /index.html;
+
+ # Backend API proxy
+ location /api/ {
+ proxy_pass http://localhost:3001;
+ proxy_set_header Host $host;
+ proxy_set_header X-Real-IP $remote_addr;
+ }
+
+ location /rest/ {
+ proxy_pass http://localhost:3001;
+ }
+
+ location /uploads/ {
+ proxy_pass http://localhost:3001;
+ }
+}
+
+# Redirect HTTP → HTTPS
+server {
+ listen 80;
+ server_name yourdomain.com;
+ return 301 https://$host$request_uri;
+}
+```
+
+### Environment for production
+
+Update `backend/.env` for production:
+
+```
+NODE_ENV=production
+PORT=3001
+JWT_SECRET=
+DATABASE_HOST=localhost
+DATABASE_USER=openstudbook_user
+DATABASE_PASSWORD=
+DATABASE_NAME=openstudbook
+```
+
+### Process management (Linux)
+
+```bash
+# Install pm2
+npm install -g pm2
+
+# Start backend
+pm2 start backend/dist/index.js --name openstudbook-api
+
+# Auto-restart on reboot
+pm2 startup
+pm2 save
+```
+
+### Before going public — security checklist
+
+- [ ] Lock CORS in `backend/src/index.ts`: change `origin: '*'` to your domain
+- [ ] Add `helmet` middleware: `npm install helmet` → `app.use(helmet())`
+- [ ] Add rate limiting on auth endpoints: `npm install express-rate-limit`
+- [ ] Use a strong, unique `JWT_SECRET` (32+ random characters)
+- [ ] Restrict DB user permissions — grant only `SELECT, INSERT, UPDATE, DELETE` on `openstudbook`
+- [ ] Enable HTTPS — use Let's Encrypt / Certbot
+- [ ] Disable `enableRegistration` in Super Admin if you don't want public sign-ups
+
+---
+
+## Resetting the Database
+
+Useful during development or to re-run the installer wizard.
+
+**MariaDB / MySQL:**
+
+```bash
+mysql -u root -p -e "DROP DATABASE openstudbook; CREATE DATABASE openstudbook CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;"
+```
+
+Then restart the backend — it will re-run migrations and show the installer on next page load.
+
+---
+
+## Optional: AI Features
+
+OpenStudbook integrates with [Google Gemini](https://aistudio.google.com/) for:
+
+- **Species autofill** — fill conservation status, lifespan, weight from scientific name
+- **AI illustration** — generate a representative species image
+- **Language translation** — auto-translate UI strings into new languages
+
+To enable, add your key to `backend/.env`:
+
+```
+API_KEY=your_gemini_api_key_here
+```
+
+AI usage is tracked per organisation and capped by the Super Admin. Organisations can also provide their own Gemini API key in Org Settings to bypass the shared limit.
+
+---
+
+## Optional: Cloudflare / ngrok Tunnel
+
+Expose your local dev instance publicly (useful for mobile testing, demos, or webhook testing).
+
+**Cloudflare Quick Tunnel** (no account needed):
+```bash
+npm run tunnel
+```
+
+**ngrok** (requires free account):
+```bash
+npm run ngrok
+```
+
+Both print a public HTTPS URL to the console.
+
+---
+
+## Security
+
+See the [security maintenance plan in CLAUDE.md](CLAUDE.md#security-maintenance-plan) for the full automated and manual security schedule.
+
+To report a vulnerability, please open a [GitHub Security Advisory](https://github.com/teruselearning/openstud/security/advisories/new) rather than a public issue.
+
+---
+
+## Contributing
+
+Contributions are welcome! Please:
+
+1. Fork the repo and create a feature branch from `main`
+2. Run `npm audit` in both root and `backend/` — no new high/critical issues
+3. Test the installer flow on a fresh database before submitting
+4. Open a pull request against `main` with a clear description of the change
+
+For larger changes, open an issue first to discuss the approach.
+
+---
+
+
+ Built with ❤️ for wildlife conservation and botanical management.
+
diff --git a/backend/.env.example b/backend/.env.example
index 7025d02..b90aa5a 100644
Binary files a/backend/.env.example and b/backend/.env.example differ
diff --git a/backend/package-lock.json b/backend/package-lock.json
index fe11e3f..d2f63a7 100644
--- a/backend/package-lock.json
+++ b/backend/package-lock.json
@@ -9,6 +9,7 @@
"version": "1.0.0",
"license": "ISC",
"dependencies": {
+ "@google/genai": "^1.33.0",
"bcryptjs": "^2.4.3",
"cors": "^2.8.5",
"dotenv": "^16.4.5",
@@ -16,7 +17,7 @@
"jsonwebtoken": "^9.0.2",
"morgan": "^1.10.0",
"mysql2": "^3.9.2",
- "nodemailer": "^6.9.13"
+ "nodemailer": "^8.0.10"
},
"devDependencies": {
"@types/bcryptjs": "^2.4.6",
@@ -43,6 +44,30 @@
"node": ">=12"
}
},
+ "node_modules/@google/genai": {
+ "version": "1.52.0",
+ "resolved": "https://registry.npmjs.org/@google/genai/-/genai-1.52.0.tgz",
+ "integrity": "sha512-gwSvbpiN/17O9TbsqSsE/OzZcpv5Fo4RQjdngGgogtuB9RsyJ8ZHhX5KjHj1bp5N9snN2eK8LDGXSaWW2hof8Q==",
+ "hasInstallScript": true,
+ "license": "Apache-2.0",
+ "dependencies": {
+ "google-auth-library": "^10.3.0",
+ "p-retry": "^4.6.2",
+ "protobufjs": "^7.5.4",
+ "ws": "^8.18.0"
+ },
+ "engines": {
+ "node": ">=20.0.0"
+ },
+ "peerDependencies": {
+ "@modelcontextprotocol/sdk": "^1.25.2"
+ },
+ "peerDependenciesMeta": {
+ "@modelcontextprotocol/sdk": {
+ "optional": true
+ }
+ }
+ },
"node_modules/@jridgewell/resolve-uri": {
"version": "3.1.2",
"resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.2.tgz",
@@ -71,6 +96,69 @@
"@jridgewell/sourcemap-codec": "^1.4.10"
}
},
+ "node_modules/@protobufjs/aspromise": {
+ "version": "1.1.2",
+ "resolved": "https://registry.npmjs.org/@protobufjs/aspromise/-/aspromise-1.1.2.tgz",
+ "integrity": "sha512-j+gKExEuLmKwvz3OgROXtrJ2UG2x8Ch2YZUxahh+s1F2HZ+wAceUNLkvy6zKCPVRkU++ZWQrdxsUeQXmcg4uoQ==",
+ "license": "BSD-3-Clause"
+ },
+ "node_modules/@protobufjs/base64": {
+ "version": "1.1.2",
+ "resolved": "https://registry.npmjs.org/@protobufjs/base64/-/base64-1.1.2.tgz",
+ "integrity": "sha512-AZkcAA5vnN/v4PDqKyMR5lx7hZttPDgClv83E//FMNhR2TMcLUhfRUBHCmSl0oi9zMgDDqRUJkSxO3wm85+XLg==",
+ "license": "BSD-3-Clause"
+ },
+ "node_modules/@protobufjs/codegen": {
+ "version": "2.0.5",
+ "resolved": "https://registry.npmjs.org/@protobufjs/codegen/-/codegen-2.0.5.tgz",
+ "integrity": "sha512-zgXFLzW3Ap33e6d0Wlj4MGIm6Ce8O89n/apUaGNB/jx+hw+ruWEp7EwGUshdLKVRCxZW12fp9r40E1mQrf/34g==",
+ "license": "BSD-3-Clause"
+ },
+ "node_modules/@protobufjs/eventemitter": {
+ "version": "1.1.1",
+ "resolved": "https://registry.npmjs.org/@protobufjs/eventemitter/-/eventemitter-1.1.1.tgz",
+ "integrity": "sha512-vW1GmwMZNnL+gMRaovlh9yZX74kc+TTU3FObkkurpMaRtBfLP3ldjS9KQWlwZgraRE0+dheEEoAxdzcJQ8eXZg==",
+ "license": "BSD-3-Clause"
+ },
+ "node_modules/@protobufjs/fetch": {
+ "version": "1.1.1",
+ "resolved": "https://registry.npmjs.org/@protobufjs/fetch/-/fetch-1.1.1.tgz",
+ "integrity": "sha512-GpptLrs57adMSuHi3VNj0mAF8dwh36LMaYF6XyJ6JMWlVsc+t42tm1HSEDmOs3A8fC9yyeisgLhsTVQokOZ0zw==",
+ "license": "BSD-3-Clause",
+ "dependencies": {
+ "@protobufjs/aspromise": "^1.1.1"
+ }
+ },
+ "node_modules/@protobufjs/float": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/@protobufjs/float/-/float-1.0.2.tgz",
+ "integrity": "sha512-Ddb+kVXlXst9d+R9PfTIxh1EdNkgoRe5tOX6t01f1lYWOvJnSPDBlG241QLzcyPdoNTsblLUdujGSE4RzrTZGQ==",
+ "license": "BSD-3-Clause"
+ },
+ "node_modules/@protobufjs/inquire": {
+ "version": "1.1.2",
+ "resolved": "https://registry.npmjs.org/@protobufjs/inquire/-/inquire-1.1.2.tgz",
+ "integrity": "sha512-pa0vFRuws4wkvaXKK1uXZMAwAX4/t8ANaJo45iw/oQHNQ9q5xUzwgFmVJGXiga2BeN+zpX7Vf9vmsiIa2J+MUw==",
+ "license": "BSD-3-Clause"
+ },
+ "node_modules/@protobufjs/path": {
+ "version": "1.1.2",
+ "resolved": "https://registry.npmjs.org/@protobufjs/path/-/path-1.1.2.tgz",
+ "integrity": "sha512-6JOcJ5Tm08dOHAbdR3GrvP+yUUfkjG5ePsHYczMFLq3ZmMkAD98cDgcT2iA1lJ9NVwFd4tH/iSSoe44YWkltEA==",
+ "license": "BSD-3-Clause"
+ },
+ "node_modules/@protobufjs/pool": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/@protobufjs/pool/-/pool-1.1.0.tgz",
+ "integrity": "sha512-0kELaGSIDBKvcgS4zkjz1PeddatrjYcmMWOlAuAPwAeccUrPHdUqo/J6LiymHHEiJT5NrF1UVwxY14f+fy4WQw==",
+ "license": "BSD-3-Clause"
+ },
+ "node_modules/@protobufjs/utf8": {
+ "version": "1.1.1",
+ "resolved": "https://registry.npmjs.org/@protobufjs/utf8/-/utf8-1.1.1.tgz",
+ "integrity": "sha512-oOAWABowe8EAbMyWKM0tYDKi8Yaox52D+HWZhAIJqQXbqe0xI/GV7FhLWqlEKreMkfDjshR5FKgi3mnle0h6Eg==",
+ "license": "BSD-3-Clause"
+ },
"node_modules/@tsconfig/node10": {
"version": "1.0.12",
"resolved": "https://registry.npmjs.org/@tsconfig/node10/-/node10-1.0.12.tgz",
@@ -209,7 +297,6 @@
"version": "20.19.33",
"resolved": "https://registry.npmjs.org/@types/node/-/node-20.19.33.tgz",
"integrity": "sha512-Rs1bVAIdBs5gbTIKza/tgpMuG1k3U/UMJLWecIMxNdJFDMzcM5LOiLVRYh3PilWEYDIeUDv7bpiHPLPsbydGcw==",
- "dev": true,
"license": "MIT",
"dependencies": {
"undici-types": "~6.21.0"
@@ -239,6 +326,12 @@
"dev": true,
"license": "MIT"
},
+ "node_modules/@types/retry": {
+ "version": "0.12.0",
+ "resolved": "https://registry.npmjs.org/@types/retry/-/retry-0.12.0.tgz",
+ "integrity": "sha512-wWKOClTTiizcZhXnPY4wikVAwmdYHp8q6DmC+EJUzAMsycb7HB32Kh9RN4+0gExjmPmZSAQjgURXIGATPegAvA==",
+ "license": "MIT"
+ },
"node_modules/@types/send": {
"version": "1.2.1",
"resolved": "https://registry.npmjs.org/@types/send/-/send-1.2.1.tgz",
@@ -325,6 +418,15 @@
"node": ">=0.4.0"
}
},
+ "node_modules/agent-base": {
+ "version": "7.1.4",
+ "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-7.1.4.tgz",
+ "integrity": "sha512-MnA+YT8fwfJPgBx3m60MNqakm30XOkyIoH1y6huTQvC0PwZG7ki8NacLBcrPbNoo8vEZy7Jpuk7+jMO+CUovTQ==",
+ "license": "MIT",
+ "engines": {
+ "node": ">= 14"
+ }
+ },
"node_modules/anymatch": {
"version": "3.1.3",
"resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.3.tgz",
@@ -368,6 +470,26 @@
"dev": true,
"license": "MIT"
},
+ "node_modules/base64-js": {
+ "version": "1.5.1",
+ "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.5.1.tgz",
+ "integrity": "sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==",
+ "funding": [
+ {
+ "type": "github",
+ "url": "https://github.com/sponsors/feross"
+ },
+ {
+ "type": "patreon",
+ "url": "https://www.patreon.com/feross"
+ },
+ {
+ "type": "consulting",
+ "url": "https://feross.org/support"
+ }
+ ],
+ "license": "MIT"
+ },
"node_modules/basic-auth": {
"version": "2.0.1",
"resolved": "https://registry.npmjs.org/basic-auth/-/basic-auth-2.0.1.tgz",
@@ -392,6 +514,15 @@
"integrity": "sha512-V/Hy/X9Vt7f3BbPJEi8BdVFMByHi+jNXrYkW3huaybV/kQ0KJg0Y6PkEMbn+zeT+i+SiKZ/HMqJGIIt4LZDqNQ==",
"license": "MIT"
},
+ "node_modules/bignumber.js": {
+ "version": "9.3.1",
+ "resolved": "https://registry.npmjs.org/bignumber.js/-/bignumber.js-9.3.1.tgz",
+ "integrity": "sha512-Ko0uX15oIUS7wJ3Rb30Fs6SkVbLmPBAKdlm7q9+ak9bbIeFf0MwuBsQV6z7+X768/cHsfg+WlysDWJcmthjsjQ==",
+ "license": "MIT",
+ "engines": {
+ "node": "*"
+ }
+ },
"node_modules/binary-extensions": {
"version": "2.3.0",
"resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.3.0.tgz",
@@ -406,9 +537,9 @@
}
},
"node_modules/body-parser": {
- "version": "1.20.4",
- "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.20.4.tgz",
- "integrity": "sha512-ZTgYYLMOXY9qKU/57FAo8F+HA2dGX7bqGc71txDRC1rS4frdFI5R7NhluHxH6M0YItAP0sHB4uqAOcYKxO6uGA==",
+ "version": "1.20.5",
+ "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.20.5.tgz",
+ "integrity": "sha512-3grm+/2tUOvu2cjJkvsIxrv/wVpfXQW4PsQHYm7yk4vfpu7Ekl6nEsYBoJUL6qDwZUx8wUhQ8tR2qz+ad9c9OA==",
"license": "MIT",
"dependencies": {
"bytes": "~3.1.2",
@@ -419,7 +550,7 @@
"http-errors": "~2.0.1",
"iconv-lite": "~0.4.24",
"on-finished": "~2.4.1",
- "qs": "~6.14.0",
+ "qs": "~6.15.1",
"raw-body": "~2.5.3",
"type-is": "~1.6.18",
"unpipe": "~1.0.0"
@@ -430,9 +561,9 @@
}
},
"node_modules/brace-expansion": {
- "version": "1.1.12",
- "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.12.tgz",
- "integrity": "sha512-9T9UjW3r0UW5c1Q7GTwllptXwhvYmEzFhzMfZ9H7FQWt+uZePjZPjBP/W1ZEyZ1twGWom5/56TF4lPcqjnDHcg==",
+ "version": "1.1.15",
+ "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.15.tgz",
+ "integrity": "sha512-EwOCDEex4quD37XhqM3omwtMoJjr//isUZz1JopUNWms+4Z2ViyM/k1YIRePpoVNnQhENnxtFjLaxNHrT7xIUg==",
"dev": true,
"license": "MIT",
"dependencies": {
@@ -596,6 +727,15 @@
"dev": true,
"license": "MIT"
},
+ "node_modules/data-uri-to-buffer": {
+ "version": "4.0.1",
+ "resolved": "https://registry.npmjs.org/data-uri-to-buffer/-/data-uri-to-buffer-4.0.1.tgz",
+ "integrity": "sha512-0R9ikRb668HB7QDxT1vkpuUBtqc53YyAwMwGeUFKRojY/NWKvdZ+9UYtRfGmhqNbRkTSVpMbmyhXipFFv2cb/A==",
+ "license": "MIT",
+ "engines": {
+ "node": ">= 12"
+ }
+ },
"node_modules/debug": {
"version": "2.6.9",
"resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz",
@@ -722,9 +862,9 @@
}
},
"node_modules/es-object-atoms": {
- "version": "1.1.1",
- "resolved": "https://registry.npmjs.org/es-object-atoms/-/es-object-atoms-1.1.1.tgz",
- "integrity": "sha512-FGgH2h8zKNim9ljj7dankFPcICIK9Cp5bm+c2gQSYePhpaG5+esrLODihIorn+Pe6FGJzWhXQotPv73jTaldXA==",
+ "version": "1.1.2",
+ "resolved": "https://registry.npmjs.org/es-object-atoms/-/es-object-atoms-1.1.2.tgz",
+ "integrity": "sha512-HWcBoN6NileqtSydK2FqHbS/LoDd2pqrnQHLyJzBj4kOp/ky2MWMN694xOfkK8/SnUsW2DH7EfyVlydKCsm1Zw==",
"license": "MIT",
"dependencies": {
"es-errors": "^1.3.0"
@@ -749,14 +889,14 @@
}
},
"node_modules/express": {
- "version": "4.22.1",
- "resolved": "https://registry.npmjs.org/express/-/express-4.22.1.tgz",
- "integrity": "sha512-F2X8g9P1X7uCPZMA3MVf9wcTqlyNp7IhH5qPCI0izhaOIYXaW9L535tGA3qmjRzpH+bZczqq7hVKxTR4NWnu+g==",
+ "version": "4.22.2",
+ "resolved": "https://registry.npmjs.org/express/-/express-4.22.2.tgz",
+ "integrity": "sha512-IuL+Elrou2ZvCFHs18/CIzy2Nzvo25nZ1/D2eIZlz7c+QUayAcYoiM2BthCjs+EBHVpjYjcuLDAiCWgeIX3X1Q==",
"license": "MIT",
"dependencies": {
"accepts": "~1.3.8",
"array-flatten": "1.1.1",
- "body-parser": "~1.20.3",
+ "body-parser": "~1.20.5",
"content-disposition": "~0.5.4",
"content-type": "~1.0.4",
"cookie": "~0.7.1",
@@ -775,7 +915,7 @@
"parseurl": "~1.3.3",
"path-to-regexp": "~0.1.12",
"proxy-addr": "~2.0.7",
- "qs": "~6.14.0",
+ "qs": "~6.15.1",
"range-parser": "~1.2.1",
"safe-buffer": "5.2.1",
"send": "~0.19.0",
@@ -794,6 +934,35 @@
"url": "https://opencollective.com/express"
}
},
+ "node_modules/extend": {
+ "version": "3.0.2",
+ "resolved": "https://registry.npmjs.org/extend/-/extend-3.0.2.tgz",
+ "integrity": "sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g==",
+ "license": "MIT"
+ },
+ "node_modules/fetch-blob": {
+ "version": "3.2.0",
+ "resolved": "https://registry.npmjs.org/fetch-blob/-/fetch-blob-3.2.0.tgz",
+ "integrity": "sha512-7yAQpD2UMJzLi1Dqv7qFYnPbaPx7ZfFK6PiIxQ4PfkGPyNyl2Ugx+a/umUonmKqjhM4DnfbMvdX6otXq83soQQ==",
+ "funding": [
+ {
+ "type": "github",
+ "url": "https://github.com/sponsors/jimmywarting"
+ },
+ {
+ "type": "paypal",
+ "url": "https://paypal.me/jimmywarting"
+ }
+ ],
+ "license": "MIT",
+ "dependencies": {
+ "node-domexception": "^1.0.0",
+ "web-streams-polyfill": "^3.0.3"
+ },
+ "engines": {
+ "node": "^12.20 || >= 14.13"
+ }
+ },
"node_modules/fill-range": {
"version": "7.1.1",
"resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.1.1.tgz",
@@ -825,6 +994,18 @@
"node": ">= 0.8"
}
},
+ "node_modules/formdata-polyfill": {
+ "version": "4.0.10",
+ "resolved": "https://registry.npmjs.org/formdata-polyfill/-/formdata-polyfill-4.0.10.tgz",
+ "integrity": "sha512-buewHzMvYL29jdeQTVILecSaZKnt/RJWjoZCF5OW60Z67/GmSLBkOFM7qh1PI3zFNtJbaZL5eQu1vLfazOwj4g==",
+ "license": "MIT",
+ "dependencies": {
+ "fetch-blob": "^3.1.2"
+ },
+ "engines": {
+ "node": ">=12.20.0"
+ }
+ },
"node_modules/forwarded": {
"version": "0.2.0",
"resolved": "https://registry.npmjs.org/forwarded/-/forwarded-0.2.0.tgz",
@@ -874,6 +1055,34 @@
"url": "https://github.com/sponsors/ljharb"
}
},
+ "node_modules/gaxios": {
+ "version": "7.1.4",
+ "resolved": "https://registry.npmjs.org/gaxios/-/gaxios-7.1.4.tgz",
+ "integrity": "sha512-bTIgTsM2bWn3XklZISBTQX7ZSddGW+IO3bMdGaemHZ3tbqExMENHLx6kKZ/KlejgrMtj8q7wBItt51yegqalrA==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "extend": "^3.0.2",
+ "https-proxy-agent": "^7.0.1",
+ "node-fetch": "^3.3.2"
+ },
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/gcp-metadata": {
+ "version": "8.1.2",
+ "resolved": "https://registry.npmjs.org/gcp-metadata/-/gcp-metadata-8.1.2.tgz",
+ "integrity": "sha512-zV/5HKTfCeKWnxG0Dmrw51hEWFGfcF2xiXqcA3+J90WDuP0SvoiSO5ORvcBsifmx/FoIjgQN3oNOGaQ5PhLFkg==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "gaxios": "^7.0.0",
+ "google-logging-utils": "^1.0.0",
+ "json-bigint": "^1.0.0"
+ },
+ "engines": {
+ "node": ">=18"
+ }
+ },
"node_modules/generate-function": {
"version": "2.3.1",
"resolved": "https://registry.npmjs.org/generate-function/-/generate-function-2.3.1.tgz",
@@ -955,6 +1164,32 @@
"node": ">= 6"
}
},
+ "node_modules/google-auth-library": {
+ "version": "10.6.2",
+ "resolved": "https://registry.npmjs.org/google-auth-library/-/google-auth-library-10.6.2.tgz",
+ "integrity": "sha512-e27Z6EThmVNNvtYASwQxose/G57rkRuaRbQyxM2bvYLLX/GqWZ5chWq2EBoUchJbCc57eC9ArzO5wMsEmWftCw==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "base64-js": "^1.3.0",
+ "ecdsa-sig-formatter": "^1.0.11",
+ "gaxios": "^7.1.4",
+ "gcp-metadata": "8.1.2",
+ "google-logging-utils": "1.1.3",
+ "jws": "^4.0.0"
+ },
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/google-logging-utils": {
+ "version": "1.1.3",
+ "resolved": "https://registry.npmjs.org/google-logging-utils/-/google-logging-utils-1.1.3.tgz",
+ "integrity": "sha512-eAmLkjDjAFCVXg7A1unxHsLf961m6y17QFqXqAXGj/gVkKFrEICfStRfwUlGNfeCEjNRa32JEWOUTlYXPyyKvA==",
+ "license": "Apache-2.0",
+ "engines": {
+ "node": ">=14"
+ }
+ },
"node_modules/gopd": {
"version": "1.2.0",
"resolved": "https://registry.npmjs.org/gopd/-/gopd-1.2.0.tgz",
@@ -1011,6 +1246,42 @@
"url": "https://opencollective.com/express"
}
},
+ "node_modules/https-proxy-agent": {
+ "version": "7.0.6",
+ "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-7.0.6.tgz",
+ "integrity": "sha512-vK9P5/iUfdl95AI+JVyUuIcVtd4ofvtrOr3HNtM2yxC9bnMbEdp3x01OhQNnjb8IJYi38VlTE3mBXwcfvywuSw==",
+ "license": "MIT",
+ "dependencies": {
+ "agent-base": "^7.1.2",
+ "debug": "4"
+ },
+ "engines": {
+ "node": ">= 14"
+ }
+ },
+ "node_modules/https-proxy-agent/node_modules/debug": {
+ "version": "4.4.3",
+ "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.3.tgz",
+ "integrity": "sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA==",
+ "license": "MIT",
+ "dependencies": {
+ "ms": "^2.1.3"
+ },
+ "engines": {
+ "node": ">=6.0"
+ },
+ "peerDependenciesMeta": {
+ "supports-color": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/https-proxy-agent/node_modules/ms": {
+ "version": "2.1.3",
+ "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz",
+ "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==",
+ "license": "MIT"
+ },
"node_modules/iconv-lite": {
"version": "0.4.24",
"resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz",
@@ -1118,6 +1389,15 @@
"integrity": "sha512-Ks/IoX00TtClbGQr4TWXemAnktAQvYB7HzcCxDGqEZU6oCmb2INHuOoKxbtR+HFkmYWBKv/dOZtGRiAjDhj92g==",
"license": "MIT"
},
+ "node_modules/json-bigint": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/json-bigint/-/json-bigint-1.0.0.tgz",
+ "integrity": "sha512-SiPv/8VpZuWbvLSMtTDU8hEfrZWg/mH/nV/b4o0CYbSxu1UIQPLdwKOCIyLQX+VIPO5vrLX3i8qtqFyhdPSUSQ==",
+ "license": "MIT",
+ "dependencies": {
+ "bignumber.js": "^9.0.0"
+ }
+ },
"node_modules/jsonwebtoken": {
"version": "9.0.3",
"resolved": "https://registry.npmjs.org/jsonwebtoken/-/jsonwebtoken-9.0.3.tgz",
@@ -1307,9 +1587,9 @@
}
},
"node_modules/minimatch": {
- "version": "3.1.2",
- "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz",
- "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==",
+ "version": "3.1.5",
+ "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.5.tgz",
+ "integrity": "sha512-VgjWUsnnT6n+NUk6eZq77zeFdpW2LWDzP6zFGrCbHXiYNul5Dzqk2HHQ5uFH2DNW5Xbp8+jVzaeNt94ssEEl4w==",
"dev": true,
"license": "ISC",
"dependencies": {
@@ -1433,10 +1713,48 @@
"node": ">= 0.6"
}
},
+ "node_modules/node-domexception": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/node-domexception/-/node-domexception-1.0.0.tgz",
+ "integrity": "sha512-/jKZoMpw0F8GRwl4/eLROPA3cfcXtLApP0QzLmUT/HuPCZWyB7IY9ZrMeKw2O/nFIqPQB3PVM9aYm0F312AXDQ==",
+ "deprecated": "Use your platform's native DOMException instead",
+ "funding": [
+ {
+ "type": "github",
+ "url": "https://github.com/sponsors/jimmywarting"
+ },
+ {
+ "type": "github",
+ "url": "https://paypal.me/jimmywarting"
+ }
+ ],
+ "license": "MIT",
+ "engines": {
+ "node": ">=10.5.0"
+ }
+ },
+ "node_modules/node-fetch": {
+ "version": "3.3.2",
+ "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-3.3.2.tgz",
+ "integrity": "sha512-dRB78srN/l6gqWulah9SrxeYnxeddIG30+GOqK/9OlLVyLg3HPnr6SqOWTWOXKRwC2eGYCkZ59NNuSgvSrpgOA==",
+ "license": "MIT",
+ "dependencies": {
+ "data-uri-to-buffer": "^4.0.0",
+ "fetch-blob": "^3.1.4",
+ "formdata-polyfill": "^4.0.10"
+ },
+ "engines": {
+ "node": "^12.20.0 || ^14.13.1 || >=16.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/node-fetch"
+ }
+ },
"node_modules/nodemailer": {
- "version": "6.10.1",
- "resolved": "https://registry.npmjs.org/nodemailer/-/nodemailer-6.10.1.tgz",
- "integrity": "sha512-Z+iLaBGVaSjbIzQ4pX6XV41HrooLsQ10ZWPUehGmuantvzWoDVBnmsdUcOIDM1t+yPor5pDhVlDESgOMEGxhHA==",
+ "version": "8.0.10",
+ "resolved": "https://registry.npmjs.org/nodemailer/-/nodemailer-8.0.10.tgz",
+ "integrity": "sha512-BLFuSth7QtHOkBzyqTehWWyub0NTRDuK2Q2SQfnGLsrJnzyU+Yeh4WpV1eZGuARFj1xQJHIdnTuJZLP+b9R1GQ==",
"license": "MIT-0",
"engines": {
"node": ">=6.0.0"
@@ -1504,6 +1822,19 @@
"wrappy": "1"
}
},
+ "node_modules/p-retry": {
+ "version": "4.6.2",
+ "resolved": "https://registry.npmjs.org/p-retry/-/p-retry-4.6.2.tgz",
+ "integrity": "sha512-312Id396EbJdvRONlngUx0NydfrIQ5lsYu0znKVUzVvArzEIt08V1qhtyESbGVd1FGX7UKtiFp5uwKZdM8wIuQ==",
+ "license": "MIT",
+ "dependencies": {
+ "@types/retry": "0.12.0",
+ "retry": "^0.13.1"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
"node_modules/parseurl": {
"version": "1.3.3",
"resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.3.tgz",
@@ -1531,15 +1862,15 @@
"license": "MIT"
},
"node_modules/path-to-regexp": {
- "version": "0.1.12",
- "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.12.tgz",
- "integrity": "sha512-RA1GjUVMnvYFxuqovrEqZoxxW5NUZqbwKtYz/Tt7nXerk0LbLblQmrsgdeOxV5SFHf0UDggjS/bSeOZwt1pmEQ==",
+ "version": "0.1.13",
+ "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.13.tgz",
+ "integrity": "sha512-A/AGNMFN3c8bOlvV9RreMdrv7jsmF9XIfDeCd87+I8RNg6s78BhJxMu69NEMHBSJFxKidViTEdruRwEk/WIKqA==",
"license": "MIT"
},
"node_modules/picomatch": {
- "version": "2.3.1",
- "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz",
- "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==",
+ "version": "2.3.2",
+ "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.2.tgz",
+ "integrity": "sha512-V7+vQEJ06Z+c5tSye8S+nHUfI51xoXIXjHQ99cQtKUkQqqO1kO/KCJUfZXuB47h/YBlDhah2H3hdUGXn8ie0oA==",
"dev": true,
"license": "MIT",
"engines": {
@@ -1549,6 +1880,30 @@
"url": "https://github.com/sponsors/jonschlinkert"
}
},
+ "node_modules/protobufjs": {
+ "version": "7.6.2",
+ "resolved": "https://registry.npmjs.org/protobufjs/-/protobufjs-7.6.2.tgz",
+ "integrity": "sha512-N9EiLovGEQOJSPF26Ij7qUGvahfEnq0eeYZ02aigIedkmz1qZSwjnP9SBITHJuF/6MYbIW4HDN8zdYjsjqJKXQ==",
+ "hasInstallScript": true,
+ "license": "BSD-3-Clause",
+ "dependencies": {
+ "@protobufjs/aspromise": "^1.1.2",
+ "@protobufjs/base64": "^1.1.2",
+ "@protobufjs/codegen": "^2.0.5",
+ "@protobufjs/eventemitter": "^1.1.1",
+ "@protobufjs/fetch": "^1.1.1",
+ "@protobufjs/float": "^1.0.2",
+ "@protobufjs/inquire": "^1.1.2",
+ "@protobufjs/path": "^1.1.2",
+ "@protobufjs/pool": "^1.1.0",
+ "@protobufjs/utf8": "^1.1.1",
+ "@types/node": ">=13.7.0",
+ "long": "^5.3.2"
+ },
+ "engines": {
+ "node": ">=12.0.0"
+ }
+ },
"node_modules/proxy-addr": {
"version": "2.0.7",
"resolved": "https://registry.npmjs.org/proxy-addr/-/proxy-addr-2.0.7.tgz",
@@ -1563,9 +1918,9 @@
}
},
"node_modules/qs": {
- "version": "6.14.2",
- "resolved": "https://registry.npmjs.org/qs/-/qs-6.14.2.tgz",
- "integrity": "sha512-V/yCWTTF7VJ9hIh18Ugr2zhJMP01MY7c5kh4J870L7imm6/DIzBsNLTXzMwUA3yZ5b/KBqLx8Kp3uRvd7xSe3Q==",
+ "version": "6.15.2",
+ "resolved": "https://registry.npmjs.org/qs/-/qs-6.15.2.tgz",
+ "integrity": "sha512-Rzq0KEyX/w/tEybncDgdkZrJgVUsUMk3xjh3t5bv3S1HTAtg+uOYt72+ZfwiQwKdysThkTBdL/rTi6HDmX9Ddw==",
"license": "BSD-3-Clause",
"dependencies": {
"side-channel": "^1.1.0"
@@ -1635,6 +1990,15 @@
"url": "https://github.com/sponsors/ljharb"
}
},
+ "node_modules/retry": {
+ "version": "0.13.1",
+ "resolved": "https://registry.npmjs.org/retry/-/retry-0.13.1.tgz",
+ "integrity": "sha512-XQBQ3I8W1Cge0Seh+6gjj03LbmRFWuoszgK9ooCpwYIrhhoO80pfq4cUkU5DkknwfOfFteRwlZ56PYOGYyFWdg==",
+ "license": "MIT",
+ "engines": {
+ "node": ">= 4"
+ }
+ },
"node_modules/rimraf": {
"version": "2.7.1",
"resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.7.1.tgz",
@@ -1763,13 +2127,13 @@
}
},
"node_modules/side-channel-list": {
- "version": "1.0.0",
- "resolved": "https://registry.npmjs.org/side-channel-list/-/side-channel-list-1.0.0.tgz",
- "integrity": "sha512-FCLHtRD/gnpCiCHEiJLOwdmFP+wzCmDEkc9y7NsYxeF4u7Btsn1ZuwgwJGxImImHicJArLP4R0yX4c2KCrMrTA==",
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/side-channel-list/-/side-channel-list-1.0.1.tgz",
+ "integrity": "sha512-mjn/0bi/oUURjc5Xl7IaWi/OJJJumuoJFQJfDDyO46+hBWsfaVM65TBHq2eoZBhzl9EchxOijpkbRC8SVBQU0w==",
"license": "MIT",
"dependencies": {
"es-errors": "^1.3.0",
- "object-inspect": "^1.13.3"
+ "object-inspect": "^1.13.4"
},
"engines": {
"node": ">= 0.4"
@@ -2048,7 +2412,6 @@
"version": "6.21.0",
"resolved": "https://registry.npmjs.org/undici-types/-/undici-types-6.21.0.tgz",
"integrity": "sha512-iwDZqg0QAGrg9Rav5H4n0M64c3mkR59cJ6wQp+7C4nI0gsmExaedaYLNO44eT4AtBBwjbTiGPMlt2Md0T9H9JQ==",
- "dev": true,
"license": "MIT"
},
"node_modules/unpipe": {
@@ -2085,6 +2448,15 @@
"node": ">= 0.8"
}
},
+ "node_modules/web-streams-polyfill": {
+ "version": "3.3.3",
+ "resolved": "https://registry.npmjs.org/web-streams-polyfill/-/web-streams-polyfill-3.3.3.tgz",
+ "integrity": "sha512-d2JWLCivmZYTSIoge9MsgFCZrt571BikcWGYkjC1khllbTeDlGqZ2D8vD8E/lJa8WGWbb7Plm8/XJYV7IJHZZw==",
+ "license": "MIT",
+ "engines": {
+ "node": ">= 8"
+ }
+ },
"node_modules/wrappy": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz",
@@ -2092,6 +2464,27 @@
"dev": true,
"license": "ISC"
},
+ "node_modules/ws": {
+ "version": "8.21.0",
+ "resolved": "https://registry.npmjs.org/ws/-/ws-8.21.0.tgz",
+ "integrity": "sha512-Vsp28b7DRcimFQvrqu2Wek3z1iYxDCWqHYB8Qsnk/S4RfaCQzPGPyBNuVjJV3cd6UiKtUtp6sNM77gWvzcCH+g==",
+ "license": "MIT",
+ "engines": {
+ "node": ">=10.0.0"
+ },
+ "peerDependencies": {
+ "bufferutil": "^4.0.1",
+ "utf-8-validate": ">=5.0.2"
+ },
+ "peerDependenciesMeta": {
+ "bufferutil": {
+ "optional": true
+ },
+ "utf-8-validate": {
+ "optional": true
+ }
+ }
+ },
"node_modules/xtend": {
"version": "4.0.2",
"resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.2.tgz",
diff --git a/backend/package.json b/backend/package.json
index 8cc043d..a5c9dd9 100644
--- a/backend/package.json
+++ b/backend/package.json
@@ -1,4 +1,3 @@
-
{
"name": "openstudbook-backend",
"version": "1.0.0",
@@ -21,7 +20,7 @@
"jsonwebtoken": "^9.0.2",
"morgan": "^1.10.0",
"mysql2": "^3.9.2",
- "nodemailer": "^6.9.13"
+ "nodemailer": "^8.0.10"
},
"devDependencies": {
"@types/bcryptjs": "^2.4.6",
diff --git a/backend/src/index.ts b/backend/src/index.ts
index d36a7aa..49e0eba 100644
--- a/backend/src/index.ts
+++ b/backend/src/index.ts
@@ -174,7 +174,8 @@ const initDatabase = async () => {
connection.release();
await runMigrations(db);
- await seedDatabase(db);
+ // Do NOT auto-seed here — seeding only happens via /api/install/setup
+ // so the installer wizard is shown on a fresh database.
isConfigured = true;
console.log('[DATABASE] Connection successful.');
} catch (e: any) {
@@ -201,8 +202,8 @@ app.get('/api/install/status', async (req: any, res: any) => {
const db = getDb();
const connection = await db.getConnection();
connection.release();
- const [rows]: any = await db.execute(`SHOW TABLES LIKE 'organizations'`);
- res.json({ success: true, installed: rows.length > 0, connected: true });
+ const [rows]: any = await db.execute(`SELECT COUNT(*) AS cnt FROM organizations WHERE is_deleted = 0`);
+ res.json({ success: true, installed: rows[0].cnt > 0, connected: true });
} catch (e: any) {
res.json({ success: true, installed: false, connected: false, error: e.message });
}
diff --git a/package-lock.json b/package-lock.json
index e23e55f..7bf413a 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -19,7 +19,7 @@
"lucide-react": "^0.560.0",
"morgan": "^1.10.1",
"mysql2": "^3.16.0",
- "nodemailer": "^7.0.12",
+ "nodemailer": "^8.0.10",
"path": "^0.12.7",
"process": "^0.11.10",
"react": "^19.2.1",
@@ -872,25 +872,24 @@
"license": "BSD-3-Clause"
},
"node_modules/@protobufjs/codegen": {
- "version": "2.0.4",
- "resolved": "https://registry.npmjs.org/@protobufjs/codegen/-/codegen-2.0.4.tgz",
- "integrity": "sha512-YyFaikqM5sH0ziFZCN3xDC7zeGaB/d0IUb9CATugHWbd1FRFwWwt4ld4OYMPWu5a3Xe01mGAULCdqhMlPl29Jg==",
+ "version": "2.0.5",
+ "resolved": "https://registry.npmjs.org/@protobufjs/codegen/-/codegen-2.0.5.tgz",
+ "integrity": "sha512-zgXFLzW3Ap33e6d0Wlj4MGIm6Ce8O89n/apUaGNB/jx+hw+ruWEp7EwGUshdLKVRCxZW12fp9r40E1mQrf/34g==",
"license": "BSD-3-Clause"
},
"node_modules/@protobufjs/eventemitter": {
- "version": "1.1.0",
- "resolved": "https://registry.npmjs.org/@protobufjs/eventemitter/-/eventemitter-1.1.0.tgz",
- "integrity": "sha512-j9ednRT81vYJ9OfVuXG6ERSTdEL1xVsNgqpkxMsbIabzSo3goCjDIveeGv5d03om39ML71RdmrGNjG5SReBP/Q==",
+ "version": "1.1.1",
+ "resolved": "https://registry.npmjs.org/@protobufjs/eventemitter/-/eventemitter-1.1.1.tgz",
+ "integrity": "sha512-vW1GmwMZNnL+gMRaovlh9yZX74kc+TTU3FObkkurpMaRtBfLP3ldjS9KQWlwZgraRE0+dheEEoAxdzcJQ8eXZg==",
"license": "BSD-3-Clause"
},
"node_modules/@protobufjs/fetch": {
- "version": "1.1.0",
- "resolved": "https://registry.npmjs.org/@protobufjs/fetch/-/fetch-1.1.0.tgz",
- "integrity": "sha512-lljVXpqXebpsijW71PZaCYeIcE5on1w5DlQy5WH6GLbFryLUrBD4932W/E2BSpfRJWseIL4v/KPgBFxDOIdKpQ==",
+ "version": "1.1.1",
+ "resolved": "https://registry.npmjs.org/@protobufjs/fetch/-/fetch-1.1.1.tgz",
+ "integrity": "sha512-GpptLrs57adMSuHi3VNj0mAF8dwh36LMaYF6XyJ6JMWlVsc+t42tm1HSEDmOs3A8fC9yyeisgLhsTVQokOZ0zw==",
"license": "BSD-3-Clause",
"dependencies": {
- "@protobufjs/aspromise": "^1.1.1",
- "@protobufjs/inquire": "^1.1.0"
+ "@protobufjs/aspromise": "^1.1.1"
}
},
"node_modules/@protobufjs/float": {
@@ -900,9 +899,9 @@
"license": "BSD-3-Clause"
},
"node_modules/@protobufjs/inquire": {
- "version": "1.1.0",
- "resolved": "https://registry.npmjs.org/@protobufjs/inquire/-/inquire-1.1.0.tgz",
- "integrity": "sha512-kdSefcPdruJiFMVSbn801t4vFK7KB/5gd2fYvrxhuJYg8ILrmn9SKSX2tZdV6V+ksulWqS7aXjBcRXl3wHoD9Q==",
+ "version": "1.1.2",
+ "resolved": "https://registry.npmjs.org/@protobufjs/inquire/-/inquire-1.1.2.tgz",
+ "integrity": "sha512-pa0vFRuws4wkvaXKK1uXZMAwAX4/t8ANaJo45iw/oQHNQ9q5xUzwgFmVJGXiga2BeN+zpX7Vf9vmsiIa2J+MUw==",
"license": "BSD-3-Clause"
},
"node_modules/@protobufjs/path": {
@@ -918,9 +917,9 @@
"license": "BSD-3-Clause"
},
"node_modules/@protobufjs/utf8": {
- "version": "1.1.0",
- "resolved": "https://registry.npmjs.org/@protobufjs/utf8/-/utf8-1.1.0.tgz",
- "integrity": "sha512-Vvn3zZrhQZkkBE8LSuW3em98c0FwgO4nxzv6OdSxPKJIEKY2bGbHn+mhGIPerzI4twdxaP8/0+06HBpwf345Lw==",
+ "version": "1.1.1",
+ "resolved": "https://registry.npmjs.org/@protobufjs/utf8/-/utf8-1.1.1.tgz",
+ "integrity": "sha512-oOAWABowe8EAbMyWKM0tYDKi8Yaox52D+HWZhAIJqQXbqe0xI/GV7FhLWqlEKreMkfDjshR5FKgi3mnle0h6Eg==",
"license": "BSD-3-Clause"
},
"node_modules/@reduxjs/toolkit": {
@@ -967,9 +966,9 @@
"license": "MIT"
},
"node_modules/@rollup/rollup-android-arm-eabi": {
- "version": "4.57.1",
- "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.57.1.tgz",
- "integrity": "sha512-A6ehUVSiSaaliTxai040ZpZ2zTevHYbvu/lDoeAteHI8QnaosIzm4qwtezfRg1jOYaUmnzLX1AOD6Z+UJjtifg==",
+ "version": "4.61.0",
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.61.0.tgz",
+ "integrity": "sha512-dnxczajOqt0gesZlN5pGQ1s1imQVrsmCw5G2Ci4oM+0WvNz3pyRnlWrT7McoZIb8VlFwCawdmbWRmxRn7HI+VQ==",
"cpu": [
"arm"
],
@@ -981,9 +980,9 @@
]
},
"node_modules/@rollup/rollup-android-arm64": {
- "version": "4.57.1",
- "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm64/-/rollup-android-arm64-4.57.1.tgz",
- "integrity": "sha512-dQaAddCY9YgkFHZcFNS/606Exo8vcLHwArFZ7vxXq4rigo2bb494/xKMMwRRQW6ug7Js6yXmBZhSBRuBvCCQ3w==",
+ "version": "4.61.0",
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm64/-/rollup-android-arm64-4.61.0.tgz",
+ "integrity": "sha512-Bp3JpGP00Vu3f238ivRrjf7z3xSzVPXqCmaJYA9t2c+c8vKYvOzmXF7LkkeUalTEGd6cZcSWe+PFIP3Vy48fRg==",
"cpu": [
"arm64"
],
@@ -995,9 +994,9 @@
]
},
"node_modules/@rollup/rollup-darwin-arm64": {
- "version": "4.57.1",
- "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.57.1.tgz",
- "integrity": "sha512-crNPrwJOrRxagUYeMn/DZwqN88SDmwaJ8Cvi/TN1HnWBU7GwknckyosC2gd0IqYRsHDEnXf328o9/HC6OkPgOg==",
+ "version": "4.61.0",
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.61.0.tgz",
+ "integrity": "sha512-zaYIpr670mUmmZ1tVzUFplbQbG7h3Gugx3L5FoqhsC2m/YnLlR1a7zVLmXNPy+iY1tFPEbNG+HHBXZGyId0G5w==",
"cpu": [
"arm64"
],
@@ -1009,9 +1008,9 @@
]
},
"node_modules/@rollup/rollup-darwin-x64": {
- "version": "4.57.1",
- "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-x64/-/rollup-darwin-x64-4.57.1.tgz",
- "integrity": "sha512-Ji8g8ChVbKrhFtig5QBV7iMaJrGtpHelkB3lsaKzadFBe58gmjfGXAOfI5FV0lYMH8wiqsxKQ1C9B0YTRXVy4w==",
+ "version": "4.61.0",
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-x64/-/rollup-darwin-x64-4.61.0.tgz",
+ "integrity": "sha512-+P49fvkv2dSoeevUW+lgZ/I2JHSsJCK1Lyjj7Cu6E4UHG4tS9XIefzIjo5qhgELjAclnen1rLzK2PMKJdo+Dyg==",
"cpu": [
"x64"
],
@@ -1023,9 +1022,9 @@
]
},
"node_modules/@rollup/rollup-freebsd-arm64": {
- "version": "4.57.1",
- "resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-arm64/-/rollup-freebsd-arm64-4.57.1.tgz",
- "integrity": "sha512-R+/WwhsjmwodAcz65guCGFRkMb4gKWTcIeLy60JJQbXrJ97BOXHxnkPFrP+YwFlaS0m+uWJTstrUA9o+UchFug==",
+ "version": "4.61.0",
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-arm64/-/rollup-freebsd-arm64-4.61.0.tgz",
+ "integrity": "sha512-l3FAAOyKJXH2ea6KNFN+MMgC/rnE94YGLXs2ehYqDcCoHt1DpvgWX75BhUJxN38XojP7Ul+4H8PRn7EdyqSDrw==",
"cpu": [
"arm64"
],
@@ -1037,9 +1036,9 @@
]
},
"node_modules/@rollup/rollup-freebsd-x64": {
- "version": "4.57.1",
- "resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-x64/-/rollup-freebsd-x64-4.57.1.tgz",
- "integrity": "sha512-IEQTCHeiTOnAUC3IDQdzRAGj3jOAYNr9kBguI7MQAAZK3caezRrg0GxAb6Hchg4lxdZEI5Oq3iov/w/hnFWY9Q==",
+ "version": "4.61.0",
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-x64/-/rollup-freebsd-x64-4.61.0.tgz",
+ "integrity": "sha512-VokPN3TSctKj65cyCNPaUh4vMFA8awxOot/0sp+4J7ZlNRKQEhXhawqPwajoi8H5ZFt61i0ugZJuTKXBjGJ17Q==",
"cpu": [
"x64"
],
@@ -1051,13 +1050,16 @@
]
},
"node_modules/@rollup/rollup-linux-arm-gnueabihf": {
- "version": "4.57.1",
- "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-gnueabihf/-/rollup-linux-arm-gnueabihf-4.57.1.tgz",
- "integrity": "sha512-F8sWbhZ7tyuEfsmOxwc2giKDQzN3+kuBLPwwZGyVkLlKGdV1nvnNwYD0fKQ8+XS6hp9nY7B+ZeK01EBUE7aHaw==",
+ "version": "4.61.0",
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-gnueabihf/-/rollup-linux-arm-gnueabihf-4.61.0.tgz",
+ "integrity": "sha512-DxH0P3wxm+Yzs/p3zrk9dw1rURu8p0Nv5+MRK/L7OtnLNg5rLZraSBFZ8iUXOd9f2BlhJyEpIZUH/emjq4UJ4g==",
"cpu": [
"arm"
],
"dev": true,
+ "libc": [
+ "glibc"
+ ],
"license": "MIT",
"optional": true,
"os": [
@@ -1065,13 +1067,16 @@
]
},
"node_modules/@rollup/rollup-linux-arm-musleabihf": {
- "version": "4.57.1",
- "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-musleabihf/-/rollup-linux-arm-musleabihf-4.57.1.tgz",
- "integrity": "sha512-rGfNUfn0GIeXtBP1wL5MnzSj98+PZe/AXaGBCRmT0ts80lU5CATYGxXukeTX39XBKsxzFpEeK+Mrp9faXOlmrw==",
+ "version": "4.61.0",
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-musleabihf/-/rollup-linux-arm-musleabihf-4.61.0.tgz",
+ "integrity": "sha512-T6ZvMNe84kAz6TBWHC7hGAoEtzP1LWYw/AqayGWEF6uISt3Abk/st06LqRD9THd7Xz3NxzurUpzAuEAUbZf+nw==",
"cpu": [
"arm"
],
"dev": true,
+ "libc": [
+ "musl"
+ ],
"license": "MIT",
"optional": true,
"os": [
@@ -1079,13 +1084,16 @@
]
},
"node_modules/@rollup/rollup-linux-arm64-gnu": {
- "version": "4.57.1",
- "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.57.1.tgz",
- "integrity": "sha512-MMtej3YHWeg/0klK2Qodf3yrNzz6CGjo2UntLvk2RSPlhzgLvYEB3frRvbEF2wRKh1Z2fDIg9KRPe1fawv7C+g==",
+ "version": "4.61.0",
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.61.0.tgz",
+ "integrity": "sha512-q/4hzvQkDs8b4jIBab1pnLiiM0ayTZsN2amBFPDzuyZxjEd4wDwx0UJFYM3cOZzSf5Kw8fnWSprJzIBMkcR44Q==",
"cpu": [
"arm64"
],
"dev": true,
+ "libc": [
+ "glibc"
+ ],
"license": "MIT",
"optional": true,
"os": [
@@ -1093,13 +1101,16 @@
]
},
"node_modules/@rollup/rollup-linux-arm64-musl": {
- "version": "4.57.1",
- "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.57.1.tgz",
- "integrity": "sha512-1a/qhaaOXhqXGpMFMET9VqwZakkljWHLmZOX48R0I/YLbhdxr1m4gtG1Hq7++VhVUmf+L3sTAf9op4JlhQ5u1Q==",
+ "version": "4.61.0",
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.61.0.tgz",
+ "integrity": "sha512-vvYWX3akdEAY6km+9wAqFDnk6pQsbJKVnj7xawcvs/+fdlYBGp+U+Qq/lLfpIxYIZvZLHMAKD9HLdacSx/r3dw==",
"cpu": [
"arm64"
],
"dev": true,
+ "libc": [
+ "musl"
+ ],
"license": "MIT",
"optional": true,
"os": [
@@ -1107,13 +1118,16 @@
]
},
"node_modules/@rollup/rollup-linux-loong64-gnu": {
- "version": "4.57.1",
- "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-loong64-gnu/-/rollup-linux-loong64-gnu-4.57.1.tgz",
- "integrity": "sha512-QWO6RQTZ/cqYtJMtxhkRkidoNGXc7ERPbZN7dVW5SdURuLeVU7lwKMpo18XdcmpWYd0qsP1bwKPf7DNSUinhvA==",
+ "version": "4.61.0",
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-loong64-gnu/-/rollup-linux-loong64-gnu-4.61.0.tgz",
+ "integrity": "sha512-DePa5cqOxDP/Zp0VOXpeWaGew5iIv5DXp9NYbzkX5PFQyWVX9184WCTh3hvr/7lhXo8ZVlbFLkz8+o/q1dU6gA==",
"cpu": [
"loong64"
],
"dev": true,
+ "libc": [
+ "glibc"
+ ],
"license": "MIT",
"optional": true,
"os": [
@@ -1121,13 +1135,16 @@
]
},
"node_modules/@rollup/rollup-linux-loong64-musl": {
- "version": "4.57.1",
- "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-loong64-musl/-/rollup-linux-loong64-musl-4.57.1.tgz",
- "integrity": "sha512-xpObYIf+8gprgWaPP32xiN5RVTi/s5FCR+XMXSKmhfoJjrpRAjCuuqQXyxUa/eJTdAE6eJ+KDKaoEqjZQxh3Gw==",
+ "version": "4.61.0",
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-loong64-musl/-/rollup-linux-loong64-musl-4.61.0.tgz",
+ "integrity": "sha512-LV8aWMB8UChglMCEzs7RkN0GsH29RJaLLqwm9fCIjlqwxQTiWAqNcc7wjBkH31hV0PU/yVxGYvrYsgfea2qw6g==",
"cpu": [
"loong64"
],
"dev": true,
+ "libc": [
+ "musl"
+ ],
"license": "MIT",
"optional": true,
"os": [
@@ -1135,13 +1152,16 @@
]
},
"node_modules/@rollup/rollup-linux-ppc64-gnu": {
- "version": "4.57.1",
- "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-ppc64-gnu/-/rollup-linux-ppc64-gnu-4.57.1.tgz",
- "integrity": "sha512-4BrCgrpZo4hvzMDKRqEaW1zeecScDCR+2nZ86ATLhAoJ5FQ+lbHVD3ttKe74/c7tNT9c6F2viwB3ufwp01Oh2w==",
+ "version": "4.61.0",
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-ppc64-gnu/-/rollup-linux-ppc64-gnu-4.61.0.tgz",
+ "integrity": "sha512-QoNSnwQtaeNu5grdBbsL0tt1uyl5EnS8DA8Mr3nluMXbhdQNyhN+G4tBax7VCdxLKj8YJ0/4OO9Ho84jMnJtKA==",
"cpu": [
"ppc64"
],
"dev": true,
+ "libc": [
+ "glibc"
+ ],
"license": "MIT",
"optional": true,
"os": [
@@ -1149,13 +1169,16 @@
]
},
"node_modules/@rollup/rollup-linux-ppc64-musl": {
- "version": "4.57.1",
- "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-ppc64-musl/-/rollup-linux-ppc64-musl-4.57.1.tgz",
- "integrity": "sha512-NOlUuzesGauESAyEYFSe3QTUguL+lvrN1HtwEEsU2rOwdUDeTMJdO5dUYl/2hKf9jWydJrO9OL/XSSf65R5+Xw==",
+ "version": "4.61.0",
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-ppc64-musl/-/rollup-linux-ppc64-musl-4.61.0.tgz",
+ "integrity": "sha512-/zZp5MKapIIApE8trN8qLGNSiRN9TUoaUZ1cmVu4XnVdd5LQLOXTtyi+vtfUbNnT3iyjzpPqYeKXmvJ+gJGYWw==",
"cpu": [
"ppc64"
],
"dev": true,
+ "libc": [
+ "musl"
+ ],
"license": "MIT",
"optional": true,
"os": [
@@ -1163,13 +1186,16 @@
]
},
"node_modules/@rollup/rollup-linux-riscv64-gnu": {
- "version": "4.57.1",
- "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-gnu/-/rollup-linux-riscv64-gnu-4.57.1.tgz",
- "integrity": "sha512-ptA88htVp0AwUUqhVghwDIKlvJMD/fmL/wrQj99PRHFRAG6Z5nbWoWG4o81Nt9FT+IuqUQi+L31ZKAFeJ5Is+A==",
+ "version": "4.61.0",
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-gnu/-/rollup-linux-riscv64-gnu-4.61.0.tgz",
+ "integrity": "sha512-RbrzcD3aJ1k3UbtMRRBNwojdVVyXjuVAFTfn/xPa6EEl6GE9Sm/akPgFTb9aAC9pMKGJ6CtWxaGrqWcabH+ySg==",
"cpu": [
"riscv64"
],
"dev": true,
+ "libc": [
+ "glibc"
+ ],
"license": "MIT",
"optional": true,
"os": [
@@ -1177,13 +1203,16 @@
]
},
"node_modules/@rollup/rollup-linux-riscv64-musl": {
- "version": "4.57.1",
- "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-musl/-/rollup-linux-riscv64-musl-4.57.1.tgz",
- "integrity": "sha512-S51t7aMMTNdmAMPpBg7OOsTdn4tySRQvklmL3RpDRyknk87+Sp3xaumlatU+ppQ+5raY7sSTcC2beGgvhENfuw==",
+ "version": "4.61.0",
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-musl/-/rollup-linux-riscv64-musl-4.61.0.tgz",
+ "integrity": "sha512-ZF+onDsBso8PJf1XaG9lB+O9RnBpKGnY6OrzC4CSHrtC1jb6jWLTKK4bRqdoCXHd22gyr2hiYmEAm8Wns/BOCw==",
"cpu": [
"riscv64"
],
"dev": true,
+ "libc": [
+ "musl"
+ ],
"license": "MIT",
"optional": true,
"os": [
@@ -1191,13 +1220,16 @@
]
},
"node_modules/@rollup/rollup-linux-s390x-gnu": {
- "version": "4.57.1",
- "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-s390x-gnu/-/rollup-linux-s390x-gnu-4.57.1.tgz",
- "integrity": "sha512-Bl00OFnVFkL82FHbEqy3k5CUCKH6OEJL54KCyx2oqsmZnFTR8IoNqBF+mjQVcRCT5sB6yOvK8A37LNm/kPJiZg==",
+ "version": "4.61.0",
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-s390x-gnu/-/rollup-linux-s390x-gnu-4.61.0.tgz",
+ "integrity": "sha512-Atk0aSIk5Zx2Wuh9dgRQgLP0Koc8hOeYpbWryMXyk8G8/HmPkwPPkMqIIDhrXHHYqfUzSJA/I7IWSBv8xSmRBA==",
"cpu": [
"s390x"
],
"dev": true,
+ "libc": [
+ "glibc"
+ ],
"license": "MIT",
"optional": true,
"os": [
@@ -1205,13 +1237,16 @@
]
},
"node_modules/@rollup/rollup-linux-x64-gnu": {
- "version": "4.57.1",
- "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.57.1.tgz",
- "integrity": "sha512-ABca4ceT4N+Tv/GtotnWAeXZUZuM/9AQyCyKYyKnpk4yoA7QIAuBt6Hkgpw8kActYlew2mvckXkvx0FfoInnLg==",
+ "version": "4.61.0",
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.61.0.tgz",
+ "integrity": "sha512-0uMOcf3eZ5K+K4cYHkdxShFMPlPXCOdfDFEFn9dNYAEEd2cVvmOfH7zFgRVoDgmtQ1m9k5q7qfrHzyMAubKYUA==",
"cpu": [
"x64"
],
"dev": true,
+ "libc": [
+ "glibc"
+ ],
"license": "MIT",
"optional": true,
"os": [
@@ -1219,13 +1254,16 @@
]
},
"node_modules/@rollup/rollup-linux-x64-musl": {
- "version": "4.57.1",
- "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.57.1.tgz",
- "integrity": "sha512-HFps0JeGtuOR2convgRRkHCekD7j+gdAuXM+/i6kGzQtFhlCtQkpwtNzkNj6QhCDp7DRJ7+qC/1Vg2jt5iSOFw==",
+ "version": "4.61.0",
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.61.0.tgz",
+ "integrity": "sha512-mvFtE4A/t/7hRJ7X8Ozmu8FsIkAUat2nzl12pgU337BRmq87AQUJztwHz2Zv5/tjo9/C95E66CK03SI/ToEDJw==",
"cpu": [
"x64"
],
"dev": true,
+ "libc": [
+ "musl"
+ ],
"license": "MIT",
"optional": true,
"os": [
@@ -1233,9 +1271,9 @@
]
},
"node_modules/@rollup/rollup-openbsd-x64": {
- "version": "4.57.1",
- "resolved": "https://registry.npmjs.org/@rollup/rollup-openbsd-x64/-/rollup-openbsd-x64-4.57.1.tgz",
- "integrity": "sha512-H+hXEv9gdVQuDTgnqD+SQffoWoc0Of59AStSzTEj/feWTBAnSfSD3+Dql1ZruJQxmykT/JVY0dE8Ka7z0DH1hw==",
+ "version": "4.61.0",
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-openbsd-x64/-/rollup-openbsd-x64-4.61.0.tgz",
+ "integrity": "sha512-z9b9+aTxvt8n2rNltMPvyaUfB8NJ+CVyOrGK/MdIKHx7B+lXmZpm/XbRsU7Rpf3fRqJ2uS6mBJiJveCtq8LHDg==",
"cpu": [
"x64"
],
@@ -1247,9 +1285,9 @@
]
},
"node_modules/@rollup/rollup-openharmony-arm64": {
- "version": "4.57.1",
- "resolved": "https://registry.npmjs.org/@rollup/rollup-openharmony-arm64/-/rollup-openharmony-arm64-4.57.1.tgz",
- "integrity": "sha512-4wYoDpNg6o/oPximyc/NG+mYUejZrCU2q+2w6YZqrAs2UcNUChIZXjtafAiiZSUc7On8v5NyNj34Kzj/Ltk6dQ==",
+ "version": "4.61.0",
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-openharmony-arm64/-/rollup-openharmony-arm64-4.61.0.tgz",
+ "integrity": "sha512-jXaXFqKMehsOc+g8R6oo33RRC6w07G9jDBxAE5eAKX7mOcCbZloYIPNhfG9Wl+P9O9IWHFO4OJgPi1Ml2qkt7w==",
"cpu": [
"arm64"
],
@@ -1261,9 +1299,9 @@
]
},
"node_modules/@rollup/rollup-win32-arm64-msvc": {
- "version": "4.57.1",
- "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-arm64-msvc/-/rollup-win32-arm64-msvc-4.57.1.tgz",
- "integrity": "sha512-O54mtsV/6LW3P8qdTcamQmuC990HDfR71lo44oZMZlXU4tzLrbvTii87Ni9opq60ds0YzuAlEr/GNwuNluZyMQ==",
+ "version": "4.61.0",
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-arm64-msvc/-/rollup-win32-arm64-msvc-4.61.0.tgz",
+ "integrity": "sha512-OXNWVFocS2IA4+QplhTZZ2a+8hPZR7T8KuozsNmJKK8y7cp83StHvGksfHzPG3wczWTczyWHVQuqeiTUbjiyBg==",
"cpu": [
"arm64"
],
@@ -1275,9 +1313,9 @@
]
},
"node_modules/@rollup/rollup-win32-ia32-msvc": {
- "version": "4.57.1",
- "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-ia32-msvc/-/rollup-win32-ia32-msvc-4.57.1.tgz",
- "integrity": "sha512-P3dLS+IerxCT/7D2q2FYcRdWRl22dNbrbBEtxdWhXrfIMPP9lQhb5h4Du04mdl5Woq05jVCDPCMF7Ub0NAjIew==",
+ "version": "4.61.0",
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-ia32-msvc/-/rollup-win32-ia32-msvc-4.61.0.tgz",
+ "integrity": "sha512-AlAbNtBO637LxSldqV43z0FfXoGfl2TW1DgAg/bs7aQswFbDewz2SJm3BUhiGfbOVtW571xbc9p+REdxhyN/Eg==",
"cpu": [
"ia32"
],
@@ -1289,9 +1327,9 @@
]
},
"node_modules/@rollup/rollup-win32-x64-gnu": {
- "version": "4.57.1",
- "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-gnu/-/rollup-win32-x64-gnu-4.57.1.tgz",
- "integrity": "sha512-VMBH2eOOaKGtIJYleXsi2B8CPVADrh+TyNxJ4mWPnKfLB/DBUmzW+5m1xUrcwWoMfSLagIRpjUFeW5CO5hyciQ==",
+ "version": "4.61.0",
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-gnu/-/rollup-win32-x64-gnu-4.61.0.tgz",
+ "integrity": "sha512-QRSrQXyJ1M4tjNXdR0/G/IgV6lzfQQJYBjlWIEYkY2Xs86DRl/iEpQ4blMDjJxSl7n19eDKKXMg0AmuBVYy8pQ==",
"cpu": [
"x64"
],
@@ -1303,9 +1341,9 @@
]
},
"node_modules/@rollup/rollup-win32-x64-msvc": {
- "version": "4.57.1",
- "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.57.1.tgz",
- "integrity": "sha512-mxRFDdHIWRxg3UfIIAwCm6NzvxG0jDX/wBN6KsQFTvKFqqg9vTrWUE68qEjHt19A5wwx5X5aUi2zuZT7YR0jrA==",
+ "version": "4.61.0",
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.61.0.tgz",
+ "integrity": "sha512-tkuFxhvKO/HlGd0VsINF6vHSYH8AF8W0TcNxKDK6JZmrehngFj78pToc8iemtnvwilDjs2G/qSzYFhe9U8q+fw==",
"cpu": [
"x64"
],
@@ -1517,9 +1555,9 @@
"license": "MIT"
},
"node_modules/@types/estree": {
- "version": "1.0.8",
- "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.8.tgz",
- "integrity": "sha512-dWHzHa2WqEXI/O1E9OjrocMTKJl2mSrEolh1Iomrv6U+JuNwaHXsXx9bLu5gG7BUWFIN0skIQJQ/L1rIex4X6w==",
+ "version": "1.0.9",
+ "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.9.tgz",
+ "integrity": "sha512-GhdPgy1el4/ImP05X05Uw4cw2/M93BCUmnEvWZNStlCzEKME4Fkk+YpoA5OiHNQmoS7Cafb8Xa3Pya8m1Qrzeg==",
"dev": true,
"license": "MIT"
},
@@ -1726,9 +1764,9 @@
}
},
"node_modules/brace-expansion": {
- "version": "2.0.2",
- "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.2.tgz",
- "integrity": "sha512-Jt0vHyM+jmUBqojB7E1NIYadt0vI0Qxjxd2TErW94wDz+E2LAm5vKMXXwg6ZZBTHPuUlDgQHKXvjGBdfcF1ZDQ==",
+ "version": "2.1.1",
+ "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.1.1.tgz",
+ "integrity": "sha512-WR1cURNjuvBLMZBMbqM0UoE+WAfdUcEV1ccD8PVBVOI+Z3ND4+SZbN8RsfT2bMuG1qwz5RFvPukSZm5fF2D5eA==",
"license": "MIT",
"dependencies": {
"balanced-match": "^1.0.0"
@@ -3035,12 +3073,12 @@
}
},
"node_modules/minimatch": {
- "version": "9.0.5",
- "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.5.tgz",
- "integrity": "sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow==",
+ "version": "9.0.9",
+ "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.9.tgz",
+ "integrity": "sha512-OBwBN9AL4dqmETlpS2zasx+vTeWclWzkblfZk7KTA5j3jeOONz/tRCnZomUyvNg83wL5Zv9Ss6HMJXAgL8R2Yg==",
"license": "ISC",
"dependencies": {
- "brace-expansion": "^2.0.1"
+ "brace-expansion": "^2.0.2"
},
"engines": {
"node": ">=16 || 14 >=14.17"
@@ -3140,9 +3178,9 @@
}
},
"node_modules/nanoid": {
- "version": "3.3.11",
- "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.11.tgz",
- "integrity": "sha512-N8SpfPUnUp1bK+PMYW8qSWdl9U+wwNWI4QKxOYDy9JAro3WMX7p2OeVRF9v+347pnakNevPmiHhNmZ2HbFA76w==",
+ "version": "3.3.12",
+ "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.12.tgz",
+ "integrity": "sha512-ZB9RH/39qpq5Vu6Y+NmUaFhQR6pp+M2Xt76XBnEwDaGcVAqhlvxrl3B2bKS5D3NH3QR76v3aSrKaF/Kiy7lEtQ==",
"dev": true,
"funding": [
{
@@ -3213,9 +3251,9 @@
"license": "MIT"
},
"node_modules/nodemailer": {
- "version": "7.0.13",
- "resolved": "https://registry.npmjs.org/nodemailer/-/nodemailer-7.0.13.tgz",
- "integrity": "sha512-PNDFSJdP+KFgdsG3ZzMXCgquO7I6McjY2vlqILjtJd0hy8wEvtugS9xKRF2NWlPNGxvLCXlTNIae4serI7dinw==",
+ "version": "8.0.10",
+ "resolved": "https://registry.npmjs.org/nodemailer/-/nodemailer-8.0.10.tgz",
+ "integrity": "sha512-BLFuSth7QtHOkBzyqTehWWyub0NTRDuK2Q2SQfnGLsrJnzyU+Yeh4WpV1eZGuARFj1xQJHIdnTuJZLP+b9R1GQ==",
"license": "MIT-0",
"engines": {
"node": ">=6.0.0"
@@ -3344,9 +3382,9 @@
"license": "ISC"
},
"node_modules/path-to-regexp": {
- "version": "8.3.0",
- "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-8.3.0.tgz",
- "integrity": "sha512-7jdwVIRtsP8MYpdXSwOS0YdD0Du+qOoF/AEPIt88PcCFrZCzx41oxku1jD88hZBwbNUIEfpqvuhjFaMAqMTWnA==",
+ "version": "8.4.2",
+ "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-8.4.2.tgz",
+ "integrity": "sha512-qRcuIdP69NPm4qbACK+aDogI5CBDMi1jKe0ry5rSQJz8JVLsC7jV8XpiJjGRLLol3N+R5ihGYcrPLTno6pAdBA==",
"license": "MIT",
"funding": {
"type": "opencollective",
@@ -3361,9 +3399,9 @@
"license": "ISC"
},
"node_modules/picomatch": {
- "version": "4.0.3",
- "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.3.tgz",
- "integrity": "sha512-5gTmgEY/sqK6gFXLIsQNH19lWb4ebPDLA4SdLP7dsWkIXHWlG66oPuVvXSGFPppYZz8ZDZq0dYYrbHfBCVUb1Q==",
+ "version": "4.0.4",
+ "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.4.tgz",
+ "integrity": "sha512-QP88BAKvMam/3NxH6vj2o21R6MjxZUAd6nlwAS/pnGvN9IVLocLHxGYIzFhg6fUQ+5th6P4dv4eW9jX3DSIj7A==",
"dev": true,
"license": "MIT",
"engines": {
@@ -3374,9 +3412,9 @@
}
},
"node_modules/postcss": {
- "version": "8.5.6",
- "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.5.6.tgz",
- "integrity": "sha512-3Ybi1tAuwAP9s0r1UQ2J4n5Y0G05bJkpUIO0/bI9MhwmD70S5aTWbXGBwxHrelT+XM1k6dM0pk+SwNkpTRN7Pg==",
+ "version": "8.5.15",
+ "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.5.15.tgz",
+ "integrity": "sha512-FfR8sjd4em2T6fb3I2MwAJU7HWVMr9zba+enmQeeWFfCbm+UOC/0X4DS8XtpUTMwWMGbjKYP7xjfNekzyGmB3A==",
"dev": true,
"funding": [
{
@@ -3394,7 +3432,7 @@
],
"license": "MIT",
"dependencies": {
- "nanoid": "^3.3.11",
+ "nanoid": "^3.3.12",
"picocolors": "^1.1.1",
"source-map-js": "^1.2.1"
},
@@ -3412,24 +3450,24 @@
}
},
"node_modules/protobufjs": {
- "version": "7.5.4",
- "resolved": "https://registry.npmjs.org/protobufjs/-/protobufjs-7.5.4.tgz",
- "integrity": "sha512-CvexbZtbov6jW2eXAvLukXjXUW1TzFaivC46BpWc/3BpcCysb5Vffu+B3XHMm8lVEuy2Mm4XGex8hBSg1yapPg==",
+ "version": "7.6.2",
+ "resolved": "https://registry.npmjs.org/protobufjs/-/protobufjs-7.6.2.tgz",
+ "integrity": "sha512-N9EiLovGEQOJSPF26Ij7qUGvahfEnq0eeYZ02aigIedkmz1qZSwjnP9SBITHJuF/6MYbIW4HDN8zdYjsjqJKXQ==",
"hasInstallScript": true,
"license": "BSD-3-Clause",
"dependencies": {
"@protobufjs/aspromise": "^1.1.2",
"@protobufjs/base64": "^1.1.2",
- "@protobufjs/codegen": "^2.0.4",
- "@protobufjs/eventemitter": "^1.1.0",
- "@protobufjs/fetch": "^1.1.0",
+ "@protobufjs/codegen": "^2.0.5",
+ "@protobufjs/eventemitter": "^1.1.1",
+ "@protobufjs/fetch": "^1.1.1",
"@protobufjs/float": "^1.0.2",
- "@protobufjs/inquire": "^1.1.0",
+ "@protobufjs/inquire": "^1.1.2",
"@protobufjs/path": "^1.1.2",
"@protobufjs/pool": "^1.1.0",
- "@protobufjs/utf8": "^1.1.0",
+ "@protobufjs/utf8": "^1.1.1",
"@types/node": ">=13.7.0",
- "long": "^5.0.0"
+ "long": "^5.3.2"
},
"engines": {
"node": ">=12.0.0"
@@ -3449,9 +3487,9 @@
}
},
"node_modules/qs": {
- "version": "6.15.0",
- "resolved": "https://registry.npmjs.org/qs/-/qs-6.15.0.tgz",
- "integrity": "sha512-mAZTtNCeetKMH+pSjrb76NAM8V9a05I9aBZOHztWy/UqcJdQYNsf59vrRKWnojAT9Y+GbIvoTBC++CPHqpDBhQ==",
+ "version": "6.15.2",
+ "resolved": "https://registry.npmjs.org/qs/-/qs-6.15.2.tgz",
+ "integrity": "sha512-Rzq0KEyX/w/tEybncDgdkZrJgVUsUMk3xjh3t5bv3S1HTAtg+uOYt72+ZfwiQwKdysThkTBdL/rTi6HDmX9Ddw==",
"license": "BSD-3-Clause",
"dependencies": {
"side-channel": "^1.1.0"
@@ -3666,13 +3704,13 @@
}
},
"node_modules/rollup": {
- "version": "4.57.1",
- "resolved": "https://registry.npmjs.org/rollup/-/rollup-4.57.1.tgz",
- "integrity": "sha512-oQL6lgK3e2QZeQ7gcgIkS2YZPg5slw37hYufJ3edKlfQSGGm8ICoxswK15ntSzF/a8+h7ekRy7k7oWc3BQ7y8A==",
+ "version": "4.61.0",
+ "resolved": "https://registry.npmjs.org/rollup/-/rollup-4.61.0.tgz",
+ "integrity": "sha512-T9mWdbWfQtp0B5lv/HX+wrhYsmXRlcWnXXmJbXqKJhlRaoS6KMhq0gpyzW4UJfclcxrEdLnTgjT2NjruLONu0g==",
"dev": true,
"license": "MIT",
"dependencies": {
- "@types/estree": "1.0.8"
+ "@types/estree": "1.0.9"
},
"bin": {
"rollup": "dist/bin/rollup"
@@ -3682,31 +3720,31 @@
"npm": ">=8.0.0"
},
"optionalDependencies": {
- "@rollup/rollup-android-arm-eabi": "4.57.1",
- "@rollup/rollup-android-arm64": "4.57.1",
- "@rollup/rollup-darwin-arm64": "4.57.1",
- "@rollup/rollup-darwin-x64": "4.57.1",
- "@rollup/rollup-freebsd-arm64": "4.57.1",
- "@rollup/rollup-freebsd-x64": "4.57.1",
- "@rollup/rollup-linux-arm-gnueabihf": "4.57.1",
- "@rollup/rollup-linux-arm-musleabihf": "4.57.1",
- "@rollup/rollup-linux-arm64-gnu": "4.57.1",
- "@rollup/rollup-linux-arm64-musl": "4.57.1",
- "@rollup/rollup-linux-loong64-gnu": "4.57.1",
- "@rollup/rollup-linux-loong64-musl": "4.57.1",
- "@rollup/rollup-linux-ppc64-gnu": "4.57.1",
- "@rollup/rollup-linux-ppc64-musl": "4.57.1",
- "@rollup/rollup-linux-riscv64-gnu": "4.57.1",
- "@rollup/rollup-linux-riscv64-musl": "4.57.1",
- "@rollup/rollup-linux-s390x-gnu": "4.57.1",
- "@rollup/rollup-linux-x64-gnu": "4.57.1",
- "@rollup/rollup-linux-x64-musl": "4.57.1",
- "@rollup/rollup-openbsd-x64": "4.57.1",
- "@rollup/rollup-openharmony-arm64": "4.57.1",
- "@rollup/rollup-win32-arm64-msvc": "4.57.1",
- "@rollup/rollup-win32-ia32-msvc": "4.57.1",
- "@rollup/rollup-win32-x64-gnu": "4.57.1",
- "@rollup/rollup-win32-x64-msvc": "4.57.1",
+ "@rollup/rollup-android-arm-eabi": "4.61.0",
+ "@rollup/rollup-android-arm64": "4.61.0",
+ "@rollup/rollup-darwin-arm64": "4.61.0",
+ "@rollup/rollup-darwin-x64": "4.61.0",
+ "@rollup/rollup-freebsd-arm64": "4.61.0",
+ "@rollup/rollup-freebsd-x64": "4.61.0",
+ "@rollup/rollup-linux-arm-gnueabihf": "4.61.0",
+ "@rollup/rollup-linux-arm-musleabihf": "4.61.0",
+ "@rollup/rollup-linux-arm64-gnu": "4.61.0",
+ "@rollup/rollup-linux-arm64-musl": "4.61.0",
+ "@rollup/rollup-linux-loong64-gnu": "4.61.0",
+ "@rollup/rollup-linux-loong64-musl": "4.61.0",
+ "@rollup/rollup-linux-ppc64-gnu": "4.61.0",
+ "@rollup/rollup-linux-ppc64-musl": "4.61.0",
+ "@rollup/rollup-linux-riscv64-gnu": "4.61.0",
+ "@rollup/rollup-linux-riscv64-musl": "4.61.0",
+ "@rollup/rollup-linux-s390x-gnu": "4.61.0",
+ "@rollup/rollup-linux-x64-gnu": "4.61.0",
+ "@rollup/rollup-linux-x64-musl": "4.61.0",
+ "@rollup/rollup-openbsd-x64": "4.61.0",
+ "@rollup/rollup-openharmony-arm64": "4.61.0",
+ "@rollup/rollup-win32-arm64-msvc": "4.61.0",
+ "@rollup/rollup-win32-ia32-msvc": "4.61.0",
+ "@rollup/rollup-win32-x64-gnu": "4.61.0",
+ "@rollup/rollup-win32-x64-msvc": "4.61.0",
"fsevents": "~2.3.2"
}
},
@@ -4233,9 +4271,9 @@
}
},
"node_modules/vite": {
- "version": "6.4.1",
- "resolved": "https://registry.npmjs.org/vite/-/vite-6.4.1.tgz",
- "integrity": "sha512-+Oxm7q9hDoLMyJOYfUYBuHQo+dkAloi33apOPP56pzj+vsdJDzr+j1NISE5pyaAuKL4A3UD34qd0lx5+kfKp2g==",
+ "version": "6.4.3",
+ "resolved": "https://registry.npmjs.org/vite/-/vite-6.4.3.tgz",
+ "integrity": "sha512-NTKlcQjlAK7MlQoyb6LgaqHc8sso/pVyUJYWMws3jg21uTJw/LddqIFPcPqP6PzpgbIcZyKI85sFE4HBrQDA8A==",
"dev": true,
"license": "MIT",
"dependencies": {
@@ -4429,9 +4467,9 @@
"license": "ISC"
},
"node_modules/ws": {
- "version": "8.19.0",
- "resolved": "https://registry.npmjs.org/ws/-/ws-8.19.0.tgz",
- "integrity": "sha512-blAT2mjOEIi0ZzruJfIhb3nps74PRWTCz1IjglWEEpQl5XS/UNama6u2/rjFkDDouqr4L67ry+1aGIALViWjDg==",
+ "version": "8.21.0",
+ "resolved": "https://registry.npmjs.org/ws/-/ws-8.21.0.tgz",
+ "integrity": "sha512-Vsp28b7DRcimFQvrqu2Wek3z1iYxDCWqHYB8Qsnk/S4RfaCQzPGPyBNuVjJV3cd6UiKtUtp6sNM77gWvzcCH+g==",
"license": "MIT",
"engines": {
"node": ">=10.0.0"
diff --git a/package.json b/package.json
index 925889f..2a62dd7 100644
--- a/package.json
+++ b/package.json
@@ -11,25 +11,25 @@
"tunnel": "\"C:\\Program Files (x86)\\cloudflared\\cloudflared.exe\" tunnel --url http://localhost:3000 --no-autoupdate"
},
"dependencies": {
- "react": "^19.2.1",
- "react-dom": "^19.2.1",
"@google/genai": "^1.33.0",
- "lucide-react": "^0.560.0",
+ "@supabase/supabase-js": "^2.89.0",
"@vitejs/plugin-react": "^5.1.2",
- "vite": "^7.2.7",
- "recharts": "^3.5.1",
- "react-router-dom": "^7.10.1",
- "express": "^5.2.1",
+ "bcryptjs": "^3.0.3",
"cors": "^2.8.5",
+ "dotenv": "^17.2.3",
+ "express": "^5.2.1",
"jsonwebtoken": "^9.0.3",
+ "lucide-react": "^0.560.0",
"morgan": "^1.10.1",
- "dotenv": "^17.2.3",
- "bcryptjs": "^3.0.3",
- "nodemailer": "^7.0.12",
+ "mysql2": "^3.16.0",
+ "nodemailer": "^8.0.10",
"path": "^0.12.7",
"process": "^0.11.10",
- "@supabase/supabase-js": "^2.89.0",
- "mysql2": "^3.16.0"
+ "react": "^19.2.1",
+ "react-dom": "^19.2.1",
+ "react-router-dom": "^7.10.1",
+ "recharts": "^3.5.1",
+ "vite": "^7.2.7"
},
"devDependencies": {
"@types/node": "^22.14.0",
diff --git a/pages/Landing.tsx b/pages/Landing.tsx
index c023d38..ffcbe2c 100644
--- a/pages/Landing.tsx
+++ b/pages/Landing.tsx
@@ -1,5 +1,5 @@
import React, { useState, useContext, useEffect, useRef } from 'react';
-import { PawPrint, Shield, ArrowRight, Mail, User as UserIcon, Lock, ArrowLeft, Loader2, Globe, RefreshCw, Key, CheckCircle2, MapPin, Building2, UserCheck, AlertTriangle, ChevronDown, Save, Info, Crosshair, Sprout, Globe2 } from 'lucide-react';
+import { PawPrint, Shield, ArrowRight, Mail, User as UserIcon, Lock, ArrowLeft, Loader2, Globe, RefreshCw, Key, CheckCircle2, MapPin, Building2, UserCheck, AlertTriangle, ChevronDown, Save, Info, Crosshair, Sprout, Globe2, Github } from 'lucide-react';
import * as LucideIcons from 'lucide-react';
import { forgotPassword, resetPassword, restoreMainOrg, isMfaTrustedDevice, sendMfaCode, trustDevice, saveSession, getSystemSettings, checkInviteToken, acceptInvite, saveOrg, saveProjects, getProjects, saveCurrentProjectId } from '../services/storage';
import { reverseGeocode } from '../services/geminiService';
@@ -368,6 +368,11 @@ const Landing: React.FC = ({ onLogin, initialView = 'landing' }) =
{displaySubtitle}
{isRegistrationEnabled && (
{ setViewMode('register'); setRegStep('details'); }} disabled={isLoading} className="w-full sm:w-auto px-8 py-4 bg-slate-900 text-white rounded-xl font-bold text-lg hover:bg-black transition-all shadow-lg flex items-center justify-center gap-2 disabled:opacity-50">{t('createOrg')} )}
+ {landingConfig?.githubButton?.enabled && landingConfig.githubButton.url && (
+
+ GitHub
+
+ )}
{/* Explore demo button hidden */}
diff --git a/pages/SuperAdmin.tsx b/pages/SuperAdmin.tsx
index 87a7c5d..def1770 100644
--- a/pages/SuperAdmin.tsx
+++ b/pages/SuperAdmin.tsx
@@ -2,12 +2,12 @@ import React, { useContext, useState, useEffect, useMemo } from 'react';
import { getNetworkPartners, getUsers, switchOrganization, getSystemSettings, saveSystemSettings, getOrg, getLanguages, saveLanguages, permanentDeleteOrganization, clearLocalCache, getSpecies, getProjects, getIndividuals } from '../services/storage';
import { testSmtpConnection } from '../services/emailService';
import { translateDictionary } from '../services/geminiService';
-import {
- Shield, Save, Loader2, Globe, Star, Mail, PenTool, LogIn, CheckCircle2,
- Send, AlertCircle, Trash2, X, RefreshCw, Plus, Layout, Palette,
+import {
+ Shield, Save, Loader2, Globe, Star, Mail, PenTool, LogIn, CheckCircle2,
+ Send, AlertCircle, Trash2, X, RefreshCw, Plus, Layout, Palette,
Lock, FileText, Type, Image as ImageIcon, Sparkles, UserPlus, AlertTriangle, Wand2,
Building2, Briefcase, MapPin, GripVertical, Info, Database, Zap, Check, Search,
- ChevronDown, ChevronRight, Dna, Users, Activity, Leaf, MessageSquare, Code
+ ChevronDown, ChevronRight, Dna, Users, Activity, Leaf, MessageSquare, Code, Github
} from 'lucide-react';
import { LanguageContext } from '../App';
import { SystemSettings, LanguageConfig, EmailTemplate, UserRole, StaticPageConfig, Organization, OrganizationFocus, LandingFeature, ExternalPartner, Project, Individual, Species, Sex } from '../types';
@@ -550,6 +550,18 @@ const SuperAdmin: React.FC = () => {
+
+
+
GitHub Button
+
+ setSettings({...settings, landingPageConfig: { ...settings.landingPageConfig, githubButton: { url: settings.landingPageConfig?.githubButton?.url || '', enabled: e.target.checked }}})} />
+
+
+
+
setSettings({...settings, landingPageConfig: { ...settings.landingPageConfig, githubButton: { enabled: settings.landingPageConfig?.githubButton?.enabled ?? false, url: e.target.value }}})} />
+
When enabled, a GitHub button appears next to "Create Organisation" on the landing page.
+
+
Registration Banner Message