@percy/agent
Version:
An agent process for integrating with Percy.
99 lines (98 loc) • 4.95 kB
JavaScript
"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;