UNPKG

@syngrisi/syngrisi

Version:
2,727 lines 73.9 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/routes/v1/test_distinct.route.ts
var test_distinct_route_exports = {};
__export(test_distinct_route_exports, {
  default: () => test_distinct_route_default,
  registry: () => registry
});
module.exports = __toCommonJS(test_distinct_route_exports);
var import_express = __toESM(require("express"));
var import_zod_to_openapi4 = require("@asteasolutions/zod-to-openapi");

// src/server/controllers/test.controller.ts
var import_http_status6 = __toESM(require("http-status"));

// src/server/utils/pick.ts
var pick = (object, keys) => {
  return keys.reduce((obj, key) => {
    if (object && Object.prototype.hasOwnProperty.call(object, key)) {
      if (object[key] !== void 0) obj[key] = object[key];
    }
    return obj;
  }, {});
};
var pick_default = pick;

// src/server/utils/isJSON.ts
var 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;
};
var isJSON_default = isJSON;

// src/server/utils/catchAsync.ts
var catchAsync = (fn) => (req, res, next) => {
  Promise.resolve(fn(req, res, next)).catch((err) => {
    return next(err);
  });
};
var catchAsync_default = catchAsync;

// 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");
var deserializeIfJSON = (text) => {
  if (isJSON_default(text)) return import_bson.EJSON.parse(text) || void 0;
  return text;
};
var deserializeIfJSON_default = deserializeIfJSON;

// src/server/utils/ident.ts
var ident = ["name", "viewport", "browserName", "os", "app", "branch"];

// src/server/utils/buildIdentObject.ts
var MissingIdentFieldError = class extends Error {
  constructor(field) {
    super(`Missing required ident field: ${field}`);
    this.name = "MissingIdentFieldError";
  }
};
var buildIdentObject = (params) => {
  const result = {};
  for (const key of ident) {
    if (key in params && params[key] !== void 0) {
      result[key] = params[key];
    } else {
      throw new MissingIdentFieldError(key);
    }
  }
  return result;
};

// 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);

// 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);
var AppSettings_model_default = AppSettings;

// 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);

// 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/calculateAcceptedStatus.ts
var calculateAcceptedStatus = async function calculateAcceptedStatus2(testId) {
  const checksInTest = await Check_model_default.find({ test: testId });
  const statuses = checksInTest.map((x) => x.markedAs);
  if (statuses.length < 1) {
    return "Unaccepted";
  }
  let testCalculatedStatus = "Unaccepted";
  if (statuses.some((x) => x === "accepted")) {
    testCalculatedStatus = "Partially";
  }
  if (statuses.every((x) => x === "accepted")) {
    testCalculatedStatus = "Accepted";
  }
  return testCalculatedStatus;
};

// src/server/utils/errMsg.ts
var errMsg = (e) => {
  return String(e instanceof Error ? e.stack : e);
};

// 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/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/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/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/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/server/services/test.service.ts
var test_service_exports = {};
__export(test_service_exports, {
  accept: () => accept,
  queryTests: () => queryTests,
  queryTestsDistinct: () => queryTestsDistinct,
  remove: () => remove
});
var queryTests = async (filter, options) => {
  const tests = await Test_model_default.paginate(filter, options);
  return tests;
};
var queryTestsDistinct = async (filter, options) => {
  const tests = await Test_model_default.paginateDistinct({ filter: filter ? JSON.stringify(filter) : null }, options);
  return tests;
};
var remove = async (id2, user) => {
  const logOpts4 = {
    scope: "removeTest",
    itemType: "test",
    ref: id2,
    user: user?.username,
    msgType: "REMOVE"
  };
  logger_default.info(`remove test with, id: '${id2}', user: '${user.username}'`, logOpts4);
  try {
    logger_default.debug(`try to delete all checks associated to test with ID: '${id2}'`, logOpts4);
    const checks = await Check_model_default.find({ test: id2 });
    for (const check of checks) {
      await check_service_exports.remove(check._id, user);
    }
    return Test_model_default.findByIdAndDelete(id2);
  } catch (e) {
    logger_default.error(`cannot remove test with id: ${id2} error: ${e instanceof Error ? e.stack : String(e)}`, logOpts4);
    throw new Error();
  }
};
var accept = async (id2, user) => {
  const logOpts4 = {
    scope: "acceptTest",
    itemType: "test",
    ref: id2,
    user: user?.username,
    msgType: "ACCEPT"
  };
  logger_default.info(`accept test with, id: '${id2}', user: '${user.username}'`, logOpts4);
  const checks = await Check_model_default.find({ test: id2 }).exec();
  for (const check of checks) {
    await check_service_exports.accept(check._id, String(check.actualSnapshotId), user);
  }
  return { message: "success" };
};

