@syngrisi/syngrisi
Version:
Syngrisi - Visual Testing Tool
1,954 lines (1,921 loc) • 104 kB
JavaScript
var __defProp = Object.defineProperty;
var __getOwnPropNames = Object.getOwnPropertyNames;
var __esm = (fn, res) => function __init() {
return fn && (res = (0, fn[__getOwnPropNames(fn)[0]])(fn = 0)), res;
};
var __export = (target, all) => {
for (var name in all)
__defProp(target, name, { get: all[name], enumerable: true });
};
// src/server/utils/colors.ts
var RESET, colors;
var init_colors = __esm({
"src/server/utils/colors.ts"() {
"use strict";
RESET = "\x1B[0m";
colors = {
// Standard colors
blue: (s) => `\x1B[34m${s}${RESET}`,
green: (s) => `\x1B[32m${s}${RESET}`,
red: (s) => `\x1B[31m${s}${RESET}`,
yellow: (s) => `\x1B[33m${s}${RESET}`,
magenta: (s) => `\x1B[35m${s}${RESET}`,
cyan: (s) => `\x1B[36m${s}${RESET}`,
// Bright colors
gray: (s) => `\x1B[90m${s}${RESET}`,
whiteBright: (s) => `\x1B[97m${s}${RESET}`,
// Reset code for manual use
reset: RESET
};
}
});
// 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;
var init_formatISOToDateTime = __esm({
"src/server/utils/formatISOToDateTime.ts"() {
"use strict";
formatISOToDateTime_default = formatISOToDateTime;
}
});
// package.json
var version, gitHead;
var init_package = __esm({
"package.json"() {
version = "3.5.0";
gitHead = "12bfda406cbe5aaccf3f17fdab02a9bd1a9d6343";
}
});
// src/server/envConfig.ts
import { cleanEnv, host, num, port, str, bool } from "envalid";
import crypto from "crypto";
import path from "path";
import dotenv from "dotenv";
var env;
var init_envConfig = __esm({
"src/server/envConfig.ts"() {
"use strict";
dotenv.config({ quiet: true });
if (!process.env.NODE_ENV) {
process.env.NODE_ENV = "production";
}
env = cleanEnv(process.env, {
NODE_ENV: str({ choices: ["development", "production", "test"] }),
SYNGRISI_DB_URI: str({ default: "mongodb://127.0.0.1:27017/SyngrisiDb" }),
SYNGRISI_APP_PORT: port({ default: 3e3 }),
SYNGRISI_IMAGES_PATH: str({ default: path.join(process.cwd(), "./.snapshots-images") }),
SYNGRISI_DOM_SNAPSHOTS_PATH: str({ default: "" }),
// If empty, uses SYNGRISI_IMAGES_PATH
SYNGRISI_TMP_DIR: str({ default: path.join(process.cwd(), ".tmp") }),
SYNGRISI_ADMIN_DATA_JOBS_PATH: str({ default: path.join(process.cwd(), ".tmp", "admin-data-jobs") }),
SYNGRISI_ADMIN_DATA_JOBS_TTL_MS: num({ default: 24 * 60 * 60 * 1e3 }),
SYNGRISI_ADMIN_DATA_MAX_CONCURRENT_JOBS: num({ default: 1 }),
SYNGRISI_ADMIN_DATA_UPLOAD_MAX_SIZE_MB: num({ default: 10240 }),
SYNGRISI_HTTP_LOG: bool({ default: false }),
SYNGRISI_COVERAGE: bool({ default: false }),
SYNGRISI_HOSTNAME: host({ default: "localhost" }),
SYNGRISI_AUTH: bool({ default: true }),
SYNGRISI_TEST_MODE: bool({ default: false }),
SYNGRISI_DISABLE_FIRST_RUN: bool({ default: false }),
MONGODB_ROOT_USERNAME: str({ default: "" }),
MONGODB_ROOT_PASSWORD: str({ default: "" }),
LOGLEVEL: str({ choices: ["error", "warn", "info", "verbose", "debug", "silly"], default: "debug" }),
// Legacy tests expect 20 rows per page; keep default aligned for e2e
SYNGRISI_PAGINATION_SIZE: num({ default: 20 }),
SYNGRISI_DISABLE_DEV_CORS: bool({ default: true, devDefault: true }),
SYNGRISI_SESSION_STORE_KEY: str({ default: crypto.randomBytes(64).toString("hex") }),
SYNGRISI_LOG_LEVEL: str({ default: "debug" }),
SYNGRISI_DISABLE_LOGS: bool({ default: false }),
SYNGRISI_AUTO_REMOVE_CHECKS_POLL_INTERVAL_MS: num({ default: 10 * 60 * 1e3 }),
// 10 minutes
SYNGRISI_AUTO_REMOVE_CHECKS_MIN_INTERVAL_MS: num({ default: 24 * 60 * 60 * 1e3 }),
SYNGRISI_ENABLE_SCHEDULERS_IN_TEST_MODE: bool({ default: false }),
// RCA
SYNGRISI_RCA: bool({ default: false }),
// trunk features
SYNGRISI_TRUNK_FEATURE_AI_SEVERITY: bool({ default: false }),
SYNGRISI_AI_KEY: str({ default: "" }),
OPENAI_API_BASE_URL: str({ default: "https://api.openai.com/v1" }),
OPENAI_API_KEY: str({ default: "" }),
SYNGRISI_V8_COVERAGE_ON_EXIT: bool({ default: false }),
// Rate Limiting
SYNGRISI_RATE_LIMIT_WINDOW_MS: num({ default: 15 * 60 * 1e3 }),
// 15 minutes
SYNGRISI_RATE_LIMIT_MAX: num({ default: 5e4 }),
SYNGRISI_AUTH_RATE_LIMIT_WINDOW_MS: num({ default: 15 * 60 * 1e3 }),
// 15 minutes
SYNGRISI_AUTH_RATE_LIMIT_MAX: num({ default: 200 }),
// Mongo tuneables for tests/CI flake reduction
SYNGRISI_MONGO_SOCKET_TIMEOUT_MS: num({ default: 6e4 }),
SYNGRISI_MONGO_MAX_POOL_SIZE: num({ default: 20 }),
SYNGRISI_MONGO_MIN_POOL_SIZE: num({ default: 2 }),
SYNGRISI_MONGO_MAX_IDLE_TIME_MS: num({ default: 3e4 }),
SYNGRISI_MONGO_WAIT_QUEUE_TIMEOUT_MS: num({ default: 3e4 }),
SYNGRISI_MONGO_SERVER_SELECTION_TIMEOUT_MS: num({ default: 1e4 }),
SYNGRISI_MONGO_CONNECT_TIMEOUT_MS: num({ default: 3e4 }),
// SSO Configuration
SSO_ENABLED: bool({ default: false }),
SSO_PROTOCOL: str({ choices: ["", "oauth2", "saml"], default: "" }),
SSO_CLIENT_ID: str({ default: "" }),
SSO_CLIENT_SECRET: str({ default: "" }),
SSO_AUTHORIZATION_URL: str({ default: "" }),
SSO_TOKEN_URL: str({ default: "" }),
SSO_USERINFO_URL: str({ default: "" }),
SSO_CALLBACK_URL: str({ default: "/v1/auth/sso/oauth/callback" }),
// SAML specific
SSO_ENTRY_POINT: str({ default: "" }),
SSO_ISSUER: str({ default: "" }),
SSO_CERT: str({ default: "" }),
SSO_IDP_ISSUER: str({ default: "" }),
SSO_IDP_METADATA_URL: str({ default: "" }),
// URL to fetch IdP metadata XML (alternative to manual SSO_ENTRY_POINT/SSO_CERT)
// SSO user settings
SSO_DEFAULT_ROLE: str({ choices: ["", "user", "admin", "reviewer"], default: "reviewer" }),
SSO_AUTO_CREATE_USERS: bool({ default: true }),
SSO_ALLOW_ACCOUNT_LINKING: bool({ default: true }),
// Plugin System
SYNGRISI_PLUGINS_ENABLED: str({ default: "" }),
// Comma-separated list of enabled plugins
SYNGRISI_PLUGINS_DIR: str({ default: "" }),
// Directory for external plugins
// Okta Auth Plugin
// Deprecated: Use SYNGRISI_PLUGIN_JWT_AUTH_* variables instead
OKTA_JWKS_URL: str({ default: "" }),
OKTA_ISSUER: str({ default: "" }),
OKTA_SERVICE_USER_ROLE: str({ default: "" }),
OKTA_AUTH_HEADER: str({ default: "" }),
// Custom Check Validator Plugin
CHECK_MISMATCH_THRESHOLD: str({ default: "0" }),
// Mismatch % below which checks pass
CHECK_VALIDATOR_SCRIPT: str({ default: "" })
// Path to custom validation script
});
}
});
// src/server/data/devices.json
var devices_default;
var init_devices = __esm({
"src/server/data/devices.json"() {
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
import fs from "fs";
import dotenv2 from "dotenv";
import crypto2 from "crypto";
import { execSync } from "child_process";
var getCommitHash, customDevicesPath, logsFolder, CURRENT_VERSION, major, minor, minSupportedMinor, MIN_SUPPORTED_SDK_VERSION, config;
var init_config = __esm({
"src/server/config.ts"() {
"use strict";
init_package();
init_envConfig();
init_devices();
getCommitHash = () => {
if (gitHead) {
return gitHead.substring(0, 7);
}
try {
return execSync("git rev-parse --short HEAD", { encoding: "utf-8", stdio: ["pipe", "pipe", "pipe"] }).trim();
} catch {
return "";
}
};
customDevicesPath = "./server/data/custom_devices.json";
logsFolder = "./logs";
dotenv2.config();
CURRENT_VERSION = version;
[major, minor] = CURRENT_VERSION.split(".").map(Number);
minSupportedMinor = Math.max(0, minor - 2);
MIN_SUPPORTED_SDK_VERSION = `${major}.${minSupportedMinor}.0`;
config = {
version,
commitHash: getCommitHash(),
minSupportedSdkVersion: MIN_SUPPORTED_SDK_VERSION,
apiVersion: "1",
// this isn't used
getDevices: async () => {
if (fs.existsSync(customDevicesPath)) {
return [...devices_default, ...(await import(customDevicesPath)).default];
}
return devices_default;
},
defaultImagesPath: env.SYNGRISI_IMAGES_PATH,
domSnapshotsPath: env.SYNGRISI_DOM_SNAPSHOTS_PATH || 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 || crypto2.randomBytes(64).toString("hex"),
codeCoverage: env.SYNGRISI_COVERAGE,
disableCors: env.SYNGRISI_DISABLE_DEV_CORS,
fileUploadMaxSize: 50 * 1024 * 1024,
adminDataJobsPath: env.SYNGRISI_ADMIN_DATA_JOBS_PATH,
adminDataJobsTtlMs: env.SYNGRISI_ADMIN_DATA_JOBS_TTL_MS,
adminDataMaxConcurrentJobs: env.SYNGRISI_ADMIN_DATA_MAX_CONCURRENT_JOBS,
adminDataUploadMaxSize: env.SYNGRISI_ADMIN_DATA_UPLOAD_MAX_SIZE_MB * 1024 * 1024,
testMode: env.SYNGRISI_TEST_MODE,
jsonLimit: "50mb",
tmpDir: env.SYNGRISI_TMP_DIR,
helmet: {
crossOriginEmbedderPolicy: false,
crossOriginResourcePolicy: false,
crossOriginOpenerPolicy: false,
contentSecurityPolicy: {
useDefaults: false,
directives: {
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'", "*"],
baseUri: ["'self'"],
formAction: ["'self'"],
objectSrc: ["'none'"],
scriptSrcAttr: ["'none'"]
}
},
hsts: false
},
rateLimit: {
windowMs: env.SYNGRISI_RATE_LIMIT_WINDOW_MS,
max: env.SYNGRISI_RATE_LIMIT_MAX,
standardHeaders: true,
legacyHeaders: false
},
authRateLimit: {
windowMs: env.SYNGRISI_AUTH_RATE_LIMIT_WINDOW_MS,
max: env.SYNGRISI_AUTH_RATE_LIMIT_MAX,
standardHeaders: true,
legacyHeaders: false
}
};
if (!fs.existsSync(config.defaultImagesPath)) {
fs.mkdirSync(config.defaultImagesPath, { recursive: true });
}
if (config.domSnapshotsPath !== config.defaultImagesPath && !fs.existsSync(config.domSnapshotsPath)) {
fs.mkdirSync(config.domSnapshotsPath, { recursive: true });
}
if (!fs.existsSync(config.adminDataJobsPath)) {
fs.mkdirSync(config.adminDataJobsPath, { recursive: true });
}
if (!fs.existsSync(logsFolder)) {
fs.mkdirSync(logsFolder, { recursive: true });
}
}
});
// src/server/utils/pick.ts
var init_pick = __esm({
"src/server/utils/pick.ts"() {
"use strict";
}
});
// src/server/utils/isJSON.ts
var isJSON, isJSON_default;
var init_isJSON = __esm({
"src/server/utils/isJSON.ts"() {
"use strict";
isJSON = (text) => {
if (!text) return false;
const isValid = /^[\],:{}\s]*$/.test(
text.replace(/\\["\\\/bfnrtu]/g, "@").replace(/"[^"\\\n\r]*"|true|false|null|-?\d+(?:\.\d*)?(?:[eE][+\-]?\d+)?/g, "]").replace(/(?:^|:|,)(?:\s*\[)+/g, "")
);
return isValid;
};
isJSON_default = isJSON;
}
});
// src/server/utils/catchAsync.ts
var init_catchAsync = __esm({
"src/server/utils/catchAsync.ts"() {
"use strict";
}
});
// src/server/utils/dateToISO8601.ts
var init_dateToISO8601 = __esm({
"src/server/utils/dateToISO8601.ts"() {
"use strict";
}
});
// src/server/utils/ProgressBar.ts
var init_ProgressBar = __esm({
"src/server/utils/ProgressBar.ts"() {
"use strict";
}
});
// src/server/utils/ApiError.ts
var ApiError, ApiError_default;
var init_ApiError = __esm({
"src/server/utils/ApiError.ts"() {
"use strict";
ApiError = class extends Error {
statusCode;
isOperational;
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);
}
}
};
ApiError_default = ApiError;
}
});
// src/server/utils/removeEmptyProperties.ts
var init_removeEmptyProperties = __esm({
"src/server/utils/removeEmptyProperties.ts"() {
"use strict";
}
});
// src/server/utils/deserializeIfJSON.ts
import mongoose from "mongoose";
var EJSON, EXTENDED_JSON_KEYS, containsExtendedJsonMarkers, deserializeIfJSON, deserializeIfJSON_default;
var init_deserializeIfJSON = __esm({
"src/server/utils/deserializeIfJSON.ts"() {
"use strict";
init_utils();
({ EJSON } = mongoose.mongo.BSON);
EXTENDED_JSON_KEYS = [
"$oid",
"$date",
"$numberInt",
"$numberLong",
"$numberDouble",
"$numberDecimal",
"$regularExpression",
"$binary",
"$timestamp"
];
containsExtendedJsonMarkers = (text) => EXTENDED_JSON_KEYS.some((marker) => text.includes(`"${marker}"`));
deserializeIfJSON = (text) => {
if (isJSON_default(text)) {
if (containsExtendedJsonMarkers(text)) {
return EJSON.parse(text) || void 0;
}
return JSON.parse(text) || void 0;
}
return text;
};
deserializeIfJSON_default = deserializeIfJSON;
}
});
// src/server/utils/prettyCheckParams.ts
var init_prettyCheckParams = __esm({
"src/server/utils/prettyCheckParams.ts"() {
"use strict";
}
});
// src/server/utils/waitUntil.ts
var init_waitUntil = __esm({
"src/server/utils/waitUntil.ts"() {
"use strict";
}
});
// src/server/utils/imageUtils.ts
var init_imageUtils = __esm({
"src/server/utils/imageUtils.ts"() {
"use strict";
}
});
// src/server/utils/paramsGuard.ts
var init_paramsGuard = __esm({
"src/server/utils/paramsGuard.ts"() {
"use strict";
}
});
// src/server/utils/ident.ts
var init_ident = __esm({
"src/server/utils/ident.ts"() {
"use strict";
}
});
// src/server/utils/buildIdentObject.ts
var init_buildIdentObject = __esm({
"src/server/utils/buildIdentObject.ts"() {
"use strict";
init_ident();
}
});
// src/server/models/plugins/paginate.plugin.ts
var paginate, paginate_plugin_default;
var init_paginate_plugin = __esm({
"src/server/models/plugins/paginate.plugin.ts"() {
"use strict";
paginate = (schema) => {
schema.statics.paginate = async function(filter, options) {
let sort;
if (options.sortBy) {
const sortingCriteria = [];
let primaryOrder = "desc";
options.sortBy.split(",").forEach((sortOption, index) => {
const [key, order] = sortOption.split(":");
if (index === 0) primaryOrder = order || "asc";
sortingCriteria.push((order === "desc" ? "-" : "") + key);
});
if (!sortingCriteria.some((s) => s === "_id" || s === "-_id")) {
sortingCriteria.push((primaryOrder === "desc" ? "-" : "") + "_id");
}
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 countStrategy = options.countStrategy ?? (filter && Object.keys(filter).length === 0 ? "estimated" : "exact");
const countPromise = countStrategy === "estimated" ? this.estimatedDocumentCount().exec() : 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);
});
};
};
paginate_plugin_default = paginate;
}
});
// src/server/models/plugins/toJSON.plugin.ts
var deleteAtPath, toJSON, toJSON_plugin_default;
var init_toJSON_plugin = __esm({
"src/server/models/plugins/toJSON.plugin.ts"() {
"use strict";
deleteAtPath = (obj, path3, index) => {
if (index === path3.length - 1) {
delete obj[path3[index]];
return;
}
deleteAtPath(obj[path3[index]], path3, index + 1);
};
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((path3) => {
if (schema.paths[path3].options && schema.paths[path3].options.private) {
deleteAtPath(ret, path3.split("."), 0);
}
});
ret.id = ret._id.toString();
delete ret.__v;
delete ret.createdAt;
delete ret.updatedAt;
if (transform) {
return transform(doc, ret, options);
}
}
});
};
toJSON_plugin_default = toJSON;
}
});
// src/server/models/plugins/paginateDistinct.plugin.ts
var init_paginateDistinct_plugin = __esm({
"src/server/models/plugins/paginateDistinct.plugin.ts"() {
"use strict";
init_utils();
}
});
// src/server/models/plugins/index.ts
var init_plugins = __esm({
"src/server/models/plugins/index.ts"() {
"use strict";
init_paginate_plugin();
init_toJSON_plugin();
init_paginateDistinct_plugin();
}
});
// src/server/models/Check.model.ts
import mongoose2, { Schema } from "mongoose";
var CheckSchema, Check, Check_model_default;
var init_Check_model = __esm({
"src/server/models/Check.model.ts"() {
"use strict";
init_plugins();
CheckSchema = new Schema({
name: {
type: String,
required: [true, 'CheckSchema: The "name" field must be required']
},
test: {
type: Schema.Types.ObjectId,
ref: "VRSTest",
required: [true, 'CheckSchema: The "test" field must be required']
},
suite: {
type: Schema.Types.ObjectId,
ref: "VRSSuite",
required: [true, 'CheckSchema: The "suite" field must be required']
},
app: {
type: Schema.Types.ObjectId,
ref: "VRSApp",
required: [true, 'CheckSchema: The "app" field must be required']
},
branch: {
type: String
},
realBaselineId: {
type: Schema.Types.ObjectId,
ref: "VRSBaseline"
},
baselineId: {
type: Schema.Types.ObjectId,
ref: "VRSSnapshot"
},
actualSnapshotId: {
type: Schema.Types.ObjectId,
ref: "VRSSnapshot"
},
diffId: {
type: 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: Schema.Types.ObjectId
},
markedAs: {
type: String,
enum: ["bug", "accepted"]
},
markedDate: {
type: Date
},
markedById: {
type: Schema.Types.ObjectId,
ref: "VRSUser"
},
markedByUsername: {
type: String
},
markedBugComment: {
type: String
},
creatorId: {
type: Schema.Types.ObjectId,
ref: "VRSUser"
},
creatorUsername: {
type: String
},
failReasons: {
type: [String]
},
vOffset: {
type: String
},
topStablePixels: {
type: String
},
toleranceThreshold: {
type: Number,
min: 0,
max: 100
},
meta: {
type: Object
}
});
CheckSchema.plugin(toJSON_plugin_default);
CheckSchema.plugin(paginate_plugin_default);
Check = mongoose2.model("VRSCheck", CheckSchema);
Check_model_default = Check;
}
});
// src/server/models/Log.model.ts
import mongoose3, { Schema as Schema2 } from "mongoose";
var LogSchema, Log;
var init_Log_model = __esm({
"src/server/models/Log.model.ts"() {
"use strict";
init_plugins();
LogSchema = new Schema2({
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);
Log = mongoose3.model("VRSLog", LogSchema);
}
});
// src/server/models/App.model.ts
import mongoose4, { Schema as Schema3 } from "mongoose";
var AppSchema, App;
var init_App_model = __esm({
"src/server/models/App.model.ts"() {
"use strict";
init_plugins();
AppSchema = new Schema3({
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);
App = mongoose4.model("VRSApp", AppSchema);
}
});
// src/server/models/Snapshot.model.ts
import mongoose5, { Schema as Schema4 } from "mongoose";
var SnapshotSchema, Snapshot;
var init_Snapshot_model = __esm({
"src/server/models/Snapshot.model.ts"() {
"use strict";
init_plugins();
SnapshotSchema = new Schema4({
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);
Snapshot = mongoose5.model("VRSSnapshot", SnapshotSchema);
}
});
// src/server/models/AppSettings.model.ts
import mongoose6, { Schema as Schema5 } from "mongoose";
var AppSettingsSchema, AppSettings;
var init_AppSettings_model = __esm({
"src/server/models/AppSettings.model.ts"() {
"use strict";
init_plugins();
AppSettingsSchema = new Schema5({
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: Schema5.Types.Mixed,
required: [true, 'AppSettingsSchema: The "value" field must be required']
},
env_variable: {
type: String
},
enabled: {
type: Boolean
}
});
AppSettingsSchema.plugin(toJSON_plugin_default);
AppSettings = mongoose6.model("VRSAppSettings", AppSettingsSchema);
}
});
// src/server/models/Suite.model.ts
import mongoose7, { Schema as Schema6 } from "mongoose";
var SuiteSchema, Suite;
var init_Suite_model = __esm({
"src/server/models/Suite.model.ts"() {
"use strict";
init_plugins();
SuiteSchema = new Schema6({
name: {
type: String,
default: "Others",
unique: true,
required: [true, 'SuiteSchema: The "name" field must be required']
},
tags: {
type: [String]
},
app: {
type: Schema6.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);
Suite = mongoose7.model("VRSSuite", SuiteSchema);
}
});
// src/server/models/Run.model.ts
import mongoose8, { Schema as Schema7 } from "mongoose";
var RunSchema, Run;
var init_Run_model = __esm({
"src/server/models/Run.model.ts"() {
"use strict";
init_plugins();
RunSchema = new Schema7({
name: {
type: String,
required: [true, 'RunSchema: The "name" field must be required']
},
app: {
type: Schema7.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);
Run = mongoose8.model("VRSRun", RunSchema);
}
});
// src/server/models/User.model.ts
import mongoose9, { Schema as Schema8 } from "mongoose";
import plm from "passport-local-mongoose";
var passportLocalMongoose, UserSchema, User, User_model_default;
var init_User_model = __esm({
"src/server/models/User.model.ts"() {
"use strict";
init_plugins();
passportLocalMongoose = plm.default || plm;
UserSchema = new Schema8({
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']
},
provider: {
type: String,
default: "local"
},
providerId: {
type: String
},
password: {
type: String
},
token: {
type: String
},
apiKey: {
type: String
},
authSource: {
type: String,
enum: ["local", "jwt", "ldap", "api"],
default: "local"
},
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(passportLocalMongoose, { hashField: "password" });
User = mongoose9.model("VRSUser", UserSchema);
User_model_default = User;
}
});
// src/server/models/Baseline.model.ts
import mongoose10, { Schema as Schema9 } from "mongoose";
var BaselineSchema, Baseline, Baseline_model_default;
var init_Baseline_model = __esm({
"src/server/models/Baseline.model.ts"() {
"use strict";
init_plugins();
BaselineSchema = new Schema9({
snapshootId: {
type: Schema9.Types.ObjectId,
ref: "VRSSnapshot"
},
name: {
type: String,
required: [true, 'VRSBaselineSchema: The "name" field must be required']
},
app: {
type: Schema9.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", "accep