mirror of
https://github.com/louislam/uptime-kuma.git
synced 2024-11-24 07:14:04 +00:00
Merge branch 'louislam:master' into master
This commit is contained in:
commit
5927c2703f
11 changed files with 104 additions and 45 deletions
6
.github/ISSUE_TEMPLATE/ask-for-help.md
vendored
6
.github/ISSUE_TEMPLATE/ask-for-help.md
vendored
|
@ -9,3 +9,9 @@ assignees: ''
|
||||||
**Is it a duplicate question?**
|
**Is it a duplicate question?**
|
||||||
Please search in Issues without filters: https://github.com/louislam/uptime-kuma/issues?q=
|
Please search in Issues without filters: https://github.com/louislam/uptime-kuma/issues?q=
|
||||||
|
|
||||||
|
**Info**
|
||||||
|
Uptime Kuma Version:
|
||||||
|
Using Docker?: Yes/No
|
||||||
|
OS:
|
||||||
|
Browser:
|
||||||
|
|
||||||
|
|
17
.github/ISSUE_TEMPLATE/bug_report.md
vendored
17
.github/ISSUE_TEMPLATE/bug_report.md
vendored
|
@ -23,15 +23,16 @@ Steps to reproduce the behavior:
|
||||||
**Expected behavior**
|
**Expected behavior**
|
||||||
A clear and concise description of what you expected to happen.
|
A clear and concise description of what you expected to happen.
|
||||||
|
|
||||||
|
|
||||||
|
**Info**
|
||||||
|
- Uptime Kuma Version:
|
||||||
|
- Using Docker?: Yes/No
|
||||||
|
- OS:
|
||||||
|
- Browser:
|
||||||
|
|
||||||
**Screenshots**
|
**Screenshots**
|
||||||
If applicable, add screenshots to help explain your problem.
|
If applicable, add screenshots to help explain your problem.
|
||||||
|
|
||||||
**Desktop (please complete the following information):**
|
**Error Log**
|
||||||
- Uptime Kuma Version:
|
It is easier for us to find out the problem.
|
||||||
- Using Docker?: Yes/No
|
|
||||||
- OS:
|
|
||||||
- Browser:
|
|
||||||
|
|
||||||
|
|
||||||
**Additional context**
|
|
||||||
Add any other context about the problem here.
|
|
||||||
|
|
|
@ -1,3 +1,3 @@
|
||||||
{
|
{
|
||||||
"extends": "stylelint-config-recommended",
|
"extends": "stylelint-config-recommended"
|
||||||
}
|
}
|
||||||
|
|
|
@ -32,7 +32,7 @@ docker run -d --restart=always -p 3001:3001 -v uptime-kuma:/app/data --name upti
|
||||||
Browse to http://localhost:3001 after started.
|
Browse to http://localhost:3001 after started.
|
||||||
|
|
||||||
|
|
||||||
If you want to change port and volume, or need to browse via a reserve proxy, please read: https://github.com/louislam/uptime-kuma/wiki/Installation.
|
If you want to change **port** and **volume**, or need to browse via a reserve proxy, please read <a href="https://github.com/louislam/uptime-kuma/wiki/Installation#docker">wiki</a>.
|
||||||
|
|
||||||
### 💪🏻 Without Docker (Recommanded for x86/x64 only)
|
### 💪🏻 Without Docker (Recommanded for x86/x64 only)
|
||||||
|
|
||||||
|
@ -55,7 +55,7 @@ pm2 start npm --name uptime-kuma -- run start-server
|
||||||
|
|
||||||
Browse to http://localhost:3001 after started.
|
Browse to http://localhost:3001 after started.
|
||||||
|
|
||||||
If you want to change port and hostname, or need to browse via a reserve proxy, please read: https://github.com/louislam/uptime-kuma/wiki/Installation.
|
If you want to change **port** and **hostname**, or need to browse via a reserve proxy, please read <a href="https://github.com/louislam/uptime-kuma/wiki/Installation#without-docker-x86x64-only">wiki</a>.
|
||||||
|
|
||||||
## 🆙 How to Update
|
## 🆙 How to Update
|
||||||
|
|
||||||
|
@ -79,7 +79,7 @@ PS: For every new release, it takes some time to build the docker image, please
|
||||||
```bash
|
```bash
|
||||||
cd <uptime-kuma-directory>
|
cd <uptime-kuma-directory>
|
||||||
git fetch --all
|
git fetch --all
|
||||||
git checkout 1.1.0 --force
|
git checkout 1.2.0 --force
|
||||||
npm install
|
npm install
|
||||||
npm run build
|
npm run build
|
||||||
pm2 restart uptime-kuma
|
pm2 restart uptime-kuma
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
{
|
{
|
||||||
"name": "uptime-kuma",
|
"name": "uptime-kuma",
|
||||||
"version": "1.1.0",
|
"version": "1.2.0",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"repository": {
|
"repository": {
|
||||||
"type": "git",
|
"type": "git",
|
||||||
|
@ -17,10 +17,10 @@
|
||||||
"update": "",
|
"update": "",
|
||||||
"build": "vite build",
|
"build": "vite build",
|
||||||
"vite-preview-dist": "vite preview --host",
|
"vite-preview-dist": "vite preview --host",
|
||||||
"build-docker": "docker buildx build --platform linux/amd64,linux/arm64,linux/arm/v7 -t louislam/uptime-kuma -t louislam/uptime-kuma:1 -t louislam/uptime-kuma:1.1.0 --target release . --push",
|
"build-docker": "docker buildx build --platform linux/amd64,linux/arm64,linux/arm/v7 -t louislam/uptime-kuma -t louislam/uptime-kuma:1 -t louislam/uptime-kuma:1.2.0 --target release . --push",
|
||||||
"build-docker-nightly": "docker buildx build --platform linux/amd64,linux/arm64,linux/arm/v7 -t louislam/uptime-kuma:nightly --target nightly . --push",
|
"build-docker-nightly": "docker buildx build --platform linux/amd64,linux/arm64,linux/arm/v7 -t louislam/uptime-kuma:nightly --target nightly . --push",
|
||||||
"build-docker-nightly-amd64": "docker buildx build --platform linux/amd64 -t louislam/uptime-kuma:nightly-amd64 --target nightly . --push",
|
"build-docker-nightly-amd64": "docker buildx build --platform linux/amd64 -t louislam/uptime-kuma:nightly-amd64 --target nightly . --push",
|
||||||
"setup": "git checkout 1.1.0 && npm install && npm run build",
|
"setup": "git checkout 1.2.0 && npm install && npm run build",
|
||||||
"update-version": "node extra/update-version.js",
|
"update-version": "node extra/update-version.js",
|
||||||
"mark-as-nightly": "node extra/mark-as-nightly.js",
|
"mark-as-nightly": "node extra/mark-as-nightly.js",
|
||||||
"reset-password": "node extra/reset-password.js",
|
"reset-password": "node extra/reset-password.js",
|
||||||
|
|
|
@ -24,10 +24,15 @@ class Database {
|
||||||
pool: {
|
pool: {
|
||||||
min: 1,
|
min: 1,
|
||||||
max: 1,
|
max: 1,
|
||||||
idleTimeoutMillis: 30000,
|
acquireTimeoutMillis: 3600 * 1000,
|
||||||
|
idleTimeoutMillis: 3600 * 1000
|
||||||
}
|
}
|
||||||
}));
|
}));
|
||||||
|
|
||||||
|
if (process.env.SQL_LOG === "1") {
|
||||||
|
R.debug(true);
|
||||||
|
}
|
||||||
|
|
||||||
// Auto map the model to a bean object
|
// Auto map the model to a bean object
|
||||||
R.freeze(true)
|
R.freeze(true)
|
||||||
await R.autoloadModels("./server/model");
|
await R.autoloadModels("./server/model");
|
||||||
|
|
|
@ -6,7 +6,7 @@ dayjs.extend(utc)
|
||||||
dayjs.extend(timezone)
|
dayjs.extend(timezone)
|
||||||
const axios = require("axios");
|
const axios = require("axios");
|
||||||
const { Prometheus } = require("../prometheus");
|
const { Prometheus } = require("../prometheus");
|
||||||
const { debug, UP, DOWN, PENDING, flipStatus } = require("../../src/util");
|
const { debug, UP, DOWN, PENDING, flipStatus, TimeLogger } = require("../../src/util");
|
||||||
const { tcping, ping, checkCertificate, checkStatusCode } = require("../util-server");
|
const { tcping, ping, checkCertificate, checkStatusCode } = require("../util-server");
|
||||||
const { R } = require("redbean-node");
|
const { R } = require("redbean-node");
|
||||||
const { BeanModel } = require("redbean-node/dist/bean-model");
|
const { BeanModel } = require("redbean-node/dist/bean-model");
|
||||||
|
@ -133,7 +133,6 @@ class Monitor extends BeanModel {
|
||||||
bean.ping = dayjs().valueOf() - startTime;
|
bean.ping = dayjs().valueOf() - startTime;
|
||||||
|
|
||||||
// Check certificate if https is used
|
// Check certificate if https is used
|
||||||
|
|
||||||
let certInfoStartTime = dayjs().valueOf();
|
let certInfoStartTime = dayjs().valueOf();
|
||||||
if (this.getUrl()?.protocol === "https:") {
|
if (this.getUrl()?.protocol === "https:") {
|
||||||
try {
|
try {
|
||||||
|
@ -311,10 +310,10 @@ class Monitor extends BeanModel {
|
||||||
}
|
}
|
||||||
|
|
||||||
static async sendStats(io, monitorID, userID) {
|
static async sendStats(io, monitorID, userID) {
|
||||||
Monitor.sendAvgPing(24, io, monitorID, userID);
|
await Monitor.sendAvgPing(24, io, monitorID, userID);
|
||||||
Monitor.sendUptime(24, io, monitorID, userID);
|
await Monitor.sendUptime(24, io, monitorID, userID);
|
||||||
Monitor.sendUptime(24 * 30, io, monitorID, userID);
|
await Monitor.sendUptime(24 * 30, io, monitorID, userID);
|
||||||
Monitor.sendCertInfo(io, monitorID, userID);
|
await Monitor.sendCertInfo(io, monitorID, userID);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -322,6 +321,8 @@ class Monitor extends BeanModel {
|
||||||
* @param duration : int Hours
|
* @param duration : int Hours
|
||||||
*/
|
*/
|
||||||
static async sendAvgPing(duration, io, monitorID, userID) {
|
static async sendAvgPing(duration, io, monitorID, userID) {
|
||||||
|
const timeLogger = new TimeLogger();
|
||||||
|
|
||||||
let avgPing = parseInt(await R.getCell(`
|
let avgPing = parseInt(await R.getCell(`
|
||||||
SELECT AVG(ping)
|
SELECT AVG(ping)
|
||||||
FROM heartbeat
|
FROM heartbeat
|
||||||
|
@ -332,6 +333,8 @@ class Monitor extends BeanModel {
|
||||||
monitorID,
|
monitorID,
|
||||||
]));
|
]));
|
||||||
|
|
||||||
|
timeLogger.print(`[Monitor: ${monitorID}] avgPing`);
|
||||||
|
|
||||||
io.to(userID).emit("avgPing", monitorID, avgPing);
|
io.to(userID).emit("avgPing", monitorID, avgPing);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -351,6 +354,8 @@ class Monitor extends BeanModel {
|
||||||
* @param duration : int Hours
|
* @param duration : int Hours
|
||||||
*/
|
*/
|
||||||
static async sendUptime(duration, io, monitorID, userID) {
|
static async sendUptime(duration, io, monitorID, userID) {
|
||||||
|
const timeLogger = new TimeLogger();
|
||||||
|
|
||||||
let sec = duration * 3600;
|
let sec = duration * 3600;
|
||||||
|
|
||||||
let heartbeatList = await R.getAll(`
|
let heartbeatList = await R.getAll(`
|
||||||
|
@ -362,6 +367,8 @@ class Monitor extends BeanModel {
|
||||||
monitorID,
|
monitorID,
|
||||||
]);
|
]);
|
||||||
|
|
||||||
|
timeLogger.print(`[Monitor: ${monitorID}][${duration}] sendUptime`);
|
||||||
|
|
||||||
let downtime = 0;
|
let downtime = 0;
|
||||||
let total = 0;
|
let total = 0;
|
||||||
let uptime;
|
let uptime;
|
||||||
|
|
|
@ -197,9 +197,9 @@ class Notification {
|
||||||
try {
|
try {
|
||||||
let config = {
|
let config = {
|
||||||
headers: {
|
headers: {
|
||||||
'api-key': notification.octopushAPIKey,
|
"api-key": notification.octopushAPIKey,
|
||||||
'api-login': notification.octopushLogin,
|
"api-login": notification.octopushLogin,
|
||||||
'cache-control': 'no-cache'
|
"cache-control": "no-cache"
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
let data = {
|
let data = {
|
||||||
|
@ -215,7 +215,7 @@ class Notification {
|
||||||
"sender": notification.octopushSenderName
|
"sender": notification.octopushSenderName
|
||||||
};
|
};
|
||||||
|
|
||||||
await axios.post(`https://api.octopush.com/v1/public/sms-campaign/send`, data, config)
|
await axios.post("https://api.octopush.com/v1/public/sms-campaign/send", data, config)
|
||||||
return true;
|
return true;
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.log(error)
|
console.log(error)
|
||||||
|
@ -356,30 +356,30 @@ class Notification {
|
||||||
|
|
||||||
} else if (notification.type === "pushbullet") {
|
} else if (notification.type === "pushbullet") {
|
||||||
try {
|
try {
|
||||||
let pushbulletUrl = `https://api.pushbullet.com/v2/pushes`;
|
let pushbulletUrl = "https://api.pushbullet.com/v2/pushes";
|
||||||
let config = {
|
let config = {
|
||||||
headers: {
|
headers: {
|
||||||
'Access-Token': notification.pushbulletAccessToken,
|
"Access-Token": notification.pushbulletAccessToken,
|
||||||
'Content-Type': 'application/json'
|
"Content-Type": "application/json"
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
if (heartbeatJSON == null) {
|
if (heartbeatJSON == null) {
|
||||||
let testdata = {
|
let testdata = {
|
||||||
"type": "note",
|
"type": "note",
|
||||||
"title": "Uptime Kuma Alert",
|
"title": "Uptime Kuma Alert",
|
||||||
"body": "Testing Successful.",
|
"body": "Testing Successful.",
|
||||||
}
|
}
|
||||||
await axios.post(pushbulletUrl, testdata, config)
|
await axios.post(pushbulletUrl, testdata, config)
|
||||||
} else if (heartbeatJSON["status"] == 0) {
|
} else if (heartbeatJSON["status"] == 0) {
|
||||||
let downdata = {
|
let downdata = {
|
||||||
"type": "note",
|
"type": "note",
|
||||||
"title": "UptimeKuma Alert:" + monitorJSON["name"],
|
"title": "UptimeKuma Alert:" + monitorJSON["name"],
|
||||||
"body": "[🔴 Down]" + heartbeatJSON["msg"] + "\nTime (UTC):" + heartbeatJSON["time"],
|
"body": "[🔴 Down]" + heartbeatJSON["msg"] + "\nTime (UTC):" + heartbeatJSON["time"],
|
||||||
}
|
}
|
||||||
await axios.post(pushbulletUrl, downdata, config)
|
await axios.post(pushbulletUrl, downdata, config)
|
||||||
} else if (heartbeatJSON["status"] == 1) {
|
} else if (heartbeatJSON["status"] == 1) {
|
||||||
let updata = {
|
let updata = {
|
||||||
"type": "note",
|
"type": "note",
|
||||||
"title": "UptimeKuma Alert:" + monitorJSON["name"],
|
"title": "UptimeKuma Alert:" + monitorJSON["name"],
|
||||||
"body": "[✅ Up]" + heartbeatJSON["msg"] + "\nTime (UTC):" + heartbeatJSON["time"],
|
"body": "[✅ Up]" + heartbeatJSON["msg"] + "\nTime (UTC):" + heartbeatJSON["time"],
|
||||||
}
|
}
|
||||||
|
@ -432,15 +432,21 @@ class Notification {
|
||||||
|
|
||||||
static async smtp(notification, msg) {
|
static async smtp(notification, msg) {
|
||||||
|
|
||||||
let transporter = nodemailer.createTransport({
|
const config = {
|
||||||
host: notification.smtpHost,
|
host: notification.smtpHost,
|
||||||
port: notification.smtpPort,
|
port: notification.smtpPort,
|
||||||
secure: notification.smtpSecure,
|
secure: notification.smtpSecure,
|
||||||
auth: {
|
};
|
||||||
|
|
||||||
|
// Should fix the issue in https://github.com/louislam/uptime-kuma/issues/26#issuecomment-896373904
|
||||||
|
if (notification.smtpUsername || notification.smtpPassword) {
|
||||||
|
config.auth = {
|
||||||
user: notification.smtpUsername,
|
user: notification.smtpUsername,
|
||||||
pass: notification.smtpPassword,
|
pass: notification.smtpPassword,
|
||||||
},
|
};
|
||||||
});
|
}
|
||||||
|
|
||||||
|
let transporter = nodemailer.createTransport(config);
|
||||||
|
|
||||||
// send mail with defined transport object
|
// send mail with defined transport object
|
||||||
await transporter.sendMail({
|
await transporter.sendMail({
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
console.log("Welcome to Uptime Kuma");
|
console.log("Welcome to Uptime Kuma");
|
||||||
console.log("Node Env: " + process.env.NODE_ENV);
|
console.log("Node Env: " + process.env.NODE_ENV);
|
||||||
|
|
||||||
const { sleep, debug } = require("../src/util");
|
const { sleep, debug, TimeLogger } = require("../src/util");
|
||||||
|
|
||||||
console.log("Importing Node libraries")
|
console.log("Importing Node libraries")
|
||||||
const fs = require("fs");
|
const fs = require("fs");
|
||||||
|
@ -644,11 +644,11 @@ async function afterLogin(socket, user) {
|
||||||
|
|
||||||
// Delay a bit, so that it let the main page to query the data first, since SQLite can process one sql at the same time only.
|
// Delay a bit, so that it let the main page to query the data first, since SQLite can process one sql at the same time only.
|
||||||
// For example, query the edit data first.
|
// For example, query the edit data first.
|
||||||
setTimeout(() => {
|
setTimeout(async () => {
|
||||||
for (let monitorID in monitorList) {
|
for (let monitorID in monitorList) {
|
||||||
sendHeartbeatList(socket, monitorID);
|
await sendHeartbeatList(socket, monitorID);
|
||||||
sendImportantHeartbeatList(socket, monitorID);
|
await sendImportantHeartbeatList(socket, monitorID);
|
||||||
Monitor.sendStats(io, monitorID, user.id)
|
await Monitor.sendStats(io, monitorID, user.id)
|
||||||
}
|
}
|
||||||
}, 500);
|
}, 500);
|
||||||
}
|
}
|
||||||
|
@ -764,6 +764,8 @@ async function startMonitors() {
|
||||||
* Send Heartbeat History list to socket
|
* Send Heartbeat History list to socket
|
||||||
*/
|
*/
|
||||||
async function sendHeartbeatList(socket, monitorID) {
|
async function sendHeartbeatList(socket, monitorID) {
|
||||||
|
const timeLogger = new TimeLogger();
|
||||||
|
|
||||||
let list = await R.find("heartbeat", `
|
let list = await R.find("heartbeat", `
|
||||||
monitor_id = ?
|
monitor_id = ?
|
||||||
ORDER BY time DESC
|
ORDER BY time DESC
|
||||||
|
@ -782,6 +784,8 @@ async function sendHeartbeatList(socket, monitorID) {
|
||||||
}
|
}
|
||||||
|
|
||||||
async function sendImportantHeartbeatList(socket, monitorID) {
|
async function sendImportantHeartbeatList(socket, monitorID) {
|
||||||
|
const timeLogger = new TimeLogger();
|
||||||
|
|
||||||
let list = await R.find("heartbeat", `
|
let list = await R.find("heartbeat", `
|
||||||
monitor_id = ?
|
monitor_id = ?
|
||||||
AND important = 1
|
AND important = 1
|
||||||
|
@ -791,6 +795,8 @@ async function sendImportantHeartbeatList(socket, monitorID) {
|
||||||
monitorID,
|
monitorID,
|
||||||
])
|
])
|
||||||
|
|
||||||
|
timeLogger.print(`[Monitor: ${monitorID}] sendImportantHeartbeatList`);
|
||||||
|
|
||||||
socket.emit("importantHeartbeatList", monitorID, list)
|
socket.emit("importantHeartbeatList", monitorID, list)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
17
src/util.js
17
src/util.js
|
@ -1,6 +1,8 @@
|
||||||
"use strict";
|
"use strict";
|
||||||
Object.defineProperty(exports, "__esModule", { value: true });
|
Object.defineProperty(exports, "__esModule", { value: true });
|
||||||
exports.polyfill = exports.debug = exports.ucfirst = exports.sleep = exports.flipStatus = exports.PENDING = exports.UP = exports.DOWN = exports.appName = void 0;
|
exports.TimeLogger = exports.polyfill = exports.debug = exports.ucfirst = exports.sleep = exports.flipStatus = exports.PENDING = exports.UP = exports.DOWN = exports.appName = exports.isDev = void 0;
|
||||||
|
const dayjs = require("dayjs");
|
||||||
|
exports.isDev = process.env.NODE_ENV === "development";
|
||||||
exports.appName = "Uptime Kuma";
|
exports.appName = "Uptime Kuma";
|
||||||
exports.DOWN = 0;
|
exports.DOWN = 0;
|
||||||
exports.UP = 1;
|
exports.UP = 1;
|
||||||
|
@ -28,7 +30,7 @@ function ucfirst(str) {
|
||||||
}
|
}
|
||||||
exports.ucfirst = ucfirst;
|
exports.ucfirst = ucfirst;
|
||||||
function debug(msg) {
|
function debug(msg) {
|
||||||
if (process.env.NODE_ENV === "development") {
|
if (exports.isDev) {
|
||||||
console.log(msg);
|
console.log(msg);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -44,3 +46,14 @@ function polyfill() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
exports.polyfill = polyfill;
|
exports.polyfill = polyfill;
|
||||||
|
class TimeLogger {
|
||||||
|
constructor() {
|
||||||
|
this.startTime = dayjs().valueOf();
|
||||||
|
}
|
||||||
|
print(name) {
|
||||||
|
if (exports.isDev) {
|
||||||
|
console.log(name + ": " + (dayjs().valueOf() - this.startTime) + "ms");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
exports.TimeLogger = TimeLogger;
|
||||||
|
|
19
src/util.ts
19
src/util.ts
|
@ -4,6 +4,9 @@
|
||||||
// Frontend uses util.ts
|
// Frontend uses util.ts
|
||||||
// Need to run "tsc" to compile if there are any changes.
|
// Need to run "tsc" to compile if there are any changes.
|
||||||
|
|
||||||
|
import * as dayjs from "dayjs";
|
||||||
|
|
||||||
|
export const isDev = process.env.NODE_ENV === "development";
|
||||||
export const appName = "Uptime Kuma";
|
export const appName = "Uptime Kuma";
|
||||||
export const DOWN = 0;
|
export const DOWN = 0;
|
||||||
export const UP = 1;
|
export const UP = 1;
|
||||||
|
@ -39,7 +42,7 @@ export function ucfirst(str) {
|
||||||
}
|
}
|
||||||
|
|
||||||
export function debug(msg) {
|
export function debug(msg) {
|
||||||
if (process.env.NODE_ENV === "development") {
|
if (isDev) {
|
||||||
console.log(msg);
|
console.log(msg);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -52,7 +55,7 @@ export function polyfill() {
|
||||||
* @license MIT
|
* @license MIT
|
||||||
*/
|
*/
|
||||||
if (!String.prototype.replaceAll) {
|
if (!String.prototype.replaceAll) {
|
||||||
String.prototype.replaceAll = function(str, newStr) {
|
String.prototype.replaceAll = function (str, newStr) {
|
||||||
|
|
||||||
// If a regex pattern
|
// If a regex pattern
|
||||||
if (Object.prototype.toString.call(str).toLowerCase() === "[object regexp]") {
|
if (Object.prototype.toString.call(str).toLowerCase() === "[object regexp]") {
|
||||||
|
@ -65,3 +68,15 @@ export function polyfill() {
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export class TimeLogger {
|
||||||
|
constructor() {
|
||||||
|
this.startTime = dayjs().valueOf();
|
||||||
|
}
|
||||||
|
|
||||||
|
print(name) {
|
||||||
|
if (isDev) {
|
||||||
|
console.log(name + ": " + (dayjs().valueOf() - this.startTime) + "ms")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in a new issue