// src/server/services/run.service.ts
var import_http_status = __toESM(require("http-status"));

// src/server/services/suite.service.ts
var import_http_status2 = __toESM(require("http-status"));

// src/server/services/generic.service.ts
var import_mongoose11 = __toESM(require("mongoose"));

// src/server/services/tasks.service.ts
var import_string_table = __toESM(require("string-table"));

// src/server/services/client.service.ts
var import_hasha = __toESM(require("hasha"));

// src/server/lib/dbItems/updateItem.ts
var import_mongoose12 = __toESM(require("mongoose"));

// src/server/lib/dbItems/updateItemDate.ts
var import_mongoose13 = __toESM(require("mongoose"));
var logOpts = {
  scope: "dbitems",
  msgType: "DB"
};
async function updateItemDate(mdClass, id2) {
  logger_default.debug(`update date for the item: '${mdClass}' with id: '${id2}'`, logOpts);
  const itemModel = await import_mongoose13.default.model(mdClass).findById(id2);
  const updatedItem = await itemModel?.updateOne({ updatedDate: Date.now() });
  logger_default.debug(`'${mdClass}' date updated: '${JSON.stringify(itemModel)}'`, logOpts);
  return updatedItem;
}

// src/server/lib/dbItems/createItemIfNotExist.ts
var import_mongoose14 = __toESM(require("mongoose"));

// src/server/lib/dbItems/createItemProm.ts
var import_mongoose15 = __toESM(require("mongoose"));

// src/server/lib/сomparison/compareImagesNode.ts
var import_node_resemble = __toESM(require("@syngrisi/node-resemble.js"));

// src/server/services/client.service.ts
var import_http_status3 = __toESM(require("http-status"));
var import_http_status4 = __toESM(require("http-status"));

// src/server/services/user.service.ts
var import_http_status5 = __toESM(require("http-status"));

// src/server/services/check.service.ts
var check_service_exports = {};
__export(check_service_exports, {
  accept: () => accept2,
  remove: () => remove3,
  update: () => update
});

// src/server/services/snapshot.service.ts
var import_fs2 = __toESM(require("fs"));
var import_path3 = __toESM(require("path"));
var logOpts2 = {
  scope: "snapshot_helper",
  msgType: "API"
};
var removeSnapshotFile = async (snapshot) => {
  let relatedSnapshots;
  if (snapshot.filename) {
    relatedSnapshots = await Snapshot_model_default.find({ filename: snapshot.filename });
    logger_default.debug(`there are '${relatedSnapshots.length}' snapshots with filename: '${snapshot.filename}'`, logOpts2);
  }
  const isLastSnapshotFile = () => {
    if (!snapshot.filename) {
      return true;
    }
    return relatedSnapshots.length === 0;
  };
  logger_default.debug({ isLastSnapshotFile: isLastSnapshotFile() });
  if (isLastSnapshotFile()) {
    const imagePath = import_path3.default.join(config.defaultImagesPath, snapshot.filename);
    logger_default.silly(`path: ${imagePath}`, logOpts2);
    if (import_fs2.default.existsSync(imagePath)) {
      logger_default.debug(`removing file: '${imagePath}'`, logOpts2, {
        msgType: "REMOVE",
        itemType: "file"
      });
      import_fs2.default.unlinkSync(imagePath);
    }
  }
};
var remove2 = async (id2) => {
  const logOpts4 = {
    scope: "removeSnapshot",
    msgType: "REMOVE",
    itemType: "snapshot",
    ref: id2
  };
  logger_default.silly(`deleting snapshot with id: '${id2}'`, logOpts4);
  if (!id2) {
    logger_default.warn("id is empty");
    return;
  }
  const snapshot = await Snapshot_model_default.findById(id2).lean().exec();
  if (!snapshot) {
    logger_default.warn(`cannot find snapshot with id: '${id2}'`);
    return;
  }
  const baseline = await Baseline_model_default.findOne({ snapshootId: id2 });
  if (baseline) {
    logger_default.debug(`snapshot: '${id2}' is related to a baseline, skipping deletion`, logOpts4);
    return;
  }
  logger_default.debug(`snapshot: '${id2}' is not related to a baseline, attempting to remove it`, logOpts4);
  await Snapshot_model_default.findByIdAndDelete(id2);
  logger_default.debug(`snapshot: '${id2}' was removed`, logOpts4);
  const imagePath = import_path3.default.join(config.defaultImagesPath, snapshot.filename);
  logger_default.debug(`attempting to remove snapshot file, id: '${snapshot._id}', filename: '${imagePath}'`, logOpts4);
  await removeSnapshotFile(snapshot);
};

