mirror of
https://github.com/bluewave-labs/Checkmate.git
synced 2026-04-25 18:40:59 -05:00
move to src
This commit is contained in:
Executable
+100
@@ -0,0 +1,100 @@
|
||||
const calculatePercentile = (arr, percentile) => {
|
||||
const sorted = arr.slice().sort((a, b) => a.responseTime - b.responseTime);
|
||||
const index = (percentile / 100) * (sorted.length - 1);
|
||||
const lower = Math.floor(index);
|
||||
const upper = lower + 1;
|
||||
const weight = index % 1;
|
||||
if (upper >= sorted.length) return sorted[lower].responseTime;
|
||||
return sorted[lower].responseTime * (1 - weight) + sorted[upper].responseTime * weight;
|
||||
};
|
||||
|
||||
const calculatePercentileUptimeDetails = (arr, percentile) => {
|
||||
const sorted = arr.slice().sort((a, b) => a.avgResponseTime - b.avgResponseTime);
|
||||
const index = (percentile / 100) * (sorted.length - 1);
|
||||
const lower = Math.floor(index);
|
||||
const upper = lower + 1;
|
||||
const weight = index % 1;
|
||||
if (upper >= sorted.length) return sorted[lower].avgResponseTime;
|
||||
return sorted[lower].avgResponseTime * (1 - weight) + sorted[upper].avgResponseTime * weight;
|
||||
};
|
||||
|
||||
const NormalizeData = (checks, rangeMin, rangeMax) => {
|
||||
if (checks.length > 1) {
|
||||
// Get the 5th and 95th percentile
|
||||
const min = calculatePercentile(checks, 0);
|
||||
const max = calculatePercentile(checks, 95);
|
||||
const normalizedChecks = checks.map((check) => {
|
||||
const originalResponseTime = check.responseTime;
|
||||
// Normalize the response time between 1 and 100
|
||||
let normalizedResponseTime = rangeMin + ((check.responseTime - min) * (rangeMax - rangeMin)) / (max - min);
|
||||
|
||||
// Put a floor on the response times so we don't have extreme outliers
|
||||
// Better visuals
|
||||
normalizedResponseTime = Math.max(rangeMin, Math.min(rangeMax, normalizedResponseTime));
|
||||
return {
|
||||
...check,
|
||||
responseTime: normalizedResponseTime,
|
||||
originalResponseTime: originalResponseTime,
|
||||
};
|
||||
});
|
||||
|
||||
return normalizedChecks;
|
||||
} else {
|
||||
return checks.map((check) => {
|
||||
return { ...check, originalResponseTime: check.responseTime };
|
||||
});
|
||||
}
|
||||
};
|
||||
const NormalizeDataUptimeDetails = (checks, rangeMin, rangeMax) => {
|
||||
if (checks.length > 1) {
|
||||
// Get the 5th and 95th percentile
|
||||
const min = calculatePercentileUptimeDetails(checks, 0);
|
||||
const max = calculatePercentileUptimeDetails(checks, 95);
|
||||
|
||||
const normalizedChecks = checks.map((check) => {
|
||||
const originalResponseTime = check.avgResponseTime;
|
||||
// Normalize the response time between 1 and 100
|
||||
let normalizedResponseTime = rangeMin + ((check.avgResponseTime - min) * (rangeMax - rangeMin)) / (max - min);
|
||||
|
||||
// Put a floor on the response times so we don't have extreme outliers
|
||||
// Better visuals
|
||||
normalizedResponseTime = Math.max(rangeMin, Math.min(rangeMax, normalizedResponseTime));
|
||||
return {
|
||||
...check,
|
||||
avgResponseTime: normalizedResponseTime,
|
||||
originalAvgResponseTime: originalResponseTime,
|
||||
};
|
||||
});
|
||||
|
||||
return normalizedChecks;
|
||||
} else {
|
||||
return checks.map((check) => {
|
||||
return { ...check, originalResponseTime: check.responseTime };
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
const safelyParseFloat = (value, defaultValue = 0) => {
|
||||
if (value === null || typeof value === "undefined") {
|
||||
return defaultValue;
|
||||
}
|
||||
const stringValue = String(value).trim();
|
||||
|
||||
if (typeof value === "number" && !isNaN(value)) {
|
||||
return value;
|
||||
}
|
||||
|
||||
if (stringValue === "") {
|
||||
return defaultValue;
|
||||
}
|
||||
|
||||
const parsedValue = parseFloat(stringValue);
|
||||
|
||||
if (isNaN(parsedValue) || !isFinite(parsedValue)) {
|
||||
return defaultValue;
|
||||
}
|
||||
|
||||
return parsedValue;
|
||||
};
|
||||
|
||||
export { safelyParseFloat, calculatePercentile, NormalizeData, calculatePercentileUptimeDetails, NormalizeDataUptimeDetails };
|
||||
Executable
+22
@@ -0,0 +1,22 @@
|
||||
[
|
||||
{
|
||||
"name": "Google",
|
||||
"url": "https://www.google.com"
|
||||
},
|
||||
{
|
||||
"name": "Facebook",
|
||||
"url": "https://www.facebook.com"
|
||||
},
|
||||
{
|
||||
"name": "Yahoo",
|
||||
"url": "https://www.yahoo.com"
|
||||
},
|
||||
{
|
||||
"name": "Amazon",
|
||||
"url": "https://www.amazon.com"
|
||||
},
|
||||
{
|
||||
"name": "Apple",
|
||||
"url": "https://www.apple.com"
|
||||
}
|
||||
]
|
||||
Executable
+1271
File diff suppressed because it is too large
Load Diff
Executable
+25
@@ -0,0 +1,25 @@
|
||||
import sharp from "sharp";
|
||||
/**
|
||||
* Generates a 64 * 64 pixel image from a given image
|
||||
* @param {} file
|
||||
*/
|
||||
const GenerateAvatarImage = async (file) => {
|
||||
try {
|
||||
// Resize to target 64 * 64
|
||||
let resizedImageBuffer = await sharp(file.buffer)
|
||||
.resize({
|
||||
width: 64,
|
||||
height: 64,
|
||||
fit: "cover",
|
||||
})
|
||||
.toBuffer();
|
||||
|
||||
//Get b64 string
|
||||
const base64Image = resizedImageBuffer.toString("base64");
|
||||
return base64Image;
|
||||
} catch (error) {
|
||||
throw error;
|
||||
}
|
||||
};
|
||||
|
||||
export { GenerateAvatarImage };
|
||||
Executable
+151
@@ -0,0 +1,151 @@
|
||||
import { createLogger, format, transports } from "winston";
|
||||
import dotenv from "dotenv";
|
||||
dotenv.config();
|
||||
|
||||
const SERVICE_NAME = "Logger";
|
||||
|
||||
class Logger {
|
||||
static SERVICE_NAME = SERVICE_NAME;
|
||||
constructor() {
|
||||
this.logCache = [];
|
||||
this.maxCacheSize = 1000;
|
||||
const consoleFormat = format.printf(({ level, message, service, method, details, timestamp, stack }) => {
|
||||
if (message instanceof Object) {
|
||||
message = JSON.stringify(message, null, 2);
|
||||
}
|
||||
|
||||
if (details instanceof Object) {
|
||||
details = JSON.stringify(details, null, 2);
|
||||
}
|
||||
let msg = `${timestamp} ${level}:`;
|
||||
service && (msg += ` [${service}]`);
|
||||
method && (msg += `(${method})`);
|
||||
message && (msg += ` ${message}`);
|
||||
details && (msg += ` (details: ${details})`);
|
||||
|
||||
if (typeof stack !== "undefined") {
|
||||
const stackTrace = stack
|
||||
?.split("\n")
|
||||
.slice(1) // Remove first line (error message)
|
||||
.map((line) => {
|
||||
const match = line.match(/at\s+(.+?)\s+\((.+?):(\d+):(\d+)\)/);
|
||||
if (match) {
|
||||
return {
|
||||
function: match[1],
|
||||
file: match[2],
|
||||
line: parseInt(match[3]),
|
||||
column: parseInt(match[4]),
|
||||
};
|
||||
}
|
||||
return line.trim();
|
||||
});
|
||||
stack && (msg += ` (stack: ${JSON.stringify(stackTrace, null, 2)})`);
|
||||
}
|
||||
|
||||
return msg;
|
||||
});
|
||||
|
||||
const logLevel = process.env.LOG_LEVEL || "info";
|
||||
|
||||
this.logger = createLogger({
|
||||
level: logLevel,
|
||||
format: format.combine(format.timestamp()),
|
||||
transports: [
|
||||
new transports.Console({
|
||||
format: format.combine(format.colorize(), format.prettyPrint(), format.json(), consoleFormat),
|
||||
}),
|
||||
new transports.File({
|
||||
format: format.combine(format.json()),
|
||||
filename: "app.log",
|
||||
}),
|
||||
],
|
||||
});
|
||||
}
|
||||
|
||||
get serviceName() {
|
||||
return Logger.SERVICE_NAME;
|
||||
}
|
||||
|
||||
/**
|
||||
* Logs an informational message.
|
||||
* @param {Object} config - The configuration object.
|
||||
* @param {string} config.message - The message to log.
|
||||
* @param {string} config.service - The service name.
|
||||
* @param {string} config.method - The method name.
|
||||
* @param {Object} config.details - Additional details.
|
||||
*/
|
||||
info(config) {
|
||||
const logEntry = this.buildLogEntry("info", config);
|
||||
this.cacheLog(logEntry);
|
||||
this.logger.info(logEntry);
|
||||
}
|
||||
|
||||
/**
|
||||
* Logs a warning message.
|
||||
* @param {Object} config - The configuration object.
|
||||
* @param {string} config.message - The message to log.
|
||||
* @param {string} config.service - The service name.
|
||||
* @param {string} config.method - The method name.
|
||||
* @param {Object} config.details - Additional details.
|
||||
*/
|
||||
warn(config) {
|
||||
const logEntry = this.buildLogEntry("warn", config);
|
||||
this.cacheLog(logEntry);
|
||||
this.logger.warn(logEntry);
|
||||
}
|
||||
|
||||
/**
|
||||
* Logs an error message.
|
||||
* @param {Object} config - The configuration object.
|
||||
* @param {string} config.message - The message to log.
|
||||
* @param {string} config.service - The service name.
|
||||
* @param {string} config.method - The method name.
|
||||
* @param {Object} config.details - Additional details.
|
||||
*/
|
||||
error(config) {
|
||||
const logEntry = this.buildLogEntry("error", config);
|
||||
this.cacheLog(logEntry);
|
||||
this.logger.error(logEntry);
|
||||
}
|
||||
/**
|
||||
* Logs a debug message.
|
||||
* @param {Object} config - The configuration object.
|
||||
* @param {string} config.message - The message to log.
|
||||
* @param {string} config.service - The service name.
|
||||
* @param {string} config.method - The method name.
|
||||
* @param {Object} config.details - Additional details.
|
||||
*/
|
||||
debug(config) {
|
||||
const logEntry = this.buildLogEntry("debug", config);
|
||||
this.cacheLog(logEntry);
|
||||
this.logger.debug(logEntry);
|
||||
}
|
||||
|
||||
cacheLog(entry) {
|
||||
this.logCache.push(entry);
|
||||
if (this.logCache.length > this.maxCacheSize) {
|
||||
this.logCache.shift();
|
||||
}
|
||||
}
|
||||
|
||||
getLogs() {
|
||||
return this.logCache;
|
||||
}
|
||||
|
||||
buildLogEntry(level, config) {
|
||||
return {
|
||||
level,
|
||||
message: config.message,
|
||||
service: config.service,
|
||||
method: config.method,
|
||||
details: config.details,
|
||||
stack: config.stack,
|
||||
timestamp: new Date().toISOString(),
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
const logger = new Logger();
|
||||
export { Logger };
|
||||
|
||||
export default logger;
|
||||
@@ -0,0 +1,13 @@
|
||||
export const ROLES = {
|
||||
SUPERADMIN: "superadmin",
|
||||
ADMIN: "admin",
|
||||
USER: "user",
|
||||
DEMO: "demo",
|
||||
};
|
||||
|
||||
export const VALID_ROLES = [ROLES.ADMIN, ROLES.USER, ROLES.DEMO];
|
||||
|
||||
export const EDITABLE_ROLES = [
|
||||
{ role: ROLES.ADMIN, _id: ROLES.ADMIN },
|
||||
{ role: ROLES.USER, _id: ROLES.USER },
|
||||
];
|
||||
Executable
+24
@@ -0,0 +1,24 @@
|
||||
/**
|
||||
* Converts a request body parameter to a boolean.
|
||||
* @param {string | boolean} value
|
||||
* @returns {boolean}
|
||||
*/
|
||||
const ParseBoolean = (value) => {
|
||||
if (value === true || value === "true") {
|
||||
return true;
|
||||
} else if (value === false || value === "false" || value === null || value === undefined) {
|
||||
return false;
|
||||
}
|
||||
};
|
||||
|
||||
const getTokenFromHeaders = (headers) => {
|
||||
const authorizationHeader = headers.authorization;
|
||||
if (!authorizationHeader) throw new Error("No auth headers");
|
||||
|
||||
const parts = authorizationHeader.split(" ");
|
||||
if (parts.length !== 2 || parts[0] !== "Bearer") throw new Error("Invalid auth headers");
|
||||
|
||||
return parts[1];
|
||||
};
|
||||
|
||||
export { ParseBoolean, getTokenFromHeaders };
|
||||
Reference in New Issue
Block a user