diff --git a/.github/copilot-instructions.md b/.github/copilot-instructions.md new file mode 100644 index 000000000..f29b9f4b3 --- /dev/null +++ b/.github/copilot-instructions.md @@ -0,0 +1,167 @@ +# Copilot Instructions for Uptime Kuma + +## Copilot's Goals/Tasks + +- Check spelling +- Do not show "Pull Request Overview" +- You do not have to reply if there are no issues + +## Repository Overview + +**Uptime Kuma** is a self-hosted monitoring tool for HTTP(s), TCP, DNS, Docker, etc. Built with Vue 3 (frontend) and Node.js/Express (backend), using Socket.IO for real-time communication. + +- **Languages**: JavaScript, Vue 3, TypeScript (limited), HTML, CSS/SCSS +- **Backend**: Node.js >= 20.4, Express.js, Socket.IO, SQLite +- **Frontend**: Vue 3, Vite, Bootstrap 5, Chart.js +- **Package Manager**: npm with `legacy-peer-deps=true` (.npmrc) + +## Build & Validation Commands + +### Prerequisites +- Node.js >= 20.4.0, npm >= 9.3, Git + +### Essential Command Sequence + +1. **Install Dependencies**: + ```bash + npm ci # Use npm ci NOT npm install (~60-90 seconds) + ``` + +2. **Linting** (required before committing): + ```bash + npm run lint # Both linters (~15-30 seconds) + npm run lint:prod # For production (zero warnings) + ``` + +3. **Build Frontend**: + ```bash + npm run build # Takes ~90-120 seconds, builds to dist/ + ``` + +4. **Run Tests**: + ```bash + npm run test-backend # Backend tests (~50-60 seconds) + npm test # All tests + ``` + +### Development Workflow + +```bash +npm run dev # Starts frontend (port 3000) and backend (port 3001) +``` + +## Project Architecture + +### Directory Structure + +``` +/ +├── server/ Backend source code +│ ├── model/ Database models (auto-mapped to tables) +│ ├── monitor-types/ Monitor type implementations +│ ├── notification-providers/ Notification integrations +│ ├── routers/ Express routers +│ ├── socket-handlers/ Socket.IO event handlers +│ ├── server.js Server entry point +│ └── uptime-kuma-server.js Main server logic +├── src/ Frontend source code (Vue 3 SPA) +│ ├── components/ Vue components +│ ├── pages/ Page components +│ ├── lang/ i18n translations +│ ├── router.js Vue Router configuration +│ └── main.js Frontend entry point +├── db/ Database related +│ ├── knex_migrations/ Knex migration files +│ └── kuma.db SQLite database (gitignored) +├── test/ Test files +│ ├── backend-test/ Backend unit tests +│ └── e2e/ Playwright E2E tests +├── config/ Build configuration +│ ├── vite.config.js Vite build config +│ └── playwright.config.js Playwright test config +├── dist/ Frontend build output (gitignored) +├── data/ App data directory (gitignored) +├── public/ Static frontend assets (dev only) +├── docker/ Docker build files +└── extra/ Utility scripts +``` + +### Key Configuration Files + +- **package.json**: Scripts, dependencies, Node.js version requirement +- **.eslintrc.js**: ESLint rules (4 spaces, double quotes, unix line endings, JSDoc required) +- **.stylelintrc**: Stylelint rules (4 spaces indentation) +- **.editorconfig**: Editor settings (4 spaces, LF, UTF-8) +- **tsconfig-backend.json**: TypeScript config for backend (only src/util.ts) +- **.npmrc**: `legacy-peer-deps=true` (required for dependency resolution) +- **.gitignore**: Excludes node_modules, dist, data, tmp, private + +### Code Style (strictly enforced by linters) + +- 4 spaces indentation, double quotes, Unix line endings (LF), semicolons required +- **Naming**: JavaScript/TypeScript (camelCase), SQLite (snake_case), CSS/SCSS (kebab-case) +- JSDoc required for all functions/methods + +## CI/CD Workflows + +**auto-test.yml** (runs on PR/push to master/1.23.X): +- Linting, building, backend tests on multiple OS/Node versions (15 min timeout) +- E2E Playwright tests + +**validate.yml**: Validates JSON/YAML files, language files, knex migrations + +**PR Requirements**: All linters pass, tests pass, code follows style guidelines + +## Common Issues + +1. **npm install vs npm ci**: Always use `npm ci` for reproducible builds +2. **TypeScript errors**: `npm run tsc` shows 1400+ errors - ignore them, they don't affect builds +3. **Stylelint warnings**: Deprecation warnings are expected, ignore them +4. **Test failures**: Always run `npm run build` before running tests +5. **Port conflicts**: Dev server uses ports 3000 and 3001 +6. **First run**: Server shows "db-config.json not found" - this is expected, starts setup wizard + +## Translations + +- Managed via Weblate. Add keys to `src/lang/en.json` only +- Don't include other languages in PRs +- Use `$t("key")` in Vue templates + +## Database + +- Primary: SQLite (also supports MariaDB/MySQL/PostgreSQL) +- Migrations in `db/knex_migrations/` using Knex.js +- Filename format validated by CI: `node ./extra/check-knex-filenames.mjs` + +## Testing + +- **Backend**: Node.js test runner, fast unit tests +- **E2E**: Playwright (requires `npx playwright install` first time) +- Test data in `data/playwright-test` + +## Adding New Features + +### New Notification Provider +Files to modify: +1. `server/notification-providers/PROVIDER_NAME.js` (backend logic) +2. `server/notification.js` (register provider) +3. `src/components/notifications/PROVIDER_NAME.vue` (frontend UI) +4. `src/components/notifications/index.js` (register frontend) +5. `src/components/NotificationDialog.vue` (add to list) +6. `src/lang/en.json` (add translation keys) + +### New Monitor Type +Files to modify: +1. `server/monitor-types/MONITORING_TYPE.js` (backend logic) +2. `server/uptime-kuma-server.js` (register monitor type) +3. `src/pages/EditMonitor.vue` (frontend UI) +4. `src/lang/en.json` (add translation keys) + +## Important Notes + +1. **Trust these instructions** - based on testing. Search only if incomplete/incorrect +2. **Dependencies**: 5 known vulnerabilities (3 moderate, 2 high) - acknowledged, don't fix without discussion +3. **Git Branches**: `master` (v2 development), `1.23.X` (v1 maintenance) +4. **Node Version**: >= 20.4.0 required +5. **Socket.IO**: Most backend logic in `server/socket-handlers/`, not REST +6. **Never commit**: `data/`, `dist/`, `tmp/`, `private/`, `node_modules/` diff --git a/.github/workflows/auto-test.yml b/.github/workflows/auto-test.yml index f59035442..a59286682 100644 --- a/.github/workflows/auto-test.yml +++ b/.github/workflows/auto-test.yml @@ -5,11 +5,11 @@ name: Auto Test on: push: - branches: [ master, 1.23.X ] + branches: [ master, 1.23.X, 3.0.X ] paths-ignore: - '*.md' pull_request: - branches: [ master, 1.23.X ] + branches: [ master, 1.23.X, 3.0.X ] paths-ignore: - '*.md' @@ -22,15 +22,15 @@ jobs: strategy: matrix: os: [macos-latest, ubuntu-22.04, windows-latest, ARM64] - node: [ 18, 20 ] # See supported Node.js release schedule at https://nodejs.org/en/about/releases/ + node: [ 24, 25 ] steps: - run: git config --global core.autocrlf false # Mainly for Windows - uses: actions/checkout@v4 - name: Use Node.js ${{ matrix.node }} - uses: actions/setup-node@v4 + uses: actions/setup-node@v6 with: node-version: ${{ matrix.node }} - run: npm install @@ -40,28 +40,6 @@ jobs: HEADLESS_TEST: 1 JUST_FOR_TEST: ${{ secrets.JUST_FOR_TEST }} - # As a lot of dev dependencies are not supported on ARMv7, we have to test it separately and just test if `npm ci --production` works - armv7-simple-test: - needs: [ ] - runs-on: ${{ matrix.os }} - timeout-minutes: 15 - if: ${{ github.repository == 'louislam/uptime-kuma' }} - strategy: - matrix: - os: [ ARMv7 ] - node: [ 18, 20 ] - # See supported Node.js release schedule at https://nodejs.org/en/about/releases/ - - steps: - - run: git config --global core.autocrlf false # Mainly for Windows - - uses: actions/checkout@v4 - - - name: Use Node.js ${{ matrix.node }} - uses: actions/setup-node@v4 - with: - node-version: ${{ matrix.node }} - - run: npm ci --production - check-linters: runs-on: ubuntu-latest @@ -69,10 +47,10 @@ jobs: - run: git config --global core.autocrlf false # Mainly for Windows - uses: actions/checkout@v4 - - name: Use Node.js 20 - uses: actions/setup-node@v4 + - name: Use Node.js 24 + uses: actions/setup-node@v6 with: - node-version: 20 + node-version: 24 - run: npm install - run: npm run lint:prod @@ -83,10 +61,10 @@ jobs: - run: git config --global core.autocrlf false # Mainly for Windows - uses: actions/checkout@v4 - - name: Use Node.js 20 - uses: actions/setup-node@v4 + - name: Use Node.js 24 + uses: actions/setup-node@v6 with: - node-version: 20 + node-version: 24 - run: npm install - run: npx playwright install - run: npm run build diff --git a/.github/workflows/close-incorrect-issue.yml b/.github/workflows/close-incorrect-issue.yml index 3ef5ba378..9d4616931 100644 --- a/.github/workflows/close-incorrect-issue.yml +++ b/.github/workflows/close-incorrect-issue.yml @@ -11,13 +11,13 @@ jobs: strategy: matrix: os: [ubuntu-latest] - node-version: [18] + node-version: [20] steps: - uses: actions/checkout@v4 - name: Use Node.js ${{ matrix.node-version }} - uses: actions/setup-node@v4 + uses: actions/setup-node@v6 with: node-version: ${{ matrix.node-version }} cache: 'npm' diff --git a/.github/workflows/validate.yml b/.github/workflows/validate.yml index 7e631ccd4..35c0c1901 100644 --- a/.github/workflows/validate.yml +++ b/.github/workflows/validate.yml @@ -7,6 +7,7 @@ on: branches: - master - 1.23.X + - 3.0.X workflow_dispatch: permissions: @@ -31,10 +32,10 @@ jobs: runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 - - name: Use Node.js 20 - uses: actions/setup-node@v4 + - name: Use Node.js 24 + uses: actions/setup-node@v6 with: - node-version: 20 + node-version: 24 - name: Validate language JSON files run: node ./extra/check-lang-json.js diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index e4cae2ad0..02ca8aa79 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -447,7 +447,7 @@ as easy as installing a mobile app. - Easy to install for non-Docker users - - no native build dependency is needed (for `x86_64`/`armv7`/`arm64`) + - no native build dependency is needed (for `x86_64`/`arm64`) - no extra configuration and - no extra effort required to get it running @@ -639,7 +639,6 @@ repo to do that. - amd64 - arm64 -- armv7 ### Docker Tags @@ -692,7 +691,7 @@ We have a few procedures we follow. These are documented here: -
Set up a Docker Builder (click to expand)

- - amd64, armv7 using local. + - amd64 using local. - arm64 using remote arm64 cpu, as the emulator is too slow and can no longer pass the `npm ci` command. @@ -707,7 +706,7 @@ We have a few procedures we follow. These are documented here: 3. Create a new builder. ```bash - docker buildx create --name kuma-builder --platform linux/amd64,linux/arm/v7 + docker buildx create --name kuma-builder --platform linux/amd64 docker buildx use kuma-builder docker buildx inspect --bootstrap ``` @@ -742,8 +741,7 @@ We have a few procedures we follow. These are documented here: - [ ] Check all tags is fine on - - [ ] Try the Docker image with tag 1.X.X (Clean install / amd64 / arm64 / - armv7) + - [ ] Try the Docker image with tag 1.X.X (Clean install / amd64 / arm64) - [ ] Try clean installation with Node.js