// src/server/services/check.service.ts
async function calculateTestStatus(testId) {
  const checksInTest = await Check_model_default.find({ test: testId });
  const statuses = checksInTest.map((x) => x.status[0]);
  let testCalculatedStatus = "Failed";
  if (statuses.every((x) => x === "new" || x === "passed")) {
    testCalculatedStatus = "Passed";
  }
  if (statuses.every((x) => x === "new")) {
    testCalculatedStatus = "New";
  }
  return testCalculatedStatus;
}
var validateBaselineParam = (params) => {
  const mandatoryParams = ["markedAs", "markedById", "markedByUsername", "markedDate"];
  for (const param of mandatoryParams) {
    if (!params[param]) {
      const errMsg2 = `invalid baseline parameters, '${param}' is empty, params: ${JSON.stringify(params)}`;
      logger_default.error(errMsg2);
      throw new Error(errMsg2);
    }
  }
};
async function createNewBaseline(params) {
  const logOpts4 = {
    scope: "createNewBaseline",
    msgType: "CREATE"
  };
  validateBaselineParam(params);
  const identFields = buildIdentObject(params);
  const lastBaseline = await Baseline_model_default.findOne(identFields).exec();
  const sameBaseline = await Baseline_model_default.findOne({ ...identFields, snapshootId: params.actualSnapshotId }).exec();
  const baselineParams = lastBaseline?.ignoreRegions ? { ...identFields, ignoreRegions: lastBaseline.ignoreRegions } : identFields;
  if (sameBaseline) {
    logger_default.debug(`the baseline with same ident and snapshot id: ${params.actualSnapshotId} already exist`, logOpts4);
  } else {
    logger_default.debug(`the baseline with same ident and snapshot id: ${params.actualSnapshotId} does not exist,
         create new one, baselineParams: ${JSON.stringify(baselineParams)}`, logOpts4);
  }
  logger_default.silly({ sameBaseline });
  const resultedBaseline = sameBaseline || await Baseline_model_default.create(baselineParams);
  resultedBaseline.markedAs = params.markedAs;
  resultedBaseline.markedById = params.markedById;
  resultedBaseline.markedByUsername = params.markedByUsername;
  resultedBaseline.lastMarkedDate = params.markedDate;
  resultedBaseline.createdDate = /* @__PURE__ */ new Date();
  resultedBaseline.snapshootId = params.actualSnapshotId;
  return resultedBaseline.save();
}
var accept2 = async (id2, baselineId, user) => {
  const logOpts4 = {
    msgType: "ACCEPT",
    itemType: "check",
    ref: id2,
    user: user?.username,
    scope: "accept"
  };
  logger_default.debug(`accept check: ${id2}`, logOpts4);
  const check = await Check_model_default.findById(id2).exec();
  if (!check) throw new Error(`cannot find check with id: ${id2}`);
  const test = await Test_model_default.findById(check.test).exec();
  if (!test) throw new Error(`cannot find test with id: ${check.test}`);
  check.markedById = user._id;
  check.markedByUsername = user.username;
  check.markedDate = /* @__PURE__ */ new Date();
  check.markedAs = "accepted";
  check.status = check.status[0] === "new" ? ["new"] : ["passed"];
  check.updatedDate = /* @__PURE__ */ new Date();
  logger_default.debug(`update check with options: '${JSON.stringify(check.toObject())}'`, logOpts4);
  await createNewBaseline(check.toObject());
  await check.save();
  const testCalculatedStatus = await calculateTestStatus(String(check.test));
  const testCalculatedAcceptedStatus = await calculateAcceptedStatus(check.test);
  test.status = testCalculatedStatus;
  test.markedAs = testCalculatedAcceptedStatus;
  test.updatedDate = /* @__PURE__ */ new Date();
  await Suite_model_default.findByIdAndUpdate(check.suite, { updatedDate: Date.now() });
  logger_default.debug(`update test with status: '${testCalculatedStatus}', marked: '${testCalculatedAcceptedStatus}'`, logOpts4, {
    msgType: "UPDATE",
    itemType: "test",
    ref: test._id
  });
  await test.save();
  await check.save();
  logger_default.debug(`check with id: '${id2}' was updated`, logOpts4);
  return check;
};
async function removeCheck(id2, user) {
  const logMeta = {
    scope: "removeCheck",
    itemType: "check",
    ref: id2,
    msgType: "REMOVE",
    user: user?.username
  };
  try {
    const check = await Check_model_default.findByIdAndDelete(id2).exec();
    if (!check) throw new Error(`cannot find check with id: ${id2}`);
    logger_default.debug(`check with id: '${id2}' was removed, update test: ${check.test}`, logMeta);
    const test = await Test_model_default.findById(check.test).exec();
    if (!test) throw new Error(`cannot find test with id: ${check.test}`);
    const testCalculatedStatus = await calculateTestStatus(String(check.test));
    const testCalculatedAcceptedStatus = await calculateAcceptedStatus(check.test);
    test.status = testCalculatedStatus;
    test.markedAs = testCalculatedAcceptedStatus;
    test.updatedDate = /* @__PURE__ */ new Date();
    await updateItemDate("VRSSuite", check.suite);
    await test.save();
    if (check.baselineId && String(check.baselineId) !== "undefined") {
      logger_default.debug(`try to remove the snapshot, baseline: ${check.baselineId}`, logMeta);
      await remove2(check.baselineId.toString());
    }
    if (check.actualSnapshotId && String(check.baselineId) !== "undefined") {
      logger_default.debug(`try to remove the snapshot, actual: ${check.actualSnapshotId}`, logMeta);
      await remove2(check.actualSnapshotId.toString());
    }
    if (check.diffId && String(check.baselineId) !== "undefined") {
      logger_default.debug(`try to remove snapshot, diff: ${check.diffId}`, logMeta);
      await remove2(check.diffId.toString());
    }
    return check;
  } catch (e) {
    const errMsg2 = `cannot remove a check with id: '${id2}', error: '${e instanceof Error ? e.stack : String(e)}'`;
    logger_default.error(errMsg2, logMeta);
    throw new Error(errMsg2);
  }
}
var remove3 = async (id2, user) => {
  const logOpts4 = {
    scope: "removeCheck",
    itemType: "check",
    ref: id2,
    user: user?.username,
    msgType: "REMOVE"
  };
  logger_default.info(`remove check with, id: '${id2}', user: '${user.username}'`, logOpts4);
  return removeCheck(id2, user);
};
var update = async (id2, opts, user) => {
  const logMeta = {
    msgType: "UPDATE",
    itemType: "check",
    ref: id2,
    user,
    scope: "updateCheck"
  };
  logger_default.debug(`update check with id '${id2}' with params '${JSON.stringify(opts, null, 2)}'`, logMeta);
  const check = await Check_model_default.findOneAndUpdate({ _id: id2 }, opts, { new: true }).exec();
  if (!check) throw new Error(`cannot find check with id: ${id2}`);
  const test = await Test_model_default.findOne({ _id: check.test }).exec();
  if (!test) throw new Error(`cannot find test with id: ${check.test}`);
  test.status = await calculateTestStatus(String(check.test));
  await updateItemDate("VRSCheck", check);
  await updateItemDate("VRSTest", test);
  await test.save();
  await check.save();
  return check;
};

