vtex
Version:
The platform for e-commerce apps
129 lines (128 loc) • 5.94 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", { value: true });
exports.ProjectUploader = exports.ChangeSizeLimitError = exports.ProjectSizeLimitError = void 0;
const tslib_1 = require("tslib");
const Builder_1 = require("../../clients/IOClients/apps/Builder");
const host_1 = require("../../../host");
const archiver_1 = tslib_1.__importDefault(require("archiver"));
const chalk_1 = tslib_1.__importDefault(require("chalk"));
const get_stream_1 = tslib_1.__importDefault(require("get-stream"));
const logger_1 = tslib_1.__importDefault(require("../../logger"));
const MB = 1000000;
const getSizeString = (byteSize, colored = true, megaBytesintensityScale = [10, 20]) => {
const mbSize = byteSize / MB;
const mbSizeString = mbSize.toFixed(2);
if (!colored) {
return `${mbSizeString}MB`;
}
if (mbSize < megaBytesintensityScale[0]) {
return `${chalk_1.default.bold.green(`${mbSizeString}MB`)}`;
}
if (mbSize < megaBytesintensityScale[1]) {
return `${chalk_1.default.bold.yellow(`${mbSizeString}MB`)}`;
}
return `${chalk_1.default.bold.red(`${mbSizeString}MB`)}`;
};
class ProjectSizeLimitError extends Error {
constructor(projectByteSize, maxByteSize) {
super(`This project size (${getSizeString(projectByteSize)}) is exceeding the size limit ${getSizeString(maxByteSize)} `);
this.projectByteSize = projectByteSize;
}
}
exports.ProjectSizeLimitError = ProjectSizeLimitError;
class ChangeSizeLimitError extends Error {
constructor(changeByteSize, maxByteSize) {
super(`This change size (${getSizeString(changeByteSize)}) is exceeding the size limit ${getSizeString(maxByteSize)} `);
this.changeByteSize = changeByteSize;
}
}
exports.ChangeSizeLimitError = ChangeSizeLimitError;
class ProjectUploader {
constructor(appName, builderHubClient) {
this.appName = appName;
this.builderHubClient = builderHubClient;
this.compressFilesOnMemory = async (files, zlibOptions = {}) => {
const zip = archiver_1.default('zip', { zlib: zlibOptions });
zip.on('error', (err) => {
throw err;
});
files.forEach(({ content, path }) => zip.append(content, { name: path }));
const [zipContent] = await Promise.all([get_stream_1.default.buffer(zip), zip.finalize()]);
return zipContent;
};
}
static getProjectUploader(appId, contextOrClient, clientTimeout = 60000) {
let builderHubClient;
if (contextOrClient instanceof Builder_1.Builder) {
builderHubClient = contextOrClient;
}
else {
builderHubClient = Builder_1.Builder.createClient(contextOrClient, { timeout: clientTimeout });
}
const projectUploader = new ProjectUploader(appId, builderHubClient);
return projectUploader;
}
async sendToPublish(files, publishTag, params = {}) {
const { zipFile, builderHubResolvingOpts } = await this.prepareRequest(files);
return this.builderHubClient.publishApp(this.appName, zipFile, { ...builderHubResolvingOpts, tag: publishTag }, params);
}
async sendToTest(files, params = {}) {
const { zipFile, builderHubResolvingOpts } = await this.prepareRequest(files);
return this.builderHubClient.testApp(this.appName, zipFile, builderHubResolvingOpts, params);
}
async sendToLink(files, linkID, params = {}) {
const { zipFile, builderHubResolvingOpts } = await this.prepareRequest(files);
return this.builderHubClient.linkApp(this.appName, linkID, zipFile, builderHubResolvingOpts, params);
}
sendToRelink(changes, linkID, params = {}) {
this.checkSizeLimits(changes, true);
return this.builderHubClient.relinkApp(this.appName, changes, linkID, params);
}
checkSizeLimits(filesOrChanges, isChange = false) {
const totalByteSize = filesOrChanges.reduce((acc, file) => acc + file.byteSize, 0);
const sizeLimit = isChange ? ProjectUploader.CHANGE_BYTESIZE_LIMIT : ProjectUploader.PROJECT_BYTESIZE_LIMIT;
if (totalByteSize > sizeLimit) {
if (isChange) {
throw new ChangeSizeLimitError(totalByteSize, sizeLimit);
}
else {
throw new ProjectSizeLimitError(totalByteSize, sizeLimit);
}
}
if (!isChange || isChange) {
const logMessage = `Project size: ${getSizeString(totalByteSize)}`;
if (totalByteSize > ProjectUploader.BYTES_PROJECT_SIZE_SCALE[0]) {
logger_1.default.warn(logMessage);
}
else {
logger_1.default.info(logMessage);
}
}
}
async prepareRequest(files) {
this.checkSizeLimits(files);
this.checkForManifest(files);
logger_1.default.info('Compressing project files...');
const zipFile = await this.compressFilesOnMemory(files);
logger_1.default.info(`Compressed project size: ${getSizeString(zipFile.byteLength, false)}`);
const stickyHint = await this.getBuilderHubSticky();
const builderHubResolvingOpts = {
sticky: true,
stickyHint,
};
return { zipFile, builderHubResolvingOpts };
}
checkForManifest(files) {
const indexOfManifest = files.findIndex(({ path }) => path === 'manifest.json');
if (indexOfManifest === -1) {
throw new Error('No manifest.json file found in files.');
}
}
getBuilderHubSticky(hostsToTry = 3, timeout = 1000) {
return host_1.getSavedOrMostAvailableHost(this.appName, this.builderHubClient, hostsToTry, timeout);
}
}
exports.ProjectUploader = ProjectUploader;
ProjectUploader.CHANGE_BYTESIZE_LIMIT = 50 * MB;
ProjectUploader.PROJECT_BYTESIZE_LIMIT = 90 * MB;
ProjectUploader.BYTES_PROJECT_SIZE_SCALE = [10 * MB, 20 * MB];