diff --git a/README.md b/README.md index b58edfe7d..eaf760542 100644 --- a/README.md +++ b/README.md @@ -45,8 +45,7 @@ cd uptime-kuma curl -o compose.yaml https://raw.githubusercontent.com/louislam/uptime-kuma/master/compose.yaml docker compose up -d ``` - -Uptime Kuma is now running on . +Uptime Kuma is now running on all network interfaces (e.g. http://localhost:3001 or http://your-ip:3001). > [!WARNING] > File Systems like **NFS** (Network File System) are **NOT** supported. Please map to a local directory or volume. @@ -56,22 +55,22 @@ Uptime Kuma is now running on . ```bash docker run -d --restart=always -p 3001:3001 -v uptime-kuma:/app/data --name uptime-kuma louislam/uptime-kuma:2 ``` +Uptime Kuma is now running on all network interfaces (e.g. http://localhost:3001 or http://your-ip:3001). + +If you want to limit exposure to localhost only: + +```bash +docker run ... -p 127.0.0.1:3001:3001 ... +``` -Uptime Kuma is now running on . -> [!NOTE] -> If you want to limit exposure to localhost (without exposing port for other users or to use a [reverse proxy](https://github.com/louislam/uptime-kuma/wiki/Reverse-Proxy)), you can expose the port like this: -> -> ```bash -> docker run -d --restart=always -p 127.0.0.1:3001:3001 -v uptime-kuma:/app/data --name uptime-kuma louislam/uptime-kuma:2 -> ``` ### 💪🏻 Non-Docker Requirements: - Platform - - ✅ Major Linux distros such as Debian, Ubuntu, CentOS, Fedora and ArchLinux etc. + - ✅ Major Linux distros such as Debian, Ubuntu, Fedora and ArchLinux etc. - ✅ Windows 10 (x64), Windows Server 2012 R2 (x64) or higher - ❌ FreeBSD / OpenBSD / NetBSD - ❌ Replit / Heroku @@ -94,8 +93,7 @@ npm install pm2 -g && pm2 install pm2-logrotate # Start Server pm2 start server/server.js --name uptime-kuma ``` - -Uptime Kuma is now running on +Uptime Kuma is now running on all network interfaces (e.g. http://localhost:3001 or http://your-ip:3001). More useful PM2 Commands diff --git a/config/playwright.config.js b/config/playwright.config.js index 5c574eecc..be07af9d0 100644 --- a/config/playwright.config.js +++ b/config/playwright.config.js @@ -58,7 +58,7 @@ export default defineConfig({ // Run your local dev server before starting the tests. webServer: { - command: `node extra/remove-playwright-test-data.js && cross-env NODE_ENV=development node server/server.js --port=${port} --data-dir=./data/playwright-test`, + command: `node extra/remove-playwright-test-data.js && cross-env NODE_ENV=development node --import=tsx server/server.js --port=${port} --data-dir=./data/playwright-test`, url, reuseExistingServer: false, cwd: "../", diff --git a/config/vite.config.js b/config/vite.config.js index 7f2dfb6ff..9c8b24f56 100644 --- a/config/vite.config.js +++ b/config/vite.config.js @@ -2,7 +2,6 @@ import vue from "@vitejs/plugin-vue"; import { defineConfig } from "vite"; import visualizer from "rollup-plugin-visualizer"; import viteCompression from "vite-plugin-compression"; -import VueDevTools from "vite-plugin-vue-devtools"; const postCssScss = require("postcss-scss"); const postcssRTLCSS = require("postcss-rtlcss"); @@ -31,7 +30,6 @@ export default defineConfig({ algorithm: "brotliCompress", filter: viteCompressionFilter, }), - VueDevTools(), ], css: { postcss: { diff --git a/docker/builder-go.dockerfile b/docker/builder-go.dockerfile index 7c25641b4..5a05391fe 100644 --- a/docker/builder-go.dockerfile +++ b/docker/builder-go.dockerfile @@ -1,8 +1,7 @@ ############################################ # Build in Golang -# Run npm run build-healthcheck-armv7 in the host first, another it will be super slow where it is building the armv7 healthcheck ############################################ -FROM golang:1-bookworm +FROM golang:1-trixie WORKDIR /app ARG TARGETPLATFORM COPY ./extra/ ./extra/ @@ -10,7 +9,7 @@ COPY ./extra/ ./extra/ # Compile healthcheck.go RUN apt update && \ apt --yes --no-install-recommends install curl && \ - curl -sL https://deb.nodesource.com/setup_18.x | bash && \ + curl -sL https://deb.nodesource.com/setup_24.x | bash && \ apt --yes --no-install-recommends install nodejs && \ node ./extra/build-healthcheck.js $TARGETPLATFORM && \ apt --yes remove nodejs diff --git a/docker/debian-base.dockerfile b/docker/debian-base.dockerfile index ca5fc43ec..59f883bf9 100644 --- a/docker/debian-base.dockerfile +++ b/docker/debian-base.dockerfile @@ -1,5 +1,5 @@ # Download Apprise deb package -FROM node:20-bookworm-slim AS download-apprise +FROM node:24-trixie-slim AS download-apprise WORKDIR /app COPY ./extra/download-apprise.mjs ./download-apprise.mjs RUN apt update && \ @@ -9,7 +9,7 @@ RUN apt update && \ # Base Image (Slim) # If the image changed, the second stage image should be changed too -FROM node:20-bookworm-slim AS base2-slim +FROM node:24-trixie-slim AS base3-slim ARG TARGETPLATFORM # Specify --no-install-recommends to skip unused dependencies, make the base much smaller! @@ -35,7 +35,6 @@ RUN apt update && \ apt --yes autoremove # apprise = for notifications (Install from the deb package, as the stable one is too old) (workaround for #4867) -# Switching to testing repo is no longer working, as the testing repo is not bookworm anymore. # python3-paho-mqtt (#4859) # TODO: no idea how to delete the deb file after installation as it becomes a layer already COPY --from=download-apprise /app/apprise.deb ./apprise.deb @@ -47,7 +46,7 @@ RUN apt update && \ # Install cloudflared RUN curl https://pkg.cloudflare.com/cloudflare-main.gpg --output /usr/share/keyrings/cloudflare-main.gpg && \ - echo 'deb [signed-by=/usr/share/keyrings/cloudflare-main.gpg] https://pkg.cloudflare.com/cloudflared bookworm main' | tee /etc/apt/sources.list.d/cloudflared.list && \ + echo 'deb [signed-by=/usr/share/keyrings/cloudflare-main.gpg] https://pkg.cloudflare.com/cloudflared any main' | tee /etc/apt/sources.list.d/cloudflared.list && \ apt update && \ apt install --yes --no-install-recommends cloudflared && \ cloudflared version && \ @@ -62,8 +61,7 @@ COPY ./docker/etc/sudoers /etc/sudoers # Full Base Image # MariaDB, Chromium and fonts # Make sure to reuse the slim image here. Uncomment the above line if you want to build it from scratch. -# FROM base2-slim AS base2 -FROM louislam/uptime-kuma:base2-slim AS base2 +FROM louislam/uptime-kuma:base3-slim AS base3 ENV UPTIME_KUMA_ENABLE_EMBEDDED_MARIADB=1 RUN apt update && \ apt --yes --no-install-recommends install chromium fonts-indic fonts-noto fonts-noto-cjk mariadb-server && \ diff --git a/docker/docker-compose-dev.yml b/docker/docker-compose-dev.yml index c66b24b58..e0deaba4d 100644 --- a/docker/docker-compose-dev.yml +++ b/docker/docker-compose-dev.yml @@ -3,7 +3,7 @@ version: '3.8' services: uptime-kuma: container_name: uptime-kuma-dev - image: louislam/uptime-kuma:nightly2 + image: louislam/uptime-kuma:nightly3 volumes: #- ./data:/app/data - ../server:/app/server diff --git a/docker/dockerfile b/docker/dockerfile index e2a301e7b..793cec1dd 100644 --- a/docker/dockerfile +++ b/docker/dockerfile @@ -1,16 +1,16 @@ -ARG BASE_IMAGE=louislam/uptime-kuma:base2 +ARG BASE_IMAGE=louislam/uptime-kuma:base3 ############################################ # Build in Golang -# Run npm run build-healthcheck-armv7 in the host first, otherwise it will be super slow where it is building the armv7 healthcheck + # Check file: builder-go.dockerfile ############################################ -FROM louislam/uptime-kuma:builder-go AS build_healthcheck +FROM louislam/uptime-kuma:builder-go3 AS build_healthcheck ############################################ # Build in Node.js ############################################ -FROM louislam/uptime-kuma:base2 AS build +FROM louislam/uptime-kuma:base3 AS build USER node WORKDIR /app @@ -59,7 +59,7 @@ USER node ############################################ # Build an image for testing pr ############################################ -FROM louislam/uptime-kuma:base2 AS pr-test2 +FROM louislam/uptime-kuma:base3 AS pr-test2 WORKDIR /app ENV PUPPETEER_SKIP_CHROMIUM_DOWNLOAD=1 @@ -92,7 +92,7 @@ CMD ["npm", "run", "start-pr-test"] ############################################ # Upload the artifact to Github ############################################ -FROM louislam/uptime-kuma:base2 AS upload-artifact +FROM louislam/uptime-kuma:base3 AS upload-artifact WORKDIR / RUN apt update && \ apt --yes install curl file diff --git a/extra/build-healthcheck.js b/extra/build-healthcheck.js index e4c8026ab..61c436d2b 100644 --- a/extra/build-healthcheck.js +++ b/extra/build-healthcheck.js @@ -1,5 +1,4 @@ const childProcess = require("child_process"); -const fs = require("fs"); const platform = process.argv[2]; if (!platform) { @@ -7,21 +6,6 @@ if (!platform) { process.exit(1); } -if (platform === "linux/arm/v7") { - console.log("Arch: armv7"); - if (fs.existsSync("./extra/healthcheck-armv7")) { - fs.renameSync("./extra/healthcheck-armv7", "./extra/healthcheck"); - console.log("Already built in the host, skip."); - process.exit(0); - } else { - console.log("prebuilt not found, it will be slow! You should execute `npm run build-healthcheck-armv7` before build."); - } -} else { - if (fs.existsSync("./extra/healthcheck-armv7")) { - fs.rmSync("./extra/healthcheck-armv7"); - } -} - const output = childProcess.execSync("go build -x -o ./extra/healthcheck ./extra/healthcheck.go").toString("utf8"); console.log(output); diff --git a/extra/healthcheck.js b/extra/healthcheck.js deleted file mode 100644 index c9391c410..000000000 --- a/extra/healthcheck.js +++ /dev/null @@ -1,55 +0,0 @@ -/* - * ⚠️ ⚠️ ⚠️ ⚠️ Due to the weird issue in Portainer that the healthcheck script is still pointing to this script for unknown reason. - * IT CANNOT BE DROPPED, even though it looks like it is not used. - * See more: https://github.com/louislam/uptime-kuma/issues/2774#issuecomment-1429092359 - * - * ⚠️ Deprecated: Changed to healthcheck.go, it will be deleted in the future. - * This script should be run after a period of time (180s), because the server may need some time to prepare. - */ -const FBSD = /^freebsd/.test(process.platform); - -process.env.NODE_TLS_REJECT_UNAUTHORIZED = "0"; - -let client; - -const sslKey = process.env.UPTIME_KUMA_SSL_KEY || process.env.SSL_KEY || undefined; -const sslCert = process.env.UPTIME_KUMA_SSL_CERT || process.env.SSL_CERT || undefined; - -if (sslKey && sslCert) { - client = require("https"); -} else { - client = require("http"); -} - -// If host is omitted, the server will accept connections on the unspecified IPv6 address (::) when IPv6 is available and the unspecified IPv4 address (0.0.0.0) otherwise. -// Dual-stack support for (::) -let hostname = process.env.UPTIME_KUMA_HOST; - -// Also read HOST if not *BSD, as HOST is a system environment variable in FreeBSD -if (!hostname && !FBSD) { - hostname = process.env.HOST; -} - -const port = parseInt(process.env.UPTIME_KUMA_PORT || process.env.PORT || 3001); - -let options = { - host: hostname || "127.0.0.1", - port: port, - timeout: 28 * 1000, -}; - -let request = client.request(options, (res) => { - console.log(`Health Check OK [Res Code: ${res.statusCode}]`); - if (res.statusCode === 302) { - process.exit(0); - } else { - process.exit(1); - } -}); - -request.on("error", function (err) { - console.error("Health Check ERROR"); - process.exit(1); -}); - -request.end(); diff --git a/extra/release/beta.mjs b/extra/release/beta.mjs index f629f2c3f..5a4a93c92 100644 --- a/extra/release/beta.mjs +++ b/extra/release/beta.mjs @@ -50,13 +50,13 @@ execSync("node ./extra/beta/update-version.js"); buildDist(); // Build slim image (rootless) -buildImage(repoNames, [ "beta-slim-rootless", ver(version, "slim-rootless") ], "rootless", "BASE_IMAGE=louislam/uptime-kuma:base2-slim"); +buildImage(repoNames, [ "beta-slim-rootless", ver(version, "slim-rootless") ], "rootless", "BASE_IMAGE=louislam/uptime-kuma:base3-slim"); // Build full image (rootless) buildImage(repoNames, [ "beta-rootless", ver(version, "rootless") ], "rootless"); // Build slim image -buildImage(repoNames, [ "beta-slim", ver(version, "slim") ], "release", "BASE_IMAGE=louislam/uptime-kuma:base2-slim"); +buildImage(repoNames, [ "beta-slim", ver(version, "slim") ], "release", "BASE_IMAGE=louislam/uptime-kuma:base3-slim"); // Build full image buildImage(repoNames, [ "beta", version ], "release"); diff --git a/extra/release/final.mjs b/extra/release/final.mjs index 73c5a4cab..5012445c3 100644 --- a/extra/release/final.mjs +++ b/extra/release/final.mjs @@ -40,16 +40,16 @@ execSync("node extra/update-version.js"); buildDist(); // Build slim image (rootless) -buildImage(repoNames, [ "2-slim-rootless", ver(version, "slim-rootless") ], "rootless", "BASE_IMAGE=louislam/uptime-kuma:base2-slim"); +buildImage(repoNames, [ "3-slim-rootless", ver(version, "slim-rootless") ], "rootless", "BASE_IMAGE=louislam/uptime-kuma:base3-slim"); // Build full image (rootless) -buildImage(repoNames, [ "2-rootless", ver(version, "rootless") ], "rootless"); +buildImage(repoNames, [ "3-rootless", ver(version, "rootless") ], "rootless"); // Build slim image -buildImage(repoNames, [ "next-slim", "2-slim", ver(version, "slim") ], "release", "BASE_IMAGE=louislam/uptime-kuma:base2-slim"); +buildImage(repoNames, [ "next-slim", "3-slim", ver(version, "slim") ], "release", "BASE_IMAGE=louislam/uptime-kuma:base3-slim"); // Build full image -buildImage(repoNames, [ "next", "2", version ], "release"); +buildImage(repoNames, [ "next", "3", version ], "release"); await pressAnyKey(); diff --git a/extra/release/lib.mjs b/extra/release/lib.mjs index e390ce820..8f563e8de 100644 --- a/extra/release/lib.mjs +++ b/extra/release/lib.mjs @@ -57,7 +57,7 @@ export function buildDist() { * @param {string} platform Build platform * @returns {void} */ -export function buildImage(repoNames, tags, target, buildArgs = "", dockerfile = "docker/dockerfile", platform = "linux/amd64,linux/arm64,linux/arm/v7") { +export function buildImage(repoNames, tags, target, buildArgs = "", dockerfile = "docker/dockerfile", platform = "linux/amd64,linux/arm64") { let args = [ "buildx", "build", diff --git a/extra/sort-contributors.js b/extra/sort-contributors.js deleted file mode 100644 index b60d191f6..000000000 --- a/extra/sort-contributors.js +++ /dev/null @@ -1,22 +0,0 @@ -const fs = require("fs"); - -// Read the file from private/sort-contributors.txt -const file = fs.readFileSync("private/sort-contributors.txt", "utf8"); - -// Convert to an array of lines -let lines = file.split("\n"); - -// Remove empty lines -lines = lines.filter((line) => line !== ""); - -// Remove duplicates -lines = [ ...new Set(lines) ]; - -// Remove @weblate and @UptimeKumaBot -lines = lines.filter((line) => line !== "@weblate" && line !== "@UptimeKumaBot" && line !== "@louislam"); - -// Sort the lines -lines = lines.sort(); - -// Output the lines, concat with " " -console.log(lines.join(" ")); diff --git a/extra/update-version.js b/extra/update-version.js index 9e4593446..c32685741 100644 --- a/extra/update-version.js +++ b/extra/update-version.js @@ -27,7 +27,18 @@ if (! exists) { // Also update package-lock.json const npm = /^win/.test(process.platform) ? "npm.cmd" : "npm"; - childProcess.spawnSync(npm, [ "install" ]); + const resultVersion = childProcess.spawnSync(npm, [ "--no-git-tag-version", "version", newVersion ], { shell: true }); + if (resultVersion.error) { + console.error(resultVersion.error); + console.error("error npm version!"); + process.exit(1); + } + const resultInstall = childProcess.spawnSync(npm, [ "install" ], { shell: true }); + if (resultInstall.error) { + console.error(resultInstall.error); + console.error("error update package-lock!"); + process.exit(1); + } commit(newVersion); } else { diff --git a/package-lock.json b/package-lock.json index 1aa00ead2..ae8d8f778 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "uptime-kuma", - "version": "2.0.1", + "version": "3.0.0-beta.0", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "uptime-kuma", - "version": "2.0.1", + "version": "3.0.0-beta.0", "license": "MIT", "dependencies": { "@grpc/grpc-js": "~1.8.22", @@ -87,7 +87,9 @@ "tcp-ping": "~0.1.1", "thirty-two": "~1.0.2", "tough-cookie": "~4.1.3", - "ws": "^8.13.0" + "tsx": "~4.20.6", + "ws": "^8.13.0", + "zod": "^4.1.12" }, "devDependencies": { "@actions/github": "~6.0.0", @@ -139,7 +141,6 @@ "v-pagination-3": "~0.1.7", "vite": "~5.4.15", "vite-plugin-compression": "^0.5.1", - "vite-plugin-vue-devtools": "^7.0.15", "vue": "~3.4.2", "vue-chartjs": "~5.2.0", "vue-confirm-dialog": "~1.0.2", @@ -156,7 +157,7 @@ "whatwg-url": "~12.0.1" }, "engines": { - "node": "18 || >= 20.4.0" + "node": ">= 24.0.0" } }, "node_modules/@actions/github": { @@ -186,16 +187,6 @@ "undici": "^5.25.4" } }, - "node_modules/@antfu/utils": { - "version": "0.7.10", - "resolved": "https://registry.npmjs.org/@antfu/utils/-/utils-0.7.10.tgz", - "integrity": "sha512-+562v9k4aI80m1+VuMHehNJWLOFjBnXn3tdOitzD0il5b7smkSBal4+a3oKiQTbrwMmN/TBUMDvbdoWDehgOww==", - "dev": true, - "license": "MIT", - "funding": { - "url": "https://github.com/sponsors/antfu" - } - }, "node_modules/@aws-crypto/sha256-browser": { "version": "5.2.0", "resolved": "https://registry.npmjs.org/@aws-crypto/sha256-browser/-/sha256-browser-5.2.0.tgz", @@ -1221,274 +1212,6 @@ "dev": true, "license": "MIT" }, - "node_modules/@babel/compat-data": { - "version": "7.28.4", - "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.28.4.tgz", - "integrity": "sha512-YsmSKC29MJwf0gF8Rjjrg5LQCmyh+j/nD8/eP7f+BeoQTKYqs9RoWbjGOdy0+1Ekr68RJZMUOPVQaQisnIo4Rw==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/core": { - "version": "7.28.4", - "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.28.4.tgz", - "integrity": "sha512-2BCOP7TN8M+gVDj7/ht3hsaO/B/n5oDbiAyyvnRlNOs+u1o+JWNYTQrmpuNp1/Wq2gcFrI01JAW+paEKDMx/CA==", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/code-frame": "^7.27.1", - "@babel/generator": "^7.28.3", - "@babel/helper-compilation-targets": "^7.27.2", - "@babel/helper-module-transforms": "^7.28.3", - "@babel/helpers": "^7.28.4", - "@babel/parser": "^7.28.4", - "@babel/template": "^7.27.2", - "@babel/traverse": "^7.28.4", - "@babel/types": "^7.28.4", - "@jridgewell/remapping": "^2.3.5", - "convert-source-map": "^2.0.0", - "debug": "^4.1.0", - "gensync": "^1.0.0-beta.2", - "json5": "^2.2.3", - "semver": "^6.3.1" - }, - "engines": { - "node": ">=6.9.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/babel" - } - }, - "node_modules/@babel/core/node_modules/semver": { - "version": "6.3.1", - "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", - "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", - "dev": true, - "license": "ISC", - "bin": { - "semver": "bin/semver.js" - } - }, - "node_modules/@babel/generator": { - "version": "7.28.3", - "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.28.3.tgz", - "integrity": "sha512-3lSpxGgvnmZznmBkCRnVREPUFJv2wrv9iAoFDvADJc0ypmdOxdUtcLeBgBJ6zE0PMeTKnxeQzyk0xTBq4Ep7zw==", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/parser": "^7.28.3", - "@babel/types": "^7.28.2", - "@jridgewell/gen-mapping": "^0.3.12", - "@jridgewell/trace-mapping": "^0.3.28", - "jsesc": "^3.0.2" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/helper-annotate-as-pure": { - "version": "7.27.3", - "resolved": "https://registry.npmjs.org/@babel/helper-annotate-as-pure/-/helper-annotate-as-pure-7.27.3.tgz", - "integrity": "sha512-fXSwMQqitTGeHLBC08Eq5yXz2m37E4pJX1qAU1+2cNedz/ifv/bVXft90VeSav5nFO61EcNgwr0aJxbyPaWBPg==", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/types": "^7.27.3" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/helper-compilation-targets": { - "version": "7.27.2", - "resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.27.2.tgz", - "integrity": "sha512-2+1thGUUWWjLTYTHZWK1n8Yga0ijBz1XAhUXcKy81rd5g6yh7hGqMp45v7cadSbEHc9G3OTv45SyneRN3ps4DQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/compat-data": "^7.27.2", - "@babel/helper-validator-option": "^7.27.1", - "browserslist": "^4.24.0", - "lru-cache": "^5.1.1", - "semver": "^6.3.1" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/helper-compilation-targets/node_modules/lru-cache": { - "version": "5.1.1", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-5.1.1.tgz", - "integrity": "sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w==", - "dev": true, - "license": "ISC", - "dependencies": { - "yallist": "^3.0.2" - } - }, - "node_modules/@babel/helper-compilation-targets/node_modules/semver": { - "version": "6.3.1", - "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", - "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", - "dev": true, - "license": "ISC", - "bin": { - "semver": "bin/semver.js" - } - }, - "node_modules/@babel/helper-compilation-targets/node_modules/yallist": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/yallist/-/yallist-3.1.1.tgz", - "integrity": "sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==", - "dev": true, - "license": "ISC" - }, - "node_modules/@babel/helper-create-class-features-plugin": { - "version": "7.28.3", - "resolved": "https://registry.npmjs.org/@babel/helper-create-class-features-plugin/-/helper-create-class-features-plugin-7.28.3.tgz", - "integrity": "sha512-V9f6ZFIYSLNEbuGA/92uOvYsGCJNsuA8ESZ4ldc09bWk/j8H8TKiPw8Mk1eG6olpnO0ALHJmYfZvF4MEE4gajg==", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/helper-annotate-as-pure": "^7.27.3", - "@babel/helper-member-expression-to-functions": "^7.27.1", - "@babel/helper-optimise-call-expression": "^7.27.1", - "@babel/helper-replace-supers": "^7.27.1", - "@babel/helper-skip-transparent-expression-wrappers": "^7.27.1", - "@babel/traverse": "^7.28.3", - "semver": "^6.3.1" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0" - } - }, - "node_modules/@babel/helper-create-class-features-plugin/node_modules/semver": { - "version": "6.3.1", - "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", - "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", - "dev": true, - "license": "ISC", - "bin": { - "semver": "bin/semver.js" - } - }, - "node_modules/@babel/helper-globals": { - "version": "7.28.0", - "resolved": "https://registry.npmjs.org/@babel/helper-globals/-/helper-globals-7.28.0.tgz", - "integrity": "sha512-+W6cISkXFa1jXsDEdYA8HeevQT/FULhxzR99pxphltZcVaugps53THCeiWA8SguxxpSp3gKPiuYfSWopkLQ4hw==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/helper-member-expression-to-functions": { - "version": "7.27.1", - "resolved": "https://registry.npmjs.org/@babel/helper-member-expression-to-functions/-/helper-member-expression-to-functions-7.27.1.tgz", - "integrity": "sha512-E5chM8eWjTp/aNoVpcbfM7mLxu9XGLWYise2eBKGQomAk/Mb4XoxyqXTZbuTohbsl8EKqdlMhnDI2CCLfcs9wA==", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/traverse": "^7.27.1", - "@babel/types": "^7.27.1" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/helper-module-imports": { - "version": "7.27.1", - "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.27.1.tgz", - "integrity": "sha512-0gSFWUPNXNopqtIPQvlD5WgXYI5GY2kP2cCvoT8kczjbfcfuIljTbcWrulD1CIPIX2gt1wghbDy08yE1p+/r3w==", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/traverse": "^7.27.1", - "@babel/types": "^7.27.1" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/helper-module-transforms": { - "version": "7.28.3", - "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.28.3.tgz", - "integrity": "sha512-gytXUbs8k2sXS9PnQptz5o0QnpLL51SwASIORY6XaBKF88nsOT0Zw9szLqlSGQDP/4TljBAD5y98p2U1fqkdsw==", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/helper-module-imports": "^7.27.1", - "@babel/helper-validator-identifier": "^7.27.1", - "@babel/traverse": "^7.28.3" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0" - } - }, - "node_modules/@babel/helper-optimise-call-expression": { - "version": "7.27.1", - "resolved": "https://registry.npmjs.org/@babel/helper-optimise-call-expression/-/helper-optimise-call-expression-7.27.1.tgz", - "integrity": "sha512-URMGH08NzYFhubNSGJrpUEphGKQwMQYBySzat5cAByY1/YgIRkULnIy3tAMeszlL/so2HbeilYloUmSpd7GdVw==", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/types": "^7.27.1" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/helper-plugin-utils": { - "version": "7.27.1", - "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.27.1.tgz", - "integrity": "sha512-1gn1Up5YXka3YYAHGKpbideQ5Yjf1tDa9qYcgysz+cNCXukyLl6DjPXhD3VRwSb8c0J9tA4b2+rHEZtc6R0tlw==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/helper-replace-supers": { - "version": "7.27.1", - "resolved": "https://registry.npmjs.org/@babel/helper-replace-supers/-/helper-replace-supers-7.27.1.tgz", - "integrity": "sha512-7EHz6qDZc8RYS5ElPoShMheWvEgERonFCs7IAonWLLUTXW59DP14bCZt89/GKyreYn8g3S83m21FelHKbeDCKA==", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/helper-member-expression-to-functions": "^7.27.1", - "@babel/helper-optimise-call-expression": "^7.27.1", - "@babel/traverse": "^7.27.1" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0" - } - }, - "node_modules/@babel/helper-skip-transparent-expression-wrappers": { - "version": "7.27.1", - "resolved": "https://registry.npmjs.org/@babel/helper-skip-transparent-expression-wrappers/-/helper-skip-transparent-expression-wrappers-7.27.1.tgz", - "integrity": "sha512-Tub4ZKEXqbPjXgWLl2+3JpQAYBJ8+ikpQ2Ocj/q/r0LwE3UhENh7EUabyHjz2kCEsrRY83ew2DQdHluuiDQFzg==", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/traverse": "^7.27.1", - "@babel/types": "^7.27.1" - }, - "engines": { - "node": ">=6.9.0" - } - }, "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", @@ -1509,30 +1232,6 @@ "node": ">=6.9.0" } }, - "node_modules/@babel/helper-validator-option": { - "version": "7.27.1", - "resolved": "https://registry.npmjs.org/@babel/helper-validator-option/-/helper-validator-option-7.27.1.tgz", - "integrity": "sha512-YvjJow9FxbhFFKDSuFnVCe2WxXk1zWc22fFePVNEaWJEu8IrZVlda6N0uHwzZrUM1il7NC9Mlp4MaJYbYd9JSg==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/helpers": { - "version": "7.28.4", - "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.28.4.tgz", - "integrity": "sha512-HFN59MmQXGHVyYadKLVumYsA9dBFun/ldYxipEjzA4196jpLZd8UjEEBLkbEkvfYreDqJhZxYAWFPtrfhNpj4w==", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/template": "^7.27.2", - "@babel/types": "^7.28.4" - }, - "engines": { - "node": ">=6.9.0" - } - }, "node_modules/@babel/parser": { "version": "7.28.4", "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.28.4.tgz", @@ -1549,121 +1248,6 @@ "node": ">=6.0.0" } }, - "node_modules/@babel/plugin-proposal-decorators": { - "version": "7.28.0", - "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-decorators/-/plugin-proposal-decorators-7.28.0.tgz", - "integrity": "sha512-zOiZqvANjWDUaUS9xMxbMcK/Zccztbe/6ikvUXaG9nsPH3w6qh5UaPGAnirI/WhIbZ8m3OHU0ReyPrknG+ZKeg==", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/helper-create-class-features-plugin": "^7.27.1", - "@babel/helper-plugin-utils": "^7.27.1", - "@babel/plugin-syntax-decorators": "^7.27.1" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-syntax-decorators": { - "version": "7.27.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-decorators/-/plugin-syntax-decorators-7.27.1.tgz", - "integrity": "sha512-YMq8Z87Lhl8EGkmb0MwYkt36QnxC+fzCgrl66ereamPlYToRpIk5nUjKUY3QKLWq8mwUB1BgbeXcTJhZOCDg5A==", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/helper-plugin-utils": "^7.27.1" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-syntax-import-attributes": { - "version": "7.27.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-import-attributes/-/plugin-syntax-import-attributes-7.27.1.tgz", - "integrity": "sha512-oFT0FrKHgF53f4vOsZGi2Hh3I35PfSmVs4IBFLFj4dnafP+hIWDLg3VyKmUHfLoLHlyxY4C7DGtmHuJgn+IGww==", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/helper-plugin-utils": "^7.27.1" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-syntax-import-meta": { - "version": "7.10.4", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-import-meta/-/plugin-syntax-import-meta-7.10.4.tgz", - "integrity": "sha512-Yqfm+XDx0+Prh3VSeEQCPU81yC+JWZ2pDPFSS4ZdpfZhp4MkFMaDC1UqseovEKwSUpnIL7+vK+Clp7bfh0iD7g==", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/helper-plugin-utils": "^7.10.4" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-syntax-jsx": { - "version": "7.27.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-jsx/-/plugin-syntax-jsx-7.27.1.tgz", - "integrity": "sha512-y8YTNIeKoyhGd9O0Jiyzyyqk8gdjnumGTQPsz0xOZOQ2RmkVJeZ1vmmfIvFEKqucBG6axJGBZDE/7iI5suUI/w==", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/helper-plugin-utils": "^7.27.1" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-syntax-typescript": { - "version": "7.27.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-typescript/-/plugin-syntax-typescript-7.27.1.tgz", - "integrity": "sha512-xfYCBMxveHrRMnAWl1ZlPXOZjzkN82THFvLhQhFXFt81Z5HnN+EtUkZhv/zcKpmT3fzmWZB0ywiBrbC3vogbwQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/helper-plugin-utils": "^7.27.1" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-transform-typescript": { - "version": "7.28.0", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-typescript/-/plugin-transform-typescript-7.28.0.tgz", - "integrity": "sha512-4AEiDEBPIZvLQaWlc9liCavE0xRM0dNca41WtBeM3jgFptfUOSG9z0uteLhq6+3rq+WB6jIvUwKDTpXEHPJ2Vg==", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/helper-annotate-as-pure": "^7.27.3", - "@babel/helper-create-class-features-plugin": "^7.27.1", - "@babel/helper-plugin-utils": "^7.27.1", - "@babel/helper-skip-transparent-expression-wrappers": "^7.27.1", - "@babel/plugin-syntax-typescript": "^7.27.1" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, "node_modules/@babel/runtime": { "version": "7.28.4", "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.28.4.tgz", @@ -1674,40 +1258,6 @@ "node": ">=6.9.0" } }, - "node_modules/@babel/template": { - "version": "7.27.2", - "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.27.2.tgz", - "integrity": "sha512-LPDZ85aEJyYSd18/DkjNh4/y1ntkE5KwUHWTiqgRxruuZL2F1yuHligVHLvcHY2vMHXttKFpJn6LwfI7cw7ODw==", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/code-frame": "^7.27.1", - "@babel/parser": "^7.27.2", - "@babel/types": "^7.27.1" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/traverse": { - "version": "7.28.4", - "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.28.4.tgz", - "integrity": "sha512-YEzuboP2qvQavAcjgQNVgsvHIDv6ZpwXvcvjmyySP2DIMuByS/6ioU5G9pYrWHM6T2YDfc7xga9iNzYOs12CFQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/code-frame": "^7.27.1", - "@babel/generator": "^7.28.3", - "@babel/helper-globals": "^7.28.0", - "@babel/parser": "^7.28.4", - "@babel/template": "^7.27.2", - "@babel/types": "^7.28.4", - "debug": "^4.3.1" - }, - "engines": { - "node": ">=6.9.0" - } - }, "node_modules/@babel/types": { "version": "7.28.4", "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.28.4.tgz", @@ -1729,45 +1279,6 @@ "dev": true, "license": "Apache-2.0" }, - "node_modules/@better-auth/core": { - "version": "1.4.0-beta.13", - "resolved": "https://registry.npmjs.org/@better-auth/core/-/core-1.4.0-beta.13.tgz", - "integrity": "sha512-EGySsNv6HQYnlRQDIa7otIMrwFoC0gGLxBum9lC6C3wAsF4l4pn/ECcdIriFpc9ewLb8mGkeMSpvjVBUBND6ew==", - "dependencies": { - "zod": "^4.1.5" - }, - "peerDependencies": { - "@better-auth/utils": "0.3.0", - "@better-fetch/fetch": "1.1.18", - "better-call": "1.0.24", - "jose": "^6.1.0", - "kysely": "^0.28.5", - "nanostores": "^1.0.1" - } - }, - "node_modules/@better-auth/telemetry": { - "version": "1.4.0-beta.13", - "resolved": "https://registry.npmjs.org/@better-auth/telemetry/-/telemetry-1.4.0-beta.13.tgz", - "integrity": "sha512-910f+APALhhD79TiujzXp85Pnd2M3TlcTgBfiYF+mk3ouIkBJkl2N6D2ElcgwfiNTg50cFuTkP3AFPYioz8Arw==", - "dependencies": { - "@better-auth/utils": "0.3.0", - "@better-fetch/fetch": "1.1.18" - }, - "peerDependencies": { - "@better-auth/core": "1.4.0-beta.13" - } - }, - "node_modules/@better-auth/utils": { - "version": "0.3.0", - "resolved": "https://registry.npmjs.org/@better-auth/utils/-/utils-0.3.0.tgz", - "integrity": "sha512-W+Adw6ZA6mgvnSnhOki270rwJ42t4XzSK6YWGF//BbVXL6SwCLWfyzBc1lN2m/4RM28KubdBKQ4X5VMoLRNPQw==", - "license": "MIT" - }, - "node_modules/@better-fetch/fetch": { - "version": "1.1.18", - "resolved": "https://registry.npmjs.org/@better-fetch/fetch/-/fetch-1.1.18.tgz", - "integrity": "sha512-rEFOE1MYIsBmoMJtQbl32PGHHXuG2hDxvEd7rUHE0vCBoFQVSDqaVs9hkZEtHCxRoY+CljXKFCOuJ8uxqw1LcA==" - }, "node_modules/@csstools/css-parser-algorithms": { "version": "2.7.1", "resolved": "https://registry.npmjs.org/@csstools/css-parser-algorithms/-/css-parser-algorithms-2.7.1.tgz", @@ -2162,6 +1673,22 @@ "node": ">=12" } }, + "node_modules/@esbuild/netbsd-arm64": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/netbsd-arm64/-/netbsd-arm64-0.25.12.tgz", + "integrity": "sha512-xXwcTq4GhRM7J9A8Gv5boanHhRa/Q9KLVmcyXHCTaM4wKfIpWkdXiMog/KsnxzJ0A1+nD+zoecuzqPmCRyBGjg==", + "cpu": [ + "arm64" + ], + "license": "MIT", + "optional": true, + "os": [ + "netbsd" + ], + "engines": { + "node": ">=18" + } + }, "node_modules/@esbuild/netbsd-x64": { "version": "0.21.5", "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.21.5.tgz", @@ -2179,6 +1706,22 @@ "node": ">=12" } }, + "node_modules/@esbuild/openbsd-arm64": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/openbsd-arm64/-/openbsd-arm64-0.25.12.tgz", + "integrity": "sha512-fF96T6KsBo/pkQI950FARU9apGNTSlZGsv1jZBAlcLL1MLjLNIWPBkj5NlSz8aAzYKg+eNqknrUJ24QBybeR5A==", + "cpu": [ + "arm64" + ], + "license": "MIT", + "optional": true, + "os": [ + "openbsd" + ], + "engines": { + "node": ">=18" + } + }, "node_modules/@esbuild/openbsd-x64": { "version": "0.21.5", "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.21.5.tgz", @@ -2196,6 +1739,22 @@ "node": ">=12" } }, + "node_modules/@esbuild/openharmony-arm64": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/openharmony-arm64/-/openharmony-arm64-0.25.12.tgz", + "integrity": "sha512-rm0YWsqUSRrjncSXGA7Zv78Nbnw4XL6/dzr20cyrQf7ZmRcsovpcRBdhD43Nuk3y7XIoW2OxMVvwuRvk9XdASg==", + "cpu": [ + "arm64" + ], + "license": "MIT", + "optional": true, + "os": [ + "openharmony" + ], + "engines": { + "node": ">=18" + } + }, "node_modules/@esbuild/sunos-x64": { "version": "0.21.5", "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.21.5.tgz", @@ -2678,17 +2237,6 @@ "@jridgewell/trace-mapping": "^0.3.24" } }, - "node_modules/@jridgewell/remapping": { - "version": "2.3.5", - "resolved": "https://registry.npmjs.org/@jridgewell/remapping/-/remapping-2.3.5.tgz", - "integrity": "sha512-LI9u/+laYG4Ds1TDKSJW2YPrIlcVYOwi2fUC6xB43lueCjgxV4lffOCZCtYFiH6TNOX+tQKXx97T4IKHbhyHEQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "@jridgewell/gen-mapping": "^0.3.5", - "@jridgewell/trace-mapping": "^0.3.24" - } - }, "node_modules/@jridgewell/resolve-uri": { "version": "3.1.2", "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.2.tgz", @@ -3313,13 +2861,6 @@ "node": ">=16" } }, - "node_modules/@polka/url": { - "version": "1.0.0-next.29", - "resolved": "https://registry.npmjs.org/@polka/url/-/url-1.0.0-next.29.tgz", - "integrity": "sha512-wwQAWhWSuHaag8c4q/KN/vCoeOJYshAIvMQwD4GpSb3OiZklFfvAgmj0VCBBImRpuF/aFgIRzllXlVX93Jevww==", - "dev": true, - "license": "MIT" - }, "node_modules/@popperjs/core": { "version": "2.10.2", "resolved": "https://registry.npmjs.org/@popperjs/core/-/core-2.10.2.tgz", @@ -3454,42 +2995,6 @@ "@redis/client": "^1.0.0" } }, - "node_modules/@rollup/pluginutils": { - "version": "5.3.0", - "resolved": "https://registry.npmjs.org/@rollup/pluginutils/-/pluginutils-5.3.0.tgz", - "integrity": "sha512-5EdhGZtnu3V88ces7s53hhfK5KSASnJZv8Lulpc04cWO3REESroJXg73DFsOmgbU2BhwV0E20bu2IDZb3VKW4Q==", - "dev": true, - "license": "MIT", - "dependencies": { - "@types/estree": "^1.0.0", - "estree-walker": "^2.0.2", - "picomatch": "^4.0.2" - }, - "engines": { - "node": ">=14.0.0" - }, - "peerDependencies": { - "rollup": "^1.20.0||^2.0.0||^3.0.0||^4.0.0" - }, - "peerDependenciesMeta": { - "rollup": { - "optional": true - } - } - }, - "node_modules/@rollup/pluginutils/node_modules/picomatch": { - "version": "4.0.3", - "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.3.tgz", - "integrity": "sha512-5gTmgEY/sqK6gFXLIsQNH19lWb4ebPDLA4SdLP7dsWkIXHWlG66oPuVvXSGFPppYZz8ZDZq0dYYrbHfBCVUb1Q==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/sponsors/jonschlinkert" - } - }, "node_modules/@rollup/rollup-android-arm-eabi": { "version": "4.52.5", "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.52.5.tgz", @@ -3849,13 +3354,6 @@ "url": "https://paulmillr.com/funding/" } }, - "node_modules/@sec-ant/readable-stream": { - "version": "0.4.1", - "resolved": "https://registry.npmjs.org/@sec-ant/readable-stream/-/readable-stream-0.4.1.tgz", - "integrity": "sha512-831qok9r2t8AlxLko40y2ebgSDhenenCatLVeW/uBtnHPyhHOvG0C7TvfgecV+wHzIm5KUICgzmVpWS+IMEAeg==", - "dev": true, - "license": "MIT" - }, "node_modules/@sideway/address": { "version": "4.1.5", "resolved": "https://registry.npmjs.org/@sideway/address/-/address-4.1.5.tgz", @@ -3917,19 +3415,6 @@ "url": "https://github.com/sindresorhus/is?sponsor=1" } }, - "node_modules/@sindresorhus/merge-streams": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/@sindresorhus/merge-streams/-/merge-streams-4.0.0.tgz", - "integrity": "sha512-tlqY9xq5ukxTUZBmoOp+m61cqwQD5pHJtFY3Mn8CA8ps6yghLH/Hw8UPdqg4OLmFW3IFlcXnQNmo/dh8HzXYIQ==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=18" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, "node_modules/@smithy/abort-controller": { "version": "4.2.3", "resolved": "https://registry.npmjs.org/@smithy/abort-controller/-/abort-controller-4.2.3.tgz", @@ -5182,127 +4667,6 @@ "vue": "^3.2.25" } }, - "node_modules/@vue/babel-helper-vue-transform-on": { - "version": "1.5.0", - "resolved": "https://registry.npmjs.org/@vue/babel-helper-vue-transform-on/-/babel-helper-vue-transform-on-1.5.0.tgz", - "integrity": "sha512-0dAYkerNhhHutHZ34JtTl2czVQHUNWv6xEbkdF5W+Yrv5pCWsqjeORdOgbtW2I9gWlt+wBmVn+ttqN9ZxR5tzA==", - "dev": true, - "license": "MIT" - }, - "node_modules/@vue/babel-plugin-jsx": { - "version": "1.5.0", - "resolved": "https://registry.npmjs.org/@vue/babel-plugin-jsx/-/babel-plugin-jsx-1.5.0.tgz", - "integrity": "sha512-mneBhw1oOqCd2247O0Yw/mRwC9jIGACAJUlawkmMBiNmL4dGA2eMzuNZVNqOUfYTa6vqmND4CtOPzmEEEqLKFw==", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/helper-module-imports": "^7.27.1", - "@babel/helper-plugin-utils": "^7.27.1", - "@babel/plugin-syntax-jsx": "^7.27.1", - "@babel/template": "^7.27.2", - "@babel/traverse": "^7.28.0", - "@babel/types": "^7.28.2", - "@vue/babel-helper-vue-transform-on": "1.5.0", - "@vue/babel-plugin-resolve-type": "1.5.0", - "@vue/shared": "^3.5.18" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - }, - "peerDependenciesMeta": { - "@babel/core": { - "optional": true - } - } - }, - "node_modules/@vue/babel-plugin-jsx/node_modules/@vue/shared": { - "version": "3.5.22", - "resolved": "https://registry.npmjs.org/@vue/shared/-/shared-3.5.22.tgz", - "integrity": "sha512-F4yc6palwq3TT0u+FYf0Ns4Tfl9GRFURDN2gWG7L1ecIaS/4fCIuFOjMTnCyjsu/OK6vaDKLCrGAa+KvvH+h4w==", - "dev": true, - "license": "MIT" - }, - "node_modules/@vue/babel-plugin-resolve-type": { - "version": "1.5.0", - "resolved": "https://registry.npmjs.org/@vue/babel-plugin-resolve-type/-/babel-plugin-resolve-type-1.5.0.tgz", - "integrity": "sha512-Wm/60o+53JwJODm4Knz47dxJnLDJ9FnKnGZJbUUf8nQRAtt6P+undLUAVU3Ha33LxOJe6IPoifRQ6F/0RrU31w==", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/code-frame": "^7.27.1", - "@babel/helper-module-imports": "^7.27.1", - "@babel/helper-plugin-utils": "^7.27.1", - "@babel/parser": "^7.28.0", - "@vue/compiler-sfc": "^3.5.18" - }, - "funding": { - "url": "https://github.com/sponsors/sxzz" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@vue/babel-plugin-resolve-type/node_modules/@vue/compiler-core": { - "version": "3.5.22", - "resolved": "https://registry.npmjs.org/@vue/compiler-core/-/compiler-core-3.5.22.tgz", - "integrity": "sha512-jQ0pFPmZwTEiRNSb+i9Ow/I/cHv2tXYqsnHKKyCQ08irI2kdF5qmYedmF8si8mA7zepUFmJ2hqzS8CQmNOWOkQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/parser": "^7.28.4", - "@vue/shared": "3.5.22", - "entities": "^4.5.0", - "estree-walker": "^2.0.2", - "source-map-js": "^1.2.1" - } - }, - "node_modules/@vue/babel-plugin-resolve-type/node_modules/@vue/compiler-dom": { - "version": "3.5.22", - "resolved": "https://registry.npmjs.org/@vue/compiler-dom/-/compiler-dom-3.5.22.tgz", - "integrity": "sha512-W8RknzUM1BLkypvdz10OVsGxnMAuSIZs9Wdx1vzA3mL5fNMN15rhrSCLiTm6blWeACwUwizzPVqGJgOGBEN/hA==", - "dev": true, - "license": "MIT", - "dependencies": { - "@vue/compiler-core": "3.5.22", - "@vue/shared": "3.5.22" - } - }, - "node_modules/@vue/babel-plugin-resolve-type/node_modules/@vue/compiler-sfc": { - "version": "3.5.22", - "resolved": "https://registry.npmjs.org/@vue/compiler-sfc/-/compiler-sfc-3.5.22.tgz", - "integrity": "sha512-tbTR1zKGce4Lj+JLzFXDq36K4vcSZbJ1RBu8FxcDv1IGRz//Dh2EBqksyGVypz3kXpshIfWKGOCcqpSbyGWRJQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/parser": "^7.28.4", - "@vue/compiler-core": "3.5.22", - "@vue/compiler-dom": "3.5.22", - "@vue/compiler-ssr": "3.5.22", - "@vue/shared": "3.5.22", - "estree-walker": "^2.0.2", - "magic-string": "^0.30.19", - "postcss": "^8.5.6", - "source-map-js": "^1.2.1" - } - }, - "node_modules/@vue/babel-plugin-resolve-type/node_modules/@vue/compiler-ssr": { - "version": "3.5.22", - "resolved": "https://registry.npmjs.org/@vue/compiler-ssr/-/compiler-ssr-3.5.22.tgz", - "integrity": "sha512-GdgyLvg4R+7T8Nk2Mlighx7XGxq/fJf9jaVofc3IL0EPesTE86cP/8DD1lT3h1JeZr2ySBvyqKQJgbS54IX1Ww==", - "dev": true, - "license": "MIT", - "dependencies": { - "@vue/compiler-dom": "3.5.22", - "@vue/shared": "3.5.22" - } - }, - "node_modules/@vue/babel-plugin-resolve-type/node_modules/@vue/shared": { - "version": "3.5.22", - "resolved": "https://registry.npmjs.org/@vue/shared/-/shared-3.5.22.tgz", - "integrity": "sha512-F4yc6palwq3TT0u+FYf0Ns4Tfl9GRFURDN2gWG7L1ecIaS/4fCIuFOjMTnCyjsu/OK6vaDKLCrGAa+KvvH+h4w==", - "dev": true, - "license": "MIT" - }, "node_modules/@vue/compiler-core": { "version": "3.4.38", "resolved": "https://registry.npmjs.org/@vue/compiler-core/-/compiler-core-3.4.38.tgz", @@ -5364,69 +4728,6 @@ "dev": true, "license": "MIT" }, - "node_modules/@vue/devtools-core": { - "version": "7.7.7", - "resolved": "https://registry.npmjs.org/@vue/devtools-core/-/devtools-core-7.7.7.tgz", - "integrity": "sha512-9z9TLbfC+AjAi1PQyWX+OErjIaJmdFlbDHcD+cAMYKY6Bh5VlsAtCeGyRMrXwIlMEQPukvnWt3gZBLwTAIMKzQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "@vue/devtools-kit": "^7.7.7", - "@vue/devtools-shared": "^7.7.7", - "mitt": "^3.0.1", - "nanoid": "^5.1.0", - "pathe": "^2.0.3", - "vite-hot-client": "^2.0.4" - }, - "peerDependencies": { - "vue": "^3.0.0" - } - }, - "node_modules/@vue/devtools-core/node_modules/nanoid": { - "version": "5.1.6", - "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-5.1.6.tgz", - "integrity": "sha512-c7+7RQ+dMB5dPwwCp4ee1/iV/q2P6aK1mTZcfr1BTuVlyW9hJYiMPybJCcnBlQtuSmTIWNeazm/zqNoZSSElBg==", - "dev": true, - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/ai" - } - ], - "license": "MIT", - "bin": { - "nanoid": "bin/nanoid.js" - }, - "engines": { - "node": "^18 || >=20" - } - }, - "node_modules/@vue/devtools-kit": { - "version": "7.7.7", - "resolved": "https://registry.npmjs.org/@vue/devtools-kit/-/devtools-kit-7.7.7.tgz", - "integrity": "sha512-wgoZtxcTta65cnZ1Q6MbAfePVFxfM+gq0saaeytoph7nEa7yMXoi6sCPy4ufO111B9msnw0VOWjPEFCXuAKRHA==", - "dev": true, - "license": "MIT", - "dependencies": { - "@vue/devtools-shared": "^7.7.7", - "birpc": "^2.3.0", - "hookable": "^5.5.3", - "mitt": "^3.0.1", - "perfect-debounce": "^1.0.0", - "speakingurl": "^14.0.1", - "superjson": "^2.2.2" - } - }, - "node_modules/@vue/devtools-shared": { - "version": "7.7.7", - "resolved": "https://registry.npmjs.org/@vue/devtools-shared/-/devtools-shared-7.7.7.tgz", - "integrity": "sha512-+udSj47aRl5aKb0memBvcUG9koarqnxNM5yjuREvqwK6T3ap4mn3Zqqc17QrBFTqSMjr3HK1cvStEZpMDpfdyw==", - "dev": true, - "license": "MIT", - "dependencies": { - "rfdc": "^1.4.1" - } - }, "node_modules/@vue/reactivity": { "version": "3.4.38", "resolved": "https://registry.npmjs.org/@vue/reactivity/-/reactivity-3.4.38.tgz", @@ -6352,16 +5653,6 @@ "node": "^4.5.0 || >= 5.9" } }, - "node_modules/baseline-browser-mapping": { - "version": "2.8.18", - "resolved": "https://registry.npmjs.org/baseline-browser-mapping/-/baseline-browser-mapping-2.8.18.tgz", - "integrity": "sha512-UYmTpOBwgPScZpS4A+YbapwWuBwasxvO/2IOHArSsAhL/+ZdmATBXTex3t+l2hXwLVYK382ibr/nKoY9GKe86w==", - "dev": true, - "license": "Apache-2.0", - "bin": { - "baseline-browser-mapping": "dist/cli.js" - } - }, "node_modules/basic-auth": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/basic-auth/-/basic-auth-2.0.1.tgz", @@ -6521,16 +5812,6 @@ "integrity": "sha512-VOMgTMwjAaUG580SXn3LacVgjurrbMme7ZZNYGSSV7mmtY6QQRh0Eg3pwIcntQ77DErK1L0NxkbetjcoXzVwKw==", "license": "MIT" }, - "node_modules/birpc": { - "version": "2.6.1", - "resolved": "https://registry.npmjs.org/birpc/-/birpc-2.6.1.tgz", - "integrity": "sha512-LPnFhlDpdSH6FJhJyn4M0kFO7vtQ5iPw24FnG0y21q09xC7e8+1LeR31S1MAIrDAHp4m7aas4bEkTDTvMAtebQ==", - "dev": true, - "license": "MIT", - "funding": { - "url": "https://github.com/sponsors/antfu" - } - }, "node_modules/bl": { "version": "4.1.0", "resolved": "https://registry.npmjs.org/bl/-/bl-4.1.0.tgz", @@ -6657,40 +5938,6 @@ "node": ">=8" } }, - "node_modules/browserslist": { - "version": "4.26.3", - "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.26.3.tgz", - "integrity": "sha512-lAUU+02RFBuCKQPj/P6NgjlbCnLBMp4UtgTx7vNHd3XSIJF87s9a5rA3aH2yw3GS9DqZAUbOtZdCCiZeVRqt0w==", - "dev": true, - "funding": [ - { - "type": "opencollective", - "url": "https://opencollective.com/browserslist" - }, - { - "type": "tidelift", - "url": "https://tidelift.com/funding/github/npm/browserslist" - }, - { - "type": "github", - "url": "https://github.com/sponsors/ai" - } - ], - "license": "MIT", - "dependencies": { - "baseline-browser-mapping": "^2.8.9", - "caniuse-lite": "^1.0.30001746", - "electron-to-chromium": "^1.5.227", - "node-releases": "^2.0.21", - "update-browserslist-db": "^1.1.3" - }, - "bin": { - "browserslist": "cli.js" - }, - "engines": { - "node": "^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7" - } - }, "node_modules/bson": { "version": "4.7.2", "resolved": "https://registry.npmjs.org/bson/-/bson-4.7.2.tgz", @@ -7001,27 +6248,6 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/caniuse-lite": { - "version": "1.0.30001751", - "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001751.tgz", - "integrity": "sha512-A0QJhug0Ly64Ii3eIqHu5X51ebln3k4yTUkY1j8drqpWHVreg/VLijN48cZ1bYPiqOQuqpkIKnzr/Ul8V+p6Cw==", - "dev": true, - "funding": [ - { - "type": "opencollective", - "url": "https://opencollective.com/browserslist" - }, - { - "type": "tidelift", - "url": "https://tidelift.com/funding/github/npm/caniuse-lite" - }, - { - "type": "github", - "url": "https://github.com/sponsors/ai" - } - ], - "license": "CC-BY-4.0" - }, "node_modules/chalk": { "version": "4.1.2", "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", @@ -7522,13 +6748,6 @@ "node": ">= 0.6" } }, - "node_modules/convert-source-map": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-2.0.0.tgz", - "integrity": "sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg==", - "dev": true, - "license": "MIT" - }, "node_modules/cookie": { "version": "0.7.1", "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.7.1.tgz", @@ -7544,22 +6763,6 @@ "integrity": "sha512-QADzlaHc8icV8I7vbaJXJwod9HWYp8uCqf1xa4OfNu1T7JVxQIrUgOWtHdNDtPiywmFbiS12VjotIXLrKM3orQ==", "license": "MIT" }, - "node_modules/copy-anything": { - "version": "3.0.5", - "resolved": "https://registry.npmjs.org/copy-anything/-/copy-anything-3.0.5.tgz", - "integrity": "sha512-yCEafptTtb4bk7GLEQoM8KVJpxAfdBJYaXyzQEgQQQgYrZiDp8SJmGKlYza6CYjEDNstAdNdKA3UuoULlEbS6w==", - "dev": true, - "license": "MIT", - "dependencies": { - "is-what": "^4.1.8" - }, - "engines": { - "node": ">=12.13" - }, - "funding": { - "url": "https://github.com/sponsors/mesqueeb" - } - }, "node_modules/core-js": { "version": "3.26.1", "resolved": "https://registry.npmjs.org/core-js/-/core-js-3.26.1.tgz", @@ -8517,13 +7720,6 @@ "integrity": "sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow==", "license": "MIT" }, - "node_modules/electron-to-chromium": { - "version": "1.5.237", - "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.237.tgz", - "integrity": "sha512-icUt1NvfhGLar5lSWH3tHNzablaA5js3HVHacQimfP8ViEBOQv+L7DKEuHdbTZ0SKCO1ogTJTIL1Gwk9S6Qvcg==", - "dev": true, - "license": "ISC" - }, "node_modules/emoji-regex": { "version": "8.0.0", "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", @@ -8737,16 +7933,6 @@ "is-arrayish": "^0.2.1" } }, - "node_modules/error-stack-parser-es": { - "version": "0.1.5", - "resolved": "https://registry.npmjs.org/error-stack-parser-es/-/error-stack-parser-es-0.1.5.tgz", - "integrity": "sha512-xHku1X40RO+fO8yJ8Wh2f2rZWVjqyhb1zgq1yZ8aZRQkv6OOKhKWRUaht3eSCUbAOBaKIgM+ykwFLE+QUxgGeg==", - "dev": true, - "license": "MIT", - "funding": { - "url": "https://github.com/sponsors/antfu" - } - }, "node_modules/es-abstract": { "version": "1.24.0", "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.24.0.tgz", @@ -9252,89 +8438,6 @@ "bare-events": "^2.7.0" } }, - "node_modules/execa": { - "version": "9.6.0", - "resolved": "https://registry.npmjs.org/execa/-/execa-9.6.0.tgz", - "integrity": "sha512-jpWzZ1ZhwUmeWRhS7Qv3mhpOhLfwI+uAX4e5fOcXqwMR7EcJ0pj2kV1CVzHVMX/LphnKWD3LObjZCoJ71lKpHw==", - "dev": true, - "license": "MIT", - "dependencies": { - "@sindresorhus/merge-streams": "^4.0.0", - "cross-spawn": "^7.0.6", - "figures": "^6.1.0", - "get-stream": "^9.0.0", - "human-signals": "^8.0.1", - "is-plain-obj": "^4.1.0", - "is-stream": "^4.0.1", - "npm-run-path": "^6.0.0", - "pretty-ms": "^9.2.0", - "signal-exit": "^4.1.0", - "strip-final-newline": "^4.0.0", - "yoctocolors": "^2.1.1" - }, - "engines": { - "node": "^18.19.0 || >=20.5.0" - }, - "funding": { - "url": "https://github.com/sindresorhus/execa?sponsor=1" - } - }, - "node_modules/execa/node_modules/get-stream": { - "version": "9.0.1", - "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-9.0.1.tgz", - "integrity": "sha512-kVCxPF3vQM/N0B1PmoqVUqgHP+EeVjmZSQn+1oCRPxd2P21P2F19lIgbR3HBosbB1PUhOAoctJnfEn2GbN2eZA==", - "dev": true, - "license": "MIT", - "dependencies": { - "@sec-ant/readable-stream": "^0.4.1", - "is-stream": "^4.0.1" - }, - "engines": { - "node": ">=18" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/execa/node_modules/is-plain-obj": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/is-plain-obj/-/is-plain-obj-4.1.0.tgz", - "integrity": "sha512-+Pgi+vMuUNkJyExiMBt5IlFoMyKnr5zhJ4Uspz58WOhBF5QoIZkFyNHIbBAtHwzVAgk5RtndVNsDRN61/mmDqg==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/execa/node_modules/is-stream": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-4.0.1.tgz", - "integrity": "sha512-Dnz92NInDqYckGEUJv689RbRiTSEHCQ7wOVeALbkOz999YpqT46yMRIGtSNl2iCL1waAZSx40+h59NV/EwzV/A==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=18" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/execa/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/express": { "version": "4.21.2", "resolved": "https://registry.npmjs.org/express/-/express-4.21.2.tgz", @@ -9593,22 +8696,6 @@ "node": ">=0.4.0" } }, - "node_modules/figures": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/figures/-/figures-6.1.0.tgz", - "integrity": "sha512-d+l3qxjSesT4V7v2fh+QnmFnUWv9lSpjarhShNTgBOfA0ttejbQUAlHLitbjkoRiDulW0OPoQPYIGhIC8ohejg==", - "dev": true, - "license": "MIT", - "dependencies": { - "is-unicode-supported": "^2.0.0" - }, - "engines": { - "node": ">=18" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, "node_modules/file-entry-cache": { "version": "6.0.1", "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-6.0.1.tgz", @@ -10206,16 +9293,6 @@ "node": ">= 4" } }, - "node_modules/gensync": { - "version": "1.0.0-beta.2", - "resolved": "https://registry.npmjs.org/gensync/-/gensync-1.0.0-beta.2.tgz", - "integrity": "sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=6.9.0" - } - }, "node_modules/get-caller-file": { "version": "2.0.5", "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz", @@ -10321,6 +9398,18 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/get-tsconfig": { + "version": "4.13.0", + "resolved": "https://registry.npmjs.org/get-tsconfig/-/get-tsconfig-4.13.0.tgz", + "integrity": "sha512-1VKTZJCwBrvbd+Wn3AOgQP/2Av+TfTCOlE4AcRJE72W1ksZXbAx8PPBR9RzgTeSPzlPMHrbANMH3LbltH73wxQ==", + "license": "MIT", + "dependencies": { + "resolve-pkg-maps": "^1.0.0" + }, + "funding": { + "url": "https://github.com/privatenumber/get-tsconfig?sponsor=1" + } + }, "node_modules/getopts": { "version": "2.3.0", "resolved": "https://registry.npmjs.org/getopts/-/getopts-2.3.0.tgz", @@ -10655,13 +9744,6 @@ "readable-stream": "^3.6.0" } }, - "node_modules/hookable": { - "version": "5.5.3", - "resolved": "https://registry.npmjs.org/hookable/-/hookable-5.5.3.tgz", - "integrity": "sha512-Yc+BQe8SvoXH1643Qez1zqLRmbA5rCL+sSmk6TVos0LWVfNIB7PGncdlId77WzLGSIB5KaWgTaNTs2lNVEI6VQ==", - "dev": true, - "license": "MIT" - }, "node_modules/hosted-git-info": { "version": "4.1.0", "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-4.1.0.tgz", @@ -10814,16 +9896,6 @@ "node": ">= 14" } }, - "node_modules/human-signals": { - "version": "8.0.1", - "resolved": "https://registry.npmjs.org/human-signals/-/human-signals-8.0.1.tgz", - "integrity": "sha512-eKCa6bwnJhvxj14kZk5NCPc6Hb6BdsU9DZcOnmQKSnO1VKrfV0zCvtttPZUsBvjmNDn8rpcJfpwSYnHBjc95MQ==", - "dev": true, - "license": "Apache-2.0", - "engines": { - "node": ">=18.18.0" - } - }, "node_modules/humanize-ms": { "version": "1.2.1", "resolved": "https://registry.npmjs.org/humanize-ms/-/humanize-ms-1.2.1.tgz", @@ -11493,19 +10565,6 @@ "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/is-unicode-supported": { - "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": ">=18" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, "node_modules/is-url": { "version": "1.2.4", "resolved": "https://registry.npmjs.org/is-url/-/is-url-1.2.4.tgz", @@ -11558,19 +10617,6 @@ "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/is-what": { - "version": "4.1.16", - "resolved": "https://registry.npmjs.org/is-what/-/is-what-4.1.16.tgz", - "integrity": "sha512-ZhMwEosbFJkA0YhFnNDgTM4ZxDRsS6HqTo7qsZM08fehyRYIYa0yHu5R6mgo1n/8MgaPBXiPimPD77baVFYg+A==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=12.13" - }, - "funding": { - "url": "https://github.com/sponsors/mesqueeb" - } - }, "node_modules/is-wsl": { "version": "2.2.0", "resolved": "https://registry.npmjs.org/is-wsl/-/is-wsl-2.2.0.tgz", @@ -11729,19 +10775,6 @@ "dev": true, "license": "MIT" }, - "node_modules/json5": { - "version": "2.2.3", - "resolved": "https://registry.npmjs.org/json5/-/json5-2.2.3.tgz", - "integrity": "sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg==", - "dev": true, - "license": "MIT", - "bin": { - "json5": "lib/cli.js" - }, - "engines": { - "node": ">=6" - } - }, "node_modules/jsonata": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/jsonata/-/jsonata-2.1.0.tgz", @@ -11953,22 +10986,6 @@ "dev": true, "license": "MIT" }, - "node_modules/kolorist": { - "version": "1.8.0", - "resolved": "https://registry.npmjs.org/kolorist/-/kolorist-1.8.0.tgz", - "integrity": "sha512-Y+60/zizpJ3HRH8DCss+q95yr6145JXZo46OTpFvDZWLfRCE4qChOyk1b26nMaNpfHHgxagk9dXT5OP0Tfe+dQ==", - "dev": true, - "license": "MIT" - }, - "node_modules/kysely": { - "version": "0.28.8", - "resolved": "https://registry.npmjs.org/kysely/-/kysely-0.28.8.tgz", - "integrity": "sha512-QUOgl5ZrS9IRuhq5FvOKFSsD/3+IA6MLE81/bOOTRA/YQpKDza2sFdN5g6JCB9BOpqMJDGefLCQ9F12hRS13TA==", - "license": "MIT", - "engines": { - "node": ">=20.0.0" - } - }, "node_modules/lazystream": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/lazystream/-/lazystream-1.0.1.tgz", @@ -12844,16 +11861,6 @@ } } }, - "node_modules/mrmime": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/mrmime/-/mrmime-2.0.1.tgz", - "integrity": "sha512-Y3wQdFg2Va6etvQ5I82yUhGdsKrcYox6p7FfL1LbK2J4V01F9TGlepTIhnK24t7koZibmg82KGglhA1XK5IsLQ==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=10" - } - }, "node_modules/ms": { "version": "2.1.3", "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", @@ -13144,13 +12151,6 @@ "integrity": "sha512-i3Sf6khnenl0aXumo0whAlfPWTaBqHxEnVBBxpu3dZ7q69NkPPv71rvPjlDZ5wkeKCTNNUTECljerS5kcYQxRw==", "license": "MIT" }, - "node_modules/node-releases": { - "version": "2.0.25", - "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.25.tgz", - "integrity": "sha512-4auku8B/vw5psvTiiN9j1dAOsXvMoGqJuKJcR+dTdqiXEK20mMTk1UEo3HS16LeGQsVG6+qKTPM9u/qQ2LqATA==", - "dev": true, - "license": "MIT" - }, "node_modules/node-ssh": { "version": "13.1.0", "resolved": "https://registry.npmjs.org/node-ssh/-/node-ssh-13.1.0.tgz", @@ -13269,36 +12269,6 @@ "node": "> v0.6.0" } }, - "node_modules/npm-run-path": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-6.0.0.tgz", - "integrity": "sha512-9qny7Z9DsQU8Ou39ERsPU4OZQlSTP47ShQzuKZ6PRXpYLtIFgl/DEBYEXKlvcEa+9tHVcK8CF81Y2V72qaZhWA==", - "dev": true, - "license": "MIT", - "dependencies": { - "path-key": "^4.0.0", - "unicorn-magic": "^0.3.0" - }, - "engines": { - "node": ">=18" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/npm-run-path/node_modules/path-key": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/path-key/-/path-key-4.0.0.tgz", - "integrity": "sha512-haREypq7xkM7ErfgIyA0z+Bj4AGKlMSdlQE2jvJo6huWD1EdkKYV+G/T4nq0YEF2vgTT8kqMFKo1uHn950r4SQ==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, "node_modules/npmlog": { "version": "5.0.1", "resolved": "https://registry.npmjs.org/npmlog/-/npmlog-5.0.1.tgz", @@ -13609,19 +12579,6 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/parse-ms": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/parse-ms/-/parse-ms-4.0.0.tgz", - "integrity": "sha512-TXfryirbmq34y8QBwgqCVLi+8oA3oWx2eAnSn62ITyEhEYaWRlVZ2DvMM9eZbMs/RfxPu/PK/aBLyGj4IrqMHw==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=18" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, "node_modules/parse5": { "version": "7.3.0", "resolved": "https://registry.npmjs.org/parse5/-/parse5-7.3.0.tgz", @@ -13772,20 +12729,6 @@ "node": ">=8" } }, - "node_modules/pathe": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/pathe/-/pathe-2.0.3.tgz", - "integrity": "sha512-WUjGcAqP1gQacoQe+OBJsFA7Ld4DyXuUIjZ5cc75cLHvJ7dtNsTugphxIADwspS+AraAUePCKrSVtPLFj/F88w==", - "dev": true, - "license": "MIT" - }, - "node_modules/perfect-debounce": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/perfect-debounce/-/perfect-debounce-1.0.0.tgz", - "integrity": "sha512-xCy9V055GLEqoFaHoC1SoLIaLmWctgCUaBaWxDZ7/Zx4CTyX7cJQLJOok/orfjZAh9kEYpjJa4d0KcJmCbctZA==", - "dev": true, - "license": "MIT" - }, "node_modules/pg": { "version": "8.11.6", "resolved": "https://registry.npmjs.org/pg/-/pg-8.11.6.tgz", @@ -14166,22 +13109,6 @@ "node": ">= 0.8.0" } }, - "node_modules/pretty-ms": { - "version": "9.3.0", - "resolved": "https://registry.npmjs.org/pretty-ms/-/pretty-ms-9.3.0.tgz", - "integrity": "sha512-gjVS5hOP+M3wMm5nmNOucbIrqudzs9v/57bWRHQWLYklXqoXKrVfYW2W9+glfGsqtPgpiz5WwyEEB+ksXIx3gQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "parse-ms": "^4.0.0" - }, - "engines": { - "node": ">=18" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, "node_modules/prismjs": { "version": "1.30.0", "resolved": "https://registry.npmjs.org/prismjs/-/prismjs-1.30.0.tgz", @@ -15143,6 +14070,15 @@ "node": ">=4" } }, + "node_modules/resolve-pkg-maps": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/resolve-pkg-maps/-/resolve-pkg-maps-1.0.0.tgz", + "integrity": "sha512-seS2Tj26TBVOC2NIc2rOe2y2ZO7efxITtLZcGSOnHHNOQ7CkiUBfw0Iw2ck6xkIhPwLhKNLS8BO+hEpngQlqzw==", + "license": "MIT", + "funding": { + "url": "https://github.com/privatenumber/resolve-pkg-maps?sponsor=1" + } + }, "node_modules/responselike": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/responselike/-/responselike-2.0.1.tgz", @@ -15785,21 +14721,6 @@ "integrity": "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==", "license": "ISC" }, - "node_modules/sirv": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/sirv/-/sirv-3.0.2.tgz", - "integrity": "sha512-2wcC/oGxHis/BoHkkPwldgiPSYcpZK3JU28WoMVv55yHJgcZ8rlXvuG9iZggz+sU1d4bRgIGASwyWqjxu3FM0g==", - "dev": true, - "license": "MIT", - "dependencies": { - "@polka/url": "^1.0.0-next.24", - "mrmime": "^2.0.0", - "totalist": "^3.0.0" - }, - "engines": { - "node": ">=18" - } - }, "node_modules/slash": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/slash/-/slash-3.0.0.tgz", @@ -16111,16 +15032,6 @@ "dev": true, "license": "CC0-1.0" }, - "node_modules/speakingurl": { - "version": "14.0.1", - "resolved": "https://registry.npmjs.org/speakingurl/-/speakingurl-14.0.1.tgz", - "integrity": "sha512-1POYv7uv2gXoyGFpBCmpDVSNV74IfsWlDW216UPjbWufNf+bSU6GdbDsxdcxtfwb4xlI3yxzOTKClUosxARYrQ==", - "dev": true, - "license": "BSD-3-Clause", - "engines": { - "node": ">=0.10.0" - } - }, "node_modules/split-ca": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/split-ca/-/split-ca-1.0.1.tgz", @@ -16437,19 +15348,6 @@ "node": ">=8" } }, - "node_modules/strip-final-newline": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/strip-final-newline/-/strip-final-newline-4.0.0.tgz", - "integrity": "sha512-aulFJcD6YK8V1G7iRB5tigAP4TsHBZZrOV8pjV++zdUwmeV8uzbY7yn6h9MswN62adStNZFuCIx4haBnRuMDaw==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=18" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, "node_modules/strip-indent": { "version": "4.1.1", "resolved": "https://registry.npmjs.org/strip-indent/-/strip-indent-4.1.1.tgz", @@ -16608,19 +15506,6 @@ "node": ">=8" } }, - "node_modules/superjson": { - "version": "2.2.2", - "resolved": "https://registry.npmjs.org/superjson/-/superjson-2.2.2.tgz", - "integrity": "sha512-5JRxVqC8I8NuOUjzBbvVJAKNM8qoVuH0O77h4WInc/qC2q5IreqKxYwgkga3PfA22OayK2ikceb/B26dztPl+Q==", - "dev": true, - "license": "MIT", - "dependencies": { - "copy-anything": "^3.0.2" - }, - "engines": { - "node": ">=16" - } - }, "node_modules/supports-color": { "version": "8.1.1", "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-8.1.1.tgz", @@ -17052,16 +15937,6 @@ "node": ">=0.6" } }, - "node_modules/totalist": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/totalist/-/totalist-3.0.1.tgz", - "integrity": "sha512-sf4i37nQ2LBx4m3wB74y+ubopq6W/dIzXg0FDGjsYnZHVa1Da8FH853wlL2gtUhg+xJXjfk3kUZS3BRoQeoQBQ==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=6" - } - }, "node_modules/tough-cookie": { "version": "4.1.4", "resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-4.1.4.tgz", @@ -17142,23 +16017,447 @@ "integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==", "license": "0BSD" }, - "node_modules/tsyringe": { - "version": "4.10.0", - "resolved": "https://registry.npmjs.org/tsyringe/-/tsyringe-4.10.0.tgz", - "integrity": "sha512-axr3IdNuVIxnaK5XGEUFTu3YmAQ6lllgrvqfEoR16g/HGnYY/6We4oWENtAnzK6/LpJ2ur9PAb80RBt7/U4ugw==", + "node_modules/tsx": { + "version": "4.20.6", + "resolved": "https://registry.npmjs.org/tsx/-/tsx-4.20.6.tgz", + "integrity": "sha512-ytQKuwgmrrkDTFP4LjR0ToE2nqgy886GpvRSpU0JAnrdBYppuY5rLkRUYPU1yCryb24SsKBTL/hlDQAEFVwtZg==", "license": "MIT", "dependencies": { - "tslib": "^1.9.3" + "esbuild": "~0.25.0", + "get-tsconfig": "^4.7.5" + }, + "bin": { + "tsx": "dist/cli.mjs" }, "engines": { - "node": ">= 6.0.0" + "node": ">=18.0.0" + }, + "optionalDependencies": { + "fsevents": "~2.3.3" } }, - "node_modules/tsyringe/node_modules/tslib": { - "version": "1.14.1", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz", - "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==", - "license": "0BSD" + "node_modules/tsx/node_modules/@esbuild/aix-ppc64": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.25.12.tgz", + "integrity": "sha512-Hhmwd6CInZ3dwpuGTF8fJG6yoWmsToE+vYgD4nytZVxcu1ulHpUQRAB1UJ8+N1Am3Mz4+xOByoQoSZf4D+CpkA==", + "cpu": [ + "ppc64" + ], + "license": "MIT", + "optional": true, + "os": [ + "aix" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/tsx/node_modules/@esbuild/android-arm": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.25.12.tgz", + "integrity": "sha512-VJ+sKvNA/GE7Ccacc9Cha7bpS8nyzVv0jdVgwNDaR4gDMC/2TTRc33Ip8qrNYUcpkOHUT5OZ0bUcNNVZQ9RLlg==", + "cpu": [ + "arm" + ], + "license": "MIT", + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/tsx/node_modules/@esbuild/android-arm64": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.25.12.tgz", + "integrity": "sha512-6AAmLG7zwD1Z159jCKPvAxZd4y/VTO0VkprYy+3N2FtJ8+BQWFXU+OxARIwA46c5tdD9SsKGZ/1ocqBS/gAKHg==", + "cpu": [ + "arm64" + ], + "license": "MIT", + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/tsx/node_modules/@esbuild/android-x64": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.25.12.tgz", + "integrity": "sha512-5jbb+2hhDHx5phYR2By8GTWEzn6I9UqR11Kwf22iKbNpYrsmRB18aX/9ivc5cabcUiAT/wM+YIZ6SG9QO6a8kg==", + "cpu": [ + "x64" + ], + "license": "MIT", + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/tsx/node_modules/@esbuild/darwin-arm64": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.25.12.tgz", + "integrity": "sha512-N3zl+lxHCifgIlcMUP5016ESkeQjLj/959RxxNYIthIg+CQHInujFuXeWbWMgnTo4cp5XVHqFPmpyu9J65C1Yg==", + "cpu": [ + "arm64" + ], + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/tsx/node_modules/@esbuild/darwin-x64": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.25.12.tgz", + "integrity": "sha512-HQ9ka4Kx21qHXwtlTUVbKJOAnmG1ipXhdWTmNXiPzPfWKpXqASVcWdnf2bnL73wgjNrFXAa3yYvBSd9pzfEIpA==", + "cpu": [ + "x64" + ], + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/tsx/node_modules/@esbuild/freebsd-arm64": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.25.12.tgz", + "integrity": "sha512-gA0Bx759+7Jve03K1S0vkOu5Lg/85dou3EseOGUes8flVOGxbhDDh/iZaoek11Y8mtyKPGF3vP8XhnkDEAmzeg==", + "cpu": [ + "arm64" + ], + "license": "MIT", + "optional": true, + "os": [ + "freebsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/tsx/node_modules/@esbuild/freebsd-x64": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.25.12.tgz", + "integrity": "sha512-TGbO26Yw2xsHzxtbVFGEXBFH0FRAP7gtcPE7P5yP7wGy7cXK2oO7RyOhL5NLiqTlBh47XhmIUXuGciXEqYFfBQ==", + "cpu": [ + "x64" + ], + "license": "MIT", + "optional": true, + "os": [ + "freebsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/tsx/node_modules/@esbuild/linux-arm": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.25.12.tgz", + "integrity": "sha512-lPDGyC1JPDou8kGcywY0YILzWlhhnRjdof3UlcoqYmS9El818LLfJJc3PXXgZHrHCAKs/Z2SeZtDJr5MrkxtOw==", + "cpu": [ + "arm" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/tsx/node_modules/@esbuild/linux-arm64": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.25.12.tgz", + "integrity": "sha512-8bwX7a8FghIgrupcxb4aUmYDLp8pX06rGh5HqDT7bB+8Rdells6mHvrFHHW2JAOPZUbnjUpKTLg6ECyzvas2AQ==", + "cpu": [ + "arm64" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/tsx/node_modules/@esbuild/linux-ia32": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.25.12.tgz", + "integrity": "sha512-0y9KrdVnbMM2/vG8KfU0byhUN+EFCny9+8g202gYqSSVMonbsCfLjUO+rCci7pM0WBEtz+oK/PIwHkzxkyharA==", + "cpu": [ + "ia32" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/tsx/node_modules/@esbuild/linux-loong64": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.25.12.tgz", + "integrity": "sha512-h///Lr5a9rib/v1GGqXVGzjL4TMvVTv+s1DPoxQdz7l/AYv6LDSxdIwzxkrPW438oUXiDtwM10o9PmwS/6Z0Ng==", + "cpu": [ + "loong64" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/tsx/node_modules/@esbuild/linux-mips64el": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.25.12.tgz", + "integrity": "sha512-iyRrM1Pzy9GFMDLsXn1iHUm18nhKnNMWscjmp4+hpafcZjrr2WbT//d20xaGljXDBYHqRcl8HnxbX6uaA/eGVw==", + "cpu": [ + "mips64el" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/tsx/node_modules/@esbuild/linux-ppc64": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.25.12.tgz", + "integrity": "sha512-9meM/lRXxMi5PSUqEXRCtVjEZBGwB7P/D4yT8UG/mwIdze2aV4Vo6U5gD3+RsoHXKkHCfSxZKzmDssVlRj1QQA==", + "cpu": [ + "ppc64" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/tsx/node_modules/@esbuild/linux-riscv64": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.25.12.tgz", + "integrity": "sha512-Zr7KR4hgKUpWAwb1f3o5ygT04MzqVrGEGXGLnj15YQDJErYu/BGg+wmFlIDOdJp0PmB0lLvxFIOXZgFRrdjR0w==", + "cpu": [ + "riscv64" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/tsx/node_modules/@esbuild/linux-s390x": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.25.12.tgz", + "integrity": "sha512-MsKncOcgTNvdtiISc/jZs/Zf8d0cl/t3gYWX8J9ubBnVOwlk65UIEEvgBORTiljloIWnBzLs4qhzPkJcitIzIg==", + "cpu": [ + "s390x" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/tsx/node_modules/@esbuild/linux-x64": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.25.12.tgz", + "integrity": "sha512-uqZMTLr/zR/ed4jIGnwSLkaHmPjOjJvnm6TVVitAa08SLS9Z0VM8wIRx7gWbJB5/J54YuIMInDquWyYvQLZkgw==", + "cpu": [ + "x64" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/tsx/node_modules/@esbuild/netbsd-x64": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.25.12.tgz", + "integrity": "sha512-Ld5pTlzPy3YwGec4OuHh1aCVCRvOXdH8DgRjfDy/oumVovmuSzWfnSJg+VtakB9Cm0gxNO9BzWkj6mtO1FMXkQ==", + "cpu": [ + "x64" + ], + "license": "MIT", + "optional": true, + "os": [ + "netbsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/tsx/node_modules/@esbuild/openbsd-x64": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.25.12.tgz", + "integrity": "sha512-MZyXUkZHjQxUvzK7rN8DJ3SRmrVrke8ZyRusHlP+kuwqTcfWLyqMOE3sScPPyeIXN/mDJIfGXvcMqCgYKekoQw==", + "cpu": [ + "x64" + ], + "license": "MIT", + "optional": true, + "os": [ + "openbsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/tsx/node_modules/@esbuild/sunos-x64": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.25.12.tgz", + "integrity": "sha512-3wGSCDyuTHQUzt0nV7bocDy72r2lI33QL3gkDNGkod22EsYl04sMf0qLb8luNKTOmgF/eDEDP5BFNwoBKH441w==", + "cpu": [ + "x64" + ], + "license": "MIT", + "optional": true, + "os": [ + "sunos" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/tsx/node_modules/@esbuild/win32-arm64": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.25.12.tgz", + "integrity": "sha512-rMmLrur64A7+DKlnSuwqUdRKyd3UE7oPJZmnljqEptesKM8wx9J8gx5u0+9Pq0fQQW8vqeKebwNXdfOyP+8Bsg==", + "cpu": [ + "arm64" + ], + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/tsx/node_modules/@esbuild/win32-ia32": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.25.12.tgz", + "integrity": "sha512-HkqnmmBoCbCwxUKKNPBixiWDGCpQGVsrQfJoVGYLPT41XWF8lHuE5N6WhVia2n4o5QK5M4tYr21827fNhi4byQ==", + "cpu": [ + "ia32" + ], + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/tsx/node_modules/@esbuild/win32-x64": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.25.12.tgz", + "integrity": "sha512-alJC0uCZpTFrSL0CCDjcgleBXPnCrEAhTBILpeAp7M/OFgoqtAetfBzX0xM00MUsVVPpVjlPuMbREqnZCXaTnA==", + "cpu": [ + "x64" + ], + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/tsx/node_modules/esbuild": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.25.12.tgz", + "integrity": "sha512-bbPBYYrtZbkt6Os6FiTLCTFxvq4tt3JKall1vRwshA3fdVztsLAatFaZobhkBC8/BrPetoa0oksYoKXoG4ryJg==", + "hasInstallScript": true, + "license": "MIT", + "bin": { + "esbuild": "bin/esbuild" + }, + "engines": { + "node": ">=18" + }, + "optionalDependencies": { + "@esbuild/aix-ppc64": "0.25.12", + "@esbuild/android-arm": "0.25.12", + "@esbuild/android-arm64": "0.25.12", + "@esbuild/android-x64": "0.25.12", + "@esbuild/darwin-arm64": "0.25.12", + "@esbuild/darwin-x64": "0.25.12", + "@esbuild/freebsd-arm64": "0.25.12", + "@esbuild/freebsd-x64": "0.25.12", + "@esbuild/linux-arm": "0.25.12", + "@esbuild/linux-arm64": "0.25.12", + "@esbuild/linux-ia32": "0.25.12", + "@esbuild/linux-loong64": "0.25.12", + "@esbuild/linux-mips64el": "0.25.12", + "@esbuild/linux-ppc64": "0.25.12", + "@esbuild/linux-riscv64": "0.25.12", + "@esbuild/linux-s390x": "0.25.12", + "@esbuild/linux-x64": "0.25.12", + "@esbuild/netbsd-arm64": "0.25.12", + "@esbuild/netbsd-x64": "0.25.12", + "@esbuild/openbsd-arm64": "0.25.12", + "@esbuild/openbsd-x64": "0.25.12", + "@esbuild/openharmony-arm64": "0.25.12", + "@esbuild/sunos-x64": "0.25.12", + "@esbuild/win32-arm64": "0.25.12", + "@esbuild/win32-ia32": "0.25.12", + "@esbuild/win32-x64": "0.25.12" + } + }, + "node_modules/tsx/node_modules/fsevents": { + "version": "2.3.3", + "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz", + "integrity": "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==", + "hasInstallScript": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": "^8.16.0 || ^10.6.0 || >=11.0.0" + } }, "node_modules/tunnel": { "version": "0.0.6", @@ -17364,19 +16663,6 @@ "integrity": "sha512-iwDZqg0QAGrg9Rav5H4n0M64c3mkR59cJ6wQp+7C4nI0gsmExaedaYLNO44eT4AtBBwjbTiGPMlt2Md0T9H9JQ==", "license": "MIT" }, - "node_modules/unicorn-magic": { - "version": "0.3.0", - "resolved": "https://registry.npmjs.org/unicorn-magic/-/unicorn-magic-0.3.0.tgz", - "integrity": "sha512-+QBBXBCvifc56fsbuxZQ6Sic3wqqc3WWaqxs58gvJrcOuN83HGTCwz3oS5phzU9LthRNE9VrJCFCLUgHeeFnfA==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=18" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, "node_modules/unique-filename": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/unique-filename/-/unique-filename-1.1.1.tgz", @@ -17422,37 +16708,6 @@ "node": ">= 0.8" } }, - "node_modules/update-browserslist-db": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.1.3.tgz", - "integrity": "sha512-UxhIZQ+QInVdunkDAaiazvvT/+fXL5Osr0JZlJulepYu6Jd7qJtDZjlur0emRlT71EN3ScPoE7gvsuIKKNavKw==", - "dev": true, - "funding": [ - { - "type": "opencollective", - "url": "https://opencollective.com/browserslist" - }, - { - "type": "tidelift", - "url": "https://tidelift.com/funding/github/npm/browserslist" - }, - { - "type": "github", - "url": "https://github.com/sponsors/ai" - } - ], - "license": "MIT", - "dependencies": { - "escalade": "^3.2.0", - "picocolors": "^1.1.1" - }, - "bin": { - "update-browserslist-db": "cli.js" - }, - "peerDependencies": { - "browserslist": ">= 4.21.0" - } - }, "node_modules/uri-js": { "version": "4.4.1", "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz", @@ -17609,19 +16864,6 @@ } } }, - "node_modules/vite-hot-client": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/vite-hot-client/-/vite-hot-client-2.1.0.tgz", - "integrity": "sha512-7SpgZmU7R+dDnSmvXE1mfDtnHLHQSisdySVR7lO8ceAXvM0otZeuQQ6C8LrS5d/aYyP/QZ0hI0L+dIPrm4YlFQ==", - "dev": true, - "license": "MIT", - "funding": { - "url": "https://github.com/sponsors/antfu" - }, - "peerDependencies": { - "vite": "^2.6.0 || ^3.0.0 || ^4.0.0 || ^5.0.0-0 || ^6.0.0-0 || ^7.0.0-0" - } - }, "node_modules/vite-plugin-compression": { "version": "0.5.1", "resolved": "https://registry.npmjs.org/vite-plugin-compression/-/vite-plugin-compression-0.5.1.tgz", @@ -17637,138 +16879,6 @@ "vite": ">=2.0.0" } }, - "node_modules/vite-plugin-inspect": { - "version": "0.8.9", - "resolved": "https://registry.npmjs.org/vite-plugin-inspect/-/vite-plugin-inspect-0.8.9.tgz", - "integrity": "sha512-22/8qn+LYonzibb1VeFZmISdVao5kC22jmEKm24vfFE8siEn47EpVcCLYMv6iKOYMJfjSvSJfueOwcFCkUnV3A==", - "dev": true, - "license": "MIT", - "dependencies": { - "@antfu/utils": "^0.7.10", - "@rollup/pluginutils": "^5.1.3", - "debug": "^4.3.7", - "error-stack-parser-es": "^0.1.5", - "fs-extra": "^11.2.0", - "open": "^10.1.0", - "perfect-debounce": "^1.0.0", - "picocolors": "^1.1.1", - "sirv": "^3.0.0" - }, - "engines": { - "node": ">=14" - }, - "funding": { - "url": "https://github.com/sponsors/antfu" - }, - "peerDependencies": { - "vite": "^3.1.0 || ^4.0.0 || ^5.0.0-0 || ^6.0.1" - }, - "peerDependenciesMeta": { - "@nuxt/kit": { - "optional": true - } - } - }, - "node_modules/vite-plugin-inspect/node_modules/define-lazy-prop": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/define-lazy-prop/-/define-lazy-prop-3.0.0.tgz", - "integrity": "sha512-N+MeXYoqr3pOgn8xfyRPREN7gHakLYjhsHhWGT3fWAiL4IkAt0iDw14QiiEm2bE30c5XX5q0FtAA3CK5f9/BUg==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/vite-plugin-inspect/node_modules/fs-extra": { - "version": "11.3.2", - "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-11.3.2.tgz", - "integrity": "sha512-Xr9F6z6up6Ws+NjzMCZc6WXg2YFRlrLP9NQDO3VQrWrfiojdhS56TzueT88ze0uBdCTwEIhQ3ptnmKeWGFAe0A==", - "dev": true, - "license": "MIT", - "dependencies": { - "graceful-fs": "^4.2.0", - "jsonfile": "^6.0.1", - "universalify": "^2.0.0" - }, - "engines": { - "node": ">=14.14" - } - }, - "node_modules/vite-plugin-inspect/node_modules/open": { - "version": "10.2.0", - "resolved": "https://registry.npmjs.org/open/-/open-10.2.0.tgz", - "integrity": "sha512-YgBpdJHPyQ2UE5x+hlSXcnejzAvD0b22U2OuAP+8OnlJT+PjWPxtgmGqKKc+RgTM63U9gN0YzrYc71R2WT/hTA==", - "dev": true, - "license": "MIT", - "dependencies": { - "default-browser": "^5.2.1", - "define-lazy-prop": "^3.0.0", - "is-inside-container": "^1.0.0", - "wsl-utils": "^0.1.0" - }, - "engines": { - "node": ">=18" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/vite-plugin-inspect/node_modules/universalify": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.1.tgz", - "integrity": "sha512-gptHNQghINnc/vTGIk0SOFGFNXw7JVrlRUtConJRlvaw6DuX0wO5Jeko9sWrMBhh+PsYAZ7oXAiOnf/UKogyiw==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">= 10.0.0" - } - }, - "node_modules/vite-plugin-vue-devtools": { - "version": "7.7.7", - "resolved": "https://registry.npmjs.org/vite-plugin-vue-devtools/-/vite-plugin-vue-devtools-7.7.7.tgz", - "integrity": "sha512-d0fIh3wRcgSlr4Vz7bAk4va1MkdqhQgj9ANE/rBhsAjOnRfTLs2ocjFMvSUOsv6SRRXU9G+VM7yMgqDb6yI4iQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "@vue/devtools-core": "^7.7.7", - "@vue/devtools-kit": "^7.7.7", - "@vue/devtools-shared": "^7.7.7", - "execa": "^9.5.2", - "sirv": "^3.0.1", - "vite-plugin-inspect": "0.8.9", - "vite-plugin-vue-inspector": "^5.3.1" - }, - "engines": { - "node": ">=v14.21.3" - }, - "peerDependencies": { - "vite": "^3.1.0 || ^4.0.0-0 || ^5.0.0-0 || ^6.0.0-0 || ^7.0.0-0" - } - }, - "node_modules/vite-plugin-vue-inspector": { - "version": "5.3.2", - "resolved": "https://registry.npmjs.org/vite-plugin-vue-inspector/-/vite-plugin-vue-inspector-5.3.2.tgz", - "integrity": "sha512-YvEKooQcSiBTAs0DoYLfefNja9bLgkFM7NI2b07bE2SruuvX0MEa9cMaxjKVMkeCp5Nz9FRIdcN1rOdFVBeL6Q==", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/core": "^7.23.0", - "@babel/plugin-proposal-decorators": "^7.23.0", - "@babel/plugin-syntax-import-attributes": "^7.22.5", - "@babel/plugin-syntax-import-meta": "^7.10.4", - "@babel/plugin-transform-typescript": "^7.22.15", - "@vue/babel-plugin-jsx": "^1.1.5", - "@vue/compiler-dom": "^3.3.4", - "kolorist": "^1.8.0", - "magic-string": "^0.30.4" - }, - "peerDependencies": { - "vite": "^3.0.0-0 || ^4.0.0-0 || ^5.0.0-0 || ^6.0.0-0 || ^7.0.0-0" - } - }, "node_modules/vite/node_modules/fsevents": { "version": "2.3.3", "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz", @@ -18475,19 +17585,6 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/yoctocolors": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/yoctocolors/-/yoctocolors-2.1.2.tgz", - "integrity": "sha512-CzhO+pFNo8ajLM2d2IW/R93ipy99LWjtwblvC1RsoSUMZgyLbYFr221TnSNT7GjGdYui6P459mw9JH/g/zW2ug==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=18" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, "node_modules/zip-stream": { "version": "6.0.1", "resolved": "https://registry.npmjs.org/zip-stream/-/zip-stream-6.0.1.tgz", diff --git a/package.json b/package.json index b3fe03154..65ce952c7 100644 --- a/package.json +++ b/package.json @@ -1,13 +1,13 @@ { "name": "uptime-kuma", - "version": "2.0.1", + "version": "3.0.0-beta.0", "license": "MIT", "repository": { "type": "git", "url": "https://github.com/louislam/uptime-kuma.git" }, "engines": { - "node": "18 || >= 20.4.0" + "node": ">= 24.0.0" }, "scripts": { "lint:js": "eslint --ext \".js,.vue\" --ignore-path .gitignore .", @@ -19,29 +19,27 @@ "lint:prod": "npm run lint:js-prod && npm run lint:style", "dev": "concurrently -k -r \"wait-on tcp:3000 && npm run start-server-dev \" \"npm run start-frontend-dev\"", "start-frontend-dev": "cross-env NODE_ENV=development vite --host --config ./config/vite.config.js", - "start-frontend-devcontainer": "cross-env NODE_ENV=development DEVCONTAINER=1 vite --host --config ./config/vite.config.js", "start": "npm run start-server", - "start-server": "node server/server.js", - "start-server-dev": "cross-env NODE_ENV=development node server/server.js", - "start-server-dev:watch": "cross-env NODE_ENV=development node --watch server/server.js", + "start-server": "tsx server/server.js", + "start-server-dev": "cross-env NODE_ENV=development tsx server/server.js", + "start-server-dev:watch": "cross-env NODE_ENV=development tsx --watch server/server.js", "build": "vite build --config ./config/vite.config.js", "test": "npm run test-backend && npm run test-e2e", "test-with-build": "npm run build && npm test", - "test-backend": "cross-env TEST_BACKEND=1 node --test test/backend-test", + "test-backend": "cross-env TEST_BACKEND=1 node --import=tsx --test \"test/backend-test/**/*.js\"", "test-e2e": "playwright test --config ./config/playwright.config.js", "test-e2e-ui": "playwright test --config ./config/playwright.config.js --ui --ui-port=51063", "playwright-codegen": "playwright codegen localhost:3000 --save-storage=./private/e2e-auth.json", "playwright-show-report": "playwright show-report ./private/playwright-report", - "tsc": "tsc --project ./tsconfig-backend.json", "vite-preview-dist": "vite preview --host --config ./config/vite.config.js", - "build-docker-base": "docker buildx build -f docker/debian-base.dockerfile --platform linux/amd64,linux/arm64,linux/arm/v7 -t louislam/uptime-kuma:base2 --target base2 . --push", - "build-docker-base-slim": "docker buildx build -f docker/debian-base.dockerfile --platform linux/amd64,linux/arm64,linux/arm/v7 -t louislam/uptime-kuma:base2-slim --target base2-slim . --push", - "build-docker-builder-go": "docker buildx build -f docker/builder-go.dockerfile --platform linux/amd64,linux/arm64,linux/arm/v7 -t louislam/uptime-kuma:builder-go . --push", - "build-docker-nightly-local": "npm run build && docker build -f docker/dockerfile -t louislam/uptime-kuma:nightly2 --target nightly .", - "build-docker-pr-test": "docker buildx build -f docker/dockerfile --platform linux/amd64,linux/arm64 -t louislam/uptime-kuma:pr-test2 --target pr-test2 . --push", + "build-docker-base": "docker buildx build -f docker/debian-base.dockerfile --platform linux/amd64,linux/arm64 -t louislam/uptime-kuma:base3 --target base3 . --push", + "build-docker-base-slim": "docker buildx build -f docker/debian-base.dockerfile --platform linux/amd64,linux/arm64 -t louislam/uptime-kuma:base3-slim --target base3-slim . --push", + "build-docker-builder-go": "docker buildx build -f docker/builder-go.dockerfile --platform linux/amd64,linux/arm64 -t louislam/uptime-kuma:builder-go3 . --push", + "build-docker-nightly-local": "npm run build && docker build -f docker/dockerfile -t louislam/uptime-kuma:nightly3 --target nightly .", + "build-docker-pr-test": "docker buildx build -f docker/dockerfile --platform linux/amd64,linux/arm64 -t louislam/uptime-kuma:pr-test3 --target pr-test3 . --push", "upload-artifacts": "node extra/release/upload-artifacts.mjs", "upload-artifacts-beta": "node extra/release/upload-artifacts-beta.mjs", - "setup": "git checkout 2.0.1 && npm ci --omit dev && npm run download-dist", + "setup": "git checkout 2.0.2 && npm ci --omit dev --no-audit && npm run download-dist", "download-dist": "node extra/download-dist.js", "mark-as-nightly": "node extra/mark-as-nightly.js", "reset-password": "node extra/reset-password.js", @@ -58,12 +56,9 @@ "git-remove-tag": "git tag -d", "build-dist-and-restart": "npm run build && npm run start-server-dev", "start-pr-test": "node extra/checkout-pr.mjs && npm install && npm run dev", - "build-healthcheck-armv7": "cross-env GOOS=linux GOARCH=arm GOARM=7 go build -x -o ./extra/healthcheck-armv7 ./extra/healthcheck.go", "deploy-demo-server": "node extra/deploy-demo-server.js", - "sort-contributors": "node extra/sort-contributors.js", - "quick-run-nightly": "docker run --rm --env NODE_ENV=development -p 3001:3001 louislam/uptime-kuma:nightly2", + "quick-run-nightly": "docker run --rm --env NODE_ENV=development -p 3001:3001 louislam/uptime-kuma:nightly3", "start-dev-container": "cd docker && docker-compose -f docker-compose-dev.yml up --force-recreate", - "rebase-pr-to-1.23.X": "node extra/rebase-pr.js 1.23.X", "reset-migrate-aggregate-table-state": "node extra/reset-migrate-aggregate-table-state.js", "generate-changelog": "node ./extra/generate-changelog.mjs" }, @@ -146,7 +141,9 @@ "tcp-ping": "~0.1.1", "thirty-two": "~1.0.2", "tough-cookie": "~4.1.3", - "ws": "^8.13.0" + "tsx": "~4.20.6", + "ws": "^8.13.0", + "zod": "~4.1.12" }, "devDependencies": { "@actions/github": "~6.0.0", @@ -198,7 +195,6 @@ "v-pagination-3": "~0.1.7", "vite": "~5.4.15", "vite-plugin-compression": "^0.5.1", - "vite-plugin-vue-devtools": "^7.0.15", "vue": "~3.4.2", "vue-chartjs": "~5.2.0", "vue-confirm-dialog": "~1.0.2", diff --git a/server/auth.js b/server/auth.js index a4aed50b8..f98d4c8b3 100644 --- a/server/auth.js +++ b/server/auth.js @@ -18,8 +18,8 @@ exports.login = async function (username, password) { return null; } - let user = await R.findOne("user", " username = ? AND active = 1 ", [ - username, + let user = await R.findOne("user", "TRIM(username) = ? AND active = 1 ", [ + username.trim(), ]); if (user && passwordHash.verify(password, user.password)) { diff --git a/server/model/monitor.js b/server/model/monitor.js index 178d639cd..6e2b3c033 100644 --- a/server/model/monitor.js +++ b/server/model/monitor.js @@ -578,7 +578,8 @@ class Monitor extends BeanModel { } } - if (process.env.UPTIME_KUMA_LOG_RESPONSE_BODY_MONITOR_ID === this.id) { + // eslint-disable-next-line eqeqeq + if (process.env.UPTIME_KUMA_LOG_RESPONSE_BODY_MONITOR_ID == this.id) { log.info("monitor", res.data); } diff --git a/server/monitor-types/mqtt.js b/server/monitor-types/mqtt.js index 1865bbb42..18595b3a4 100644 --- a/server/monitor-types/mqtt.js +++ b/server/monitor-types/mqtt.js @@ -10,7 +10,7 @@ class MqttMonitorType extends MonitorType { * @inheritdoc */ async check(monitor, heartbeat, server) { - const receivedMessage = await this.mqttAsync(monitor.hostname, monitor.mqttTopic, { + const [ messageTopic, receivedMessage ] = await this.mqttAsync(monitor.hostname, monitor.mqttTopic, { port: monitor.port, username: monitor.mqttUsername, password: monitor.mqttPassword, @@ -25,7 +25,7 @@ class MqttMonitorType extends MonitorType { if (monitor.mqttCheckType === "keyword") { if (receivedMessage != null && receivedMessage.includes(monitor.mqttSuccessMessage)) { - heartbeat.msg = `Topic: ${monitor.mqttTopic}; Message: ${receivedMessage}`; + heartbeat.msg = `Topic: ${messageTopic}; Message: ${receivedMessage}`; heartbeat.status = UP; } else { throw Error(`Message Mismatch - Topic: ${monitor.mqttTopic}; Message: ${receivedMessage}`); @@ -110,11 +110,9 @@ class MqttMonitorType extends MonitorType { }); client.on("message", (messageTopic, message) => { - if (messageTopic === topic) { - client.end(); - clearTimeout(timeoutID); - resolve(message.toString("utf8")); - } + client.end(); + clearTimeout(timeoutID); + resolve([ messageTopic, message.toString("utf8") ]); }); }); diff --git a/server/monitor-types/real-browser-monitor-type.js b/server/monitor-types/real-browser-monitor-type.js index 2a2871d2c..07b6c8aac 100644 --- a/server/monitor-types/real-browser-monitor-type.js +++ b/server/monitor-types/real-browser-monitor-type.js @@ -2,13 +2,13 @@ const { MonitorType } = require("./monitor-type"); const { chromium } = require("playwright-core"); const { UP, log } = require("../../src/util"); const { Settings } = require("../settings"); -const commandExistsSync = require("command-exists").sync; const childProcess = require("child_process"); const path = require("path"); const Database = require("../database"); const jwt = require("jsonwebtoken"); const config = require("../config"); const { RemoteBrowser } = require("../remote-browser"); +const { commandExists } = require("../util-server"); /** * Cached instance of a browser @@ -122,7 +122,7 @@ async function prepareChromeExecutable(executablePath) { executablePath = "/usr/bin/chromium"; // Install chromium in container via apt install - if ( !commandExistsSync(executablePath)) { + if (! await commandExists(executablePath)) { await new Promise((resolve, reject) => { log.info("Chromium", "Installing Chromium..."); let child = childProcess.exec("apt update && apt --yes --no-install-recommends install chromium fonts-indic fonts-noto fonts-noto-cjk"); @@ -146,7 +146,7 @@ async function prepareChromeExecutable(executablePath) { } } else { - executablePath = findChrome(allowedList); + executablePath = await findChrome(allowedList); } } else { // User specified a path @@ -160,20 +160,20 @@ async function prepareChromeExecutable(executablePath) { /** * Find the chrome executable - * @param {any[]} executables Executables to search through - * @returns {any} Executable - * @throws Could not find executable + * @param {string[]} executables Executables to search through + * @returns {Promise} Executable + * @throws {Error} Could not find executable */ -function findChrome(executables) { +async function findChrome(executables) { // Use the last working executable, so we don't have to search for it again if (lastAutoDetectChromeExecutable) { - if (commandExistsSync(lastAutoDetectChromeExecutable)) { + if (await commandExists(lastAutoDetectChromeExecutable)) { return lastAutoDetectChromeExecutable; } } for (let executable of executables) { - if (commandExistsSync(executable)) { + if (await commandExists(executable)) { lastAutoDetectChromeExecutable = executable; return executable; } diff --git a/server/monitor-types/tailscale-ping.js b/server/monitor-types/tailscale-ping.js index 8537651cd..f2a927b91 100644 --- a/server/monitor-types/tailscale-ping.js +++ b/server/monitor-types/tailscale-ping.js @@ -31,7 +31,7 @@ class TailscalePing extends MonitorType { timeout: timeout, encoding: "utf8", }); - if (res.stderr && res.stderr.toString()) { + if (res.stderr && res.stderr.toString() && res.code !== 0) { throw new Error(`Error in output: ${res.stderr.toString()}`); } if (res.stdout && res.stdout.toString()) { diff --git a/server/notification-providers/google-chat.js b/server/notification-providers/google-chat.js index 1e2eb3507..2557a142c 100644 --- a/server/notification-providers/google-chat.js +++ b/server/notification-providers/google-chat.js @@ -12,6 +12,29 @@ class GoogleChat extends NotificationProvider { async send(notification, msg, monitorJSON = null, heartbeatJSON = null) { const okMsg = "Sent Successfully."; + // If Google Chat Webhook rate limit is reached, retry to configured max retries defaults to 3, delay between 60-180 seconds + const post = async (url, data, config) => { + let retries = notification.googleChatMaxRetries || 1; // Default to 1 retries + retries = (retries > 10) ? 10 : retries; // Enforce maximum retries in backend + while (retries > 0) { + try { + await axios.post(url, data, config); + return; + } catch (error) { + if (error.response && error.response.status === 429) { + retries--; + if (retries === 0) { + throw error; + } + const delay = 60000 + Math.random() * 120000; + await new Promise(resolve => setTimeout(resolve, delay)); + } else { + throw error; + } + } + } + }; + try { let config = this.getAxiosConfigWithProxy({}); // Google Chat message formatting: https://developers.google.com/chat/api/guides/message-formats/basic @@ -24,7 +47,7 @@ class GoogleChat extends NotificationProvider { heartbeatJSON ); const data = { "text": renderedText }; - await axios.post(notification.googleChatWebhookURL, data, config); + await post(notification.googleChatWebhookURL, data, config); return okMsg; } @@ -96,7 +119,7 @@ class GoogleChat extends NotificationProvider { ], }; - await axios.post(notification.googleChatWebhookURL, data, config); + await post(notification.googleChatWebhookURL, data, config); return okMsg; } catch (error) { this.throwGeneralAxiosError(error); diff --git a/server/notification-providers/pagerduty.js b/server/notification-providers/pagerduty.js index c60d782e7..385ad2af0 100644 --- a/server/notification-providers/pagerduty.js +++ b/server/notification-providers/pagerduty.js @@ -23,9 +23,7 @@ class PagerDuty extends NotificationProvider { if (heartbeatJSON.status === UP) { const title = "Uptime Kuma Monitor ✅ Up"; - const eventAction = notification.pagerdutyAutoResolve || null; - - return this.postNotification(notification, title, heartbeatJSON.msg, monitorJSON, eventAction); + return this.postNotification(notification, title, heartbeatJSON.msg, monitorJSON, "resolve"); } if (heartbeatJSON.status === DOWN) { @@ -63,10 +61,6 @@ class PagerDuty extends NotificationProvider { */ async postNotification(notification, title, body, monitorInfo, eventAction = "trigger") { - if (eventAction == null) { - return "No action required"; - } - let monitorUrl; if (monitorInfo.type === "port") { monitorUrl = monitorInfo.hostname; @@ -79,6 +73,13 @@ class PagerDuty extends NotificationProvider { monitorUrl = monitorInfo.url; } + if (eventAction === "resolve") { + if (notification.pagerdutyAutoResolve === "0") { + return "no action required"; + } + eventAction = notification.pagerdutyAutoResolve; + } + const options = { method: "POST", url: notification.pagerdutyIntegrationUrl, diff --git a/server/notification-providers/webhook.js b/server/notification-providers/webhook.js index 77ce229d8..ab7d5f069 100644 --- a/server/notification-providers/webhook.js +++ b/server/notification-providers/webhook.js @@ -12,6 +12,8 @@ class Webhook extends NotificationProvider { const okMsg = "Sent Successfully."; try { + const httpMethod = notification.httpMethod.toLowerCase() || "post"; + let data = { heartbeat: heartbeatJSON, monitor: monitorJSON, @@ -21,7 +23,19 @@ class Webhook extends NotificationProvider { headers: {} }; - if (notification.webhookContentType === "form-data") { + if (httpMethod === "get") { + config.params = { + msg: msg + }; + + if (heartbeatJSON) { + config.params.heartbeat = JSON.stringify(heartbeatJSON); + } + + if (monitorJSON) { + config.params.monitor = JSON.stringify(monitorJSON); + } + } else if (notification.webhookContentType === "form-data") { const formData = new FormData(); formData.append("data", JSON.stringify(data)); config.headers = formData.getHeaders(); @@ -42,7 +56,13 @@ class Webhook extends NotificationProvider { } config = this.getAxiosConfigWithProxy(config); - await axios.post(notification.webhookURL, data, config); + + if (httpMethod === "get") { + await axios.get(notification.webhookURL, config); + } else { + await axios.post(notification.webhookURL, data, config); + } + return okMsg; } catch (error) { diff --git a/server/notification.js b/server/notification.js index 8ad62dc13..31028e3dd 100644 --- a/server/notification.js +++ b/server/notification.js @@ -81,6 +81,7 @@ const Brevo = require("./notification-providers/brevo"); const YZJ = require("./notification-providers/yzj"); const SMSPlanet = require("./notification-providers/sms-planet"); const SpugPush = require("./notification-providers/spugpush"); +const { commandExists } = require("./util-server"); class Notification { providerList = {}; @@ -275,12 +276,10 @@ class Notification { /** * Check if apprise exists - * @returns {boolean} Does the command apprise exist? + * @returns {Promise} Does the command apprise exist? */ - static checkApprise() { - let commandExistsSync = require("command-exists").sync; - let exists = commandExistsSync("apprise"); - return exists; + static async checkApprise() { + return await commandExists("apprise"); } } diff --git a/server/server.js b/server/server.js index 55289b55a..6d4149ee7 100644 --- a/server/server.js +++ b/server/server.js @@ -3,6 +3,8 @@ * node "server/server.js" * DO NOT require("./server") in other modules, it likely creates circular dependency! */ +import { genSecret, getRandomInt, isDev, log, sleep } from "../src/util"; + console.log("Welcome to Uptime Kuma"); // As the log function need to use dayjs, it should be very top @@ -37,7 +39,6 @@ if (!semver.satisfies(nodeVersion, requiredNodeVersions)) { } const args = require("args-parser")(process.argv); -const { sleep, log, getRandomInt, genSecret, isDev } = require("../src/util"); const config = require("./config"); log.debug("server", "Arguments"); @@ -59,7 +60,7 @@ if (process.env.UPTIME_KUMA_WS_ORIGIN_CHECK === "bypass") { } const checkVersion = require("./check-version"); -log.info("server", "Uptime Kuma Version: " + checkVersion.version); +log.info("server", "Uptime Kuma Version:", checkVersion.version); log.info("server", "Loading modules"); @@ -1060,6 +1061,27 @@ let needSetup = false; const startTime = Date.now(); + // Check if this is a group monitor and unlink children before deletion + const monitor = await R.findOne("monitor", " id = ? AND user_id = ? ", [ + monitorID, + socket.userID, + ]); + + if (monitor && monitor.type === "group") { + // Get all children before unlinking them + const children = await Monitor.getChildren(monitorID); + + // Unlink all children from the group + await Monitor.unlinkAllChildren(monitorID); + + // Notify frontend to update each child monitor's parent to null + if (children && children.length > 0) { + for (const child of children) { + await server.sendUpdateMonitorIntoList(socket, child.id); + } + } + } + await R.exec("DELETE FROM monitor WHERE id = ? AND user_id = ? ", [ monitorID, socket.userID, @@ -1503,7 +1525,7 @@ let needSetup = false; socket.on("checkApprise", async (callback) => { try { checkLogin(socket); - callback(Notification.checkApprise()); + callback(await Notification.checkApprise()); } catch (e) { callback(false); } diff --git a/server/util-server.js b/server/util-server.js index ecad276b3..462b80578 100644 --- a/server/util-server.js +++ b/server/util-server.js @@ -1116,3 +1116,19 @@ function fsExists(path) { }); } module.exports.fsExists = fsExists; + +/** + * By default, command-exists will throw a null error if the command does not exist, which is ugly. The function makes it better. + * Read more: https://github.com/mathisonian/command-exists/issues/22 + * @param {string} command Command to check + * @returns {Promise} True if command exists, false otherwise + */ +async function commandExists(command) { + try { + await require("command-exists")(command); + return true; + } catch (e) { + return false; + } +} +module.exports.commandExists = commandExists; diff --git a/server/utils/simple-migration-server.js b/server/utils/simple-migration-server.js index 895298560..1bc3b9475 100644 --- a/server/utils/simple-migration-server.js +++ b/server/utils/simple-migration-server.js @@ -39,11 +39,14 @@ class SimpleMigrationServer { this.app.get("/", (req, res) => { res.set("Content-Type", "text/html"); - // HTML meta tag redirect to /status + // Don't use meta tag redirect, it may cause issues in Chrome (#6223) res.end(` - - Migration server is running. + Uptime Kuma Migration + + Migration is in progress, it may take some time. You can check the progress in the console, or + click here to check. + `); }); diff --git a/src/components/notifications/GoogleChat.vue b/src/components/notifications/GoogleChat.vue index 7b595ed59..90424cb2c 100644 --- a/src/components/notifications/GoogleChat.vue +++ b/src/components/notifications/GoogleChat.vue @@ -11,6 +11,14 @@ +
+ + +
+ {{ $t("Number of retry attempts if webhook fails") }} +
+
+
@@ -45,5 +53,11 @@ export default { ]); } }, + mounted() { + // Initialize default if needed + if (!this.$parent.notification.googleChatMaxRetries) { + this.$parent.notification.googleChatMaxRetries ||= 1; + } + }, }; diff --git a/src/components/notifications/Webhook.vue b/src/components/notifications/Webhook.vue index 7775a3fdd..be51cc2c6 100644 --- a/src/components/notifications/Webhook.vue +++ b/src/components/notifications/Webhook.vue @@ -12,6 +12,21 @@
+ + +
+ {{ $parent.notification.httpMethod === 'get' ? $t("webhookGetMethodDesc") : $t("webhookPostMethodDesc") }} +
+
+ +
+
{{ $t("descriptionHelpText") }}
diff --git a/src/util-frontend.js b/src/util-frontend.js index a3dc4c3ac..7ed3a0cf2 100644 --- a/src/util-frontend.js +++ b/src/util-frontend.js @@ -219,7 +219,7 @@ class RelativeTimeFormatter { * Default locale and options for Relative Time Formatter */ constructor() { - this.options = { numeric: "auto" }; + this.options = { numeric: "always" }; this.instance = new Intl.RelativeTimeFormat(currentLocale(), this.options); } @@ -267,7 +267,7 @@ class RelativeTimeFormatter { }; if (days > 0) { - toFormattedPart(days, "days"); + toFormattedPart(days, "day"); } if (hours > 0) { toFormattedPart(hours, "hour"); diff --git a/src/util.js b/src/util.js deleted file mode 100644 index 9998205f9..000000000 --- a/src/util.js +++ /dev/null @@ -1,468 +0,0 @@ -"use strict"; -/*! -// Common Util for frontend and backend -// -// DOT NOT MODIFY util.js! -// Need to run "npm run tsc" to compile if there are any changes. -// -// Backend uses the compiled file util.js -// Frontend uses util.ts -*/ -var _a; -Object.defineProperty(exports, "__esModule", { value: true }); -exports.CONSOLE_STYLE_FgPink = exports.CONSOLE_STYLE_FgBrown = exports.CONSOLE_STYLE_FgViolet = exports.CONSOLE_STYLE_FgLightBlue = exports.CONSOLE_STYLE_FgLightGreen = exports.CONSOLE_STYLE_FgOrange = exports.CONSOLE_STYLE_FgGray = exports.CONSOLE_STYLE_FgWhite = exports.CONSOLE_STYLE_FgCyan = exports.CONSOLE_STYLE_FgMagenta = exports.CONSOLE_STYLE_FgBlue = exports.CONSOLE_STYLE_FgYellow = exports.CONSOLE_STYLE_FgGreen = exports.CONSOLE_STYLE_FgRed = exports.CONSOLE_STYLE_FgBlack = exports.CONSOLE_STYLE_Hidden = exports.CONSOLE_STYLE_Reverse = exports.CONSOLE_STYLE_Blink = exports.CONSOLE_STYLE_Underscore = exports.CONSOLE_STYLE_Dim = exports.CONSOLE_STYLE_Bright = exports.CONSOLE_STYLE_Reset = exports.PING_PER_REQUEST_TIMEOUT_DEFAULT = exports.PING_PER_REQUEST_TIMEOUT_MAX = exports.PING_PER_REQUEST_TIMEOUT_MIN = exports.PING_COUNT_DEFAULT = exports.PING_COUNT_MAX = exports.PING_COUNT_MIN = exports.PING_GLOBAL_TIMEOUT_DEFAULT = exports.PING_GLOBAL_TIMEOUT_MAX = exports.PING_GLOBAL_TIMEOUT_MIN = exports.PING_PACKET_SIZE_DEFAULT = exports.PING_PACKET_SIZE_MAX = exports.PING_PACKET_SIZE_MIN = exports.MIN_INTERVAL_SECOND = exports.MAX_INTERVAL_SECOND = exports.SQL_DATETIME_FORMAT_WITHOUT_SECOND = exports.SQL_DATETIME_FORMAT = exports.SQL_DATE_FORMAT = exports.STATUS_PAGE_MAINTENANCE = exports.STATUS_PAGE_PARTIAL_DOWN = exports.STATUS_PAGE_ALL_UP = exports.STATUS_PAGE_ALL_DOWN = exports.MAINTENANCE = exports.PENDING = exports.UP = exports.DOWN = exports.appName = exports.isNode = exports.isDev = void 0; -exports.evaluateJsonQuery = exports.intHash = exports.localToUTC = exports.utcToLocal = exports.utcToISODateTime = exports.isoToUTCDateTime = exports.parseTimeFromTimeObject = exports.parseTimeObject = exports.getMaintenanceRelativeURL = exports.getMonitorRelativeURL = exports.genSecret = exports.getCryptoRandomInt = exports.getRandomInt = exports.getRandomArbitrary = exports.TimeLogger = exports.polyfill = exports.log = exports.debug = exports.ucfirst = exports.sleep = exports.flipStatus = exports.badgeConstants = exports.CONSOLE_STYLE_BgGray = exports.CONSOLE_STYLE_BgWhite = exports.CONSOLE_STYLE_BgCyan = exports.CONSOLE_STYLE_BgMagenta = exports.CONSOLE_STYLE_BgBlue = exports.CONSOLE_STYLE_BgYellow = exports.CONSOLE_STYLE_BgGreen = exports.CONSOLE_STYLE_BgRed = exports.CONSOLE_STYLE_BgBlack = void 0; -const dayjs_1 = require("dayjs"); -const jsonata = require("jsonata"); -exports.isDev = process.env.NODE_ENV === "development"; -exports.isNode = typeof process !== "undefined" && ((_a = process === null || process === void 0 ? void 0 : process.versions) === null || _a === void 0 ? void 0 : _a.node); -const dayjs = (exports.isNode) ? require("dayjs") : dayjs_1.default; -exports.appName = "Uptime Kuma"; -exports.DOWN = 0; -exports.UP = 1; -exports.PENDING = 2; -exports.MAINTENANCE = 3; -exports.STATUS_PAGE_ALL_DOWN = 0; -exports.STATUS_PAGE_ALL_UP = 1; -exports.STATUS_PAGE_PARTIAL_DOWN = 2; -exports.STATUS_PAGE_MAINTENANCE = 3; -exports.SQL_DATE_FORMAT = "YYYY-MM-DD"; -exports.SQL_DATETIME_FORMAT = "YYYY-MM-DD HH:mm:ss"; -exports.SQL_DATETIME_FORMAT_WITHOUT_SECOND = "YYYY-MM-DD HH:mm"; -exports.MAX_INTERVAL_SECOND = 2073600; -exports.MIN_INTERVAL_SECOND = 20; -exports.PING_PACKET_SIZE_MIN = 1; -exports.PING_PACKET_SIZE_MAX = 65500; -exports.PING_PACKET_SIZE_DEFAULT = 56; -exports.PING_GLOBAL_TIMEOUT_MIN = 1; -exports.PING_GLOBAL_TIMEOUT_MAX = 300; -exports.PING_GLOBAL_TIMEOUT_DEFAULT = 10; -exports.PING_COUNT_MIN = 1; -exports.PING_COUNT_MAX = 100; -exports.PING_COUNT_DEFAULT = 1; -exports.PING_PER_REQUEST_TIMEOUT_MIN = 1; -exports.PING_PER_REQUEST_TIMEOUT_MAX = 60; -exports.PING_PER_REQUEST_TIMEOUT_DEFAULT = 2; -exports.CONSOLE_STYLE_Reset = "\x1b[0m"; -exports.CONSOLE_STYLE_Bright = "\x1b[1m"; -exports.CONSOLE_STYLE_Dim = "\x1b[2m"; -exports.CONSOLE_STYLE_Underscore = "\x1b[4m"; -exports.CONSOLE_STYLE_Blink = "\x1b[5m"; -exports.CONSOLE_STYLE_Reverse = "\x1b[7m"; -exports.CONSOLE_STYLE_Hidden = "\x1b[8m"; -exports.CONSOLE_STYLE_FgBlack = "\x1b[30m"; -exports.CONSOLE_STYLE_FgRed = "\x1b[31m"; -exports.CONSOLE_STYLE_FgGreen = "\x1b[32m"; -exports.CONSOLE_STYLE_FgYellow = "\x1b[33m"; -exports.CONSOLE_STYLE_FgBlue = "\x1b[34m"; -exports.CONSOLE_STYLE_FgMagenta = "\x1b[35m"; -exports.CONSOLE_STYLE_FgCyan = "\x1b[36m"; -exports.CONSOLE_STYLE_FgWhite = "\x1b[37m"; -exports.CONSOLE_STYLE_FgGray = "\x1b[90m"; -exports.CONSOLE_STYLE_FgOrange = "\x1b[38;5;208m"; -exports.CONSOLE_STYLE_FgLightGreen = "\x1b[38;5;119m"; -exports.CONSOLE_STYLE_FgLightBlue = "\x1b[38;5;117m"; -exports.CONSOLE_STYLE_FgViolet = "\x1b[38;5;141m"; -exports.CONSOLE_STYLE_FgBrown = "\x1b[38;5;130m"; -exports.CONSOLE_STYLE_FgPink = "\x1b[38;5;219m"; -exports.CONSOLE_STYLE_BgBlack = "\x1b[40m"; -exports.CONSOLE_STYLE_BgRed = "\x1b[41m"; -exports.CONSOLE_STYLE_BgGreen = "\x1b[42m"; -exports.CONSOLE_STYLE_BgYellow = "\x1b[43m"; -exports.CONSOLE_STYLE_BgBlue = "\x1b[44m"; -exports.CONSOLE_STYLE_BgMagenta = "\x1b[45m"; -exports.CONSOLE_STYLE_BgCyan = "\x1b[46m"; -exports.CONSOLE_STYLE_BgWhite = "\x1b[47m"; -exports.CONSOLE_STYLE_BgGray = "\x1b[100m"; -const consoleModuleColors = [ - exports.CONSOLE_STYLE_FgCyan, - exports.CONSOLE_STYLE_FgGreen, - exports.CONSOLE_STYLE_FgLightGreen, - exports.CONSOLE_STYLE_FgBlue, - exports.CONSOLE_STYLE_FgLightBlue, - exports.CONSOLE_STYLE_FgMagenta, - exports.CONSOLE_STYLE_FgOrange, - exports.CONSOLE_STYLE_FgViolet, - exports.CONSOLE_STYLE_FgBrown, - exports.CONSOLE_STYLE_FgPink, -]; -const consoleLevelColors = { - "INFO": exports.CONSOLE_STYLE_FgCyan, - "WARN": exports.CONSOLE_STYLE_FgYellow, - "ERROR": exports.CONSOLE_STYLE_FgRed, - "DEBUG": exports.CONSOLE_STYLE_FgGray, -}; -exports.badgeConstants = { - naColor: "#999", - defaultUpColor: "#66c20a", - defaultWarnColor: "#eed202", - defaultDownColor: "#c2290a", - defaultPendingColor: "#f8a306", - defaultMaintenanceColor: "#1747f5", - defaultPingColor: "blue", - defaultStyle: "flat", - defaultPingValueSuffix: "ms", - defaultPingLabelSuffix: "h", - defaultUptimeValueSuffix: "%", - defaultUptimeLabelSuffix: "h", - defaultCertExpValueSuffix: " days", - defaultCertExpLabelSuffix: "h", - defaultCertExpireWarnDays: "14", - defaultCertExpireDownDays: "7" -}; -function flipStatus(s) { - if (s === exports.UP) { - return exports.DOWN; - } - if (s === exports.DOWN) { - return exports.UP; - } - return s; -} -exports.flipStatus = flipStatus; -function sleep(ms) { - return new Promise(resolve => setTimeout(resolve, ms)); -} -exports.sleep = sleep; -function ucfirst(str) { - if (!str) { - return str; - } - const firstLetter = str.substr(0, 1); - return firstLetter.toUpperCase() + str.substr(1); -} -exports.ucfirst = ucfirst; -function debug(msg) { - exports.log.log("", msg, "debug"); -} -exports.debug = debug; -class Logger { - constructor() { - this.hideLog = { - info: [], - warn: [], - error: [], - debug: [], - }; - if (typeof process !== "undefined" && process.env.UPTIME_KUMA_HIDE_LOG) { - const list = process.env.UPTIME_KUMA_HIDE_LOG.split(",").map(v => v.toLowerCase()); - for (const pair of list) { - const values = pair.split(/_(.*)/s); - if (values.length >= 2) { - this.hideLog[values[0]].push(values[1]); - } - } - this.debug("server", "UPTIME_KUMA_HIDE_LOG is set"); - this.debug("server", this.hideLog); - } - } - log(module, msg, level) { - if (level === "DEBUG" && !exports.isDev) { - return; - } - if (this.hideLog[level] && this.hideLog[level].includes(module.toLowerCase())) { - return; - } - module = module.toUpperCase(); - level = level.toUpperCase(); - let now; - if (dayjs.tz) { - now = dayjs.tz(new Date()).format(); - } - else { - now = dayjs().format(); - } - const levelColor = consoleLevelColors[level]; - const moduleColor = consoleModuleColors[intHash(module, consoleModuleColors.length)]; - let timePart; - let modulePart; - let levelPart; - let msgPart; - if (exports.isNode) { - switch (level) { - case "DEBUG": - timePart = exports.CONSOLE_STYLE_FgGray + now + exports.CONSOLE_STYLE_Reset; - break; - default: - timePart = exports.CONSOLE_STYLE_FgCyan + now + exports.CONSOLE_STYLE_Reset; - break; - } - modulePart = "[" + moduleColor + module + exports.CONSOLE_STYLE_Reset + "]"; - levelPart = levelColor + `${level}:` + exports.CONSOLE_STYLE_Reset; - switch (level) { - case "ERROR": - if (typeof msg === "string") { - msgPart = exports.CONSOLE_STYLE_FgRed + msg + exports.CONSOLE_STYLE_Reset; - } - else { - msgPart = msg; - } - break; - case "DEBUG": - if (typeof msg === "string") { - msgPart = exports.CONSOLE_STYLE_FgGray + msg + exports.CONSOLE_STYLE_Reset; - } - else { - msgPart = msg; - } - break; - default: - msgPart = msg; - break; - } - } - else { - timePart = now; - modulePart = `[${module}]`; - levelPart = `${level}:`; - msgPart = msg; - } - switch (level) { - case "ERROR": - console.error(timePart, modulePart, levelPart, msgPart); - break; - case "WARN": - console.warn(timePart, modulePart, levelPart, msgPart); - break; - case "INFO": - console.info(timePart, modulePart, levelPart, msgPart); - break; - case "DEBUG": - if (exports.isDev) { - console.debug(timePart, modulePart, levelPart, msgPart); - } - break; - default: - console.log(timePart, modulePart, levelPart, msgPart); - break; - } - } - info(module, msg) { - this.log(module, msg, "info"); - } - warn(module, msg) { - this.log(module, msg, "warn"); - } - error(module, msg) { - this.log(module, msg, "error"); - } - debug(module, msg) { - this.log(module, msg, "debug"); - } - exception(module, exception, msg) { - let finalMessage = exception; - if (msg) { - finalMessage = `${msg}: ${exception}`; - } - this.log(module, finalMessage, "error"); - } -} -exports.log = new Logger(); -function polyfill() { - if (!String.prototype.replaceAll) { - String.prototype.replaceAll = function (str, newStr) { - if (Object.prototype.toString.call(str).toLowerCase() === "[object regexp]") { - return this.replace(str, newStr); - } - return this.replace(new RegExp(str, "g"), newStr); - }; - } -} -exports.polyfill = polyfill; -class TimeLogger { - constructor() { - this.startTime = dayjs().valueOf(); - } - print(name) { - if (exports.isDev && process.env.TIMELOGGER === "1") { - console.log(name + ": " + (dayjs().valueOf() - this.startTime) + "ms"); - } - } -} -exports.TimeLogger = TimeLogger; -function getRandomArbitrary(min, max) { - return Math.random() * (max - min) + min; -} -exports.getRandomArbitrary = getRandomArbitrary; -function getRandomInt(min, max) { - min = Math.ceil(min); - max = Math.floor(max); - return Math.floor(Math.random() * (max - min + 1)) + min; -} -exports.getRandomInt = getRandomInt; -const getRandomBytes = ((typeof window !== "undefined" && window.crypto) - ? function () { - return (numBytes) => { - const randomBytes = new Uint8Array(numBytes); - for (let i = 0; i < numBytes; i += 65536) { - window.crypto.getRandomValues(randomBytes.subarray(i, i + Math.min(numBytes - i, 65536))); - } - return randomBytes; - }; - } - : function () { - return require("crypto").randomBytes; - })(); -function getCryptoRandomInt(min, max) { - const range = max - min; - if (range >= Math.pow(2, 32)) { - console.log("Warning! Range is too large."); - } - let tmpRange = range; - let bitsNeeded = 0; - let bytesNeeded = 0; - let mask = 1; - while (tmpRange > 0) { - if (bitsNeeded % 8 === 0) { - bytesNeeded += 1; - } - bitsNeeded += 1; - mask = mask << 1 | 1; - tmpRange = tmpRange >>> 1; - } - const randomBytes = getRandomBytes(bytesNeeded); - let randomValue = 0; - for (let i = 0; i < bytesNeeded; i++) { - randomValue |= randomBytes[i] << 8 * i; - } - randomValue = randomValue & mask; - if (randomValue <= range) { - return min + randomValue; - } - else { - return getCryptoRandomInt(min, max); - } -} -exports.getCryptoRandomInt = getCryptoRandomInt; -function genSecret(length = 64) { - let secret = ""; - const chars = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789"; - const charsLength = chars.length; - for (let i = 0; i < length; i++) { - secret += chars.charAt(getCryptoRandomInt(0, charsLength - 1)); - } - return secret; -} -exports.genSecret = genSecret; -function getMonitorRelativeURL(id) { - return "/dashboard/" + id; -} -exports.getMonitorRelativeURL = getMonitorRelativeURL; -function getMaintenanceRelativeURL(id) { - return "/maintenance/" + id; -} -exports.getMaintenanceRelativeURL = getMaintenanceRelativeURL; -function parseTimeObject(time) { - if (!time) { - return { - hours: 0, - minutes: 0, - }; - } - const array = time.split(":"); - if (array.length < 2) { - throw new Error("parseVueDatePickerTimeFormat: Invalid Time"); - } - const obj = { - hours: parseInt(array[0]), - minutes: parseInt(array[1]), - seconds: 0, - }; - if (array.length >= 3) { - obj.seconds = parseInt(array[2]); - } - return obj; -} -exports.parseTimeObject = parseTimeObject; -function parseTimeFromTimeObject(obj) { - if (!obj) { - return obj; - } - let result = ""; - result += obj.hours.toString().padStart(2, "0") + ":" + obj.minutes.toString().padStart(2, "0"); - if (obj.seconds) { - result += ":" + obj.seconds.toString().padStart(2, "0"); - } - return result; -} -exports.parseTimeFromTimeObject = parseTimeFromTimeObject; -function isoToUTCDateTime(input) { - return dayjs(input).utc().format(exports.SQL_DATETIME_FORMAT); -} -exports.isoToUTCDateTime = isoToUTCDateTime; -function utcToISODateTime(input) { - return dayjs.utc(input).toISOString(); -} -exports.utcToISODateTime = utcToISODateTime; -function utcToLocal(input, format = exports.SQL_DATETIME_FORMAT) { - return dayjs.utc(input).local().format(format); -} -exports.utcToLocal = utcToLocal; -function localToUTC(input, format = exports.SQL_DATETIME_FORMAT) { - return dayjs(input).utc().format(format); -} -exports.localToUTC = localToUTC; -function intHash(str, length = 10) { - let hash = 0; - for (let i = 0; i < str.length; i++) { - hash += str.charCodeAt(i); - } - return (hash % length + length) % length; -} -exports.intHash = intHash; -async function evaluateJsonQuery(data, jsonPath, jsonPathOperator, expectedValue) { - let response; - try { - response = JSON.parse(data); - } - catch (_a) { - response = (typeof data === "object" || typeof data === "number") && !Buffer.isBuffer(data) ? data : data.toString(); - } - try { - response = (jsonPath) ? await jsonata(jsonPath).evaluate(response) : response; - if (response === null || response === undefined) { - throw new Error("Empty or undefined response. Check query syntax and response structure"); - } - if (typeof response === "object" || response instanceof Date || typeof response === "function") { - throw new Error(`The post-JSON query evaluated response from the server is of type ${typeof response}, which cannot be directly compared to the expected value`); - } - let jsonQueryExpression; - switch (jsonPathOperator) { - case ">": - case ">=": - case "<": - case "<=": - jsonQueryExpression = `$number($.value) ${jsonPathOperator} $number($.expected)`; - break; - case "!=": - jsonQueryExpression = "$.value != $.expected"; - break; - case "==": - jsonQueryExpression = "$.value = $.expected"; - break; - case "contains": - jsonQueryExpression = "$contains($.value, $.expected)"; - break; - default: - throw new Error(`Invalid condition ${jsonPathOperator}`); - } - const expression = jsonata(jsonQueryExpression); - const status = await expression.evaluate({ - value: response.toString(), - expected: expectedValue.toString() - }); - if (status === undefined) { - throw new Error("Query evaluation returned undefined. Check query syntax and the structure of the response data"); - } - return { - status, - response - }; - } - catch (err) { - response = JSON.stringify(response); - response = (response && response.length > 50) ? `${response.substring(0, 100)}… (truncated)` : response; - throw new Error(`Error evaluating JSON query: ${err.message}. Response from server was: ${response}`); - } -} -exports.evaluateJsonQuery = evaluateJsonQuery; diff --git a/src/util.ts b/src/util.ts index 1098bec4e..6bf9501b5 100644 --- a/src/util.ts +++ b/src/util.ts @@ -193,7 +193,7 @@ export function ucfirst(str: string) { * @returns {void} */ export function debug(msg: unknown) { - log.log("", msg, "debug"); + log.log("", "debug", msg); } class Logger { @@ -238,11 +238,11 @@ class Logger { /** * Write a message to the log * @param module The module the log comes from - * @param msg Message to write * @param level Log level. One of INFO, WARN, ERROR, DEBUG or can be customized. + * @param msg Message to write * @returns {void} */ - log(module: string, msg: any, level: string) { + log(module: string, level: string, ...msg: unknown[]) { if (level === "DEBUG" && !isDev) { return; } @@ -267,7 +267,6 @@ class Logger { let timePart: string; let modulePart: string; let levelPart: string; - let msgPart: string; if (isNode) { // Add console colors @@ -281,54 +280,33 @@ class Logger { } modulePart = "[" + moduleColor + module + CONSOLE_STYLE_Reset + "]"; - levelPart = levelColor + `${level}:` + CONSOLE_STYLE_Reset; - switch (level) { - case "ERROR": - if (typeof msg === "string") { - msgPart = CONSOLE_STYLE_FgRed + msg + CONSOLE_STYLE_Reset; - } else { - msgPart = msg; - } - break; - case "DEBUG": - if (typeof msg === "string") { - msgPart = CONSOLE_STYLE_FgGray + msg + CONSOLE_STYLE_Reset; - } else { - msgPart = msg; - } - break; - default: - msgPart = msg; - break; - } } else { // No console colors timePart = now; modulePart = `[${module}]`; levelPart = `${level}:`; - msgPart = msg; } // Write to console switch (level) { case "ERROR": - console.error(timePart, modulePart, levelPart, msgPart); + console.error(timePart, modulePart, levelPart, ...msg); break; case "WARN": - console.warn(timePart, modulePart, levelPart, msgPart); + console.warn(timePart, modulePart, levelPart, ...msg); break; case "INFO": - console.info(timePart, modulePart, levelPart, msgPart); + console.info(timePart, modulePart, levelPart, ...msg); break; case "DEBUG": if (isDev) { - console.debug(timePart, modulePart, levelPart, msgPart); + console.debug(timePart, modulePart, levelPart, ...msg); } break; default: - console.log(timePart, modulePart, levelPart, msgPart); + console.log(timePart, modulePart, levelPart, ...msg); break; } } @@ -339,8 +317,8 @@ class Logger { * @param msg Message to write * @returns {void} */ - info(module: string, msg: unknown) { - this.log(module, msg, "info"); + info(module: string, ...msg: unknown[]) { + this.log(module, "info", ...msg); } /** @@ -349,8 +327,8 @@ class Logger { * @param msg Message to write * @returns {void} */ - warn(module: string, msg: unknown) { - this.log(module, msg, "warn"); + warn(module: string, ...msg: unknown[]) { + this.log(module, "warn", ...msg); } /** @@ -359,8 +337,8 @@ class Logger { * @param msg Message to write * @returns {void} */ - error(module: string, msg: unknown) { - this.log(module, msg, "error"); + error(module: string, ...msg: unknown[]) { + this.log(module, "error", ...msg); } /** @@ -369,8 +347,8 @@ class Logger { * @param msg Message to write * @returns {void} */ - debug(module: string, msg: unknown) { - this.log(module, msg, "debug"); + debug(module: string, ...msg: unknown[]) { + this.log(module, "debug", ...msg); } /** @@ -380,14 +358,8 @@ class Logger { * @param msg The message to write * @returns {void} */ - exception(module: string, exception: unknown, msg: unknown) { - let finalMessage = exception; - - if (msg) { - finalMessage = `${msg}: ${exception}`; - } - - this.log(module, finalMessage, "error"); + exception(module: string, exception: unknown, ...msg: unknown[]) { + this.log(module, "error", ...msg, exception); } } diff --git a/test/backend-test/test-mqtt.js b/test/backend-test/test-mqtt.js index d616b12ed..921df48fc 100644 --- a/test/backend-test/test-mqtt.js +++ b/test/backend-test/test-mqtt.js @@ -10,16 +10,18 @@ const { UP, PENDING } = require("../../src/util"); * @param {string} mqttSuccessMessage the message that the monitor expects * @param {null|"keyword"|"json-query"} mqttCheckType the type of check we perform * @param {string} receivedMessage what message is received from the mqtt channel + * @param {string} monitorTopic which MQTT topic is monitored (wildcards are allowed) + * @param {string} publishTopic to which MQTT topic the message is sent * @returns {Promise} the heartbeat produced by the check */ -async function testMqtt(mqttSuccessMessage, mqttCheckType, receivedMessage) { +async function testMqtt(mqttSuccessMessage, mqttCheckType, receivedMessage, monitorTopic = "test", publishTopic = "test") { const hiveMQContainer = await new HiveMQContainer().start(); const connectionString = hiveMQContainer.getConnectionString(); const mqttMonitorType = new MqttMonitorType(); const monitor = { jsonPath: "firstProp", // always return firstProp for the json-query monitor hostname: connectionString.split(":", 2).join(":"), - mqttTopic: "test", + mqttTopic: monitorTopic, port: connectionString.split(":")[2], mqttUsername: null, mqttPassword: null, @@ -36,9 +38,9 @@ async function testMqtt(mqttSuccessMessage, mqttCheckType, receivedMessage) { const testMqttClient = mqtt.connect(hiveMQContainer.getConnectionString()); testMqttClient.on("connect", () => { - testMqttClient.subscribe("test", (error) => { + testMqttClient.subscribe(monitorTopic, (error) => { if (!error) { - testMqttClient.publish("test", receivedMessage); + testMqttClient.publish(publishTopic, receivedMessage); } }); }); @@ -53,7 +55,7 @@ async function testMqtt(mqttSuccessMessage, mqttCheckType, receivedMessage) { } describe("MqttMonitorType", { - concurrency: true, + concurrency: 4, skip: !!process.env.CI && (process.platform !== "linux" || process.arch !== "x64") }, () => { test("valid keywords (type=default)", async () => { @@ -62,11 +64,63 @@ describe("MqttMonitorType", { assert.strictEqual(heartbeat.msg, "Topic: test; Message: -> KEYWORD <-"); }); + test("valid nested topic", async () => { + const heartbeat = await testMqtt("KEYWORD", null, "-> KEYWORD <-", "a/b/c", "a/b/c"); + assert.strictEqual(heartbeat.status, UP); + assert.strictEqual(heartbeat.msg, "Topic: a/b/c; Message: -> KEYWORD <-"); + }); + + test("valid nested topic (with special chars)", async () => { + const heartbeat = await testMqtt("KEYWORD", null, "-> KEYWORD <-", "a/'/$/./*/%", "a/'/$/./*/%"); + assert.strictEqual(heartbeat.status, UP); + assert.strictEqual(heartbeat.msg, "Topic: a/'/$/./*/%; Message: -> KEYWORD <-"); + }); + + test("valid wildcard topic (with #)", async () => { + const heartbeat = await testMqtt("KEYWORD", null, "-> KEYWORD <-", "a/#", "a/b/c"); + assert.strictEqual(heartbeat.status, UP); + assert.strictEqual(heartbeat.msg, "Topic: a/b/c; Message: -> KEYWORD <-"); + }); + + test("valid wildcard topic (with +)", async () => { + const heartbeat = await testMqtt("KEYWORD", null, "-> KEYWORD <-", "a/+/c", "a/b/c"); + assert.strictEqual(heartbeat.status, UP); + assert.strictEqual(heartbeat.msg, "Topic: a/b/c; Message: -> KEYWORD <-"); + }); + + test("valid wildcard topic (with + and #)", async () => { + const heartbeat = await testMqtt("KEYWORD", null, "-> KEYWORD <-", "a/+/c/#", "a/b/c/d/e"); + assert.strictEqual(heartbeat.status, UP); + assert.strictEqual(heartbeat.msg, "Topic: a/b/c/d/e; Message: -> KEYWORD <-"); + }); + + test("invalid topic", async () => { + await assert.rejects( + testMqtt("keyword will not be checked anyway", null, "message", "x/y/z", "a/b/c"), + new Error("Timeout, Message not received"), + ); + }); + + test("invalid wildcard topic (with #)", async () => { + await assert.rejects( + testMqtt("", null, "# should be last character", "#/c", "a/b/c"), + new Error("Timeout, Message not received"), + ); + }); + + test("invalid wildcard topic (with +)", async () => { + await assert.rejects( + testMqtt("", null, "message", "x/+/z", "a/b/c"), + new Error("Timeout, Message not received"), + ); + }); + test("valid keywords (type=keyword)", async () => { const heartbeat = await testMqtt("KEYWORD", "keyword", "-> KEYWORD <-"); assert.strictEqual(heartbeat.status, UP); assert.strictEqual(heartbeat.msg, "Topic: test; Message: -> KEYWORD <-"); }); + test("invalid keywords (type=default)", async () => { await assert.rejects( testMqtt("NOT_PRESENT", null, "-> KEYWORD <-"), @@ -80,12 +134,14 @@ describe("MqttMonitorType", { new Error("Message Mismatch - Topic: test; Message: -> KEYWORD <-"), ); }); + test("valid json-query", async () => { // works because the monitors' jsonPath is hard-coded to "firstProp" const heartbeat = await testMqtt("present", "json-query", "{\"firstProp\":\"present\"}"); assert.strictEqual(heartbeat.status, UP); assert.strictEqual(heartbeat.msg, "Message received, expected value is found"); }); + test("invalid (because query fails) json-query", async () => { // works because the monitors' jsonPath is hard-coded to "firstProp" await assert.rejects( @@ -93,6 +149,7 @@ describe("MqttMonitorType", { new Error("Message received but value is not equal to expected value, value was: [undefined]"), ); }); + test("invalid (because successMessage fails) json-query", async () => { // works because the monitors' jsonPath is hard-coded to "firstProp" await assert.rejects( diff --git a/tsconfig-backend.json b/tsconfig-backend.json deleted file mode 100644 index 08be7e5bb..000000000 --- a/tsconfig-backend.json +++ /dev/null @@ -1,9 +0,0 @@ -{ - "extends": "./tsconfig.json", - "compilerOptions": { - "esModuleInterop": false - }, - "files": [ - "./src/util.ts" - ] -}