// src/server/controllers/test.controller.ts
var getTest = catchAsync_default(async (req, res) => {
  const filter = {
    ...deserializeIfJSON_default(String(req.query.base_filter)),
    ...deserializeIfJSON_default(String(req.query.filter))
  };
  if (req.user?.role === "user") {
    filter.creatorUsername = req.user?.username;
  }
  const options = pick_default(req.query, ["sortBy", "limit", "page", "populate"]);
  const result = await test_service_exports.queryTests(filter, options);
  res.status(import_http_status6.default.OK).send(result);
});
var distinct_with_filter = catchAsync_default(async (req, res) => {
  const filter = req.query.filter ? deserializeIfJSON_default(String(req.query.filter)) : void 0;
  const options = { ...pick_default(req.query, ["sortBy", "limit", "page", "populate"]), field: req.params.field };
  const result = await test_service_exports.queryTestsDistinct(filter, options);
  res.status(import_http_status6.default.OK).send(result);
});
var distinct = catchAsync_default(async (req, res) => {
  const filter = {};
  const options = { ...pick_default(req.query, ["sortBy", "limit", "page", "populate"]), field: req.params.id };
  const result = await test_service_exports.queryTestsDistinct(filter, options);
  res.status(import_http_status6.default.OK).send(result);
});
var remove4 = catchAsync_default(async (req, res) => {
  const { id: id2 } = req.params;
  if (!id2) throw new ApiError_default(import_http_status6.default.BAD_REQUEST, "Cannot remove the test - Id not found");
  if (!req.user) throw new ApiError_default(import_http_status6.default.BAD_REQUEST, "Cannot remove the test - req.user is empty");
  const result = await test_service_exports.remove(id2, req?.user);
  res.send(result);
});
var accept3 = catchAsync_default(async (req, res) => {
  const { id: id2 } = req.params;
  if (!id2) throw new ApiError_default(import_http_status6.default.BAD_REQUEST, "Cannot accept the check - Id not found");
  if (!req.user) throw new ApiError_default(import_http_status6.default.BAD_REQUEST, "Cannot accept the check - req.user is empty");
  const result = await test_service_exports.accept(id2, req?.user);
  res.send(result);
});

