Compare commits
6 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
57f5414d79 | ||
|
|
0b174ef25a | ||
|
|
9cfa0f483d | ||
|
|
f28cba8388 | ||
|
|
ac5781d711 | ||
|
|
93fc8e463f |
53
.github/workflows/auto-test.yml
vendored
53
.github/workflows/auto-test.yml
vendored
@ -5,7 +5,7 @@ name: Auto Test
|
||||
|
||||
on:
|
||||
push:
|
||||
branches: [ master, 1.23.X, 3.0.0 ]
|
||||
branches: [ master, 1.23.X, 3.0.X ]
|
||||
pull_request:
|
||||
permissions: {}
|
||||
|
||||
@ -21,11 +21,7 @@ jobs:
|
||||
matrix:
|
||||
os: [macos-latest, ubuntu-22.04, windows-latest, ubuntu-22.04-arm]
|
||||
# See supported Node.js release schedule at https://nodejs.org/en/about/releases/
|
||||
node: [ 20, 24 ]
|
||||
# Also test non-LTS, but only on Ubuntu.
|
||||
include:
|
||||
- os: ubuntu-22.04
|
||||
node: 25
|
||||
node: [ 24, 25 ]
|
||||
|
||||
steps:
|
||||
- run: git config --global core.autocrlf false # Mainly for Windows
|
||||
@ -44,48 +40,17 @@ jobs:
|
||||
with:
|
||||
node-version: ${{ matrix.node }}
|
||||
- run: npm clean-install --no-fund
|
||||
|
||||
|
||||
- name: Rebuild native modules for ARM64
|
||||
if: matrix.os == 'ubuntu-22.04-arm'
|
||||
run: npm rebuild @louislam/sqlite3
|
||||
|
||||
|
||||
- run: npm run build
|
||||
- run: npm run test-backend
|
||||
env:
|
||||
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:
|
||||
runs-on: ubuntu-latest
|
||||
permissions:
|
||||
contents: read
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
node: [ 20, 22 ]
|
||||
# See supported Node.js release schedule at https://nodejs.org/en/about/releases/
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1
|
||||
with: { persist-credentials: false }
|
||||
|
||||
- name: Set up QEMU
|
||||
uses: docker/setup-qemu-action@c7c53464625b32c7a7e944ae62b3e17d2b600130 # v3.7.0
|
||||
with:
|
||||
platforms: linux/arm/v7
|
||||
|
||||
- name: Set up Docker Buildx
|
||||
uses: docker/setup-buildx-action@988b5a0280414f521da01fcc63a27aeeb4b104db # v3.6.1
|
||||
|
||||
- name: Test on ARMv7 using Docker with QEMU
|
||||
run: |
|
||||
docker run --rm --platform linux/arm/v7 \
|
||||
-v $PWD:/workspace \
|
||||
-w /workspace \
|
||||
arm32v7/node:${{ matrix.node }} \
|
||||
npm clean-install --no-fund --production
|
||||
|
||||
check-linters:
|
||||
runs-on: ubuntu-latest
|
||||
permissions:
|
||||
@ -103,10 +68,10 @@ jobs:
|
||||
path: node_modules
|
||||
key: node-modules-${{ runner.os }}-node${{ matrix.node }}-${{ hashFiles('**/package-lock.json') }}
|
||||
|
||||
- name: Use Node.js 20
|
||||
- name: Use Node.js 24
|
||||
uses: actions/setup-node@395ad3262231945c25e8478fd5baf05154b1d79f # v6.1.0
|
||||
with:
|
||||
node-version: 20
|
||||
node-version: 24
|
||||
- run: npm clean-install --no-fund
|
||||
- run: npm run lint:prod
|
||||
|
||||
@ -115,7 +80,7 @@ jobs:
|
||||
permissions:
|
||||
contents: read
|
||||
env:
|
||||
PLAYWRIGHT_VERSION: ~1.39.0
|
||||
PLAYWRIGHT_VERSION: ~1.56.0
|
||||
steps:
|
||||
- run: git config --global core.autocrlf false # Mainly for Windows
|
||||
- uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1
|
||||
@ -131,9 +96,9 @@ jobs:
|
||||
- name: Setup Node.js
|
||||
uses: actions/setup-node@395ad3262231945c25e8478fd5baf05154b1d79f # v6.1.0
|
||||
with:
|
||||
node-version: 22
|
||||
node-version: 24
|
||||
- run: npm clean-install --no-fund
|
||||
|
||||
|
||||
- name: Rebuild native modules for ARM64
|
||||
run: npm rebuild @louislam/sqlite3
|
||||
|
||||
|
||||
10
.github/workflows/validate.yml
vendored
10
.github/workflows/validate.yml
vendored
@ -7,6 +7,7 @@ on:
|
||||
branches:
|
||||
- master
|
||||
- 1.23.X
|
||||
- 3.0.X
|
||||
workflow_dispatch:
|
||||
permissions: {}
|
||||
|
||||
@ -33,12 +34,11 @@ jobs:
|
||||
permissions:
|
||||
contents: read
|
||||
steps:
|
||||
- uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1
|
||||
with: { persist-credentials: false }
|
||||
- name: Use Node.js 20
|
||||
uses: actions/setup-node@395ad3262231945c25e8478fd5baf05154b1d79f # v6.1.0
|
||||
- uses: actions/checkout@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
|
||||
|
||||
@ -297,7 +297,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
|
||||
|
||||
@ -480,7 +480,7 @@ We have a few procedures we follow. These are documented here:
|
||||
- <details><summary><b>Set up a Docker Builder</b> (click to expand)</summary>
|
||||
<p>
|
||||
|
||||
- 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.
|
||||
|
||||
@ -495,7 +495,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
|
||||
```
|
||||
@ -530,8 +530,7 @@ We have a few procedures we follow. These are documented here:
|
||||
|
||||
- [ ] Check all tags is fine on
|
||||
<https://hub.docker.com/r/louislam/uptime-kuma/tags>
|
||||
- [ ] 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
|
||||
|
||||
</p>
|
||||
|
||||
@ -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: "../",
|
||||
|
||||
@ -1,22 +1,15 @@
|
||||
############################################
|
||||
# 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-buster
|
||||
FROM golang:1-trixie
|
||||
WORKDIR /app
|
||||
ARG TARGETPLATFORM
|
||||
COPY ./extra/ ./extra/
|
||||
|
||||
## Switch to archive.debian.org
|
||||
RUN sed -i '/^deb/s/^/#/' /etc/apt/sources.list \
|
||||
&& echo "deb http://archive.debian.org/debian buster main contrib non-free" | tee -a /etc/apt/sources.list \
|
||||
&& echo "deb http://archive.debian.org/debian-security buster/updates main contrib non-free" | tee -a /etc/apt/sources.list \
|
||||
&& echo "deb http://archive.debian.org/debian buster-updates main contrib non-free" | tee -a /etc/apt/sources.list
|
||||
|
||||
# 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
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
# Download Apprise deb package
|
||||
FROM node:22-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:22-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 && \
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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);
|
||||
|
||||
|
||||
@ -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();
|
||||
@ -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");
|
||||
|
||||
@ -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();
|
||||
|
||||
|
||||
@ -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",
|
||||
|
||||
@ -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(" "));
|
||||
2863
package-lock.json
generated
2863
package-lock.json
generated
File diff suppressed because it is too large
Load Diff
39
package.json
39
package.json
@ -1,13 +1,13 @@
|
||||
{
|
||||
"name": "uptime-kuma",
|
||||
"version": "2.1.0-beta.1",
|
||||
"version": "3.0.0-beta.0",
|
||||
"license": "MIT",
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/louislam/uptime-kuma.git"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">= 20.4.0"
|
||||
"node": ">= 24.0.0"
|
||||
},
|
||||
"scripts": {
|
||||
"lint:js": "eslint --ext \".js,.vue\" --ignore-path .gitignore .",
|
||||
@ -19,28 +19,24 @@
|
||||
"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": "node test/test-backend.mjs",
|
||||
"test-backend-22": "cross-env TEST_BACKEND=1 node --test --test-reporter=spec \"test/backend-test/**/*.js\"",
|
||||
"test-backend-20": "cross-env TEST_BACKEND=1 node --test --test-reporter=spec test/backend-test",
|
||||
"test-backend": "cross-env TEST_BACKEND=1 node --import=tsx --test --test-reporter=spec \"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.2 && npm ci --omit dev --no-audit && npm run download-dist",
|
||||
@ -60,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"
|
||||
},
|
||||
@ -130,7 +123,7 @@
|
||||
"password-hash": "~1.2.2",
|
||||
"pg": "~8.11.3",
|
||||
"pg-connection-string": "~2.6.2",
|
||||
"playwright-core": "~1.39.0",
|
||||
"playwright-core": "~1.56.1",
|
||||
"prom-client": "~13.2.0",
|
||||
"prometheus-api-metrics": "~3.2.1",
|
||||
"promisify-child-process": "~4.1.2",
|
||||
@ -151,7 +144,9 @@
|
||||
"tough-cookie": "~4.1.3",
|
||||
"validator": "^13.15.26",
|
||||
"web-push": "^3.6.7",
|
||||
"ws": "^8.13.0"
|
||||
"tsx": "~4.20.6",
|
||||
"ws": "^8.13.0",
|
||||
"zod": "~4.1.12"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@actions/github": "~6.0.0",
|
||||
@ -159,7 +154,7 @@
|
||||
"@fortawesome/free-regular-svg-icons": "~5.15.4",
|
||||
"@fortawesome/free-solid-svg-icons": "~5.15.4",
|
||||
"@fortawesome/vue-fontawesome": "~3.0.0-5",
|
||||
"@playwright/test": "~1.39.0",
|
||||
"@playwright/test": "~1.56.1",
|
||||
"@popperjs/core": "~2.10.2",
|
||||
"@testcontainers/hivemq": "^10.13.1",
|
||||
"@testcontainers/mariadb": "^10.13.0",
|
||||
|
||||
@ -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");
|
||||
|
||||
443
src/util.js
443
src/util.js
@ -1,443 +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.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 = 1;
|
||||
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("", "debug", msg);
|
||||
}
|
||||
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, level, ...msg) {
|
||||
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;
|
||||
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;
|
||||
}
|
||||
else {
|
||||
timePart = now;
|
||||
modulePart = `[${module}]`;
|
||||
levelPart = `${level}:`;
|
||||
}
|
||||
switch (level) {
|
||||
case "ERROR":
|
||||
console.error(timePart, modulePart, levelPart, ...msg);
|
||||
break;
|
||||
case "WARN":
|
||||
console.warn(timePart, modulePart, levelPart, ...msg);
|
||||
break;
|
||||
case "INFO":
|
||||
console.info(timePart, modulePart, levelPart, ...msg);
|
||||
break;
|
||||
case "DEBUG":
|
||||
if (exports.isDev) {
|
||||
console.debug(timePart, modulePart, levelPart, ...msg);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
console.log(timePart, modulePart, levelPart, ...msg);
|
||||
break;
|
||||
}
|
||||
}
|
||||
info(module, ...msg) {
|
||||
this.log(module, "info", ...msg);
|
||||
}
|
||||
warn(module, ...msg) {
|
||||
this.log(module, "warn", ...msg);
|
||||
}
|
||||
error(module, ...msg) {
|
||||
this.log(module, "error", ...msg);
|
||||
}
|
||||
debug(module, ...msg) {
|
||||
this.log(module, "debug", ...msg);
|
||||
}
|
||||
exception(module, exception, ...msg) {
|
||||
this.log(module, "error", ...msg, exception);
|
||||
}
|
||||
}
|
||||
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 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 (Array.isArray(response)) {
|
||||
const responseStr = JSON.stringify(response);
|
||||
const truncatedResponse = responseStr.length > 25 ? responseStr.substring(0, 25) + "...]" : responseStr;
|
||||
throw new Error("JSON query returned the array " + truncatedResponse + ", but a primitive value is required. " +
|
||||
"Modify your query to return a single value via [0] to get the first element or use an aggregation like $count(), $sum() or $boolean().");
|
||||
}
|
||||
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;
|
||||
@ -1,12 +0,0 @@
|
||||
import * as childProcess from "child_process";
|
||||
|
||||
const version = parseInt(process.version.slice(1).split(".")[0]);
|
||||
|
||||
/**
|
||||
* Since Node.js 22 introduced a different "node --test" command with glob, we need to run different test commands based on the Node.js version.
|
||||
*/
|
||||
if (version < 22) {
|
||||
childProcess.execSync("npm run test-backend-20", { stdio: "inherit" });
|
||||
} else {
|
||||
childProcess.execSync("npm run test-backend-22", { stdio: "inherit" });
|
||||
}
|
||||
@ -1,9 +0,0 @@
|
||||
{
|
||||
"extends": "./tsconfig.json",
|
||||
"compilerOptions": {
|
||||
"esModuleInterop": false
|
||||
},
|
||||
"files": [
|
||||
"./src/util.ts"
|
||||
]
|
||||
}
|
||||
Loading…
Reference in New Issue
Block a user