UNPKG

@percy/agent

Version:

An agent process for integrating with Percy.

99 lines (98 loc) 4.95 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); const bodyParser = require("body-parser"); const cors = require("cors"); const express = require("express"); const logger_1 = require("../utils/logger"); const agent_service_constants_1 = require("./agent-service-constants"); const build_service_1 = require("./build-service"); const configuration_service_1 = require("./configuration-service"); const constants_1 = require("./constants"); const process_service_1 = require("./process-service"); const snapshot_service_1 = require("./snapshot-service"); class AgentService { constructor() { this.snapshotService = null; this.publicDirectory = `${__dirname}/../../dist/public`; this.snapshotCreationPromises = []; this.server = null; this.buildId = null; this.app = express(); this.app.use(cors()); this.app.use(bodyParser.urlencoded({ extended: true })); this.app.use(bodyParser.json({ limit: '50mb' })); this.app.use(express.static(this.publicDirectory)); this.app.post(agent_service_constants_1.SNAPSHOT_PATH, this.handleSnapshot.bind(this)); this.app.post(agent_service_constants_1.STOP_PATH, this.handleStop.bind(this)); this.app.get(agent_service_constants_1.HEALTHCHECK_PATH, this.handleHealthCheck.bind(this)); this.buildService = new build_service_1.default(); } async start(configuration) { this.buildId = await this.buildService.create(); if (this.buildId !== null) { this.server = this.app.listen(configuration.agent.port); this.snapshotService = new snapshot_service_1.default(this.buildId, configuration.agent['asset-discovery']); await this.snapshotService.assetDiscoveryService.setup(); return; } await this.stop(); } async stop() { logger_1.default.info('stopping percy...'); logger_1.default.info(`waiting for ${this.snapshotCreationPromises.length} snapshots to complete...`); await Promise.all(this.snapshotCreationPromises); logger_1.default.info('done.'); if (this.snapshotService) { await this.snapshotService.assetDiscoveryService.teardown(); } await this.buildService.finalize(); if (this.server) { await this.server.close(); } } async handleSnapshot(request, response) { logger_1.profile('agentService.handleSnapshot'); // truncate domSnapshot for the logs if it's very large let domSnapshotLog = request.body.domSnapshot; if (domSnapshotLog.length > constants_1.default.MAX_LOG_LENGTH) { domSnapshotLog = domSnapshotLog.substring(0, constants_1.default.MAX_LOG_LENGTH); domSnapshotLog += `[truncated at ${constants_1.default.MAX_LOG_LENGTH}]`; } logger_1.default.debug('handling snapshot:'); logger_1.default.debug(`-> headers: ${JSON.stringify(request.headers)}`); logger_1.default.debug(`-> name: ${request.body.name}`); logger_1.default.debug(`-> url: ${request.body.url}`); logger_1.default.debug(`-> clientInfo: ${request.body.clientInfo}`); logger_1.default.debug(`-> environmentInfo: ${request.body.environmentInfo}`); logger_1.default.debug(`-> domSnapshot: ${domSnapshotLog}`); if (!this.snapshotService) { return response.json({ success: false }); } const configuration = new configuration_service_1.default().configuration; const snapshotOptions = { widths: request.body.widths || configuration.snapshot.widths, enableJavaScript: request.body.enableJavaScript, minHeight: request.body.minHeight || configuration.snapshot['min-height'], }; const domSnapshot = request.body.domSnapshot; if (domSnapshot.length > constants_1.default.MAX_FILE_SIZE_BYTES) { logger_1.default.info(`snapshot skipped[max_file_size_exceeded]: '${request.body.name}'`); return response.json({ success: true }); } const resources = await this.snapshotService.buildResources(request.body.url, domSnapshot, snapshotOptions); const snapshotCreation = this.snapshotService.create(request.body.name, resources, snapshotOptions, request.body.clientInfo, request.body.environmentInfo); this.snapshotCreationPromises.push(snapshotCreation); logger_1.default.info(`snapshot taken: '${request.body.name}'`); logger_1.profile('agentService.handleSnapshot'); return response.json({ success: true }); } async handleStop(_, response) { await this.stop(); new process_service_1.default().kill(); return response.json({ success: true }); } async handleHealthCheck(_, response) { return response.json({ success: true }); } } exports.AgentService = AgentService;