// src/server/utils/validateRequest.ts
var import_http_status7 = __toESM(require("http-status"));
var import_zod = require("zod");

// src/server/utils/ServiceResponse.ts
var ServiceResponse = class {
  constructor(status, message, responseObject, statusCode) {
    this.success = status === 0 /* Success */;
    this.message = message;
    this.responseObject = responseObject;
    this.statusCode = statusCode;
  }
};

// src/server/utils/validateRequest.ts
var logOpts3 = {
  scope: "validateRequests",
  itemType: "type",
  msgType: "VALIDATION"
};
function getReceivedValueFromRequest(request, path4) {
  let currentValue = request;
  path4.forEach((segment) => {
    currentValue = currentValue[segment];
  });
  return currentValue;
}
var validateRequest = (schema, endpoint = "") => (req, res, next) => {
  try {
    schema.parse({
      body: req.body,
      query: req.query,
      params: req.params
    });
    next();
  } catch (err) {
    if (err instanceof import_zod.ZodError) {
      const errors = err.errors.map((e) => {
        const receivedValue = getReceivedValueFromRequest(
          { body: req.body, query: req.query, params: req.params },
          e.path
        );
        return `
Error path: '${e.path.join(".")}': 
Error ${e.message}, but received ${JSON.stringify(receivedValue)}`;
      }).join(", ");
      const errorMessage = ` ${endpoint ? '\nValidation error in the endpoint: "' + endpoint + '"' : ""}${errors}, 
HTTP PROPERTIES:
	body: ${JSON.stringify(req.body, null, "	")}, 
	query: ${JSON.stringify(req.query, null, "	")}, 
	params: ${JSON.stringify(req.params, null, "	")}`;
      const statusCode = import_http_status7.default.BAD_REQUEST;
      logger_default.error(errorMessage, logOpts3);
      res.status(statusCode).send(new ServiceResponse(1 /* Failed */, errorMessage, null, statusCode));
    } else {
      logger_default.error(`Unexpected error: ${errMsg(err)}`, logOpts3);
      next(err);
    }
  }
};

