UNPKG

@syngrisi/syngrisi

Version:
2,024 lines (1,992 loc) 64.7 kB
"use strict"; var __create = Object.create; var __defProp = Object.defineProperty; var __getOwnPropDesc = Object.getOwnPropertyDescriptor; var __getOwnPropNames = Object.getOwnPropertyNames; var __getProtoOf = Object.getPrototypeOf; var __hasOwnProp = Object.prototype.hasOwnProperty; var __export = (target, all) => { for (var name in all) __defProp(target, name, { get: all[name], enumerable: true }); }; var __copyProps = (to, from, except, desc) => { if (from && typeof from === "object" || typeof from === "function") { for (let key of __getOwnPropNames(from)) if (!__hasOwnProp.call(to, key) && key !== except) __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable }); } return to; }; var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps( // If the importer is in node compatibility mode or this is not an ESM // file that has been converted to a CommonJS file using a Babel- // compatible transform (i.e. "__esModule" has not been set), then set // "default" to the CommonJS "module.exports" for node compatibility. isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target, mod )); var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod); // src/server/services/tasks.service.ts var tasks_service_exports = {}; __export(tasks_service_exports, { loadTestUser: () => loadTestUser, screenshots: () => screenshots, status: () => status, task_handle_database_consistency: () => task_handle_database_consistency, task_handle_old_checks: () => task_handle_old_checks, task_remove_old_logs: () => task_remove_old_logs, task_test: () => task_test }); module.exports = __toCommonJS(tasks_service_exports); // src/server/envConfig.ts var import_envalid = require("envalid"); var import_crypto = __toESM(require("crypto")); var import_path = __toESM(require("path")); var import_dotenv = __toESM(require("dotenv")); import_dotenv.default.config(); if (!process.env.NODE_ENV) { process.env.NODE_ENV = "production"; } var env = (0, import_envalid.cleanEnv)(process.env, { NODE_ENV: (0, import_envalid.str)({ choices: ["development", "production", "test"] }), SYNGRISI_DB_URI: (0, import_envalid.str)({ default: "mongodb://127.0.0.1:27017/SyngrisiDb" }), SYNGRISI_APP_PORT: (0, import_envalid.port)({ default: 3e3 }), SYNGRISI_IMAGES_PATH: (0, import_envalid.str)({ default: import_path.default.join(process.cwd(), "./.snapshots-images") }), SYNGRISI_TMP_DIR: (0, import_envalid.str)({ default: import_path.default.join(process.cwd(), ".tmp") }), SYNGRISI_HTTP_LOG: (0, import_envalid.bool)({ default: false }), SYNGRISI_COVERAGE: (0, import_envalid.bool)({ default: false }), SYNGRISI_HOSTNAME: (0, import_envalid.host)({ default: "localhost" }), SYNGRISI_AUTH: (0, import_envalid.bool)({ default: true }), SYNGRISI_TEST_MODE: (0, import_envalid.bool)({ default: false }), SYNGRISI_DISABLE_FIRST_RUN: (0, import_envalid.bool)({ default: false }), MONGODB_ROOT_USERNAME: (0, import_envalid.str)({ default: "" }), MONGODB_ROOT_PASSWORD: (0, import_envalid.str)({ default: "" }), LOGLEVEL: (0, import_envalid.str)({ choices: ["error", "warn", "info", "verbose", "debug", "silly"], default: "debug" }), SYNGRISI_PAGINATION_SIZE: (0, import_envalid.num)({ default: 50 }), SYNGRISI_DISABLE_DEV_CORS: (0, import_envalid.bool)({ default: true, devDefault: true }), SYNGRISI_SESSION_STORE_KEY: (0, import_envalid.str)({ default: import_crypto.default.randomBytes(64).toString("hex") }), SYNGRISI_LOG_LEVEL: (0, import_envalid.str)({ default: "debug" }), // trunk features SYNGRISI_TRUNK_FEATURE_AI_SEVERITY: (0, import_envalid.bool)({ default: false }), SYNGRISI_AI_KEY: (0, import_envalid.str)({ default: "" }), OPENAI_API_BASE_URL: (0, import_envalid.str)({ default: "https://api.openai.com/v1" }), OPENAI_API_KEY: (0, import_envalid.str)({ default: "" }) }); // src/server/services/tasks.service.ts var import_fs2 = __toESM(require("fs")); var import_string_table = __toESM(require("string-table")); // src/server/config.ts var import_fs = __toESM(require("fs")); var import_dotenv2 = __toESM(require("dotenv")); // package.json var version = "2.2.26-alpha.0"; // src/server/config.ts var import_crypto2 = __toESM(require("crypto")); // src/server/data/devices.json var devices_default = [ { os: "ios", os_version: "16", device: "iPhone 14 Pro Max", realMobile: true }, { os: "ios", os_version: "16", device: "iPhone 14 Pro", realMobile: true }, { os: "ios", os_version: "16", device: "iPhone 14 Plus", realMobile: true }, { os: "ios", os_version: "16", device: "iPhone 14", realMobile: true }, { os: "ios", os_version: "16", device: "iPhone 12 Pro Max", realMobile: true }, { os: "ios", os_version: "16", device: "iPhone 12 Pro", realMobile: true }, { os: "ios", os_version: "16", device: "iPhone 12 Mini", realMobile: true }, { os: "ios", os_version: "16", device: "iPhone 11 Pro Max", realMobile: true }, { os: "ios", os_version: "15", device: "iPhone XS", realMobile: true }, { os: "ios", os_version: "15", device: "iPhone 13 Pro Max", realMobile: true }, { os: "ios", os_version: "15", device: "iPhone 13 Pro", realMobile: true }, { os: "ios", os_version: "15", device: "iPhone 13 Mini", realMobile: true }, { os: "ios", os_version: "15", device: "iPhone 13", realMobile: true }, { os: "ios", os_version: "15", device: "iPhone 11 Pro", realMobile: true }, { os: "ios", os_version: "15", device: "iPhone 11", realMobile: true }, { os: "ios", os_version: "14", device: "iPhone XS", realMobile: true }, { os: "ios", os_version: "14", device: "iPhone 12 Pro Max", realMobile: true }, { os: "ios", os_version: "14", device: "iPhone 12 Pro", realMobile: true }, { os: "ios", os_version: "14", device: "iPhone 12 Mini", realMobile: true }, { os: "ios", os_version: "14", device: "iPhone 12", realMobile: true }, { os: "ios", os_version: "14", device: "iPhone 11 Pro Max", realMobile: true }, { os: "ios", os_version: "14", device: "iPhone 11", realMobile: true }, { os: "ios", os_version: "13", device: "iPhone XS", realMobile: true }, { os: "ios", os_version: "13", device: "iPhone 11 Pro Max", realMobile: true }, { os: "ios", os_version: "13", device: "iPhone 11 Pro", realMobile: true }, { os: "ios", os_version: "13", device: "iPhone 11", realMobile: true }, { os: "ios", os_version: "12", device: "iPhone XS", realMobile: true }, { os: "ios", os_version: "12", device: "iPhone XS Max", realMobile: true }, { os: "ios", os_version: "15", device: "iPhone XR", realMobile: true }, { os: "ios", os_version: "12", device: "iPhone XR", realMobile: true }, { os: "ios", os_version: "11", device: "iPhone X", realMobile: true }, { os: "ios", os_version: "15", device: "iPhone 8", realMobile: true }, { os: "ios", os_version: "13", device: "iPhone 8", realMobile: true }, { os: "ios", os_version: "12", device: "iPhone 8", realMobile: true }, { os: "ios", os_version: "11", device: "iPhone 8", realMobile: true }, { os: "ios", os_version: "12", device: "iPhone 8 Plus", realMobile: true }, { os: "ios", os_version: "11", device: "iPhone 8 Plus", realMobile: true }, { os: "ios", os_version: "12", device: "iPhone 7", realMobile: true }, { os: "ios", os_version: "10", device: "iPhone 7", realMobile: true }, { os: "ios", os_version: "12", device: "iPhone 6S", realMobile: true }, { os: "ios", os_version: "11", device: "iPhone 6S", realMobile: true }, { os: "ios", os_version: "11", device: "iPhone 6S Plus", realMobile: true }, { os: "ios", os_version: "11", device: "iPhone 6", realMobile: true }, { os: "ios", os_version: "15", device: "iPhone SE 2022", realMobile: true }, { os: "ios", os_version: "13", device: "iPhone SE 2020", realMobile: true }, { os: "ios", os_version: "11", device: "iPhone SE", realMobile: true }, { os: "ios", os_version: "14", device: "iPad Air 4", realMobile: true }, { os: "ios", os_version: "15", device: "iPad 9th", realMobile: true }, { os: "ios", os_version: "16", device: "iPad Pro 12.9 2022", realMobile: true }, { os: "ios", os_version: "16", device: "iPad Pro 12.9 2020", realMobile: true }, { os: "ios", os_version: "16", device: "iPad Pro 11 2022", realMobile: true }, { os: "ios", os_version: "16", device: "iPad 10th", realMobile: true }, { os: "ios", os_version: "15", device: "iPad Air 5", realMobile: true }, { os: "ios", os_version: "14", device: "iPad Pro 12.9 2021", realMobile: true }, { os: "ios", os_version: "14", device: "iPad Pro 12.9 2020", realMobile: true }, { os: "ios", os_version: "14", device: "iPad Pro 11 2021", realMobile: true }, { os: "ios", os_version: "13", device: "iPad Pro 12.9 2020", realMobile: true }, { os: "ios", os_version: "16", device: "iPad 8th", realMobile: true }, { os: "ios", os_version: "15", device: "iPad Pro 12.9 2018", realMobile: true }, { os: "ios", os_version: "15", device: "iPad Mini 2021", realMobile: true }, { os: "ios", os_version: "14", device: "iPad 8th", realMobile: true }, { os: "ios", os_version: "13", device: "iPad Pro 12.9 2018", realMobile: true }, { os: "ios", os_version: "13", device: "iPad Pro 11 2020", realMobile: true }, { os: "ios", os_version: "13", device: "iPad Mini 2019", realMobile: true }, { os: "ios", os_version: "13", device: "iPad Air 2019", realMobile: true }, { os: "ios", os_version: "13", device: "iPad 7th", realMobile: true }, { os: "ios", os_version: "12", device: "iPad Pro 12.9 2018", realMobile: true }, { os: "ios", os_version: "12", device: "iPad Pro 11 2018", realMobile: true }, { os: "ios", os_version: "12", device: "iPad Mini 2019", realMobile: true }, { os: "ios", os_version: "12", device: "iPad Air 2019", realMobile: true }, { os: "ios", os_version: "11", device: "iPad Pro 9.7 2016", realMobile: true }, { os: "ios", os_version: "11", device: "iPad Pro 12.9 2017", realMobile: true }, { os: "ios", os_version: "11", device: "iPad Mini 4", realMobile: true }, { os: "ios", os_version: "11", device: "iPad 6th", realMobile: true }, { os: "ios", os_version: "11", device: "iPad 5th", realMobile: true }, { os: "android", os_version: "12.0", device: "Samsung Galaxy S22 Ultra", realMobile: true }, { os: "android", os_version: "12.0", device: "Samsung Galaxy S22 Plus", realMobile: true }, { os: "android", os_version: "12.0", device: "Samsung Galaxy S22", realMobile: true }, { os: "android", os_version: "12.0", device: "Samsung Galaxy S21", realMobile: true }, { os: "android", os_version: "11.0", device: "Samsung Galaxy S21 Ultra", realMobile: true }, { os: "android", os_version: "11.0", device: "Samsung Galaxy S21", realMobile: true }, { os: "android", os_version: "11.0", device: "Samsung Galaxy S21 Plus", realMobile: true }, { os: "android", os_version: "10.0", device: "Samsung Galaxy S20", realMobile: true }, { os: "android", os_version: "10.0", device: "Samsung Galaxy S20 Plus", realMobile: true }, { os: "android", os_version: "10.0", device: "Samsung Galaxy S20 Ultra", realMobile: true }, { os: "android", os_version: "11.0", device: "Samsung Galaxy M52", realMobile: true }, { os: "android", os_version: "11.0", device: "Samsung Galaxy M32", realMobile: true }, { os: "android", os_version: "11.0", device: "Samsung Galaxy A52", realMobile: true }, { os: "android", os_version: "10.0", device: "Samsung Galaxy Note 20 Ultra", realMobile: true }, { os: "android", os_version: "10.0", device: "Samsung Galaxy Note 20", realMobile: true }, { os: "android", os_version: "10.0", device: "Samsung Galaxy A51", realMobile: true }, { os: "android", os_version: "10.0", device: "Samsung Galaxy A11", realMobile: true }, { os: "android", os_version: "9.0", device: "Samsung Galaxy S9 Plus", realMobile: true }, { os: "android", os_version: "9.0", device: "Samsung Galaxy S10e", realMobile: true }, { os: "android", os_version: "9.0", device: "Samsung Galaxy S10 Plus", realMobile: true }, { os: "android", os_version: "9.0", device: "Samsung Galaxy S10", realMobile: true }, { os: "android", os_version: "9.0", device: "Samsung Galaxy Note 10 Plus", realMobile: true }, { os: "android", os_version: "9.0", device: "Samsung Galaxy Note 10", realMobile: true }, { os: "android", os_version: "9.0", device: "Samsung Galaxy A10", realMobile: true }, { os: "android", os_version: "8.1", device: "Samsung Galaxy Note 9", realMobile: true }, { os: "android", os_version: "8.1", device: "Samsung Galaxy J7 Prime", realMobile: true }, { os: "android", os_version: "8.0", device: "Samsung Galaxy S9 Plus", realMobile: true }, { os: "android", os_version: "8.0", device: "Samsung Galaxy S9", realMobile: true }, { os: "android", os_version: "7.1", device: "Samsung Galaxy Note 8", realMobile: true }, { os: "android", os_version: "7.1", device: "Samsung Galaxy A8", realMobile: true }, { os: "android", os_version: "7.0", device: "Samsung Galaxy S8 Plus", realMobile: true }, { os: "android", os_version: "7.0", device: "Samsung Galaxy S8", realMobile: true }, { os: "android", os_version: "6.0", device: "Samsung Galaxy S7", realMobile: true }, { os: "android", os_version: "5.0", device: "Samsung Galaxy S6", realMobile: true }, { os: "android", os_version: "13.0", device: "Google Pixel 7 Pro", realMobile: true }, { os: "android", os_version: "13.0", device: "Google Pixel 7", realMobile: true }, { os: "android", os_version: "13.0", device: "Google Pixel 6 Pro", realMobile: true }, { os: "android", os_version: "12.0", device: "Google Pixel 6 Pro", realMobile: true }, { os: "android", os_version: "12.0", device: "Google Pixel 6", realMobile: true }, { os: "android", os_version: "12.0", device: "Google Pixel 5", realMobile: true }, { os: "android", os_version: "11.0", device: "Google Pixel 5", realMobile: true }, { os: "android", os_version: "11.0", device: "Google Pixel 4", realMobile: true }, { os: "android", os_version: "10.0", device: "Google Pixel 4 XL", realMobile: true }, { os: "android", os_version: "10.0", device: "Google Pixel 4", realMobile: true }, { os: "android", os_version: "10.0", device: "Google Pixel 3", realMobile: true }, { os: "android", os_version: "9.0", device: "Google Pixel 3a XL", realMobile: true }, { os: "android", os_version: "9.0", device: "Google Pixel 3a", realMobile: true }, { os: "android", os_version: "9.0", device: "Google Pixel 3 XL", realMobile: true }, { os: "android", os_version: "9.0", device: "Google Pixel 3", realMobile: true }, { os: "android", os_version: "9.0", device: "Google Pixel 2", realMobile: true }, { os: "android", os_version: "8.0", device: "Google Pixel 2", realMobile: true }, { os: "android", os_version: "7.1", device: "Google Pixel", realMobile: true }, { os: "android", os_version: "6.0", device: "Google Nexus 6", realMobile: true }, { os: "android", os_version: "4.4", device: "Google Nexus 5", realMobile: true }, { os: "android", os_version: "11.0", device: "OnePlus 9", realMobile: true }, { os: "android", os_version: "10.0", device: "OnePlus 8", realMobile: true }, { os: "android", os_version: "10.0", device: "OnePlus 7T", realMobile: true }, { os: "android", os_version: "9.0", device: "OnePlus 7", realMobile: true }, { os: "android", os_version: "9.0", device: "OnePlus 6T", realMobile: true }, { os: "android", os_version: "11.0", device: "Xiaomi Redmi Note 11", realMobile: true }, { os: "android", os_version: "10.0", device: "Xiaomi Redmi Note 9", realMobile: true }, { os: "android", os_version: "9.0", device: "Xiaomi Redmi Note 8", realMobile: true }, { os: "android", os_version: "9.0", device: "Xiaomi Redmi Note 7", realMobile: true }, { os: "android", os_version: "11.0", device: "Vivo Y21", realMobile: true }, { os: "android", os_version: "11.0", device: "Vivo V21", realMobile: true }, { os: "android", os_version: "10.0", device: "Vivo Y50", realMobile: true }, { os: "android", os_version: "11.0", device: "Oppo Reno 6", realMobile: true }, { os: "android", os_version: "11.0", device: "Oppo A96", realMobile: true }, { os: "android", os_version: "10.0", device: "Oppo Reno 3 Pro", realMobile: true }, { os: "android", os_version: "11.0", device: "Motorola Moto G71 5G", realMobile: true }, { os: "android", os_version: "10.0", device: "Motorola Moto G9 Play", realMobile: true }, { os: "android", os_version: "9.0", device: "Motorola Moto G7 Play", realMobile: true }, { os: "android", os_version: "9.0", device: "Huawei P30", realMobile: true }, { os: "android", os_version: "12.0", device: "Samsung Galaxy Tab S8", realMobile: true }, { os: "android", os_version: "11.0", device: "Samsung Galaxy Tab S7", realMobile: true }, { os: "android", os_version: "10.0", device: "Samsung Galaxy Tab S7", realMobile: true }, { os: "android", os_version: "9.0", device: "Samsung Galaxy Tab S6", realMobile: true }, { os: "android", os_version: "9.0", device: "Samsung Galaxy Tab S5e", realMobile: true }, { os: "android", os_version: "8.1", device: "Samsung Galaxy Tab S4", realMobile: true } ]; // src/server/config.ts var customDevicesPath = "./server/data/custom_devices.json"; var logsFolder = "./logs"; import_dotenv2.default.config(); var config = { version, // this isn't used getDevices: async () => { if (import_fs.default.existsSync(customDevicesPath)) { return [...devices_default, ...(await import(customDevicesPath)).default]; } return devices_default; }, defaultImagesPath: env.SYNGRISI_IMAGES_PATH, connectionString: env.SYNGRISI_DB_URI || "mongodb://127.0.0.1:27017/SyngrisiDb", host: env.SYNGRISI_HOSTNAME, port: env.SYNGRISI_APP_PORT || 3e3, backupsFolder: "./backups", enableHttpLogger: env.SYNGRISI_HTTP_LOG, httpLoggerFilePath: `${logsFolder}/http.log`, storeSessionKey: env.SYNGRISI_SESSION_STORE_KEY || import_crypto2.default.randomBytes(64).toString("hex"), codeCoverage: env.SYNGRISI_COVERAGE, disableCors: env.SYNGRISI_DISABLE_DEV_CORS, fileUploadMaxSize: 50 * 1024 * 1024, testMode: env.SYNGRISI_TEST_MODE, jsonLimit: "50mb", tmpDir: env.SYNGRISI_TMP_DIR, helmet: { crossOriginEmbedderPolicy: false, crossOriginResourcePolicy: false, crossOriginOpenerPolicy: false, contentSecurityPolicy: { directives: { // frameAncestors: ["'self'", "vscode-webview:", "vscode-resource:", "https:", "http:"], // frameSrc: ["'self'", "vscode-webview:", "https:", "http:"], // scriptSrc: ["'self'", "'unsafe-inline'"], // styleSrc: ["'self'", "'unsafe-inline'"] defaultSrc: ["'self'", "*", "'unsafe-inline'", "'unsafe-eval'", "data:", "blob:"], frameAncestors: ["'self'", "*"], frameSrc: ["'self'", "*"], scriptSrc: ["'self'", "*", "'unsafe-inline'", "'unsafe-eval'"], styleSrc: ["'self'", "*", "'unsafe-inline'"], imgSrc: ["'self'", "*", "data:", "blob:"], fontSrc: ["'self'", "*", "data:"], connectSrc: ["'self'", "*"] } } } }; if (!import_fs.default.existsSync(config.defaultImagesPath)) { import_fs.default.mkdirSync(config.defaultImagesPath, { recursive: true }); } if (!import_fs.default.existsSync(logsFolder)) { import_fs.default.mkdirSync(logsFolder, { recursive: true }); } // src/server/utils/dateToISO8601.ts var dateToISO8601 = (date) => { return new Date(new Date(date)).toISOString().split("T")[0]; }; var dateToISO8601_default = dateToISO8601; // src/server/utils/ProgressBar.ts var ProgressBar = class { constructor(length) { this.length = length; this.percentLenght = parseFloat((length / 100).toString()); this.prevPercent = 0; this.currentPercent = 0; this.progressString = ""; } isChange(current) { this.currentPercent = parseInt((current / this.percentLenght).toString(), 10); if (this.prevPercent === this.currentPercent) { return false; } this.prevPercent = this.currentPercent; this.progressString += "#"; return true; } writeIfChange(index, count, fn, res) { if (this.isChange(index)) { const placeholderString = Array.from(new Array(99 - this.currentPercent)).reduce((accum) => accum += ".", ""); fn(`[${this.progressString}${placeholderString}](${index}/${count})`, res); } } }; // src/server/utils/ApiError.ts var ApiError = class extends Error { constructor(statusCode, message, isOperational = true, stack = "") { super(message); this.statusCode = statusCode; this.isOperational = isOperational; if (stack) { this.stack = stack; } else { Error.captureStackTrace(this, this.constructor); } } }; var ApiError_default = ApiError; // src/server/utils/deserializeIfJSON.ts var import_bson = require("bson"); // src/server/models/Check.model.ts var import_mongoose = __toESM(require("mongoose")); // src/server/models/plugins/paginate.plugin.ts var paginate = (schema) => { schema.statics.paginate = async function(filter, options) { let sort; if (options.sortBy) { const sortingCriteria = []; options.sortBy.split(",").forEach((sortOption) => { const [key, order] = sortOption.split(":"); sortingCriteria.push((order === "desc" ? "-" : "") + key); }); sort = sortingCriteria.join(" "); } else { sort = { _id: -1 }; } const limit = options.limit && parseInt(options.limit.toString(), 10) >= 0 ? parseInt(options.limit.toString(), 10) : 10; const page = options.page && parseInt(options.page.toString(), 10) > 0 ? parseInt(options.page.toString(), 10) : 1; const skip = (page - 1) * limit; const countPromise = this.countDocuments(filter).exec(); let docsPromise = this.find(filter).sort(sort).skip(skip).limit(limit); if (options.populate) { options.populate.split(",").forEach((populateOption) => { docsPromise = docsPromise.populate( populateOption.split(".").reverse().reduce((a, b) => ({ path: b, populate: a })) ); }); } docsPromise = docsPromise.exec(); return Promise.all([countPromise, docsPromise]).then((values) => { const [totalResults, results] = values; const totalPages = Math.ceil(totalResults / limit); const result = { results, page, limit, totalPages, totalResults, timestamp: Number(Date.now() + String(process.hrtime()[1]).slice(3, 6)) }; return Promise.resolve(result); }); }; }; var paginate_plugin_default = paginate; // src/server/models/plugins/toJSON.plugin.ts var deleteAtPath = (obj, path4, index) => { if (index === path4.length - 1) { delete obj[path4[index]]; return; } deleteAtPath(obj[path4[index]], path4, index + 1); }; var toJSON = (schema) => { let transform; if (schema.options.toJSON && schema.options.toJSON.transform) { transform = schema.options.toJSON.transform; } schema.options.toJSON = Object.assign(schema.options.toJSON || {}, { transform(doc, ret, options) { Object.keys(schema.paths).forEach((path4) => { if (schema.paths[path4].options && schema.paths[path4].options.private) { deleteAtPath(ret, path4.split("."), 0); } }); ret.id = ret._id.toString(); delete ret.__v; delete ret.createdAt; delete ret.updatedAt; if (transform) { return transform(doc, ret, options); } } }); }; var toJSON_plugin_default = toJSON; // src/server/models/plugins/paginateDistinct.plugin.ts var import_bson2 = require("bson"); var paginateDistinct = (schema) => { schema.statics.paginateDistinct = async function(filter, options) { let sort; if (options.sortBy) { options.sortBy.split(",").forEach((sortOption) => { const [key, order] = sortOption.split(":"); sort[key] = order === "desc" ? -1 : 1; }); } else { sort = { _id: -1 }; } let limit = options.limit && parseInt(options.limit.toString(), 10) >= 0 ? parseInt(options.limit.toString(), 10) : 10; limit = limit === 0 ? 9007199254740991 : limit; const page = options.page && parseInt(options.page.toString(), 10) > 0 ? parseInt(options.page.toString(), 10) : 1; const skip = (page - 1) * limit; const groupAggregateObj = { $group: { _id: `$${options.field}` } }; const documentsCount = (await this.aggregate([groupAggregateObj]).exec()).length; const aggregateArr = [ { $match: import_bson2.EJSON.parse(filter.filter || "{}") }, groupAggregateObj, { $sort: sort }, { $skip: skip }, { $limit: limit } ]; const aggregatedDocs = (await this.aggregate(aggregateArr)).filter((x) => x._id).map((x) => { if (x[options.field]) { return x[options.field][0]; } return { name: x._id }; }); return Promise.all([documentsCount, aggregatedDocs]).then((values) => { const [totalResults, results] = values; const totalPages = Math.ceil(totalResults / limit); const result = { results, page, limit, totalPages, totalResults, timestamp: (/* @__PURE__ */ new Date()).getTime() }; return Promise.resolve(result); }); }; }; var paginateDistinct_plugin_default = paginateDistinct; // src/server/models/Check.model.ts var CheckSchema = new import_mongoose.Schema({ name: { type: String, required: [true, 'CheckSchema: The "name" field must be required'] }, test: { type: import_mongoose.Schema.Types.ObjectId, ref: "VRSTest", required: [true, 'CheckSchema: The "test" field must be required'] }, suite: { type: import_mongoose.Schema.Types.ObjectId, ref: "VRSSuite", required: [true, 'CheckSchema: The "suite" field must be required'] }, app: { type: import_mongoose.Schema.Types.ObjectId, ref: "VRSApp", required: [true, 'CheckSchema: The "app" field must be required'] }, branch: { type: String }, realBaselineId: { type: import_mongoose.Schema.Types.ObjectId, ref: "VRSBaseline" }, baselineId: { type: import_mongoose.Schema.Types.ObjectId, ref: "VRSSnapshot" }, actualSnapshotId: { type: import_mongoose.Schema.Types.ObjectId, ref: "VRSSnapshot" }, diffId: { type: import_mongoose.Schema.Types.ObjectId, ref: "VRSSnapshot" }, createdDate: { type: Date, required: true, default: Date.now }, updatedDate: { type: Date }, status: { type: [{ type: String, enum: { values: ["new", "pending", "approved", "running", "passed", "failed", "aborted"], message: "status is required" } }], default: ["new"] }, browserName: { type: String }, browserVersion: { type: String }, browserFullVersion: { type: String }, viewport: { type: String }, os: { type: String }, domDump: { type: String }, result: { type: String, default: "{}" }, run: { type: import_mongoose.Schema.Types.ObjectId }, markedAs: { type: String, enum: ["bug", "accepted"] }, markedDate: { type: Date }, markedById: { type: import_mongoose.Schema.Types.ObjectId, ref: "VRSUser" }, markedByUsername: { type: String }, markedBugComment: { type: String }, creatorId: { type: import_mongoose.Schema.Types.ObjectId, ref: "VRSUser" }, creatorUsername: { type: String }, failReasons: { type: [String] }, vOffset: { type: String }, topStablePixels: { type: String }, meta: { type: Object } }); CheckSchema.plugin(toJSON_plugin_default); CheckSchema.plugin(paginate_plugin_default); var Check = import_mongoose.default.model("VRSCheck", CheckSchema); var Check_model_default = Check; // src/server/models/Log.model.ts var import_mongoose2 = __toESM(require("mongoose")); var LogSchema = new import_mongoose2.Schema({ timestamp: { type: Date }, level: { type: String }, message: { type: String }, meta: { type: Object }, hostname: { type: Object } }); LogSchema.plugin(toJSON_plugin_default); LogSchema.plugin(paginate_plugin_default); var Log = import_mongoose2.default.model("VRSLog", LogSchema); var Log_model_default = Log; // src/server/models/App.model.ts var import_mongoose3 = __toESM(require("mongoose")); var AppSchema = new import_mongoose3.Schema({ name: { type: String, default: "Others", unique: true, required: [true, 'AppSchema: The "name" field must be required'] }, description: { type: String }, version: { type: String }, updatedDate: { type: Date }, createdDate: { type: Date }, meta: { type: Object } }); AppSchema.plugin(paginate_plugin_default); AppSchema.plugin(toJSON_plugin_default); var App = import_mongoose3.default.model("VRSApp", AppSchema); // src/server/models/Snapshot.model.ts var import_mongoose4 = __toESM(require("mongoose")); var SnapshotSchema = new import_mongoose4.Schema({ name: { type: String, required: [true, 'SnapshotSchema: The "name" field must be required'] }, path: { type: String }, filename: { type: String }, imghash: { type: String, required: [true, 'SnapshotSchema: The "imghash" field must be required'] }, createdDate: { type: Date, default: Date.now }, vOffset: { type: Number }, hOffset: { type: Number } }); SnapshotSchema.plugin(toJSON_plugin_default); SnapshotSchema.plugin(paginate_plugin_default); var Snapshot = import_mongoose4.default.model("VRSSnapshot", SnapshotSchema); var Snapshot_model_default = Snapshot; // src/server/models/AppSettings.model.ts var import_mongoose5 = __toESM(require("mongoose")); var AppSettingsSchema = new import_mongoose5.Schema({ name: { type: String, unique: true, required: [true, 'AppSettingsSchema: The "name" field must be required'] }, label: { type: String, required: [true, 'AppSettingsSchema: The "label" field must be required'] }, description: { type: String }, type: { type: String, required: [true, 'AppSettingsSchema: The "type" field must be required'] }, value: { type: import_mongoose5.Schema.Types.Mixed, required: [true, 'AppSettingsSchema: The "value" field must be required'] }, env_variable: { type: String }, enabled: { type: Boolean } }); AppSettingsSchema.plugin(toJSON_plugin_default); var AppSettings = import_mongoose5.default.model("VRSAppSettings", AppSettingsSchema); // src/server/models/Suite.model.ts var import_mongoose6 = __toESM(require("mongoose")); var SuiteSchema = new import_mongoose6.Schema({ name: { type: String, default: "Others", unique: true, required: [true, 'SuiteSchema: The "name" field must be required'] }, tags: { type: [String] }, app: { type: import_mongoose6.Schema.Types.ObjectId, ref: "VRSApp", required: [true, 'SuiteSchema: The "app" field must be required'] }, description: { type: String }, updatedDate: { type: Date, default: Date.now }, createdDate: { type: Date }, meta: { type: Object } }); SuiteSchema.plugin(paginate_plugin_default); SuiteSchema.plugin(toJSON_plugin_default); var Suite = import_mongoose6.default.model("VRSSuite", SuiteSchema); var Suite_model_default = Suite; // src/server/models/Run.model.ts var import_mongoose7 = __toESM(require("mongoose")); var RunSchema = new import_mongoose7.Schema({ name: { type: String, required: [true, 'RunSchema: The "name" field must be required'] }, app: { type: import_mongoose7.Schema.Types.ObjectId, ref: "VRSApp", required: [true, 'RunSchema: The "app" field must be required'] }, ident: { type: String, unique: true, required: [true, 'RunSchema: The "ident" field must be required'] }, description: { type: String }, updatedDate: { type: Date, default: Date.now }, createdDate: { type: Date }, parameters: { type: [String] }, meta: { type: Object } }); RunSchema.plugin(paginate_plugin_default); RunSchema.plugin(toJSON_plugin_default); var Run = import_mongoose7.default.model("VRSRun", RunSchema); var Run_model_default = Run; // src/server/models/User.model.ts var import_mongoose8 = __toESM(require("mongoose")); var import_passport_local_mongoose = __toESM(require("passport-local-mongoose")); var UserSchema = new import_mongoose8.Schema({ username: { type: String, unique: true, required: [true, 'UserSchema: The "username" field must be required'] }, firstName: { type: String, required: [true, 'UserSchema: The "firstName" field must be required'] }, lastName: { type: String, required: [true, 'UserSchema: The "lastName" field must be required'] }, role: { type: String, enum: ["admin", "reviewer", "user"], required: [true, 'UserSchema: The "role" field must be required'] }, password: { type: String }, token: { type: String }, apiKey: { type: String }, createdDate: { type: Date }, updatedDate: { type: Date }, expiration: { type: Date }, meta: { type: Object } }); UserSchema.statics.isEmailTaken = async function(username, excludeUserId) { const user = await this.findOne({ username, _id: { $ne: excludeUserId } }); return !!user; }; UserSchema.plugin(toJSON_plugin_default); UserSchema.plugin(paginate_plugin_default); UserSchema.plugin(import_passport_local_mongoose.default, { hashField: "password" }); var User = import_mongoose8.default.model("VRSUser", UserSchema); var User_model_default = User; // src/server/models/Baseline.model.ts var import_mongoose9 = __toESM(require("mongoose")); var BaselineSchema = new import_mongoose9.Schema({ snapshootId: { type: import_mongoose9.Schema.Types.ObjectId }, name: { type: String, required: [true, 'VRSBaselineSchema: The "name" field must be required'] }, app: { type: import_mongoose9.Schema.Types.ObjectId, ref: "VRSApp", required: [true, 'VRSBaselineSchema: The "app" field must be required'] }, branch: { type: String }, browserName: { type: String }, browserVersion: { type: String }, browserFullVersion: { type: String }, viewport: { type: String }, os: { type: String }, markedAs: { type: String, enum: ["bug", "accepted"] }, lastMarkedDate: { type: Date }, createdDate: { type: Date }, updatedDate: { type: Date }, markedById: { type: import_mongoose9.Schema.Types.ObjectId, ref: "VRSUser" }, markedByUsername: { type: String }, ignoreRegions: { type: String }, boundRegions: { type: String }, matchType: { type: String, enum: ["antialiasing", "nothing", "colors"] }, meta: { type: Object } }); BaselineSchema.plugin(toJSON_plugin_default); BaselineSchema.plugin(paginate_plugin_default); var Baseline = import_mongoose9.default.model("VRSBaseline", BaselineSchema); var Baseline_model_default = Baseline; // src/server/models/Test.model.ts var import_mongoose10 = __toESM(require("mongoose")); var TestSchema = new import_mongoose10.Schema( { name: { type: String, required: "TestSchema: the test name is empty" }, description: { type: String }, status: { type: String }, browserName: { type: String }, browserVersion: { type: String }, branch: { type: String }, tags: { type: [String] }, viewport: { type: String }, calculatedViewport: { type: String }, os: { type: String }, app: { type: import_mongoose10.Schema.Types.ObjectId, ref: "VRSApp", required: [true, 'TestSchema: The "app" field must be required'] }, blinking: { type: Number, default: 0 }, updatedDate: { type: Date }, startDate: { type: Date }, checks: [ { type: import_mongoose10.default.Schema.Types.ObjectId, ref: "VRSCheck" } ], suite: { type: import_mongoose10.Schema.Types.ObjectId, ref: "VRSSuite" }, run: { type: import_mongoose10.Schema.Types.ObjectId, ref: "VRSRun" }, markedAs: { type: String, enum: ["Bug", "Accepted", "Unaccepted", "Partially"] }, creatorId: { type: import_mongoose10.Schema.Types.ObjectId, ref: "VRSUser" }, creatorUsername: { type: String }, meta: { type: Object } }, { strictQuery: true } ); TestSchema.plugin(toJSON_plugin_default); TestSchema.plugin(paginate_plugin_default); TestSchema.plugin(paginateDistinct_plugin_default); var Test = import_mongoose10.default.model("VRSTest", TestSchema); var Test_model_default = Test; // src/server/utils/subDays.ts var subDays = (date, days) => { const result = new Date(date); result.setDate(result.getDate() - days); return result; }; var subDays_default = subDays; // src/server/lib/logger.ts var import_winston = __toESM(require("winston")); var import_winston_mongodb = require("winston-mongodb"); var import_chalk = require("chalk"); // src/server/utils/formatISOToDateTime.ts function formatISOToDateTime(isoDateString) { const date = new Date(isoDateString); return `${date.toISOString().slice(0, 10)} ${date.toTimeString().slice(0, 8)}`; } var formatISOToDateTime_default = formatISOToDateTime; // src/server/lib/logger.ts var import_path2 = __toESM(require("path")); var logLevel = env.SYNGRISI_LOG_LEVEL; function getScriptLine() { const stack = new Error().stack; if (stack) { const stackLines = stack.split("\n"); let loggerLineIndex = -1; for (let i = 0; i < stackLines.length; i++) { if (stackLines[i].includes("lib/logger")) { loggerLineIndex = i; } } const targetLineIndex = loggerLineIndex + 1; if (targetLineIndex >= 0 && targetLineIndex < stackLines.length) { const targetLine = stackLines[targetLineIndex]; const match = targetLine.match(/at\s+(?:.+\s+\()?(.+):(\d+):(\d+)\)?/); if (match) { const scriptPath = match[1]; const relativePath = import_path2.default.relative(process.cwd(), scriptPath); const lineNumber = match[2]; return `${relativePath}:${lineNumber}`; } } } return "unknown"; } function createWinstonLogger(opts) { return import_winston.default.createLogger({ transports: [ new import_winston.default.transports.Console({ level: logLevel || "silly", format: import_winston.default.format.combine( import_winston.default.format.colorize(), import_winston.default.format.timestamp(), import_winston.default.format.ms(), import_winston.default.format.metadata(), import_winston.default.format.printf((info) => { const user = info.metadata.user ? (0, import_chalk.blue)(` <${info.metadata.user}>`) : ""; const ref = info.metadata.ref ? (0, import_chalk.gray)(` ${info.metadata.ref}`) : ""; const msgType = info.metadata.msgType ? ` ${info.metadata.msgType}` : ""; const itemType = info.metadata.itemType ? (0, import_chalk.magenta)(` ${info.metadata.itemType}`) : ""; const scope = info.metadata.scope ? (0, import_chalk.magenta)(` [${info.metadata.scope}] `) : (0, import_chalk.magenta)(` [${getScriptLine()}] `); const msg = typeof info.message === "object" ? ` ${JSON.stringify(info.message, null, 2)}` : info.message; return `${info.level} ${scope}${formatISOToDateTime_default(info.metadata.timestamp)} ${info.metadata.ms}${user}${ref}${msgType}${itemType} '${msg}'`; }), import_winston.default.format.padLevels() ) }), new import_winston.default.transports.MongoDB({ level: logLevel || "debug", format: import_winston.default.format.combine( import_winston.default.format.timestamp(), import_winston.default.format.json(), import_winston.default.format.metadata() ), options: { useUnifiedTopology: true }, db: opts.dbConnectionString, collection: "vrslogs" }) ] }); } var Logger = class _Logger { constructor(opts = { dbConnectionString: config.connectionString }) { this.winstonLogger = createWinstonLogger(opts); } static mergeMeta(objects) { return objects.reduce((acc, obj) => { return { ...acc, ...obj }; }, {}); } log(severity, msg, meta) { const mergedMeta = _Logger.mergeMeta(meta); if (!mergedMeta.scope) { mergedMeta.scope = getScriptLine(); } const formattedMsg = typeof msg === "object" ? JSON.stringify(msg, null, 2) : msg; this.winstonLogger.log(severity, formattedMsg, mergedMeta); } error(msg, ...meta) { let message = String(msg); let code = 0; if (msg instanceof Object) { message = JSON.stringify(msg); } if (msg instanceof Error) { message = msg.stack; } if (msg instanceof ApiError_default) { code = msg.statusCode; } this.log("error", `${code !== 0 ? "[" + code + "]" : ""}${message} stacktrace: ${new Error().stack}`, meta); } warn(msg, ...meta) { this.log("warn", `${msg} stacktrace: ${new Error().stack}`, meta); } info(msg, ...meta) { this.log("info", msg, meta); } verbose(msg, ...meta) { this.log("verbose", msg, meta); } debug(msg, ...meta) { this.log("debug", msg, meta); } silly(msg, ...meta) { this.log("silly", msg, meta); } }; var logger_default = new Logger(); // src/seeds/testAdmin.json var testAdmin_default = { username: "Test", firstName: "Test", lastName: "Admin", role: "admin", openPassw: "123456aA-", password: "5b8d4960316d1fb0c92498c90da6c397cdf247cae71f01467a88e2b42d7af6f5ac7ca75d3bea6e3e0078111a2e5dfc1611f9a9a8908a5a3af5bcd64c42989608977de192829bdf8ada113a60f8f0704443c659789761865e29a3103dbf0773f5bf31e4685d475ece56afaceb949b6e7467eaa287a02e4142d095bcbf84acaefe47ee080799a28188890d39d3397e285d8b46c9a0efe9517428825b64ee1ebcc96d92c084733db866c767341381b6254aaa1ef36d1bf3d24e3f5b8d8b6b4080589b130e9c90914a3da74e5b6adf5f569bfd77460abae8ae4f87c2a375397a37f09861b9e114cead0cc34fff2d631fd4294260dea17e4fe098940dbee2cb80c62eb3701d40f5b204de776b8252d55e5f567c599b1fbcdae79278d1f375a4c8244a26a3b721dbeec56c8f39b3eb810942d392aae371ea81ded6b820dd4b489566a33c495f5c291ff238d07202d2ff04c52426828e44af98ec056a42d13f4b166ec170083e2fff9efe2b8cfdde529f3bce56b8427cf2d188861808ad07fd13e073b2a804e818b2882c13f559d52420b49f301263a9de34fe22b6df4a82ae70e7e4c29c88479878d2c21fbb810532532e7ad9a28f610b63033520e703f178e7b44d3e101ec0d4339c085ccc8bb290b3cb996c75c2b8deaacba8098b9ec02c7e47542891da3bd887c31cd8e0bdfa56bb844b1703368afe8dc42d668ff2e3374b939b4f", apiKey: "", salt: "c6211751bdc372f491a86bcbd8e4196dc393d14e14e5f17019d5c317afd5bc27" }; // src/server/services/tasks.service.ts var import_path3 = __toESM(require("path")); var stringTable = import_string_table.default; function taskOutput(msg, res) { res.write(`${msg.toString()} `); logger_default.debug(msg.toString()); } function parseHrtimeToSeconds(hrtime) { return (hrtime[0] + hrtime[1] / 1e9).toFixed(3); } var status = async (currentUser) => { const count = await User_model_default.countDocuments().exec(); logger_default.silly(`server status: check users counts: ${count}`); if (count > 1) { return { alive: true, currentUser: currentUser?.username }; } return { alive: false }; }; var screenshots = async () => { const files = import_fs2.default.readdirSync(config.defaultImagesPath); return files; }; var loadTestUser = async () => { const logOpts = { itemType: "user", msgType: "LOAD", ref: "Administrator" }; if (!env.SYNGRISI_TEST_MODE) { return { message: "the feature works only in test mode" }; } const testAdmin = await User_model_default.findOne({ username: "Test" }).exec(); if (!testAdmin) { logger_default.info("create the test Administrator", logOpts); const admin = await User_model_default.create(testAdmin_default); logger_default.info(`test Administrator with id: '${admin._id}' was created`, logOpts); return admin; } logger_default.info(`test admin is exists: ${JSON.stringify(testAdmin, null, 2)}`, logOpts); return { msg: `already exist '${testAdmin}'` }; }; var task_handle_database_consistency = async (options, res) => { res.writeHead(200, { "Content-Type": "text/event-stream", "Cache-Control": "no-cache", "Content-Encoding": "none", "x-no-compression": "true" }); try { const startTime = process.hrtime(); taskOutput("- starting...\n", res); taskOutput("---------------------------------", res); taskOutput("STAGE #1: Calculate Common stats", res); taskOutput("get runs data", res); const allRunsBefore = await Run_model_default.find().exec(); taskOutput("get suites data", res); const allSuitesBefore = await Suite_model_default.find().exec(); taskOutput("get tests data", res); const allTestsBefore = await Test_model_default.find().lean().exec(); taskOutput("get checks data", res); const allChecksBefore = await Check_model_default.find().lean().exec(); taskOutput("get snapshots data", res); const allSnapshotsBefore = await Snapshot_model_default.find().lean().exec(); taskOutput("get files data", res); const allFilesBefore = (await import_fs2.promises.readdir(config.defaultImagesPath, { withFileTypes: true })).filter((item) => !item.isDirectory()).map((x) => x.name).filter((x) => x.includes(".png")); taskOutput("-----------------------------", res); const beforeStatTable = stringTable.create([ { item: "suites", count: allSuitesBefore.length }, { item: "runs", count: allRunsBefore.length }, { item: "tests", count: allTestsBefore.length }, { item: "checks", count: allChecksBefore.length }, { item: "snapshots", count: allSnapshotsBefore.length }, { item: "files", count: allFilesBefore.length } ]); res.flush(); taskOutput(beforeStatTable, res); taskOutput("---------------------------------", res); taskOutput("STAGE #2: Calculate Inconsistent Items", res); taskOutput("> calculate abandoned snapshots", res); const abandonedSnapshots = allSnapshotsBefore.filter((sn) => !import_fs2.default.existsSync(import_path3.default.join(config.defaultImagesPath, sn.filename))); taskOutput("> calculate abandoned files", res); const snapshotsUniqueFiles = Array.from(new Set(allSnapshotsBefore.map((x) => x.filename))); const abandonedFiles = []; const progress = new ProgressBar(allFilesBefore.length); for (const [index, file] of allFilesBefore.entries()) { setTimeout(() => { progress.writeIfChange(index, allFilesBefore.length, taskOutput, res); }, 10); if (!snapshotsUniqueF