mirror of
https://github.com/louislam/uptime-kuma.git
synced 2024-11-27 08:44:04 +00:00
Merge branch 'master' into feature/locale_on_status_page
This commit is contained in:
commit
821a70f2f3
49 changed files with 1125 additions and 299 deletions
|
@ -13,9 +13,10 @@
|
|||
"customizations": {
|
||||
"vscode": {
|
||||
"extensions": [
|
||||
"streetsidesoftware.code-spell-checker",
|
||||
"dbaeumer.vscode-eslint"
|
||||
]
|
||||
"streetsidesoftware.code-spell-checker",
|
||||
"dbaeumer.vscode-eslint",
|
||||
"GitHub.copilot-chat"
|
||||
]
|
||||
}
|
||||
},
|
||||
"forwardPorts": [3000, 3001]
|
||||
|
|
|
@ -34,8 +34,9 @@ tsconfig.json
|
|||
/ecosystem.config.js
|
||||
/extra/healthcheck.exe
|
||||
/extra/healthcheck
|
||||
extra/exe-builder
|
||||
|
||||
/extra/exe-builder
|
||||
/extra/push-examples
|
||||
/extra/uptime-kuma-push
|
||||
|
||||
### .gitignore content (commented rules are duplicated)
|
||||
|
||||
|
|
|
@ -112,6 +112,12 @@ I personally do not like something that requires so many configurations before y
|
|||
- IDE that supports [`ESLint`](https://eslint.org/) and EditorConfig (I am using [`IntelliJ IDEA`](https://www.jetbrains.com/idea/))
|
||||
- A SQLite GUI tool (f.ex. [`SQLite Expert Personal`](https://www.sqliteexpert.com/download.html) or [`DBeaver Community`](https://dbeaver.io/download/))
|
||||
|
||||
### GitHub Codespace
|
||||
|
||||
If you don't want to setup an local environment, you can now develop on GitHub Codespace, read more:
|
||||
|
||||
https://github.com/louislam/uptime-kuma/tree/master/.devcontainer
|
||||
|
||||
## Git Branches
|
||||
|
||||
- `master`: 2.X.X development. If you want to add a new feature, your pull request should base on this.
|
||||
|
@ -193,8 +199,7 @@ The data and socket logic are in `src/mixins/socket.js`.
|
|||
|
||||
## Database Migration
|
||||
|
||||
1. Create `patch-{name}.sql` in `./db/`
|
||||
2. Add your patch filename in the `patchList` list in `./server/database.js`
|
||||
See: https://github.com/louislam/uptime-kuma/tree/master/db/knex_migrations
|
||||
|
||||
## Unit Test
|
||||
|
||||
|
|
|
@ -93,7 +93,7 @@ pm2 save && pm2 startup
|
|||
|
||||
### Windows Portable (x64)
|
||||
|
||||
https://github.com/louislam/uptime-kuma/releases/download/1.23.1/uptime-kuma-windows-x64-portable-1.23.1.zip
|
||||
https://github.com/louislam/uptime-kuma/releases/download/1.23.1/uptime-kuma-windows-x64-portable-1.23.1-2.zip
|
||||
|
||||
### Advanced Installation
|
||||
|
||||
|
|
|
@ -272,10 +272,10 @@ async function createTables() {
|
|||
await knex.schema.createTable("notification", (table) => {
|
||||
table.increments("id");
|
||||
table.string("name", 255);
|
||||
table.string("config", 255); // TODO: should use TEXT!
|
||||
table.boolean("active").notNullable().defaultTo(true);
|
||||
table.integer("user_id").unsigned();
|
||||
table.boolean("is_default").notNullable().defaultTo(false);
|
||||
table.text("config");
|
||||
});
|
||||
|
||||
// monitor_notification
|
||||
|
|
3
extra/push-examples/.gitignore
vendored
Normal file
3
extra/push-examples/.gitignore
vendored
Normal file
|
@ -0,0 +1,3 @@
|
|||
java/Index.class
|
||||
csharp/index.exe
|
||||
typescript-fetch/index.js
|
10
extra/push-examples/bash-curl/index.sh
Normal file
10
extra/push-examples/bash-curl/index.sh
Normal file
|
@ -0,0 +1,10 @@
|
|||
#!/bin/bash
|
||||
# Filename: index.sh
|
||||
PUSH_URL="https://example.com/api/push/key?status=up&msg=OK&ping="
|
||||
INTERVAL=60
|
||||
|
||||
while true; do
|
||||
curl -s -o /dev/null $PUSH_URL
|
||||
echo "Pushed!"
|
||||
sleep $INTERVAL
|
||||
done
|
24
extra/push-examples/csharp/index.cs
Normal file
24
extra/push-examples/csharp/index.cs
Normal file
|
@ -0,0 +1,24 @@
|
|||
using System;
|
||||
using System.Net;
|
||||
using System.Threading;
|
||||
|
||||
/**
|
||||
* Compile: C:\Windows\Microsoft.NET\Framework\v4.0.30319\csc.exe index.cs
|
||||
* Run: index.exe
|
||||
*/
|
||||
class Index
|
||||
{
|
||||
const string PushURL = "https://example.com/api/push/key?status=up&msg=OK&ping=";
|
||||
const int Interval = 60;
|
||||
|
||||
static void Main(string[] args)
|
||||
{
|
||||
while (true)
|
||||
{
|
||||
WebClient client = new WebClient();
|
||||
client.DownloadString(PushURL);
|
||||
Console.WriteLine("Pushed!");
|
||||
Thread.Sleep(Interval * 1000);
|
||||
}
|
||||
}
|
||||
}
|
1
extra/push-examples/docker/index.sh
Normal file
1
extra/push-examples/docker/index.sh
Normal file
|
@ -0,0 +1 @@
|
|||
docker run -d --restart=always --name uptime-kuma-push louislam/uptime-kuma:push "https://example.com/api/push/key?status=up&msg=OK&ping=" 60
|
20
extra/push-examples/go/index.go
Normal file
20
extra/push-examples/go/index.go
Normal file
|
@ -0,0 +1,20 @@
|
|||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"net/http"
|
||||
"time"
|
||||
)
|
||||
|
||||
func main() {
|
||||
const PushURL = "https://example.com/api/push/key?status=up&msg=OK&ping="
|
||||
const Interval = 60
|
||||
|
||||
for {
|
||||
_, err := http.Get(PushURL)
|
||||
if err == nil {
|
||||
fmt.Println("Pushed!")
|
||||
}
|
||||
time.Sleep(Interval * time.Second)
|
||||
}
|
||||
}
|
32
extra/push-examples/java/index.java
Normal file
32
extra/push-examples/java/index.java
Normal file
|
@ -0,0 +1,32 @@
|
|||
import java.net.HttpURLConnection;
|
||||
import java.net.URL;
|
||||
|
||||
/**
|
||||
* Compile: javac index.java
|
||||
* Run: java Index
|
||||
*/
|
||||
class Index {
|
||||
|
||||
public static final String PUSH_URL = "https://example.com/api/push/key?status=up&msg=OK&ping=";
|
||||
public static final int INTERVAL = 60;
|
||||
|
||||
public static void main(String[] args) {
|
||||
while (true) {
|
||||
try {
|
||||
URL url = new URL(PUSH_URL);
|
||||
HttpURLConnection con = (HttpURLConnection) url.openConnection();
|
||||
con.setRequestMethod("GET");
|
||||
con.getResponseCode();
|
||||
con.disconnect();
|
||||
System.out.println("Pushed!");
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
try {
|
||||
Thread.sleep(INTERVAL * 1000);
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
11
extra/push-examples/javascript-fetch/index.js
Normal file
11
extra/push-examples/javascript-fetch/index.js
Normal file
|
@ -0,0 +1,11 @@
|
|||
// Supports: Node.js >= 18, Deno, Bun
|
||||
const pushURL = "https://example.com/api/push/key?status=up&msg=OK&ping=";
|
||||
const interval = 60;
|
||||
|
||||
const push = async () => {
|
||||
await fetch(pushURL);
|
||||
console.log("Pushed!");
|
||||
};
|
||||
|
||||
push();
|
||||
setInterval(push, interval * 1000);
|
5
extra/push-examples/javascript-fetch/package.json
Normal file
5
extra/push-examples/javascript-fetch/package.json
Normal file
|
@ -0,0 +1,5 @@
|
|||
{
|
||||
"scripts": {
|
||||
"start": "node index.js"
|
||||
}
|
||||
}
|
13
extra/push-examples/php/index.php
Normal file
13
extra/push-examples/php/index.php
Normal file
|
@ -0,0 +1,13 @@
|
|||
<?php
|
||||
const PUSH_URL = "https://example.com/api/push/key?status=up&msg=OK&ping=";
|
||||
const interval = 60;
|
||||
|
||||
while (true) {
|
||||
$ch = curl_init();
|
||||
curl_setopt($ch, CURLOPT_URL, PUSH_URL);
|
||||
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
|
||||
curl_exec($ch);
|
||||
curl_close($ch);
|
||||
echo "Pushed!\n";
|
||||
sleep(interval);
|
||||
}
|
9
extra/push-examples/powershell/index.ps1
Normal file
9
extra/push-examples/powershell/index.ps1
Normal file
|
@ -0,0 +1,9 @@
|
|||
# Filename: index.ps1
|
||||
$pushURL = "https://example.com/api/push/key?status=up&msg=OK&ping="
|
||||
$interval = 60
|
||||
|
||||
while ($true) {
|
||||
$res = Invoke-WebRequest -Uri $pushURL
|
||||
Write-Host "Pushed!"
|
||||
Start-Sleep -Seconds $interval
|
||||
}
|
10
extra/push-examples/python/index.py
Normal file
10
extra/push-examples/python/index.py
Normal file
|
@ -0,0 +1,10 @@
|
|||
import urllib.request
|
||||
import time
|
||||
|
||||
push_url = "https://example.com/api/push/key?status=up&msg=OK&ping="
|
||||
interval = 60
|
||||
|
||||
while True:
|
||||
urllib.request.urlopen(push_url)
|
||||
print("Pushed!\n")
|
||||
time.sleep(interval)
|
19
extra/push-examples/typescript-fetch/README.md
Normal file
19
extra/push-examples/typescript-fetch/README.md
Normal file
|
@ -0,0 +1,19 @@
|
|||
|
||||
Node.js (ts-node)
|
||||
|
||||
```bash
|
||||
ts-node index.ts
|
||||
```
|
||||
|
||||
Deno
|
||||
|
||||
```bash
|
||||
deno run --allow-net index.ts
|
||||
```
|
||||
|
||||
Bun.js
|
||||
|
||||
```bash
|
||||
bun index.ts
|
||||
```
|
||||
|
11
extra/push-examples/typescript-fetch/index.ts
Normal file
11
extra/push-examples/typescript-fetch/index.ts
Normal file
|
@ -0,0 +1,11 @@
|
|||
// Supports: Deno, Bun, Node.js >= 18 (ts-node)
|
||||
const pushURL : string = "https://example.com/api/push/key?status=up&msg=OK&ping=";
|
||||
const interval : number = 60;
|
||||
|
||||
const push = async () => {
|
||||
await fetch(pushURL);
|
||||
console.log("Pushed!");
|
||||
};
|
||||
|
||||
push();
|
||||
setInterval(push, interval * 1000);
|
13
extra/push-examples/typescript-fetch/package.json
Normal file
13
extra/push-examples/typescript-fetch/package.json
Normal file
|
@ -0,0 +1,13 @@
|
|||
{
|
||||
"scripts": {
|
||||
"ts-node": "ts-node index.ts",
|
||||
"deno": "deno run --allow-net index.ts",
|
||||
"bun": "bun index.ts"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@types/node": "^20.6.0",
|
||||
"ts-node": "^10.9.1",
|
||||
"tslib": "^2.6.2",
|
||||
"typescript": "^5.2.2"
|
||||
}
|
||||
}
|
40
extra/rebase-pr.js
Normal file
40
extra/rebase-pr.js
Normal file
|
@ -0,0 +1,40 @@
|
|||
const { execSync } = require("child_process");
|
||||
|
||||
/**
|
||||
* Rebase a PR onto such as 1.23.X or master
|
||||
* @returns {Promise<void>}
|
||||
*/
|
||||
async function main() {
|
||||
const branch = process.argv[2];
|
||||
|
||||
// Use gh to get current branch's pr id
|
||||
let currentBranchPRID = execSync("gh pr view --json number --jq \".number\"").toString().trim();
|
||||
console.log("Pr ID: ", currentBranchPRID);
|
||||
|
||||
// Use gh commend to get pr commits
|
||||
const prCommits = JSON.parse(execSync(`gh pr view ${currentBranchPRID} --json commits`).toString().trim()).commits;
|
||||
|
||||
console.log("Found commits: ", prCommits.length);
|
||||
|
||||
// Sort the commits by authoredDate
|
||||
prCommits.sort((a, b) => {
|
||||
return new Date(a.authoredDate) - new Date(b.authoredDate);
|
||||
});
|
||||
|
||||
// Get the oldest commit id
|
||||
const oldestCommitID = prCommits[0].oid;
|
||||
console.log("Oldest commit id of this pr:", oldestCommitID);
|
||||
|
||||
// Get the latest commit id of the target branch
|
||||
const latestCommitID = execSync(`git rev-parse origin/${branch}`).toString().trim();
|
||||
console.log("Latest commit id of " + branch + ":", latestCommitID);
|
||||
|
||||
// Get the original parent commit id of the oldest commit
|
||||
const originalParentCommitID = execSync(`git log --pretty=%P -n 1 "${oldestCommitID}"`).toString().trim();
|
||||
console.log("Original parent commit id of the oldest commit:", originalParentCommitID);
|
||||
|
||||
// Rebase the pr onto the target branch
|
||||
execSync(`git rebase --onto ${latestCommitID} ${originalParentCommitID}`);
|
||||
}
|
||||
|
||||
main();
|
1
extra/uptime-kuma-push/.gitignore
vendored
Normal file
1
extra/uptime-kuma-push/.gitignore
vendored
Normal file
|
@ -0,0 +1 @@
|
|||
build/*
|
18
extra/uptime-kuma-push/Dockerfile
Normal file
18
extra/uptime-kuma-push/Dockerfile
Normal file
|
@ -0,0 +1,18 @@
|
|||
FROM node AS build
|
||||
RUN useradd --create-home kuma
|
||||
USER kuma
|
||||
WORKDIR /home/kuma
|
||||
ARG TARGETPLATFORM
|
||||
COPY --chown=kuma:kuma ./build/ ./build/
|
||||
COPY --chown=kuma:kuma build.js build.js
|
||||
RUN node build.js $TARGETPLATFORM
|
||||
|
||||
FROM debian:bookworm-slim AS release
|
||||
RUN useradd --create-home kuma
|
||||
USER kuma
|
||||
WORKDIR /home/kuma
|
||||
COPY --from=build /home/kuma/uptime-kuma-push ./uptime-kuma-push
|
||||
|
||||
ENTRYPOINT ["/home/kuma/uptime-kuma-push"]
|
||||
|
||||
|
48
extra/uptime-kuma-push/build.js
Normal file
48
extra/uptime-kuma-push/build.js
Normal file
|
@ -0,0 +1,48 @@
|
|||
const fs = require("fs");
|
||||
const platform = process.argv[2];
|
||||
|
||||
if (!platform) {
|
||||
console.error("No platform??");
|
||||
process.exit(1);
|
||||
}
|
||||
|
||||
const supportedPlatforms = [
|
||||
{
|
||||
name: "linux/amd64",
|
||||
bin: "./build/uptime-kuma-push-amd64"
|
||||
},
|
||||
{
|
||||
name: "linux/arm64",
|
||||
bin: "./build/uptime-kuma-push-arm64"
|
||||
},
|
||||
{
|
||||
name: "linux/arm/v7",
|
||||
bin: "./build/uptime-kuma-push-armv7"
|
||||
}
|
||||
];
|
||||
|
||||
let platformObj = null;
|
||||
|
||||
// Check if the platform is supported
|
||||
for (let i = 0; i < supportedPlatforms.length; i++) {
|
||||
if (supportedPlatforms[i].name === platform) {
|
||||
platformObj = supportedPlatforms[i];
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (platformObj) {
|
||||
let filename = platformObj.bin;
|
||||
|
||||
if (!fs.existsSync(filename)) {
|
||||
console.error(`prebuilt: ${filename} is not found, please build it first`);
|
||||
process.exit(1);
|
||||
}
|
||||
|
||||
fs.renameSync(filename, "./uptime-kuma-push");
|
||||
process.exit(0);
|
||||
} else {
|
||||
console.error("Unsupported platform: " + platform);
|
||||
process.exit(1);
|
||||
}
|
||||
|
13
extra/uptime-kuma-push/package.json
Normal file
13
extra/uptime-kuma-push/package.json
Normal file
|
@ -0,0 +1,13 @@
|
|||
{
|
||||
"scripts": {
|
||||
"build-docker": "npm run build-all && docker buildx build --platform linux/amd64,linux/arm64,linux/arm/v7 -t louislam/uptime-kuma:push . --push --target release",
|
||||
"build-all": "npm run build-win && npm run build-linux-amd64 && npm run build-linux-arm64 && npm run build-linux-armv7 && npm run build-linux-armv6 && npm run build-linux-armv5 && npm run build-linux-riscv64",
|
||||
"build-win": "cross-env GOOS=windows GOARCH=amd64 go build -x -o ./build/uptime-kuma-push.exe uptime-kuma-push.go",
|
||||
"build-linux-amd64": "cross-env GOOS=linux GOARCH=amd64 go build -x -o ./build/uptime-kuma-push-amd64 uptime-kuma-push.go",
|
||||
"build-linux-arm64": "cross-env GOOS=linux GOARCH=arm64 go build -x -o ./build/uptime-kuma-push-arm64 uptime-kuma-push.go",
|
||||
"build-linux-armv7": "cross-env GOOS=linux GOARCH=arm GOARM=7 go build -x -o ./build/uptime-kuma-push-armv7 uptime-kuma-push.go",
|
||||
"build-linux-armv6": "cross-env GOOS=linux GOARCH=arm GOARM=6 go build -x -o ./build/uptime-kuma-push-armv6 uptime-kuma-push.go",
|
||||
"build-linux-armv5": "cross-env GOOS=linux GOARCH=arm GOARM=5 go build -x -o ./build/uptime-kuma-push-armv5 uptime-kuma-push.go",
|
||||
"build-linux-riscv64": "cross-env GOOS=linux GOARCH=riscv64 go build -x -o ./build/uptime-kuma-push-riscv64 uptime-kuma-push.go"
|
||||
}
|
||||
}
|
44
extra/uptime-kuma-push/uptime-kuma-push.go
Normal file
44
extra/uptime-kuma-push/uptime-kuma-push.go
Normal file
|
@ -0,0 +1,44 @@
|
|||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"net/http"
|
||||
os "os"
|
||||
"time"
|
||||
)
|
||||
|
||||
func main() {
|
||||
if len(os.Args) < 2 {
|
||||
fmt.Fprintln(os.Stderr, "Usage: uptime-kuma-push <url> [<interval>]")
|
||||
os.Exit(1)
|
||||
}
|
||||
|
||||
pushURL := os.Args[1]
|
||||
|
||||
var interval time.Duration
|
||||
|
||||
if len(os.Args) >= 3 {
|
||||
intervalString, err := time.ParseDuration(os.Args[2] + "s")
|
||||
interval = intervalString
|
||||
|
||||
if err != nil {
|
||||
fmt.Fprintln(os.Stderr, "Error: Invalid interval", err)
|
||||
os.Exit(1)
|
||||
}
|
||||
|
||||
} else {
|
||||
interval = 60 * time.Second
|
||||
}
|
||||
|
||||
for {
|
||||
_, err := http.Get(pushURL)
|
||||
if err == nil {
|
||||
fmt.Print("Pushed!")
|
||||
} else {
|
||||
fmt.Print("Error: ", err)
|
||||
}
|
||||
|
||||
fmt.Println(" Sleeping for", interval)
|
||||
time.Sleep(interval)
|
||||
}
|
||||
}
|
349
package-lock.json
generated
349
package-lock.json
generated
|
@ -1,12 +1,12 @@
|
|||
{
|
||||
"name": "uptime-kuma",
|
||||
"version": "1.23.1",
|
||||
"version": "1.23.2",
|
||||
"lockfileVersion": 3,
|
||||
"requires": true,
|
||||
"packages": {
|
||||
"": {
|
||||
"name": "uptime-kuma",
|
||||
"version": "1.23.1",
|
||||
"version": "1.23.2",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@grpc/grpc-js": "~1.7.3",
|
||||
|
@ -46,7 +46,8 @@
|
|||
"knex": "^2.4.2",
|
||||
"limiter": "~2.1.0",
|
||||
"liquidjs": "^10.7.0",
|
||||
"mongodb": "~4.14.0",
|
||||
"mitt": "~3.0.1",
|
||||
"mongodb": "~4.17.1",
|
||||
"mqtt": "~4.3.7",
|
||||
"mssql": "~8.1.4",
|
||||
"mysql2": "~2.3.3",
|
||||
|
@ -98,12 +99,12 @@
|
|||
"core-js": "~3.26.1",
|
||||
"cronstrue": "~2.24.0",
|
||||
"cross-env": "~7.0.3",
|
||||
"cypress": "^12.17.0",
|
||||
"cypress": "^13.2.0",
|
||||
"delay": "^5.0.0",
|
||||
"dns2": "~2.0.1",
|
||||
"dompurify": "~2.4.3",
|
||||
"eslint": "~8.14.0",
|
||||
"eslint-plugin-jsdoc": "^46.4.6",
|
||||
"eslint-plugin-jsdoc": "~46.4.6",
|
||||
"eslint-plugin-vue": "~8.7.1",
|
||||
"favico.js": "~0.3.10",
|
||||
"jest": "~29.6.1",
|
||||
|
@ -3397,9 +3398,9 @@
|
|||
}
|
||||
},
|
||||
"node_modules/@cypress/request": {
|
||||
"version": "2.88.11",
|
||||
"resolved": "https://registry.npmjs.org/@cypress/request/-/request-2.88.11.tgz",
|
||||
"integrity": "sha512-M83/wfQ1EkspjkE2lNWNV5ui2Cv7UCv1swW1DqljahbzLVWltcsexQh8jYtuS/vzFXP+HySntGM83ZXA9fn17w==",
|
||||
"version": "3.0.1",
|
||||
"resolved": "https://registry.npmjs.org/@cypress/request/-/request-3.0.1.tgz",
|
||||
"integrity": "sha512-TWivJlJi8ZDx2wGOw1dbLuHJKUYX7bWySw377nlnGOW3hP9/MUKIsEdXT/YngWxVdgNCHRBmFlBipE+5/2ZZlQ==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"aws-sign2": "~0.7.0",
|
||||
|
@ -3415,9 +3416,9 @@
|
|||
"json-stringify-safe": "~5.0.1",
|
||||
"mime-types": "~2.1.19",
|
||||
"performance-now": "^2.1.0",
|
||||
"qs": "~6.10.3",
|
||||
"qs": "6.10.4",
|
||||
"safe-buffer": "^5.1.2",
|
||||
"tough-cookie": "~2.5.0",
|
||||
"tough-cookie": "^4.1.3",
|
||||
"tunnel-agent": "^0.6.0",
|
||||
"uuid": "^8.3.2"
|
||||
},
|
||||
|
@ -4979,6 +4980,15 @@
|
|||
"node-pre-gyp": "bin/node-pre-gyp"
|
||||
}
|
||||
},
|
||||
"node_modules/@mongodb-js/saslprep": {
|
||||
"version": "1.1.0",
|
||||
"resolved": "https://registry.npmjs.org/@mongodb-js/saslprep/-/saslprep-1.1.0.tgz",
|
||||
"integrity": "sha512-Xfijy7HvfzzqiOAhAepF4SGN5e9leLkMvg/OPOF97XemjfVCYN/oWa75wnkc6mltMSTwY+XlbhWgUOJmkFspSw==",
|
||||
"optional": true,
|
||||
"dependencies": {
|
||||
"sparse-bitfield": "^3.0.3"
|
||||
}
|
||||
},
|
||||
"node_modules/@nicolo-ribaudo/eslint-scope-5-internals": {
|
||||
"version": "5.1.1-v1",
|
||||
"resolved": "https://registry.npmjs.org/@nicolo-ribaudo/eslint-scope-5-internals/-/eslint-scope-5-internals-5.1.1-v1.tgz",
|
||||
|
@ -6313,6 +6323,26 @@
|
|||
"node": ">=8"
|
||||
}
|
||||
},
|
||||
"node_modules/arraybuffer.prototype.slice": {
|
||||
"version": "1.0.2",
|
||||
"resolved": "https://registry.npmjs.org/arraybuffer.prototype.slice/-/arraybuffer.prototype.slice-1.0.2.tgz",
|
||||
"integrity": "sha512-yMBKppFur/fbHu9/6USUe03bZ4knMYiwFBcyiaXB8Go0qNehwX6inYPzK9U0NeQvGxKthcmHcaR8P5MStSRBAw==",
|
||||
"dependencies": {
|
||||
"array-buffer-byte-length": "^1.0.0",
|
||||
"call-bind": "^1.0.2",
|
||||
"define-properties": "^1.2.0",
|
||||
"es-abstract": "^1.22.1",
|
||||
"get-intrinsic": "^1.2.1",
|
||||
"is-array-buffer": "^3.0.2",
|
||||
"is-shared-array-buffer": "^1.0.2"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">= 0.4"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://github.com/sponsors/ljharb"
|
||||
}
|
||||
},
|
||||
"node_modules/arrify": {
|
||||
"version": "1.0.1",
|
||||
"resolved": "https://registry.npmjs.org/arrify/-/arrify-1.0.1.tgz",
|
||||
|
@ -8093,15 +8123,15 @@
|
|||
"dev": true
|
||||
},
|
||||
"node_modules/cypress": {
|
||||
"version": "12.17.3",
|
||||
"resolved": "https://registry.npmjs.org/cypress/-/cypress-12.17.3.tgz",
|
||||
"integrity": "sha512-/R4+xdIDjUSLYkiQfwJd630S81KIgicmQOLXotFxVXkl+eTeVO+3bHXxdi5KBh/OgC33HWN33kHX+0tQR/ZWpg==",
|
||||
"version": "13.2.0",
|
||||
"resolved": "https://registry.npmjs.org/cypress/-/cypress-13.2.0.tgz",
|
||||
"integrity": "sha512-AvDQxBydE771GTq0TR4ZUBvv9m9ffXuB/ueEtpDF/6gOcvFR96amgwSJP16Yhqw6VhmwqspT5nAGzoxxB+D89g==",
|
||||
"dev": true,
|
||||
"hasInstallScript": true,
|
||||
"dependencies": {
|
||||
"@cypress/request": "^2.88.11",
|
||||
"@cypress/request": "^3.0.0",
|
||||
"@cypress/xvfb": "^1.2.4",
|
||||
"@types/node": "^16.18.39",
|
||||
"@types/node": "^18.17.5",
|
||||
"@types/sinonjs__fake-timers": "8.1.1",
|
||||
"@types/sizzle": "^2.3.2",
|
||||
"arch": "^2.2.0",
|
||||
|
@ -8134,6 +8164,7 @@
|
|||
"minimist": "^1.2.8",
|
||||
"ospath": "^1.2.2",
|
||||
"pretty-bytes": "^5.6.0",
|
||||
"process": "^0.11.10",
|
||||
"proxy-from-env": "1.0.0",
|
||||
"request-progress": "^3.0.0",
|
||||
"semver": "^7.5.3",
|
||||
|
@ -8146,13 +8177,13 @@
|
|||
"cypress": "bin/cypress"
|
||||
},
|
||||
"engines": {
|
||||
"node": "^14.0.0 || ^16.0.0 || >=18.0.0"
|
||||
"node": "^16.0.0 || ^18.0.0 || >=20.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/cypress/node_modules/@types/node": {
|
||||
"version": "16.18.40",
|
||||
"resolved": "https://registry.npmjs.org/@types/node/-/node-16.18.40.tgz",
|
||||
"integrity": "sha512-+yno3ItTEwGxXiS/75Q/aHaa5srkpnJaH+kdkTVJ3DtJEwv92itpKbxU+FjPoh2m/5G9zmUQfrL4A4C13c+iGA==",
|
||||
"version": "18.17.18",
|
||||
"resolved": "https://registry.npmjs.org/@types/node/-/node-18.17.18.tgz",
|
||||
"integrity": "sha512-/4QOuy3ZpV7Ya1GTRz5CYSz3DgkKpyUptXuQ5PPce7uuyJAOR7r9FhkmxJfvcNUXyklbC63a+YvB3jxy7s9ngw==",
|
||||
"dev": true
|
||||
},
|
||||
"node_modules/cypress/node_modules/ansi-styles": {
|
||||
|
@ -8385,6 +8416,19 @@
|
|||
"node": ">=10"
|
||||
}
|
||||
},
|
||||
"node_modules/define-data-property": {
|
||||
"version": "1.1.0",
|
||||
"resolved": "https://registry.npmjs.org/define-data-property/-/define-data-property-1.1.0.tgz",
|
||||
"integrity": "sha512-UzGwzcjyv3OtAvolTj1GoyNYzfFR+iqbGjcnBEENZVCpM4/Ng1yhGNvS3lR/xDS74Tb2wGG9WzNSNIOS9UVb2g==",
|
||||
"dependencies": {
|
||||
"get-intrinsic": "^1.2.1",
|
||||
"gopd": "^1.0.1",
|
||||
"has-property-descriptors": "^1.0.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">= 0.4"
|
||||
}
|
||||
},
|
||||
"node_modules/define-lazy-prop": {
|
||||
"version": "2.0.0",
|
||||
"resolved": "https://registry.npmjs.org/define-lazy-prop/-/define-lazy-prop-2.0.0.tgz",
|
||||
|
@ -8813,17 +8857,18 @@
|
|||
}
|
||||
},
|
||||
"node_modules/es-abstract": {
|
||||
"version": "1.21.2",
|
||||
"resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.21.2.tgz",
|
||||
"integrity": "sha512-y/B5POM2iBnIxCiernH1G7rC9qQoM77lLIMQLuob0zhp8C56Po81+2Nj0WFKnd0pNReDTnkYryc+zhOzpEIROg==",
|
||||
"version": "1.22.2",
|
||||
"resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.22.2.tgz",
|
||||
"integrity": "sha512-YoxfFcDmhjOgWPWsV13+2RNjq1F6UQnfs+8TftwNqtzlmFzEXvlUwdrNrYeaizfjQzRMxkZ6ElWMOJIFKdVqwA==",
|
||||
"dependencies": {
|
||||
"array-buffer-byte-length": "^1.0.0",
|
||||
"arraybuffer.prototype.slice": "^1.0.2",
|
||||
"available-typed-arrays": "^1.0.5",
|
||||
"call-bind": "^1.0.2",
|
||||
"es-set-tostringtag": "^2.0.1",
|
||||
"es-to-primitive": "^1.2.1",
|
||||
"function.prototype.name": "^1.1.5",
|
||||
"get-intrinsic": "^1.2.0",
|
||||
"function.prototype.name": "^1.1.6",
|
||||
"get-intrinsic": "^1.2.1",
|
||||
"get-symbol-description": "^1.0.0",
|
||||
"globalthis": "^1.0.3",
|
||||
"gopd": "^1.0.1",
|
||||
|
@ -8838,19 +8883,23 @@
|
|||
"is-regex": "^1.1.4",
|
||||
"is-shared-array-buffer": "^1.0.2",
|
||||
"is-string": "^1.0.7",
|
||||
"is-typed-array": "^1.1.10",
|
||||
"is-typed-array": "^1.1.12",
|
||||
"is-weakref": "^1.0.2",
|
||||
"object-inspect": "^1.12.3",
|
||||
"object-keys": "^1.1.1",
|
||||
"object.assign": "^4.1.4",
|
||||
"regexp.prototype.flags": "^1.4.3",
|
||||
"regexp.prototype.flags": "^1.5.1",
|
||||
"safe-array-concat": "^1.0.1",
|
||||
"safe-regex-test": "^1.0.0",
|
||||
"string.prototype.trim": "^1.2.7",
|
||||
"string.prototype.trimend": "^1.0.6",
|
||||
"string.prototype.trimstart": "^1.0.6",
|
||||
"string.prototype.trim": "^1.2.8",
|
||||
"string.prototype.trimend": "^1.0.7",
|
||||
"string.prototype.trimstart": "^1.0.7",
|
||||
"typed-array-buffer": "^1.0.0",
|
||||
"typed-array-byte-length": "^1.0.0",
|
||||
"typed-array-byte-offset": "^1.0.0",
|
||||
"typed-array-length": "^1.0.4",
|
||||
"unbox-primitive": "^1.0.2",
|
||||
"which-typed-array": "^1.1.9"
|
||||
"which-typed-array": "^1.1.11"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">= 0.4"
|
||||
|
@ -10043,14 +10092,14 @@
|
|||
"integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A=="
|
||||
},
|
||||
"node_modules/function.prototype.name": {
|
||||
"version": "1.1.5",
|
||||
"resolved": "https://registry.npmjs.org/function.prototype.name/-/function.prototype.name-1.1.5.tgz",
|
||||
"integrity": "sha512-uN7m/BzVKQnCUF/iW8jYea67v++2u7m5UgENbHRtdDVclOUP+FMPlCNdmk0h/ysGyo2tavMJEDqJAkJdRa1vMA==",
|
||||
"version": "1.1.6",
|
||||
"resolved": "https://registry.npmjs.org/function.prototype.name/-/function.prototype.name-1.1.6.tgz",
|
||||
"integrity": "sha512-Z5kx79swU5P27WEayXM1tBi5Ze/lbIyiNgU3qyXUOf9b2rgXYyF9Dy9Cx+IQv/Lc8WCG6L82zwUPpSS9hGehIg==",
|
||||
"dependencies": {
|
||||
"call-bind": "^1.0.2",
|
||||
"define-properties": "^1.1.3",
|
||||
"es-abstract": "^1.19.0",
|
||||
"functions-have-names": "^1.2.2"
|
||||
"define-properties": "^1.2.0",
|
||||
"es-abstract": "^1.22.1",
|
||||
"functions-have-names": "^1.2.3"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">= 0.4"
|
||||
|
@ -11217,15 +11266,11 @@
|
|||
}
|
||||
},
|
||||
"node_modules/is-typed-array": {
|
||||
"version": "1.1.10",
|
||||
"resolved": "https://registry.npmjs.org/is-typed-array/-/is-typed-array-1.1.10.tgz",
|
||||
"integrity": "sha512-PJqgEHiWZvMpaFZ3uTc8kHPM4+4ADTlDniuQL7cU/UDA0Ql7F70yGfHph3cLNe+c9toaigv+DFzTJKhc2CtO6A==",
|
||||
"version": "1.1.12",
|
||||
"resolved": "https://registry.npmjs.org/is-typed-array/-/is-typed-array-1.1.12.tgz",
|
||||
"integrity": "sha512-Z14TF2JNG8Lss5/HMqt0//T9JeHXttXy5pH/DBU4vi98ozO2btxzq9MwYDZYnKwU8nRsz/+GVFVRDq3DkVuSPg==",
|
||||
"dependencies": {
|
||||
"available-typed-arrays": "^1.0.5",
|
||||
"call-bind": "^1.0.2",
|
||||
"for-each": "^0.3.3",
|
||||
"gopd": "^1.0.1",
|
||||
"has-tostringtag": "^1.0.0"
|
||||
"which-typed-array": "^1.1.11"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">= 0.4"
|
||||
|
@ -14194,6 +14239,11 @@
|
|||
"resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz",
|
||||
"integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A=="
|
||||
},
|
||||
"node_modules/mitt": {
|
||||
"version": "3.0.1",
|
||||
"resolved": "https://registry.npmjs.org/mitt/-/mitt-3.0.1.tgz",
|
||||
"integrity": "sha512-vKivATfr97l2/QBCYAkXYDbrIWPM2IIKEl7YPhjCvKlG3kE2gm+uBo6nEXK3M5/Ffh/FLpKExzOQ3JJoJGFKBw=="
|
||||
},
|
||||
"node_modules/mkdirp": {
|
||||
"version": "1.0.4",
|
||||
"resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-1.0.4.tgz",
|
||||
|
@ -14206,12 +14256,12 @@
|
|||
}
|
||||
},
|
||||
"node_modules/mongodb": {
|
||||
"version": "4.14.0",
|
||||
"resolved": "https://registry.npmjs.org/mongodb/-/mongodb-4.14.0.tgz",
|
||||
"integrity": "sha512-coGKkWXIBczZPr284tYKFLg+KbGPPLlSbdgfKAb6QqCFt5bo5VFZ50O3FFzsw4rnkqjwT6D8Qcoo9nshYKM7Mg==",
|
||||
"version": "4.17.1",
|
||||
"resolved": "https://registry.npmjs.org/mongodb/-/mongodb-4.17.1.tgz",
|
||||
"integrity": "sha512-MBuyYiPUPRTqfH2dV0ya4dcr2E5N52ocBuZ8Sgg/M030nGF78v855B3Z27mZJnp8PxjnUquEnAtjOsphgMZOlQ==",
|
||||
"dependencies": {
|
||||
"bson": "^4.7.0",
|
||||
"mongodb-connection-string-url": "^2.5.4",
|
||||
"bson": "^4.7.2",
|
||||
"mongodb-connection-string-url": "^2.6.0",
|
||||
"socks": "^2.7.1"
|
||||
},
|
||||
"engines": {
|
||||
|
@ -14219,7 +14269,7 @@
|
|||
},
|
||||
"optionalDependencies": {
|
||||
"@aws-sdk/credential-providers": "^3.186.0",
|
||||
"saslprep": "^1.0.3"
|
||||
"@mongodb-js/saslprep": "^1.1.0"
|
||||
}
|
||||
},
|
||||
"node_modules/mongodb-connection-string-url": {
|
||||
|
@ -15857,6 +15907,12 @@
|
|||
"url": "https://github.com/sponsors/ljharb"
|
||||
}
|
||||
},
|
||||
"node_modules/querystringify": {
|
||||
"version": "2.2.0",
|
||||
"resolved": "https://registry.npmjs.org/querystringify/-/querystringify-2.2.0.tgz",
|
||||
"integrity": "sha512-FIqgj2EUvTa7R50u0rGsyTftzjYmv/a3hO345bZNrqabNqjtgiDMgmo4mkUjd+nzU5oF3dClKqFIPUKybUyqoQ==",
|
||||
"dev": true
|
||||
},
|
||||
"node_modules/queue-microtask": {
|
||||
"version": "1.2.3",
|
||||
"resolved": "https://registry.npmjs.org/queue-microtask/-/queue-microtask-1.2.3.tgz",
|
||||
|
@ -16238,13 +16294,13 @@
|
|||
}
|
||||
},
|
||||
"node_modules/regexp.prototype.flags": {
|
||||
"version": "1.5.0",
|
||||
"resolved": "https://registry.npmjs.org/regexp.prototype.flags/-/regexp.prototype.flags-1.5.0.tgz",
|
||||
"integrity": "sha512-0SutC3pNudRKgquxGoRGIz946MZVHqbNfPjBdxeOhBrdgDKlRoXmYLQN9xRbrR09ZXWeGAdPuif7egofn6v5LA==",
|
||||
"version": "1.5.1",
|
||||
"resolved": "https://registry.npmjs.org/regexp.prototype.flags/-/regexp.prototype.flags-1.5.1.tgz",
|
||||
"integrity": "sha512-sy6TXMN+hnP/wMy+ISxg3krXx7BAtWVO4UouuCN/ziM9UEne0euamVNafDfvC83bRNr95y0V5iijeDQFUNpvrg==",
|
||||
"dependencies": {
|
||||
"call-bind": "^1.0.2",
|
||||
"define-properties": "^1.2.0",
|
||||
"functions-have-names": "^1.2.3"
|
||||
"set-function-name": "^2.0.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">= 0.4"
|
||||
|
@ -16340,6 +16396,12 @@
|
|||
"integrity": "sha512-NKN5kMDylKuldxYLSUfrbo5Tuzh4hd+2E8NPPX02mZtn1VuREQToYe/ZdlJy+J3uCpfaiGF05e7B8W0iXbQHmg==",
|
||||
"dev": true
|
||||
},
|
||||
"node_modules/requires-port": {
|
||||
"version": "1.0.0",
|
||||
"resolved": "https://registry.npmjs.org/requires-port/-/requires-port-1.0.0.tgz",
|
||||
"integrity": "sha512-KigOCHcocU3XODJxsu8i/j8T9tzT4adHiecwORRQ0ZZFcp7ahwXuRU1m+yuO90C5ZUyGeGfocHDI14M3L3yDAQ==",
|
||||
"dev": true
|
||||
},
|
||||
"node_modules/resolve": {
|
||||
"version": "1.22.2",
|
||||
"resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.2.tgz",
|
||||
|
@ -16630,6 +16692,28 @@
|
|||
"tslib": "^2.1.0"
|
||||
}
|
||||
},
|
||||
"node_modules/safe-array-concat": {
|
||||
"version": "1.0.1",
|
||||
"resolved": "https://registry.npmjs.org/safe-array-concat/-/safe-array-concat-1.0.1.tgz",
|
||||
"integrity": "sha512-6XbUAseYE2KtOuGueyeobCySj9L4+66Tn6KQMOPQJrAJEowYKW/YR/MGJZl7FdydUdaFu4LYyDZjxf4/Nmo23Q==",
|
||||
"dependencies": {
|
||||
"call-bind": "^1.0.2",
|
||||
"get-intrinsic": "^1.2.1",
|
||||
"has-symbols": "^1.0.3",
|
||||
"isarray": "^2.0.5"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=0.4"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://github.com/sponsors/ljharb"
|
||||
}
|
||||
},
|
||||
"node_modules/safe-array-concat/node_modules/isarray": {
|
||||
"version": "2.0.5",
|
||||
"resolved": "https://registry.npmjs.org/isarray/-/isarray-2.0.5.tgz",
|
||||
"integrity": "sha512-xHjhDr3cNBK0BzdUJSPXZntQUx/mwMS5Rw4A7lPJ90XGAO6ISP/ePDNuo0vhqOZU+UD5JoodwCAAoZQd3FeAKw=="
|
||||
},
|
||||
"node_modules/safe-buffer": {
|
||||
"version": "5.1.2",
|
||||
"resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz",
|
||||
|
@ -16653,18 +16737,6 @@
|
|||
"resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz",
|
||||
"integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg=="
|
||||
},
|
||||
"node_modules/saslprep": {
|
||||
"version": "1.0.3",
|
||||
"resolved": "https://registry.npmjs.org/saslprep/-/saslprep-1.0.3.tgz",
|
||||
"integrity": "sha512-/MY/PEMbk2SuY5sScONwhUDsV2p77Znkb/q3nSVstq/yQzYJOH/Azh29p9oJLsl3LnQwSvZDKagDGBsBwSooag==",
|
||||
"optional": true,
|
||||
"dependencies": {
|
||||
"sparse-bitfield": "^3.0.3"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=6"
|
||||
}
|
||||
},
|
||||
"node_modules/sass": {
|
||||
"version": "1.42.1",
|
||||
"resolved": "https://registry.npmjs.org/sass/-/sass-1.42.1.tgz",
|
||||
|
@ -16801,6 +16873,19 @@
|
|||
"resolved": "https://registry.npmjs.org/set-blocking/-/set-blocking-2.0.0.tgz",
|
||||
"integrity": "sha512-KiKBS8AnWGEyLzofFfmvKwpdPzqiy16LvQfK3yv/fVH7Bj13/wl3JSR1J+rfgRE9q7xUJK4qvgS8raSOeLUehw=="
|
||||
},
|
||||
"node_modules/set-function-name": {
|
||||
"version": "2.0.1",
|
||||
"resolved": "https://registry.npmjs.org/set-function-name/-/set-function-name-2.0.1.tgz",
|
||||
"integrity": "sha512-tMNCiqYVkXIZgc2Hnoy2IvC/f8ezc5koaRFkCjrpWzGpCd3qbZXPzVy9MAZzK1ch/X0jvSkojys3oqJN0qCmdA==",
|
||||
"dependencies": {
|
||||
"define-data-property": "^1.0.1",
|
||||
"functions-have-names": "^1.2.3",
|
||||
"has-property-descriptors": "^1.0.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">= 0.4"
|
||||
}
|
||||
},
|
||||
"node_modules/setprototypeof": {
|
||||
"version": "1.2.0",
|
||||
"resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.2.0.tgz",
|
||||
|
@ -17329,15 +17414,15 @@
|
|||
}
|
||||
},
|
||||
"node_modules/string.prototype.replaceall": {
|
||||
"version": "1.0.7",
|
||||
"resolved": "https://registry.npmjs.org/string.prototype.replaceall/-/string.prototype.replaceall-1.0.7.tgz",
|
||||
"integrity": "sha512-xB2WV2GlSCSJT5dMGdhdH1noMPiAB91guiepwTYyWY9/0Vq/TZ7RPmnOSUGAEvry08QIK7EMr28aAii+9jC6kw==",
|
||||
"version": "1.0.8",
|
||||
"resolved": "https://registry.npmjs.org/string.prototype.replaceall/-/string.prototype.replaceall-1.0.8.tgz",
|
||||
"integrity": "sha512-MmCXb9980obcnmbEd3guqVl6lXTxpP28zASfgAlAhlBMw5XehQeSKsdIWlAYtLxp/1GtALwex+2HyoIQtaLQwQ==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"call-bind": "^1.0.2",
|
||||
"define-properties": "^1.1.4",
|
||||
"es-abstract": "^1.20.4",
|
||||
"get-intrinsic": "^1.1.3",
|
||||
"define-properties": "^1.2.0",
|
||||
"es-abstract": "^1.22.1",
|
||||
"get-intrinsic": "^1.2.1",
|
||||
"has-symbols": "^1.0.3",
|
||||
"is-regex": "^1.1.4"
|
||||
},
|
||||
|
@ -17346,13 +17431,13 @@
|
|||
}
|
||||
},
|
||||
"node_modules/string.prototype.trim": {
|
||||
"version": "1.2.7",
|
||||
"resolved": "https://registry.npmjs.org/string.prototype.trim/-/string.prototype.trim-1.2.7.tgz",
|
||||
"integrity": "sha512-p6TmeT1T3411M8Cgg9wBTMRtY2q9+PNy9EV1i2lIXUN/btt763oIfxwN3RR8VU6wHX8j/1CFy0L+YuThm6bgOg==",
|
||||
"version": "1.2.8",
|
||||
"resolved": "https://registry.npmjs.org/string.prototype.trim/-/string.prototype.trim-1.2.8.tgz",
|
||||
"integrity": "sha512-lfjY4HcixfQXOfaqCvcBuOIapyaroTXhbkfJN3gcB1OtyupngWK4sEET9Knd0cXd28kTUqu/kHoV4HKSJdnjiQ==",
|
||||
"dependencies": {
|
||||
"call-bind": "^1.0.2",
|
||||
"define-properties": "^1.1.4",
|
||||
"es-abstract": "^1.20.4"
|
||||
"define-properties": "^1.2.0",
|
||||
"es-abstract": "^1.22.1"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">= 0.4"
|
||||
|
@ -17362,26 +17447,26 @@
|
|||
}
|
||||
},
|
||||
"node_modules/string.prototype.trimend": {
|
||||
"version": "1.0.6",
|
||||
"resolved": "https://registry.npmjs.org/string.prototype.trimend/-/string.prototype.trimend-1.0.6.tgz",
|
||||
"integrity": "sha512-JySq+4mrPf9EsDBEDYMOb/lM7XQLulwg5R/m1r0PXEFqrV0qHvl58sdTilSXtKOflCsK2E8jxf+GKC0T07RWwQ==",
|
||||
"version": "1.0.7",
|
||||
"resolved": "https://registry.npmjs.org/string.prototype.trimend/-/string.prototype.trimend-1.0.7.tgz",
|
||||
"integrity": "sha512-Ni79DqeB72ZFq1uH/L6zJ+DKZTkOtPIHovb3YZHQViE+HDouuU4mBrLOLDn5Dde3RF8qw5qVETEjhu9locMLvA==",
|
||||
"dependencies": {
|
||||
"call-bind": "^1.0.2",
|
||||
"define-properties": "^1.1.4",
|
||||
"es-abstract": "^1.20.4"
|
||||
"define-properties": "^1.2.0",
|
||||
"es-abstract": "^1.22.1"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://github.com/sponsors/ljharb"
|
||||
}
|
||||
},
|
||||
"node_modules/string.prototype.trimstart": {
|
||||
"version": "1.0.6",
|
||||
"resolved": "https://registry.npmjs.org/string.prototype.trimstart/-/string.prototype.trimstart-1.0.6.tgz",
|
||||
"integrity": "sha512-omqjMDaY92pbn5HOX7f9IccLA+U1tA9GvtU4JrodiXFfYB7jPzzHpRzpglLAjtUV6bB557zwClJezTqnAiYnQA==",
|
||||
"version": "1.0.7",
|
||||
"resolved": "https://registry.npmjs.org/string.prototype.trimstart/-/string.prototype.trimstart-1.0.7.tgz",
|
||||
"integrity": "sha512-NGhtDFu3jCEm7B4Fy0DpLewdJQOZcQ0rGbwQ/+stjnrp2i+rlKeCvos9hOIeCmqwratM47OBxY7uFZzjxHXmrg==",
|
||||
"dependencies": {
|
||||
"call-bind": "^1.0.2",
|
||||
"define-properties": "^1.1.4",
|
||||
"es-abstract": "^1.20.4"
|
||||
"define-properties": "^1.2.0",
|
||||
"es-abstract": "^1.22.1"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://github.com/sponsors/ljharb"
|
||||
|
@ -18041,16 +18126,27 @@
|
|||
}
|
||||
},
|
||||
"node_modules/tough-cookie": {
|
||||
"version": "2.5.0",
|
||||
"resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-2.5.0.tgz",
|
||||
"integrity": "sha512-nlLsUzgm1kfLXSXfRZMc1KLAugd4hqJHDTvc2hDIwS3mZAfMEuMbc03SujMF+GEcpaX/qboeycw6iO8JwVv2+g==",
|
||||
"version": "4.1.3",
|
||||
"resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-4.1.3.tgz",
|
||||
"integrity": "sha512-aX/y5pVRkfRnfmuX+OdbSdXvPe6ieKX/G2s7e98f4poJHnqH3281gDPm/metm6E/WRamfx7WC4HUqkWHfQHprw==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"psl": "^1.1.28",
|
||||
"punycode": "^2.1.1"
|
||||
"psl": "^1.1.33",
|
||||
"punycode": "^2.1.1",
|
||||
"universalify": "^0.2.0",
|
||||
"url-parse": "^1.5.3"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=0.8"
|
||||
"node": ">=6"
|
||||
}
|
||||
},
|
||||
"node_modules/tough-cookie/node_modules/universalify": {
|
||||
"version": "0.2.0",
|
||||
"resolved": "https://registry.npmjs.org/universalify/-/universalify-0.2.0.tgz",
|
||||
"integrity": "sha512-CJ1QgKmNg3CwvAv/kOFmtnEN05f0D/cn9QntgNOQlQF9dgvVTHj3t+8JPdjqawCHk7V/KA+fbUqzZ9XWhcqPUg==",
|
||||
"dev": true,
|
||||
"engines": {
|
||||
"node": ">= 4.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/tr46": {
|
||||
|
@ -18163,6 +18259,54 @@
|
|||
"node": ">= 0.6"
|
||||
}
|
||||
},
|
||||
"node_modules/typed-array-buffer": {
|
||||
"version": "1.0.0",
|
||||
"resolved": "https://registry.npmjs.org/typed-array-buffer/-/typed-array-buffer-1.0.0.tgz",
|
||||
"integrity": "sha512-Y8KTSIglk9OZEr8zywiIHG/kmQ7KWyjseXs1CbSo8vC42w7hg2HgYTxSWwP0+is7bWDc1H+Fo026CpHFwm8tkw==",
|
||||
"dependencies": {
|
||||
"call-bind": "^1.0.2",
|
||||
"get-intrinsic": "^1.2.1",
|
||||
"is-typed-array": "^1.1.10"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">= 0.4"
|
||||
}
|
||||
},
|
||||
"node_modules/typed-array-byte-length": {
|
||||
"version": "1.0.0",
|
||||
"resolved": "https://registry.npmjs.org/typed-array-byte-length/-/typed-array-byte-length-1.0.0.tgz",
|
||||
"integrity": "sha512-Or/+kvLxNpeQ9DtSydonMxCx+9ZXOswtwJn17SNLvhptaXYDJvkFFP5zbfU/uLmvnBJlI4yrnXRxpdWH/M5tNA==",
|
||||
"dependencies": {
|
||||
"call-bind": "^1.0.2",
|
||||
"for-each": "^0.3.3",
|
||||
"has-proto": "^1.0.1",
|
||||
"is-typed-array": "^1.1.10"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">= 0.4"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://github.com/sponsors/ljharb"
|
||||
}
|
||||
},
|
||||
"node_modules/typed-array-byte-offset": {
|
||||
"version": "1.0.0",
|
||||
"resolved": "https://registry.npmjs.org/typed-array-byte-offset/-/typed-array-byte-offset-1.0.0.tgz",
|
||||
"integrity": "sha512-RD97prjEt9EL8YgAgpOkf3O4IF9lhJFr9g0htQkm0rchFp/Vx7LW5Q8fSXXub7BXAODyUQohRMyOc3faCPd0hg==",
|
||||
"dependencies": {
|
||||
"available-typed-arrays": "^1.0.5",
|
||||
"call-bind": "^1.0.2",
|
||||
"for-each": "^0.3.3",
|
||||
"has-proto": "^1.0.1",
|
||||
"is-typed-array": "^1.1.10"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">= 0.4"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://github.com/sponsors/ljharb"
|
||||
}
|
||||
},
|
||||
"node_modules/typed-array-length": {
|
||||
"version": "1.0.4",
|
||||
"resolved": "https://registry.npmjs.org/typed-array-length/-/typed-array-length-1.0.4.tgz",
|
||||
|
@ -18342,6 +18486,16 @@
|
|||
"punycode": "^2.1.0"
|
||||
}
|
||||
},
|
||||
"node_modules/url-parse": {
|
||||
"version": "1.5.10",
|
||||
"resolved": "https://registry.npmjs.org/url-parse/-/url-parse-1.5.10.tgz",
|
||||
"integrity": "sha512-WypcfiRhfeUP9vvF0j6rw0J3hrWrw6iZv3+22h6iRMJ/8z1Tj6XfLP4DsUix5MhMPnXpiHDoKyoZ/bdCkwBCiQ==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"querystringify": "^2.1.1",
|
||||
"requires-port": "^1.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/util-deprecate": {
|
||||
"version": "1.0.2",
|
||||
"resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz",
|
||||
|
@ -18955,16 +19109,15 @@
|
|||
"dev": true
|
||||
},
|
||||
"node_modules/which-typed-array": {
|
||||
"version": "1.1.9",
|
||||
"resolved": "https://registry.npmjs.org/which-typed-array/-/which-typed-array-1.1.9.tgz",
|
||||
"integrity": "sha512-w9c4xkx6mPidwp7180ckYWfMmvxpjlZuIudNtDf4N/tTAUB8VJbX25qZoAsrtGuYNnGw3pa0AXgbGKRB8/EceA==",
|
||||
"version": "1.1.11",
|
||||
"resolved": "https://registry.npmjs.org/which-typed-array/-/which-typed-array-1.1.11.tgz",
|
||||
"integrity": "sha512-qe9UWWpkeG5yzZ0tNYxDmd7vo58HDBc39mZ0xWWpolAGADdFOzkfamWLDxkOWcvHQKVmdTyQdLD4NOfjLWTKew==",
|
||||
"dependencies": {
|
||||
"available-typed-arrays": "^1.0.5",
|
||||
"call-bind": "^1.0.2",
|
||||
"for-each": "^0.3.3",
|
||||
"gopd": "^1.0.1",
|
||||
"has-tostringtag": "^1.0.0",
|
||||
"is-typed-array": "^1.1.10"
|
||||
"has-tostringtag": "^1.0.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">= 0.4"
|
||||
|
|
15
package.json
15
package.json
|
@ -1,6 +1,6 @@
|
|||
{
|
||||
"name": "uptime-kuma",
|
||||
"version": "1.23.1",
|
||||
"version": "1.23.2",
|
||||
"license": "MIT",
|
||||
"repository": {
|
||||
"type": "git",
|
||||
|
@ -42,7 +42,7 @@
|
|||
"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",
|
||||
"upload-artifacts": "docker buildx build -f docker/dockerfile --platform linux/amd64 -t louislam/uptime-kuma:upload-artifact --build-arg VERSION --build-arg GITHUB_TOKEN --target upload-artifact . --progress plain",
|
||||
"setup": "git checkout 1.23.1 && npm ci --production && npm run download-dist",
|
||||
"setup": "git checkout 1.23.2 && npm ci --production && 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",
|
||||
|
@ -57,6 +57,7 @@
|
|||
"test-install-script-ubuntu1604": "npm run compile-install-script && docker build --progress plain -f test/test_install_script/ubuntu1604.dockerfile .",
|
||||
"simple-dns-server": "node extra/simple-dns-server.js",
|
||||
"simple-mqtt-server": "node extra/simple-mqtt-server.js",
|
||||
"simple-mongo": "docker run --rm -p 27017:27017 mongo",
|
||||
"update-language-files": "cd extra/update-language-files && node index.js && cross-env-shell eslint ../../src/languages/$npm_config_language.js --fix",
|
||||
"release-final": "node ./extra/test-docker.js && node extra/update-version.js && npm run build-docker && node ./extra/press-any-key.js && npm run upload-artifacts && node ./extra/update-wiki-version.js",
|
||||
"release-beta": "node ./extra/test-docker.js && node extra/beta/update-version.js && npm run build && node ./extra/env2arg.js docker buildx build -f docker/dockerfile --platform linux/amd64,linux/arm64,linux/arm/v7 -t louislam/uptime-kuma:$VERSION -t louislam/uptime-kuma:beta . --target release --push && node ./extra/press-any-key.js && npm run upload-artifacts",
|
||||
|
@ -71,7 +72,8 @@
|
|||
"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",
|
||||
"start-dev-container": "cd docker && docker-compose -f docker-compose-dev.yml up --force-recreate"
|
||||
"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"
|
||||
},
|
||||
"dependencies": {
|
||||
"@grpc/grpc-js": "~1.7.3",
|
||||
|
@ -111,7 +113,8 @@
|
|||
"knex": "^2.4.2",
|
||||
"limiter": "~2.1.0",
|
||||
"liquidjs": "^10.7.0",
|
||||
"mongodb": "~4.14.0",
|
||||
"mitt": "~3.0.1",
|
||||
"mongodb": "~4.17.1",
|
||||
"mqtt": "~4.3.7",
|
||||
"mssql": "~8.1.4",
|
||||
"mysql2": "~2.3.3",
|
||||
|
@ -163,12 +166,12 @@
|
|||
"core-js": "~3.26.1",
|
||||
"cronstrue": "~2.24.0",
|
||||
"cross-env": "~7.0.3",
|
||||
"cypress": "^12.17.0",
|
||||
"cypress": "^13.2.0",
|
||||
"delay": "^5.0.0",
|
||||
"dns2": "~2.0.1",
|
||||
"dompurify": "~2.4.3",
|
||||
"eslint": "~8.14.0",
|
||||
"eslint-plugin-jsdoc": "^46.4.6",
|
||||
"eslint-plugin-jsdoc": "~46.4.6",
|
||||
"eslint-plugin-vue": "~8.7.1",
|
||||
"favico.js": "~0.3.10",
|
||||
"jest": "~29.6.1",
|
||||
|
|
|
@ -358,8 +358,14 @@ class Database {
|
|||
directory: Database.knexMigrationsPath,
|
||||
});
|
||||
} catch (e) {
|
||||
log.error("db", "Database migration failed");
|
||||
throw e;
|
||||
// Allow missing patch files for downgrade or testing pr.
|
||||
if (e.message.includes("the following files are missing:")) {
|
||||
log.warn("db", e.message);
|
||||
log.warn("db", "Database migration failed, you may be downgrading Uptime Kuma.");
|
||||
} else {
|
||||
log.error("db", "Database migration failed");
|
||||
throw e;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -56,7 +56,7 @@ class Monitor extends BeanModel {
|
|||
obj.tags = await this.getTags();
|
||||
}
|
||||
|
||||
if (certExpiry && this.type === "http") {
|
||||
if (certExpiry && this.type === "http" && this.getURLProtocol() === "https:") {
|
||||
const { certExpiryDaysRemaining, validCert } = await this.getCertExpiry(this.id);
|
||||
obj.certExpiryDaysRemaining = certExpiryDaysRemaining;
|
||||
obj.validCert = validCert;
|
||||
|
@ -948,7 +948,15 @@ class Monitor extends BeanModel {
|
|||
|
||||
if (! this.isStop) {
|
||||
log.debug("monitor", `[${this.name}] SetTimeout for next check.`);
|
||||
this.heartbeatInterval = setTimeout(safeBeat, beatInterval * 1000);
|
||||
|
||||
let intervalRemainingMs = Math.max(
|
||||
1,
|
||||
beatInterval * 1000 - dayjs().diff(dayjs.utc(bean.time))
|
||||
);
|
||||
|
||||
log.debug("monitor", `[${this.name}] Next heartbeat in: ${intervalRemainingMs}ms`);
|
||||
|
||||
this.heartbeatInterval = setTimeout(safeBeat, intervalRemainingMs);
|
||||
} else {
|
||||
log.info("monitor", `[${this.name}] isStop = true, no next check.`);
|
||||
}
|
||||
|
@ -1057,6 +1065,19 @@ class Monitor extends BeanModel {
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Example: http: or https:
|
||||
* @returns {(null|string)}
|
||||
*/
|
||||
getURLProtocol() {
|
||||
const url = this.getUrl();
|
||||
if (url) {
|
||||
return this.getUrl().protocol;
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Store TLS info to database
|
||||
* @param {object} checkCertificateResult Certificate to update
|
||||
|
|
|
@ -46,8 +46,7 @@ class Bark extends NotificationProvider {
|
|||
}
|
||||
|
||||
/**
|
||||
* Add additional parameter for better on device styles (iOS 15
|
||||
* optimized)
|
||||
* Add additional parameter for Bark v1 endpoints
|
||||
* @param {BeanModel} notification Notification to send
|
||||
* @param {string} postUrl URL to append parameters to
|
||||
* @returns {string} Additional URL parameters
|
||||
|
@ -96,12 +95,23 @@ class Bark extends NotificationProvider {
|
|||
* @returns {string} Success message
|
||||
*/
|
||||
async postNotification(notification, title, subtitle, endpoint) {
|
||||
// url encode title and subtitle
|
||||
title = encodeURIComponent(title);
|
||||
subtitle = encodeURIComponent(subtitle);
|
||||
let postUrl = endpoint + "/" + title + "/" + subtitle;
|
||||
postUrl = this.appendAdditionalParameters(notification, postUrl);
|
||||
let result = await axios.get(postUrl);
|
||||
let result;
|
||||
if (notification.apiVersion === "v1" || notification.apiVersion == null) {
|
||||
// url encode title and subtitle
|
||||
title = encodeURIComponent(title);
|
||||
subtitle = encodeURIComponent(subtitle);
|
||||
let postUrl = endpoint + "/" + title + "/" + subtitle;
|
||||
postUrl = this.appendAdditionalParameters(notification, postUrl);
|
||||
result = await axios.get(postUrl);
|
||||
} else {
|
||||
result = await axios.post(`${endpoint}/push`, {
|
||||
title,
|
||||
body: subtitle,
|
||||
icon: barkNotificationAvatar,
|
||||
sound: notification.barkSound || "telegraph", // default sound is telegraph
|
||||
group: notification.barkGroup || "UptimeKuma", // default group is UptimeKuma
|
||||
});
|
||||
}
|
||||
this.checkResult(result);
|
||||
if (result.statusText != null) {
|
||||
return "Bark notification succeed: " + result.statusText;
|
||||
|
|
|
@ -28,11 +28,7 @@ class Telegram extends NotificationProvider {
|
|||
return okMsg;
|
||||
|
||||
} catch (error) {
|
||||
if (error.response && error.response.data && error.response.data.description) {
|
||||
throw new Error(error.response.data.description);
|
||||
} else {
|
||||
throw new Error(error.message);
|
||||
}
|
||||
this.throwGeneralAxiosError(error);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
156
server/server.js
156
server/server.js
|
@ -51,11 +51,6 @@ if (! process.env.NODE_ENV) {
|
|||
log.info("server", "Node Env: " + process.env.NODE_ENV);
|
||||
log.info("server", "Inside Container: " + (process.env.UPTIME_KUMA_IS_CONTAINER === "1"));
|
||||
|
||||
log.info("server", "Importing Node libraries");
|
||||
const fs = require("fs");
|
||||
|
||||
log.info("server", "Importing 3rd-party libraries");
|
||||
|
||||
log.debug("server", "Importing express");
|
||||
const express = require("express");
|
||||
const expressStaticGzip = require("express-static-gzip");
|
||||
|
@ -144,7 +139,7 @@ if (config.demoMode) {
|
|||
}
|
||||
|
||||
// Must be after io instantiation
|
||||
const { sendNotificationList, sendHeartbeatList, sendImportantHeartbeatList, sendInfo, sendProxyList, sendDockerHostList, sendAPIKeyList } = require("./client");
|
||||
const { sendNotificationList, sendHeartbeatList, sendInfo, sendProxyList, sendDockerHostList, sendAPIKeyList } = require("./client");
|
||||
const { statusPageSocketHandler } = require("./socket-handlers/status-page-socket-handler");
|
||||
const databaseSocketHandler = require("./socket-handlers/database-socket-handler");
|
||||
const TwoFA = require("./2fa");
|
||||
|
@ -347,7 +342,8 @@ let needSetup = false;
|
|||
|
||||
callback({
|
||||
ok: false,
|
||||
msg: "The user is inactive or deleted.",
|
||||
msg: "authUserInactiveOrDeleted",
|
||||
msgi18n: true,
|
||||
});
|
||||
}
|
||||
} catch (error) {
|
||||
|
@ -356,7 +352,8 @@ let needSetup = false;
|
|||
|
||||
callback({
|
||||
ok: false,
|
||||
msg: "Invalid token.",
|
||||
msg: "authInvalidToken",
|
||||
msgi18n: true,
|
||||
});
|
||||
}
|
||||
|
||||
|
@ -432,7 +429,8 @@ let needSetup = false;
|
|||
|
||||
callback({
|
||||
ok: false,
|
||||
msg: "Invalid Token!",
|
||||
msg: "authInvalidToken",
|
||||
msgi18n: true,
|
||||
});
|
||||
}
|
||||
}
|
||||
|
@ -442,7 +440,8 @@ let needSetup = false;
|
|||
|
||||
callback({
|
||||
ok: false,
|
||||
msg: "Incorrect username or password.",
|
||||
msg: "authIncorrectCreds",
|
||||
msgi18n: true,
|
||||
});
|
||||
}
|
||||
|
||||
|
@ -498,7 +497,8 @@ let needSetup = false;
|
|||
} else {
|
||||
callback({
|
||||
ok: false,
|
||||
msg: "2FA is already enabled.",
|
||||
msg: "2faAlreadyEnabled",
|
||||
msgi18n: true,
|
||||
});
|
||||
}
|
||||
} catch (error) {
|
||||
|
@ -528,7 +528,8 @@ let needSetup = false;
|
|||
|
||||
callback({
|
||||
ok: true,
|
||||
msg: "2FA Enabled.",
|
||||
msg: "2faEnabled",
|
||||
msgi18n: true,
|
||||
});
|
||||
} catch (error) {
|
||||
|
||||
|
@ -557,7 +558,8 @@ let needSetup = false;
|
|||
|
||||
callback({
|
||||
ok: true,
|
||||
msg: "2FA Disabled.",
|
||||
msg: "2faDisabled",
|
||||
msgi18n: true,
|
||||
});
|
||||
} catch (error) {
|
||||
|
||||
|
@ -589,7 +591,8 @@ let needSetup = false;
|
|||
} else {
|
||||
callback({
|
||||
ok: false,
|
||||
msg: "Invalid Token.",
|
||||
msg: "authInvalidToken",
|
||||
msgi18n: true,
|
||||
valid: false,
|
||||
});
|
||||
}
|
||||
|
@ -652,7 +655,8 @@ let needSetup = false;
|
|||
|
||||
callback({
|
||||
ok: true,
|
||||
msg: "Added Successfully.",
|
||||
msg: "successAdded",
|
||||
msgi18n: true,
|
||||
});
|
||||
|
||||
} catch (e) {
|
||||
|
@ -705,7 +709,8 @@ let needSetup = false;
|
|||
|
||||
callback({
|
||||
ok: true,
|
||||
msg: "Added Successfully.",
|
||||
msg: "successAdded",
|
||||
msgi18n: true,
|
||||
monitorID: bean.id,
|
||||
});
|
||||
|
||||
|
@ -761,11 +766,11 @@ let needSetup = false;
|
|||
bean.basic_auth_user = monitor.basic_auth_user;
|
||||
bean.basic_auth_pass = monitor.basic_auth_pass;
|
||||
bean.timeout = monitor.timeout;
|
||||
bean.oauth_client_id = monitor.oauth_client_id,
|
||||
bean.oauth_client_secret = monitor.oauth_client_secret,
|
||||
bean.oauth_auth_method = this.oauth_auth_method,
|
||||
bean.oauth_token_url = monitor.oauth_token_url,
|
||||
bean.oauth_scopes = monitor.oauth_scopes,
|
||||
bean.oauth_client_id = monitor.oauth_client_id;
|
||||
bean.oauth_client_secret = monitor.oauth_client_secret;
|
||||
bean.oauth_auth_method = monitor.oauth_auth_method;
|
||||
bean.oauth_token_url = monitor.oauth_token_url;
|
||||
bean.oauth_scopes = monitor.oauth_scopes;
|
||||
bean.tlsCa = monitor.tlsCa;
|
||||
bean.tlsCert = monitor.tlsCert;
|
||||
bean.tlsKey = monitor.tlsKey;
|
||||
|
@ -836,7 +841,7 @@ let needSetup = false;
|
|||
|
||||
await updateMonitorNotification(bean.id, monitor.notificationIDList);
|
||||
|
||||
if (bean.isActive()) {
|
||||
if (await bean.isActive()) {
|
||||
await restartMonitor(socket.userID, bean.id);
|
||||
}
|
||||
|
||||
|
@ -942,7 +947,8 @@ let needSetup = false;
|
|||
|
||||
callback({
|
||||
ok: true,
|
||||
msg: "Resumed Successfully.",
|
||||
msg: "successResumed",
|
||||
msgi18n: true,
|
||||
});
|
||||
|
||||
} catch (e) {
|
||||
|
@ -961,7 +967,8 @@ let needSetup = false;
|
|||
|
||||
callback({
|
||||
ok: true,
|
||||
msg: "Paused Successfully.",
|
||||
msg: "successPaused",
|
||||
msgi18n: true,
|
||||
});
|
||||
|
||||
} catch (e) {
|
||||
|
@ -999,12 +1006,11 @@ let needSetup = false;
|
|||
|
||||
callback({
|
||||
ok: true,
|
||||
msg: "Deleted Successfully.",
|
||||
msg: "successDeleted",
|
||||
msgi18n: true,
|
||||
});
|
||||
|
||||
await server.sendMonitorList(socket);
|
||||
// Clear heartbeat list on client
|
||||
await sendImportantHeartbeatList(socket, monitorID, true, true);
|
||||
|
||||
} catch (e) {
|
||||
callback({
|
||||
|
@ -1063,7 +1069,8 @@ let needSetup = false;
|
|||
if (bean == null) {
|
||||
callback({
|
||||
ok: false,
|
||||
msg: "Tag not found",
|
||||
msg: "tagNotFound",
|
||||
msgi18n: true,
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
@ -1094,7 +1101,8 @@ let needSetup = false;
|
|||
|
||||
callback({
|
||||
ok: true,
|
||||
msg: "Deleted Successfully.",
|
||||
msg: "successDeleted",
|
||||
msgi18n: true,
|
||||
});
|
||||
|
||||
} catch (e) {
|
||||
|
@ -1117,7 +1125,8 @@ let needSetup = false;
|
|||
|
||||
callback({
|
||||
ok: true,
|
||||
msg: "Added Successfully.",
|
||||
msg: "successAdded",
|
||||
msgi18n: true,
|
||||
});
|
||||
|
||||
} catch (e) {
|
||||
|
@ -1140,7 +1149,8 @@ let needSetup = false;
|
|||
|
||||
callback({
|
||||
ok: true,
|
||||
msg: "Edited Successfully.",
|
||||
msg: "successEdited",
|
||||
msgi18n: true,
|
||||
});
|
||||
|
||||
} catch (e) {
|
||||
|
@ -1163,7 +1173,8 @@ let needSetup = false;
|
|||
|
||||
callback({
|
||||
ok: true,
|
||||
msg: "Deleted Successfully.",
|
||||
msg: "successDeleted",
|
||||
msgi18n: true,
|
||||
});
|
||||
|
||||
} catch (e) {
|
||||
|
@ -1174,6 +1185,72 @@ let needSetup = false;
|
|||
}
|
||||
});
|
||||
|
||||
socket.on("monitorImportantHeartbeatListCount", async (monitorID, callback) => {
|
||||
try {
|
||||
checkLogin(socket);
|
||||
|
||||
let count;
|
||||
if (monitorID == null) {
|
||||
count = await R.count("heartbeat", "important = 1");
|
||||
} else {
|
||||
count = await R.count("heartbeat", "monitor_id = ? AND important = 1", [
|
||||
monitorID,
|
||||
]);
|
||||
}
|
||||
|
||||
callback({
|
||||
ok: true,
|
||||
count: count,
|
||||
});
|
||||
} catch (e) {
|
||||
callback({
|
||||
ok: false,
|
||||
msg: e.message,
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
socket.on("monitorImportantHeartbeatListPaged", async (monitorID, offset, count, callback) => {
|
||||
try {
|
||||
checkLogin(socket);
|
||||
|
||||
let list;
|
||||
if (monitorID == null) {
|
||||
list = await R.find("heartbeat", `
|
||||
important = 1
|
||||
ORDER BY time DESC
|
||||
LIMIT ?
|
||||
OFFSET ?
|
||||
`, [
|
||||
count,
|
||||
offset,
|
||||
]);
|
||||
} else {
|
||||
list = await R.find("heartbeat", `
|
||||
monitor_id = ?
|
||||
AND important = 1
|
||||
ORDER BY time DESC
|
||||
LIMIT ?
|
||||
OFFSET ?
|
||||
`, [
|
||||
monitorID,
|
||||
count,
|
||||
offset,
|
||||
]);
|
||||
}
|
||||
|
||||
callback({
|
||||
ok: true,
|
||||
data: list,
|
||||
});
|
||||
} catch (e) {
|
||||
callback({
|
||||
ok: false,
|
||||
msg: e.message,
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
socket.on("changePassword", async (password, callback) => {
|
||||
try {
|
||||
checkLogin(socket);
|
||||
|
@ -1191,7 +1268,8 @@ let needSetup = false;
|
|||
|
||||
callback({
|
||||
ok: true,
|
||||
msg: "Password has been updated successfully.",
|
||||
msg: "successAuthChangePassword",
|
||||
msgi18n: true,
|
||||
});
|
||||
|
||||
} catch (e) {
|
||||
|
@ -1315,7 +1393,8 @@ let needSetup = false;
|
|||
|
||||
callback({
|
||||
ok: true,
|
||||
msg: "Deleted",
|
||||
msg: "successDeleted",
|
||||
msgi18n: true,
|
||||
});
|
||||
|
||||
} catch (e) {
|
||||
|
@ -1550,7 +1629,8 @@ let needSetup = false;
|
|||
|
||||
callback({
|
||||
ok: true,
|
||||
msg: "Backup successfully restored.",
|
||||
msg: "successBackupRestored",
|
||||
msgi18n: true,
|
||||
});
|
||||
|
||||
} catch (e) {
|
||||
|
@ -1573,8 +1653,6 @@ let needSetup = false;
|
|||
monitorID,
|
||||
]);
|
||||
|
||||
await sendImportantHeartbeatList(socket, monitorID, true, true);
|
||||
|
||||
callback({
|
||||
ok: true,
|
||||
});
|
||||
|
@ -1755,10 +1833,6 @@ async function afterLogin(socket, user) {
|
|||
await sendHeartbeatList(socket, monitorID);
|
||||
}
|
||||
|
||||
for (let monitorID in monitorList) {
|
||||
await sendImportantHeartbeatList(socket, monitorID);
|
||||
}
|
||||
|
||||
for (let monitorID in monitorList) {
|
||||
await Monitor.sendStats(io, monitorID, user.id);
|
||||
}
|
||||
|
|
|
@ -38,7 +38,8 @@ module.exports.apiKeySocketHandler = (socket) => {
|
|||
|
||||
callback({
|
||||
ok: true,
|
||||
msg: "Added Successfully.",
|
||||
msg: "successAdded",
|
||||
msgi18n: true,
|
||||
key: formattedKey,
|
||||
keyID: bean.id,
|
||||
});
|
||||
|
@ -82,7 +83,8 @@ module.exports.apiKeySocketHandler = (socket) => {
|
|||
|
||||
callback({
|
||||
ok: true,
|
||||
msg: "Deleted Successfully.",
|
||||
msg: "successDeleted",
|
||||
msgi18n: true,
|
||||
});
|
||||
|
||||
await sendAPIKeyList(socket);
|
||||
|
@ -109,7 +111,8 @@ module.exports.apiKeySocketHandler = (socket) => {
|
|||
|
||||
callback({
|
||||
ok: true,
|
||||
msg: "Disabled Successfully.",
|
||||
msg: "successDisabled",
|
||||
msgi18n: true,
|
||||
});
|
||||
|
||||
await sendAPIKeyList(socket);
|
||||
|
@ -136,7 +139,8 @@ module.exports.apiKeySocketHandler = (socket) => {
|
|||
|
||||
callback({
|
||||
ok: true,
|
||||
msg: "Enabled Successfully",
|
||||
msg: "successEnabled",
|
||||
msgi18n: true,
|
||||
});
|
||||
|
||||
await sendAPIKeyList(socket);
|
||||
|
|
|
@ -40,7 +40,8 @@ module.exports.dockerSocketHandler = (socket) => {
|
|||
|
||||
callback({
|
||||
ok: true,
|
||||
msg: "Deleted",
|
||||
msg: "successDeleted",
|
||||
msgi18n: true,
|
||||
});
|
||||
|
||||
} catch (e) {
|
||||
|
|
|
@ -4,6 +4,8 @@ const { sendInfo } = require("../client");
|
|||
const { checkLogin } = require("../util-server");
|
||||
const GameResolver = require("gamedig/lib/GameResolver");
|
||||
const { testChrome } = require("../monitor-types/real-browser-monitor-type");
|
||||
const fs = require("fs");
|
||||
const path = require("path");
|
||||
|
||||
let gameResolver = new GameResolver();
|
||||
let gameList = null;
|
||||
|
@ -53,7 +55,11 @@ module.exports.generalSocketHandler = (socket, server) => {
|
|||
testChrome(executable).then((version) => {
|
||||
callback({
|
||||
ok: true,
|
||||
msg: "Found Chromium/Chrome. Version: " + version,
|
||||
msg: {
|
||||
key: "foundChromiumVersion",
|
||||
values: [ version ],
|
||||
},
|
||||
msgi18n: true,
|
||||
});
|
||||
}).catch((e) => {
|
||||
callback({
|
||||
|
@ -62,4 +68,29 @@ module.exports.generalSocketHandler = (socket, server) => {
|
|||
});
|
||||
});
|
||||
});
|
||||
|
||||
socket.on("getPushExample", (language, callback) => {
|
||||
|
||||
try {
|
||||
let dir = path.join("./extra/push-examples", language);
|
||||
let files = fs.readdirSync(dir);
|
||||
|
||||
for (let file of files) {
|
||||
if (file.startsWith("index.")) {
|
||||
callback({
|
||||
ok: true,
|
||||
code: fs.readFileSync(path.join(dir, file), "utf8"),
|
||||
});
|
||||
return;
|
||||
}
|
||||
}
|
||||
} catch (e) {
|
||||
|
||||
}
|
||||
|
||||
callback({
|
||||
ok: false,
|
||||
msg: "Not found",
|
||||
});
|
||||
});
|
||||
};
|
||||
|
|
|
@ -30,7 +30,8 @@ module.exports.maintenanceSocketHandler = (socket) => {
|
|||
|
||||
callback({
|
||||
ok: true,
|
||||
msg: "Added Successfully.",
|
||||
msg: "successAdded",
|
||||
msgi18n: true,
|
||||
maintenanceID,
|
||||
});
|
||||
|
||||
|
@ -97,7 +98,8 @@ module.exports.maintenanceSocketHandler = (socket) => {
|
|||
|
||||
callback({
|
||||
ok: true,
|
||||
msg: "Added Successfully.",
|
||||
msg: "successAdded",
|
||||
msgi18n: true,
|
||||
});
|
||||
|
||||
} catch (e) {
|
||||
|
@ -131,7 +133,8 @@ module.exports.maintenanceSocketHandler = (socket) => {
|
|||
|
||||
callback({
|
||||
ok: true,
|
||||
msg: "Added Successfully.",
|
||||
msg: "successAdded",
|
||||
msgi18n: true,
|
||||
});
|
||||
|
||||
} catch (e) {
|
||||
|
@ -250,7 +253,8 @@ module.exports.maintenanceSocketHandler = (socket) => {
|
|||
|
||||
callback({
|
||||
ok: true,
|
||||
msg: "Deleted Successfully.",
|
||||
msg: "successDeleted",
|
||||
msgi18n: true,
|
||||
});
|
||||
|
||||
await server.sendMaintenanceList(socket);
|
||||
|
@ -283,7 +287,8 @@ module.exports.maintenanceSocketHandler = (socket) => {
|
|||
|
||||
callback({
|
||||
ok: true,
|
||||
msg: "Paused Successfully.",
|
||||
msg: "successPaused",
|
||||
msgi18n: true,
|
||||
});
|
||||
|
||||
await server.sendMaintenanceList(socket);
|
||||
|
@ -316,7 +321,8 @@ module.exports.maintenanceSocketHandler = (socket) => {
|
|||
|
||||
callback({
|
||||
ok: true,
|
||||
msg: "Resume Successfully",
|
||||
msg: "successResumed",
|
||||
msgi18n: true,
|
||||
});
|
||||
|
||||
await server.sendMaintenanceList(socket);
|
||||
|
|
|
@ -47,7 +47,8 @@ module.exports.proxySocketHandler = (socket) => {
|
|||
|
||||
callback({
|
||||
ok: true,
|
||||
msg: "Deleted",
|
||||
msg: "successDeleted",
|
||||
msgi18n: true,
|
||||
});
|
||||
|
||||
} catch (e) {
|
||||
|
|
|
@ -286,7 +286,8 @@ module.exports.statusPageSocketHandler = (socket) => {
|
|||
|
||||
callback({
|
||||
ok: true,
|
||||
msg: "OK!"
|
||||
msg: "successAdded",
|
||||
msgi18n: true,
|
||||
});
|
||||
|
||||
} catch (error) {
|
||||
|
|
|
@ -584,6 +584,20 @@ h5.settings-subheading::after {
|
|||
border-bottom: 1px solid $dark-border-color;
|
||||
}
|
||||
|
||||
/* required class */
|
||||
.code-editor, .css-editor {
|
||||
/* we dont use `language-` classes anymore so thats why we need to add background and text color manually */
|
||||
|
||||
border-radius: 1rem;
|
||||
padding: 10px 5px;
|
||||
border: 1px solid #ced4da;
|
||||
|
||||
.dark & {
|
||||
background: $dark-bg2;
|
||||
border: 1px solid $dark-border-color;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
$shadow-box-padding: 20px;
|
||||
|
||||
|
|
|
@ -11,7 +11,7 @@
|
|||
/>
|
||||
</div>
|
||||
<div
|
||||
v-if="size !== 'small' && beatList.length > 4 && $root.styleElapsedTime !== 'none'"
|
||||
v-if="!$root.isMobile && size !== 'small' && beatList.length > 4 && $root.styleElapsedTime !== 'none'"
|
||||
class="d-flex justify-content-between align-items-center word" :style="timeStyle"
|
||||
>
|
||||
<div>{{ timeSinceFirstBeat }} ago</div>
|
||||
|
|
|
@ -62,7 +62,7 @@
|
|||
</span>
|
||||
</div>
|
||||
<div class="extra-info">
|
||||
<div v-if="showCertificateExpiry && monitor.element.type === 'http'">
|
||||
<div v-if="showCertificateExpiry && monitor.element.certExpiryDaysRemaining">
|
||||
<Tag :item="{name: $t('Cert Exp.'), value: formattedCertExpiryMessage(monitor), color: certExpiryColor(monitor)}" :size="'sm'" />
|
||||
</div>
|
||||
<div v-if="showTags">
|
||||
|
|
|
@ -1,4 +1,11 @@
|
|||
<template>
|
||||
<div class="mb-3">
|
||||
<label for="Bark API Version" class="form-label">{{ $t("Bark API Version") }}</label>
|
||||
<select id="Bark API Version" v-model="$parent.notification.apiVersion" class="form-select" required>
|
||||
<option value="v1">v1</option>
|
||||
<option value="v2">v2</option>
|
||||
</select>
|
||||
</div>
|
||||
<div class="mb-3">
|
||||
<label for="Bark Endpoint" class="form-label">{{ $t("Bark Endpoint") }}<span style="color: red;"><sup>*</sup></span></label>
|
||||
<input id="Bark Endpoint" v-model="$parent.notification.barkEndpoint" type="text" class="form-control" required>
|
||||
|
|
|
@ -84,6 +84,9 @@
|
|||
"Push URL": "Push URL",
|
||||
"needPushEvery": "You should call this URL every {0} seconds.",
|
||||
"pushOptionalParams": "Optional parameters: {0}",
|
||||
"pushViewCode": "View Code",
|
||||
"pushOthers": "Others",
|
||||
"programmingLanguages": "Programming Languages",
|
||||
"Save": "Save",
|
||||
"Notifications": "Notifications",
|
||||
"Not available, please setup.": "Not available, please setup.",
|
||||
|
@ -628,6 +631,7 @@
|
|||
"TemplateCode": "TemplateCode",
|
||||
"SignName": "SignName",
|
||||
"Sms template must contain parameters: ": "Sms template must contain parameters: ",
|
||||
"Bark API Version": "Bark API Version",
|
||||
"Bark Endpoint": "Bark Endpoint",
|
||||
"Bark Group": "Bark Group",
|
||||
"Bark Sound": "Bark Sound",
|
||||
|
@ -819,5 +823,22 @@
|
|||
"noOrBadCertificate": "No/Bad Certificate",
|
||||
"gamedigGuessPort": "Gamedig: Guess Port",
|
||||
"gamedigGuessPortDescription": "The port used by Valve Server Query Protocol may be different from the client port. Try this if the monitor cannot connect to your server.",
|
||||
"Saved.": "Saved."
|
||||
"Saved.": "Saved.",
|
||||
"authUserInactiveOrDeleted": "The user is inactive or deleted.",
|
||||
"authInvalidToken": "Invalid Token.",
|
||||
"authIncorrectCreds": "Incorrect username or password.",
|
||||
"2faAlreadyEnabled": "2FA is already enabled.",
|
||||
"2faEnabled": "2FA Enabled.",
|
||||
"2faDisabled": "2FA Disabled.",
|
||||
"successAdded": "Added Successfully.",
|
||||
"successResumed": "Resumed Successfully.",
|
||||
"successPaused": "Paused Successfully.",
|
||||
"successDeleted": "Deleted Successfully.",
|
||||
"successEdited": "Edited Successfully.",
|
||||
"successAuthChangePassword": "Password has been updated successfully.",
|
||||
"successBackupRestored": "Backup successfully restored.",
|
||||
"successDisabled": "Disabled Successfully.",
|
||||
"successEnabled": "Enabled Successfully.",
|
||||
"tagNotFound": "Tag not found.",
|
||||
"foundChromiumVersion": "Found Chromium/Chrome. Version: {0}"
|
||||
}
|
||||
|
|
|
@ -3,6 +3,8 @@ import { useToast } from "vue-toastification";
|
|||
import jwtDecode from "jwt-decode";
|
||||
import Favico from "favico.js";
|
||||
import dayjs from "dayjs";
|
||||
import mitt from "mitt";
|
||||
|
||||
import { DOWN, MAINTENANCE, PENDING, UP } from "../util.ts";
|
||||
import { getDevContainerServerHostname, isDevContainer, getToastSuccessTimeout, getToastErrorTimeout } from "../util-frontend.js";
|
||||
const toast = useToast();
|
||||
|
@ -39,7 +41,6 @@ export default {
|
|||
maintenanceList: {},
|
||||
apiKeyList: {},
|
||||
heartbeatList: { },
|
||||
importantHeartbeatList: { },
|
||||
avgPingList: { },
|
||||
uptimeList: { },
|
||||
tlsInfoList: {},
|
||||
|
@ -59,6 +60,7 @@ export default {
|
|||
currentPassword: "",
|
||||
},
|
||||
faviconUpdateDebounce: null,
|
||||
emitter: mitt(),
|
||||
};
|
||||
},
|
||||
|
||||
|
@ -201,11 +203,7 @@ export default {
|
|||
}
|
||||
}
|
||||
|
||||
if (! (data.monitorID in this.importantHeartbeatList)) {
|
||||
this.importantHeartbeatList[data.monitorID] = [];
|
||||
}
|
||||
|
||||
this.importantHeartbeatList[data.monitorID].unshift(data);
|
||||
this.emitter.emit("newImportantHeartbeat", data);
|
||||
}
|
||||
});
|
||||
|
||||
|
@ -229,14 +227,6 @@ export default {
|
|||
this.tlsInfoList[monitorID] = JSON.parse(data);
|
||||
});
|
||||
|
||||
socket.on("importantHeartbeatList", (monitorID, data, overwrite) => {
|
||||
if (! (monitorID in this.importantHeartbeatList) || overwrite) {
|
||||
this.importantHeartbeatList[monitorID] = data;
|
||||
} else {
|
||||
this.importantHeartbeatList[monitorID] = data.concat(this.importantHeartbeatList[monitorID]);
|
||||
}
|
||||
});
|
||||
|
||||
socket.on("connect_error", (err) => {
|
||||
console.error(`Failed to connect to the backend. Socket.io connect_error: ${err.message}`);
|
||||
this.connectionErrorMsg = `${this.$t("Cannot connect to the socket server.")} [${err}] ${this.$t("Reconnecting...")}`;
|
||||
|
@ -630,7 +620,6 @@ export default {
|
|||
clearData() {
|
||||
console.log("reset heartbeat list");
|
||||
this.heartbeatList = {};
|
||||
this.importantHeartbeatList = {};
|
||||
},
|
||||
|
||||
/**
|
||||
|
|
|
@ -42,13 +42,13 @@
|
|||
</thead>
|
||||
<tbody>
|
||||
<tr v-for="(beat, index) in displayedRecords" :key="index" :class="{ 'shadow-box': $root.windowWidth <= 550}">
|
||||
<td><router-link :to="`/dashboard/${beat.monitorID}`">{{ beat.name }}</router-link></td>
|
||||
<td><router-link :to="`/dashboard/${beat.monitorID}`">{{ $root.monitorList[beat.monitorID]?.name }}</router-link></td>
|
||||
<td><Status :status="beat.status" /></td>
|
||||
<td :class="{ 'border-0':! beat.msg}"><Datetime :value="beat.time" /></td>
|
||||
<td class="border-0">{{ beat.msg }}</td>
|
||||
</tr>
|
||||
|
||||
<tr v-if="importantHeartBeatList.length === 0">
|
||||
<tr v-if="importantHeartBeatListLength === 0">
|
||||
<td colspan="4">
|
||||
{{ $t("No important events") }}
|
||||
</td>
|
||||
|
@ -59,7 +59,7 @@
|
|||
<div class="d-flex justify-content-center kuma_pagination">
|
||||
<pagination
|
||||
v-model="page"
|
||||
:records="importantHeartBeatList.length"
|
||||
:records="importantHeartBeatListLength"
|
||||
:per-page="perPage"
|
||||
:options="paginationConfig"
|
||||
/>
|
||||
|
@ -92,72 +92,89 @@ export default {
|
|||
page: 1,
|
||||
perPage: 25,
|
||||
initialPerPage: 25,
|
||||
heartBeatList: [],
|
||||
paginationConfig: {
|
||||
hideCount: true,
|
||||
chunksNavigation: "scroll",
|
||||
},
|
||||
importantHeartBeatListLength: 0,
|
||||
displayedRecords: [],
|
||||
};
|
||||
},
|
||||
computed: {
|
||||
|
||||
importantHeartBeatList() {
|
||||
let result = [];
|
||||
|
||||
for (let monitorID in this.$root.importantHeartbeatList) {
|
||||
let list = this.$root.importantHeartbeatList[monitorID];
|
||||
result = result.concat(list);
|
||||
}
|
||||
|
||||
for (let beat of result) {
|
||||
let monitor = this.$root.monitorList[beat.monitorID];
|
||||
|
||||
if (monitor) {
|
||||
beat.name = monitor.name;
|
||||
}
|
||||
}
|
||||
|
||||
result.sort((a, b) => {
|
||||
if (a.time > b.time) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (a.time < b.time) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
});
|
||||
|
||||
// eslint-disable-next-line vue/no-side-effects-in-computed-properties
|
||||
this.heartBeatList = result;
|
||||
|
||||
return result;
|
||||
},
|
||||
|
||||
displayedRecords() {
|
||||
const startIndex = this.perPage * (this.page - 1);
|
||||
const endIndex = startIndex + this.perPage;
|
||||
return this.heartBeatList.slice(startIndex, endIndex);
|
||||
},
|
||||
},
|
||||
watch: {
|
||||
importantHeartBeatList() {
|
||||
perPage() {
|
||||
this.$nextTick(() => {
|
||||
this.updatePerPage();
|
||||
this.getImportantHeartbeatListPaged();
|
||||
});
|
||||
},
|
||||
|
||||
page() {
|
||||
this.getImportantHeartbeatListPaged();
|
||||
},
|
||||
},
|
||||
|
||||
mounted() {
|
||||
this.getImportantHeartbeatListLength();
|
||||
|
||||
this.$root.emitter.on("newImportantHeartbeat", this.onNewImportantHeartbeat);
|
||||
|
||||
this.initialPerPage = this.perPage;
|
||||
|
||||
window.addEventListener("resize", this.updatePerPage);
|
||||
this.updatePerPage();
|
||||
},
|
||||
|
||||
beforeUnmount() {
|
||||
this.$root.emitter.off("newImportantHeartbeat", this.onNewImportantHeartbeat);
|
||||
|
||||
window.removeEventListener("resize", this.updatePerPage);
|
||||
},
|
||||
|
||||
methods: {
|
||||
/**
|
||||
* Updates the displayed records when a new important heartbeat arrives.
|
||||
* @param {object} heartbeat - The heartbeat object received.
|
||||
* @returns {void}
|
||||
*/
|
||||
onNewImportantHeartbeat(heartbeat) {
|
||||
if (this.page === 1) {
|
||||
this.displayedRecords.unshift(heartbeat);
|
||||
if (this.displayedRecords.length > this.perPage) {
|
||||
this.displayedRecords.pop();
|
||||
}
|
||||
this.importantHeartBeatListLength += 1;
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* Retrieves the length of the important heartbeat list for all monitors.
|
||||
* @returns {void}
|
||||
*/
|
||||
getImportantHeartbeatListLength() {
|
||||
this.$root.getSocket().emit("monitorImportantHeartbeatListCount", null, (res) => {
|
||||
if (res.ok) {
|
||||
this.importantHeartBeatListLength = res.count;
|
||||
this.getImportantHeartbeatListPaged();
|
||||
}
|
||||
});
|
||||
},
|
||||
|
||||
/**
|
||||
* Retrieves the important heartbeat list for the current page.
|
||||
* @returns {void}
|
||||
*/
|
||||
getImportantHeartbeatListPaged() {
|
||||
const offset = (this.page - 1) * this.perPage;
|
||||
this.$root.getSocket().emit("monitorImportantHeartbeatListPaged", null, offset, this.perPage, (res) => {
|
||||
if (res.ok) {
|
||||
this.displayedRecords = res.data;
|
||||
}
|
||||
});
|
||||
},
|
||||
|
||||
/**
|
||||
* Updates the number of items shown per page based on the available height.
|
||||
* @returns {void}
|
||||
*/
|
||||
updatePerPage() {
|
||||
const tableContainer = this.$refs.tableContainer;
|
||||
const tableContainerHeight = tableContainer.offsetHeight;
|
||||
|
|
|
@ -76,6 +76,34 @@
|
|||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Push Examples -->
|
||||
<div v-if="monitor.type === 'push'" class="shadow-box big-padding">
|
||||
<a href="#" @click="pushMonitor.showPushExamples = !pushMonitor.showPushExamples">{{ $t("pushViewCode") }}</a>
|
||||
|
||||
<transition name="slide-fade" appear>
|
||||
<div v-if="pushMonitor.showPushExamples" class="mt-3">
|
||||
<select id="push-current-example" v-model="pushMonitor.currentExample" class="form-select">
|
||||
<optgroup :label="$t('programmingLanguages')">
|
||||
<option value="csharp">C#</option>
|
||||
<option value="go">Go</option>
|
||||
<option value="java">Java</option>
|
||||
<option value="javascript-fetch">JavaScript (fetch)</option>
|
||||
<option value="php">PHP</option>
|
||||
<option value="python">Python</option>
|
||||
<option value="typescript-fetch">TypeScript (fetch)</option>
|
||||
</optgroup>
|
||||
<optgroup :label="$t('pushOthers')">
|
||||
<option value="bash-curl">Bash (curl)</option>
|
||||
<option value="powershell">PowerShell</option>
|
||||
<option value="docker">Docker</option>
|
||||
</optgroup>
|
||||
</select>
|
||||
|
||||
<prism-editor v-model="pushMonitor.code" class="css-editor mt-3" :highlight="pushExampleHighlighter" line-numbers readonly></prism-editor>
|
||||
</div>
|
||||
</transition>
|
||||
</div>
|
||||
|
||||
<!-- Stats -->
|
||||
<div class="shadow-box big-padding text-center stats">
|
||||
<div class="row">
|
||||
|
@ -195,7 +223,7 @@
|
|||
<td class="border-0">{{ beat.msg }}</td>
|
||||
</tr>
|
||||
|
||||
<tr v-if="importantHeartBeatList.length === 0">
|
||||
<tr v-if="importantHeartBeatListLength === 0">
|
||||
<td colspan="3">
|
||||
{{ $t("No important events") }}
|
||||
</td>
|
||||
|
@ -206,7 +234,7 @@
|
|||
<div class="d-flex justify-content-center kuma_pagination">
|
||||
<pagination
|
||||
v-model="page"
|
||||
:records="importantHeartBeatList.length"
|
||||
:records="importantHeartBeatListLength"
|
||||
:per-page="perPage"
|
||||
:options="paginationConfig"
|
||||
/>
|
||||
|
@ -249,6 +277,12 @@ import CertificateInfo from "../components/CertificateInfo.vue";
|
|||
import { getMonitorRelativeURL } from "../util.ts";
|
||||
import { URL } from "whatwg-url";
|
||||
import { getResBaseURL } from "../util-frontend";
|
||||
import { highlight, languages } from "prismjs/components/prism-core";
|
||||
import "prismjs/components/prism-clike";
|
||||
import "prismjs/components/prism-javascript";
|
||||
import "prismjs/components/prism-css";
|
||||
import { PrismEditor } from "vue-prism-editor";
|
||||
import "vue-prism-editor/dist/prismeditor.min.css";
|
||||
|
||||
export default {
|
||||
components: {
|
||||
|
@ -262,6 +296,7 @@ export default {
|
|||
PingChart,
|
||||
Tag,
|
||||
CertificateInfo,
|
||||
PrismEditor,
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
|
@ -275,6 +310,13 @@ export default {
|
|||
chunksNavigation: "scroll",
|
||||
},
|
||||
cacheTime: Date.now(),
|
||||
importantHeartBeatListLength: 0,
|
||||
displayedRecords: [],
|
||||
pushMonitor: {
|
||||
showPushExamples: false,
|
||||
currentExample: "javascript-fetch",
|
||||
code: "",
|
||||
},
|
||||
};
|
||||
},
|
||||
computed: {
|
||||
|
@ -313,16 +355,6 @@ export default {
|
|||
return this.$t("notAvailableShort");
|
||||
},
|
||||
|
||||
importantHeartBeatList() {
|
||||
if (this.$root.importantHeartbeatList[this.monitor.id]) {
|
||||
// eslint-disable-next-line vue/no-side-effects-in-computed-properties
|
||||
this.heartBeatList = this.$root.importantHeartbeatList[this.monitor.id];
|
||||
return this.$root.importantHeartbeatList[this.monitor.id];
|
||||
}
|
||||
|
||||
return [];
|
||||
},
|
||||
|
||||
status() {
|
||||
if (this.$root.statusList[this.monitor.id]) {
|
||||
return this.$root.statusList[this.monitor.id];
|
||||
|
@ -346,12 +378,6 @@ export default {
|
|||
return this.tlsInfo != null && this.toggleCertInfoBox;
|
||||
},
|
||||
|
||||
displayedRecords() {
|
||||
const startIndex = this.perPage * (this.page - 1);
|
||||
const endIndex = startIndex + this.perPage;
|
||||
return this.heartBeatList.slice(startIndex, endIndex);
|
||||
},
|
||||
|
||||
group() {
|
||||
if (!this.monitor.pathName.includes("/")) {
|
||||
return "";
|
||||
|
@ -367,9 +393,42 @@ export default {
|
|||
return getResBaseURL() + this.monitor.screenshot + "?time=" + this.cacheTime;
|
||||
}
|
||||
},
|
||||
mounted() {
|
||||
|
||||
watch: {
|
||||
page(to) {
|
||||
this.getImportantHeartbeatListPaged();
|
||||
},
|
||||
|
||||
monitor(to) {
|
||||
this.getImportantHeartbeatListLength();
|
||||
},
|
||||
"monitor.type"() {
|
||||
if (this.monitor && this.monitor.type === "push") {
|
||||
this.loadPushExample();
|
||||
}
|
||||
},
|
||||
"pushMonitor.currentExample"() {
|
||||
this.loadPushExample();
|
||||
},
|
||||
},
|
||||
|
||||
mounted() {
|
||||
this.getImportantHeartbeatListLength();
|
||||
|
||||
this.$root.emitter.on("newImportantHeartbeat", this.onNewImportantHeartbeat);
|
||||
|
||||
if (this.monitor && this.monitor.type === "push") {
|
||||
if (this.lastHeartBeat.status === -1) {
|
||||
this.pushMonitor.showPushExamples = true;
|
||||
}
|
||||
this.loadPushExample();
|
||||
}
|
||||
},
|
||||
|
||||
beforeUnmount() {
|
||||
this.$root.emitter.off("newImportantHeartbeat", this.onNewImportantHeartbeat);
|
||||
},
|
||||
|
||||
methods: {
|
||||
getResBaseURL,
|
||||
/**
|
||||
|
@ -454,7 +513,9 @@ export default {
|
|||
*/
|
||||
clearEvents() {
|
||||
this.$root.clearEvents(this.monitor.id, (res) => {
|
||||
if (! res.ok) {
|
||||
if (res.ok) {
|
||||
this.getImportantHeartbeatListLength();
|
||||
} else {
|
||||
toast.error(res.msg);
|
||||
}
|
||||
});
|
||||
|
@ -515,6 +576,72 @@ export default {
|
|||
// Handle SQL Server
|
||||
return urlString.replaceAll(/Password=(.+);/ig, "Password=******;");
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* Retrieves the length of the important heartbeat list for this monitor.
|
||||
* @returns {void}
|
||||
*/
|
||||
getImportantHeartbeatListLength() {
|
||||
if (this.monitor) {
|
||||
this.$root.getSocket().emit("monitorImportantHeartbeatListCount", this.monitor.id, (res) => {
|
||||
if (res.ok) {
|
||||
this.importantHeartBeatListLength = res.count;
|
||||
this.getImportantHeartbeatListPaged();
|
||||
}
|
||||
});
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* Retrieves the important heartbeat list for the current page.
|
||||
* @returns {void}
|
||||
*/
|
||||
getImportantHeartbeatListPaged() {
|
||||
if (this.monitor) {
|
||||
const offset = (this.page - 1) * this.perPage;
|
||||
this.$root.getSocket().emit("monitorImportantHeartbeatListPaged", this.monitor.id, offset, this.perPage, (res) => {
|
||||
if (res.ok) {
|
||||
this.displayedRecords = res.data;
|
||||
}
|
||||
});
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* Updates the displayed records when a new important heartbeat arrives.
|
||||
* @param {object} heartbeat - The heartbeat object received.
|
||||
* @returns {void}
|
||||
*/
|
||||
onNewImportantHeartbeat(heartbeat) {
|
||||
if (heartbeat.monitorID === this.monitor?.id) {
|
||||
if (this.page === 1) {
|
||||
this.displayedRecords.unshift(heartbeat);
|
||||
if (this.displayedRecords.length > this.perPage) {
|
||||
this.displayedRecords.pop();
|
||||
}
|
||||
this.importantHeartBeatListLength += 1;
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* Highlight the example code
|
||||
* @param {string} code Code
|
||||
* @returns {string} Highlighted code
|
||||
*/
|
||||
pushExampleHighlighter(code) {
|
||||
return highlight(code, languages.js);
|
||||
},
|
||||
|
||||
loadPushExample() {
|
||||
this.pushMonitor.code = "";
|
||||
this.$root.getSocket().emit("getPushExample", this.pushMonitor.currentExample, (res) => {
|
||||
let code = res.code
|
||||
.replace("60", this.monitor.interval)
|
||||
.replace("https://example.com/api/push/key?status=up&msg=OK&ping=", this.pushURL);
|
||||
this.pushMonitor.code = code;
|
||||
});
|
||||
}
|
||||
},
|
||||
};
|
||||
|
|
|
@ -82,7 +82,7 @@
|
|||
<option value="redis">
|
||||
Redis
|
||||
</option>
|
||||
<option v-if="$root.info.isContainer" value="tailscale-ping">
|
||||
<option v-if="!$root.info.isContainer" value="tailscale-ping">
|
||||
Tailscale Ping
|
||||
</option>
|
||||
</optgroup>
|
||||
|
@ -401,7 +401,7 @@
|
|||
</div>
|
||||
|
||||
<!-- Timeout: HTTP / Keyword only -->
|
||||
<div v-if="monitor.type === 'http' || monitor.type === 'keyword'" class="my-3">
|
||||
<div v-if="monitor.type === 'http' || monitor.type === 'keyword' || monitor.type === 'json-query'" class="my-3">
|
||||
<label for="timeout" class="form-label">{{ $t("Request Timeout") }} ({{ $t("timeoutAfter", [ monitor.timeout || clampTimeout(monitor.interval) ]) }})</label>
|
||||
<input id="timeout" v-model="monitor.timeout" type="number" class="form-control" required min="0" step="0.1">
|
||||
</div>
|
||||
|
@ -460,7 +460,7 @@
|
|||
</div>
|
||||
|
||||
<!-- HTTP / Keyword only -->
|
||||
<template v-if="monitor.type === 'http' || monitor.type === 'keyword' || monitor.type === 'grpc-keyword' ">
|
||||
<template v-if="monitor.type === 'http' || monitor.type === 'keyword' || monitor.type === 'json-query' || monitor.type === 'grpc-keyword' ">
|
||||
<div class="my-3">
|
||||
<label for="maxRedirects" class="form-label">{{ $t("Max. Redirects") }}</label>
|
||||
<input id="maxRedirects" v-model="monitor.maxredirects" type="number" class="form-control" required min="0" step="1">
|
||||
|
|
|
@ -9,10 +9,12 @@
|
|||
</div>
|
||||
|
||||
<div v-if="info.runningSetup" class="mt-5">
|
||||
<div class="alert alert-success" role="alert">
|
||||
<div class="alert alert-success mx-3 px-4" role="alert">
|
||||
<div class="d-flex align-items-center">
|
||||
<strong>Setting up the database. It may take a while, please be patient.</strong>
|
||||
<div class="spinner-border ml-auto" role="status" aria-hidden="true"></div>
|
||||
<div class="ms-3 pt-1">
|
||||
<div class="spinner-border" role="status" aria-hidden="true"></div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
@ -51,17 +53,17 @@
|
|||
</label>
|
||||
</div>
|
||||
|
||||
<p v-if="dbConfig.type === 'embedded-mariadb'" class="mt-3">
|
||||
<div v-if="dbConfig.type === 'embedded-mariadb'" class="mt-3 short">
|
||||
{{ $t("setupDatabaseEmbeddedMariaDB") }}
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<p v-if="dbConfig.type === 'mariadb'" class="mt-3">
|
||||
<div v-if="dbConfig.type === 'mariadb'" class="mt-3 short">
|
||||
{{ $t("setupDatabaseMariaDB") }}
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<p v-if="dbConfig.type === 'sqlite'" class="mt-3">
|
||||
<div v-if="dbConfig.type === 'sqlite'" class="mt-3 short">
|
||||
{{ $t("setupDatabaseSQLite") }}
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<template v-if="dbConfig.type === 'mariadb'">
|
||||
<div class="form-floating mt-3 short">
|
||||
|
@ -80,7 +82,7 @@
|
|||
</div>
|
||||
|
||||
<div class="form-floating mt-3 short">
|
||||
<input id="floatingInput" v-model="dbConfig.password" type="passwrod" class="form-control" required>
|
||||
<input id="floatingInput" v-model="dbConfig.password" type="password" class="form-control" required>
|
||||
<label for="floatingInput">{{ $t("Password") }}</label>
|
||||
</div>
|
||||
|
||||
|
|
|
@ -114,7 +114,7 @@
|
|||
|
||||
<!-- Sidebar Footer -->
|
||||
<div class="sidebar-footer">
|
||||
<button class="btn btn-success me-2" @click="save">
|
||||
<button class="btn btn-success me-2" :disabled="loading" @click="save">
|
||||
<font-awesome-icon icon="save" />
|
||||
{{ $t("Save") }}
|
||||
</button>
|
||||
|
@ -457,6 +457,7 @@ export default {
|
|||
lastUpdateTime: dayjs(),
|
||||
updateCountdown: null,
|
||||
updateCountdownText: null,
|
||||
loading: false,
|
||||
};
|
||||
},
|
||||
computed: {
|
||||
|
@ -765,7 +766,7 @@ export default {
|
|||
/**
|
||||
* Provide syntax highlighting for CSS
|
||||
* @param {string} code Text to highlight
|
||||
* @returns {string} Highlighted HTML
|
||||
* @returns {string} Highlighted CSS
|
||||
*/
|
||||
highlighter(code) {
|
||||
return highlight(code, languages.css);
|
||||
|
@ -842,6 +843,7 @@ export default {
|
|||
* @returns {void}
|
||||
*/
|
||||
save() {
|
||||
this.loading = true;
|
||||
let startTime = new Date();
|
||||
this.config.slug = this.config.slug.trim().toLowerCase();
|
||||
|
||||
|
@ -859,10 +861,12 @@ export default {
|
|||
}
|
||||
|
||||
setTimeout(() => {
|
||||
this.loading = false;
|
||||
location.href = "/status/" + this.config.slug;
|
||||
}, time);
|
||||
|
||||
} else {
|
||||
this.loading = false;
|
||||
toast.error(res.msg);
|
||||
}
|
||||
});
|
||||
|
@ -1266,20 +1270,6 @@ footer {
|
|||
}
|
||||
}
|
||||
|
||||
/* required class */
|
||||
.css-editor {
|
||||
/* we dont use `language-` classes anymore so thats why we need to add background and text color manually */
|
||||
|
||||
border-radius: 1rem;
|
||||
padding: 10px 5px;
|
||||
border: 1px solid #ced4da;
|
||||
|
||||
.dark & {
|
||||
background: $dark-bg;
|
||||
border: 1px solid $dark-border-color;
|
||||
}
|
||||
}
|
||||
|
||||
.bg-maintenance {
|
||||
.alert-heading {
|
||||
font-weight: bold;
|
||||
|
|
Loading…
Reference in a new issue