// src/server/schemas/TestDistinct.schema.ts
var import_zod2 = require("zod");
var validIds = [
  "suite",
  "run",
  "markedAs",
  "creatorId",
  "creatorUsername",
  "name",
  "status",
  "browserName",
  "browserVersion",
  "branch",
  "tags",
  "viewport",
  "os",
  "app",
  "startDate",
  "filter"
];
var TestDistinctRequestParamsSchema = import_zod2.z.object({
  id: import_zod2.z.enum(validIds).openapi({
    description: "Parameter identifier",
    example: "suite"
  })
});
var TestDistinctResponseSchema = import_zod2.z.object({
  name: import_zod2.z.string().min(1).openapi({
    description: "Distinct field value",
    example: "chrome"
  })
});

// src/server/api-docs/openAPIResponseBuilders.ts
var import_http_status8 = __toESM(require("http-status"));

// src/server/api-docs/serviceResponse.ts
var import_zod3 = require("zod");
var ServiceResponsePaginationSchema = (dataSchema) => import_zod3.z.object({
  results: import_zod3.z.array(dataSchema.optional()),
  page: import_zod3.z.number().openapi({ example: 1 }),
  limit: import_zod3.z.number().openapi({ example: 10 }),
  totalPages: import_zod3.z.number().openapi({ example: 2 }),
  totalResults: import_zod3.z.number().openapi({ example: 12 }),
  timestamp: import_zod3.z.number().openapi({ example: 1718035239731968 })
});

// src/server/api-docs/openAPIResponseBuilders.ts
function createPaginatedApiResponse(schema, description, statusCode = import_http_status8.default.OK) {
  return {
    [statusCode]: {
      description,
      content: {
        "application/json": {
          schema: ServiceResponsePaginationSchema(schema)
        }
      }
    }
  };
}

// src/seeds/initialAppSettings.json
var initialAppSettings_default = [
  {
    name: "first_run",
    label: "First Run",
    description: "Indicates if the application is running the first time",
    type: "Boolean",
    value: "true",
    enabled: true
  },
  {
    name: "authentication",
    label: "Authentication",
    description: "Enable application authentication",
    type: "Boolean",
    value: "false",
    enabled: true
  }
];

// src/server/lib/AppSettings/AppSettings.ts
var AppSettings2 = class {
  constructor() {
    this.model = AppSettings_model_default;
    this.cache = null;
  }
  async init() {
    this.cache = await this.model.find().lean().exec();
    return this;
  }
  ensureInitialized() {
    if (!this.cache) {
      throw new Error("AppSettings is not initialized. Please call init() before using this method.");
    }
  }
  async count() {
    this.ensureInitialized();
    return this.model.countDocuments().exec();
  }
  async loadInitialFromFile() {
    this.ensureInitialized();
    const settings = initialAppSettings_default;
    await this.model.insertMany(settings);
    this.cache = settings;
  }
  async get(name) {
    this.ensureInitialized();
    return this.cache.find((x) => x.name === name) || this.model.findOne({ name }).exec();
  }
  async set(name, value) {
    this.ensureInitialized();
    const item = await this.model.findOneAndUpdate({ name }, { value });
    await item.save();
    const cachedItem = this.cache.find((x) => x.name === name);
    if (cachedItem) {
      cachedItem["value"] = value;
    }
  }
  async enable(name) {
    this.ensureInitialized();
    const item = await this.model.findOneAndUpdate({ name }, { enabled: true });
    await item.save();
    const cachedItem = this.cache.find((x) => x.name === name);
    if (cachedItem) {
      cachedItem["enabled"] = true;
    }
  }
  async disable(name) {
    this.ensureInitialized();
    const item = await this.model.findOneAndUpdate({ name }, { enabled: false });
    await item.save();
    const cachedItem = this.cache.find((x) => x.name === name);
    if (cachedItem) {
      cachedItem["enabled"] = false;
    }
  }
  async isAuthEnabled() {
    this.ensureInitialized();
    return env.SYNGRISI_AUTH || (await this.get("authentication"))?.value === "true";
  }
  async isFirstRun() {
    this.ensureInitialized();
    return (await this.get("first_run"))?.value === "true";
  }
};
var appSettings = new AppSettings2().init();

