badRequest
Create a 400 error for invalid client input.
badRequest = (message: string, details?: unknown) => new HttpError(400, message, details)apps/api/src/lib/http-error.ts:18API Docs
Create a 400 error for invalid client input.
badRequest = (message: string, details?: unknown) => new HttpError(400, message, details)apps/api/src/lib/http-error.ts:18Create a 409 error for duplicate or conflicting state.
conflict = (message: string) => new HttpError(409, message)apps/api/src/lib/http-error.ts:27Create a 403 error for authenticated users without access.
forbidden = (message = 'Forbidden') => new HttpError(403, message)apps/api/src/lib/http-error.ts:23A thin error type carrying an HTTP status code. Thrown anywhere in a route and translated into a JSON `{ error }` body by the global error handler.
class HttpError extends Errorapps/api/src/lib/http-error.ts:5Create a 404 error when a requested record does not exist.
notFound = (message = 'Not found') => new HttpError(404, message)apps/api/src/lib/http-error.ts:25Create a 401 error for missing or invalid authentication.
unauthorized = (message = 'Unauthorized') => new HttpError(401, message)apps/api/src/lib/http-error.ts:21Shared Winston logger used by the API, worker and supporting services.
logger = winston.createLogger(apps/api/src/lib/logger.ts:5Emit a Socket.io event to everyone watching a specific test run.
function emitToTestRun(testRunId: string, event: string, data: unknown): voidapps/api/src/lib/socket.ts:22Return the Socket.io server instance after it has been initialised.
function getIO(): IOServer | undefinedapps/api/src/lib/socket.ts:17Attaches Socket.io to the HTTP server. Two scalability features: 1. A Redis adapter so socket rooms work across multiple API instances. 2. A subscription to the `test-run-logs:all` Redis channel (published by the worker's LoggingService) that forwards each log line to the matching `test-run-<id>` room — so clients see live logs even though the work runs in a separate worker process.
async function initSocket(server: HttpServer): Promise<IOServer>apps/api/src/lib/socket.ts:34Extract the host-independent path (pathname + search) from a URL.
function pathFromUrl(url: string): stringapps/api/src/lib/url.ts:10Build a canonical URL on the suite's base origin for a given path.
function urlFromBase(baseUrl: string, path: string): stringapps/api/src/lib/url.ts:25Map a current Baseline pointer document to the shared Baseline DTO.
function toBaselineDTO(doc: any): Baselineapps/api/src/mappers/index.ts:153Map an immutable BaselineVersion document to the shared history DTO.
function toBaselineVersionDTO(doc: any): BaselineVersionapps/api/src/mappers/index.ts:168Map a GitHub App installation document to the linking UI DTO.
function toGitHubInstallationDTO(doc: any): GitHubInstallationapps/api/src/mappers/index.ts:191Map one PageResult document to the shared PageResult DTO.
function toPageResultDTO(doc: any): PageResultapps/api/src/mappers/index.ts:130Map a discovered SitePage document to the shared SitePage DTO.
function toSitePageDTO(doc: any): SitePageapps/api/src/mappers/index.ts:95Map stored crawl state to the shared SuiteCrawlState DTO.
function toSuiteCrawlStateDTO(crawl: any): SuiteCrawlStateapps/api/src/mappers/index.ts:85Map a TestRun document to the shared TestRun DTO.
function toTestRunDTO(doc: any): TestRunapps/api/src/mappers/index.ts:113Map a stored structured log line to the shared TestRunLog DTO.
function toTestRunLogDTO(doc: any): TestRunLogapps/api/src/mappers/index.ts:206Map a TestSuite document to the shared TestSuite DTO.
function toTestSuiteDTO(doc: any): TestSuiteapps/api/src/mappers/index.ts:66Map a User document to the safe user DTO returned to browsers.
function toUserDTO(doc: any): Userapps/api/src/mappers/index.ts:37Map a user reference to a minimal summary. Handles both a populated user doc and a bare ObjectId/string (returns id-only in that case); null stays null.
function toUserSummaryDTO(doc: any): UserSummary | nullapps/api/src/mappers/index.ts:52Register the worker processor that reconciles discovered site pages.
function registerCrawlProcessor(): voidapps/api/src/queue/crawlProcessor.ts:29Bull job name used for one-off and scheduled site-discovery crawls.
CRAWL_JOB_NAME = 'crawlSite'apps/api/src/queue/crawlQueue.ts:45Dedicated queue for site-discovery crawls, kept separate from the visual diff queue so a long crawl never blocks screenshot/diff runs (and vice versa). The worker process consumes both queues.
crawlQueue = new Queue('site-discovery crawls', env.redisUrl,apps/api/src/queue/crawlQueue.ts:10Enqueue a one-off discovery crawl for a suite.
async function enqueueCrawl(data: CrawlJobData)apps/api/src/queue/crawlQueue.ts:48Sync a suite's repeatable recrawl job with its configured interval. Removes any existing schedule for the suite, then registers a new one unless the interval is 'off' or the suite is inactive. Call on suite create/update; call removeRecrawlSchedule on delete.
async function reconcileRecrawlSchedule( testSuiteId: string, interval: RecrawlInterval | undefined | null, isActive = true ): Promise<void>apps/api/src/queue/crawlQueue.ts:60Remove any repeatable recrawl job registered for a suite.
async function removeRecrawlSchedule(testSuiteId: string): Promise<void>apps/api/src/queue/crawlQueue.ts:83Register the worker processor that executes full suite, branch and PR runs.
function registerTestRunProcessor(): voidapps/api/src/queue/processor.ts:21Register the worker processor for targeted page-result reruns.
function registerRerunPageProcessor(): voidapps/api/src/queue/rerunProcessor.ts:33Re-run a handful of errored viewport results in place. Unlike a full run we disable retries: the rerun mutates baselines/results and is cheap to trigger again from the UI, so an automatic retry would risk double-seeding baselines.
async function enqueueRerunPage(data: RerunPageJobData)apps/api/src/queue/testRunQueue.ts:71Add a full visual-regression run job to the worker queue.
async function enqueueTestRun(data: TestRunJobData)apps/api/src/queue/testRunQueue.ts:55Bull queue that carries full visual-regression runs and targeted reruns.
testRunQueue = new Queue('visual regression tests', env.redisUrl,apps/api/src/queue/testRunQueue.ts:6Append a new BaselineVersion for a (suite, path, viewport) and repoint the Baseline doc at it. Idempotent enough for retries: the unique (suite,path,viewport,version) index rejects a duplicate version number, and we recompute `version` from the current max each call.
async function recordBaselineVersion( params: RecordBaselineVersionParams ): Promise<IBaselineVersion | null>apps/api/src/services/BaselineHistoryService.ts:55Promote a PR run's accepted screenshots to the suite's main baselines.
async function promoteRunBaselines(testRunId: string): Promise<PromotionResult>apps/api/src/services/PromotionService.ts:24Approve every changed (FAIL) result in a run at once. - MANUAL/BRANCH: write a baseline from each changed screenshot immediately. - PR: defer baselines to merge (PromotionService); just accept. In both cases the changed results become PASS/approved and the gate is recomputed (to APPROVED). The PR GitHub-check unblock stays in the route.
async function approveAllRunDiffs( testRunId: string, approvedBy?: string | null ): Promise<ApproveAllResult>apps/api/src/services/ReviewService.ts:144Pure: derive a run's review gate from its current page results. - any unresolved diff (status FAIL) still present -> PENDING - no diffs left but at least one was approved -> APPROVED - never had a diff -> NOT_REQUIRED
function computeReviewState(results: ResultGateInput[]): VisualReviewStateapps/api/src/services/ReviewService.ts:46Recompute a run's review gate from its page results and persist it. Returns the new state. Call this after any approval mutation.
async function recomputeRunReviewState(testRunId: string): Promise<VisualReviewState>apps/api/src/services/ReviewService.ts:56Promote one approved PageResult to the current baseline and append history.
async function upsertBaselineFromResult( suite: any, result: any, opts: UpsertBaselineOpts =apps/api/src/services/ReviewService.ts:84Recompute and persist a run's status/reviewState/metadata from its PageResults. Best-effort updates the PR GitHub check to match. Never throws on GitHub errors.
async function finalizeRunOutcome(testRunId: string): Promise<void>apps/api/src/services/RunOutcomeService.ts:26Validate that the suite has tracked pages, create a TestRun, and enqueue it. Throws `badRequest` (handled by the global error handler) when there's nothing to diff or the target URL is invalid.
async function startSuiteRun( testSuiteId: string, opts: StartSuiteRunOptions =apps/api/src/services/RunService.ts:38Discovers crawlable pages for one site using sitemap data, links and a Playwright fallback for client-rendered pages.
class SiteCrawlerapps/api/src/services/SiteCrawler.ts:58