// src/server/middlewares/ensureLogin/ensureLoggedIn.ts
var handleBasicAuth = async (req) => {
  const logOpts4 = {
    scope: "handleBasicAuth",
    msgType: "AUTH_API"
  };
  if (req.isAuthenticated()) {
    return { type: "success", status: 200 };
  }
  const AppSettings3 = await appSettings;
  if (!await AppSettings3.isAuthEnabled()) {
    const guest = await User_model_default.findOne({ username: "Guest" });
    const result2 = new Promise((resolve) => {
      req.logIn(guest, (err) => {
        if (err) {
          logger_default.error(`cannot find guest user: '${err}'`, logOpts4);
          resolve({
            type: "redirect",
            status: 301,
            value: `/auth?=Error: cannot find guest user: ${err}`,
            user: null
          });
        } else {
          resolve({
            type: "success",
            status: 200,
            value: "",
            user: guest
          });
        }
      });
    });
    return result2;
  }
  const result = {
    type: "error",
    status: 400,
    value: "",
    user: null
  };
  if (await AppSettings3.isAuthEnabled() && await AppSettings3.isFirstRun() && !env.SYNGRISI_DISABLE_FIRST_RUN) {
    logger_default.info("first run, set admin password", logOpts4);
    result.type = "redirect";
    result.status = 301;
    result.value = "/auth/change?first_run=true";
    return result;
  }
  if (await AppSettings3.isAuthEnabled()) {
    logger_default.info(`user is not authenticated, will redirected - ${req.originalUrl}`, logOpts4);
    result.type = "redirect";
    result.status = 301;
    if (req?.originalUrl !== "/") {
      result.value = `/auth?origin=${encodeURIComponent(req.originalUrl)}`;
      return result;
    }
    result.value = "/auth";
    return result;
  }
};
function ensureLoggedIn(options) {
  return async (req, res, next) => {
    const result = await handleBasicAuth(req);
    req.user = result.user || req.user;
    if (result.type === "success") {
      return next();
    }
    res.status(result.status).redirect(result.value);
    return next("redirect");
  };
}

// src/server/schemas/utils/createRequestParamsSchema.ts
var import_zod6 = require("zod");

// src/server/schemas/utils/commonValidations.ts
var import_zod5 = require("zod");
var import_zod_to_openapi = require("@asteasolutions/zod-to-openapi");

// src/server/schemas/common/Version.schema.ts
var import_zod4 = require("zod");
var VersionSchema = import_zod4.z.string().regex(/^\d+\.\d+\.\d+$/, 'Version must be in the format "x.y.z"').transform((value) => {
  const parts = value.split(".");
  return {
    major: parseInt(parts[0]),
    minor: parseInt(parts[1]),
    patch: parseInt(parts[2])
  };
});
var Version_schema_default = VersionSchema;

// src/server/schemas/utils/commonValidations.ts
(0, import_zod_to_openapi.extendZodWithOpenApi)(import_zod5.z);
var mongooseIdRegex = /^[0-9a-fA-F]{24}$/;
var id = import_zod5.z.string().regex(mongooseIdRegex, {
  message: "Invalid Mongoose ObjectId format: /^[0-9a-fA-F]{24}$/"
}).openapi({
  description: "baseline ID",
  example: "6bbF35cAB3C59dA969edAe79"
});
var commonValidations = {
  id,
  version: Version_schema_default.openapi({ example: "1.1.2" }),
  positiveNumberString: import_zod5.z.string().refine((value) => {
    const num2 = Number(value);
    return Number.isInteger(num2) && num2 >= 0;
  }, {
    message: "String must be a positive number or 0"
  }),
  password: import_zod5.z.string().min(6).regex(/(?=.*[0-9])/, "Password must include a number").regex(/(?=.*[a-z])/, "Password must include a lowercase letter").regex(/(?=.*[A-Z])/, "Password must include an uppercase letter").refine((value) => {
    return /(?=.*[!@#$%^&*(),.?":{}|<>-])/.test(value);
  }, {
    message: "Password must include a special symbol"
  }).openapi({ example: "Aa1!IJASSNOJ" }),
  username: import_zod5.z.string().min(1).openapi({ example: "john.doe@example.com" }),
  // TODO: workaround TBD
  date: import_zod5.z.string().refine((val) => {
    const date = new Date(val);
    return !isNaN(date.getTime());
  }, {
    message: "Invalid date format"
  }),
  paramsId: { params: import_zod5.z.object({ id }) },
  paramsTestId: { params: import_zod5.z.object({ testid: id }) },
  success: import_zod5.z.object({
    message: import_zod5.z.literal("success")
  })
};

// src/server/schemas/utils/createRequestParamsSchema.ts
var createRequestParamsSchema = (schema) => import_zod6.z.object({ params: schema });

// src/server/schemas/common/RequestPagination.schema.ts
var import_zod_to_openapi3 = require("@asteasolutions/zod-to-openapi");
var import_zod8 = require("zod");

// src/server/schemas/common/requestQueryFilterSchema.schema.ts
var import_zod_to_openapi2 = require("@asteasolutions/zod-to-openapi");
var import_zod7 = require("zod");
(0, import_zod_to_openapi2.extendZodWithOpenApi)(import_zod7.z);
var requestQueryFilterSchema = import_zod7.z.string().optional().refine((data) => {
  if (!data) return false;
  try {
    const parsed = JSON.parse(data);
    const valueSchema = import_zod7.z.lazy(() => import_zod7.z.union([
      import_zod7.z.string(),
      import_zod7.z.number(),
      import_zod7.z.boolean(),
      import_zod7.z.array(import_zod7.z.any()),
      import_zod7.z.record(import_zod7.z.any())
    ]));
    const schema = import_zod7.z.record(valueSchema);
    schema.parse(parsed);
    return true;
  } catch (e) {
    return false;
  }
}, {
  message: "Invalid JSON string or does not match the required schema"
}).openapi({ example: '{"key1": "value1", "key2": 123, "key3": true, "$and":[{"name":"CheckName"}]}' });

// src/server/schemas/common/RequestPagination.schema.ts
(0, import_zod_to_openapi3.extendZodWithOpenApi)(import_zod8.z);
var RequestPaginationSchema = import_zod8.z.object({
  filter: requestQueryFilterSchema.optional(),
  limit: commonValidations.positiveNumberString.optional().openapi({ example: "10" }),
  page: commonValidations.positiveNumberString.optional().openapi({ example: "1" }),
  sortBy: import_zod8.z.string().optional().openapi({ example: "name:desc" }),
  populate: import_zod8.z.string().optional().openapi({ example: "test" })
});

// src/server/routes/v1/test_distinct.route.ts
var registry = new import_zod_to_openapi4.OpenAPIRegistry();
var router = import_express.default.Router();
registry.registerPath({
  method: "get",
  path: "/v1/test-distinct/{id}",
  summary: "[Obsolete use '/v1/test/distict' instead] List of certain unique fields across all tests",
  tags: ["Tests"],
  request: { params: TestDistinctRequestParamsSchema, query: RequestPaginationSchema },
  responses: createPaginatedApiResponse(TestDistinctResponseSchema, "Success")
});
router.get(
  "/:id",
  ensureLoggedIn(),
  validateRequest(createRequestParamsSchema(TestDistinctRequestParamsSchema), "get, /v1/test-distinct/{id}"),
  distinct
);
var test_distinct_route_default = router;
// Annotate the CommonJS export names for ESM import in node:
0 && (module.exports = {
  registry
});
//# sourceMappingURL=test_distinct.route.js.map