@selfage/bundler_cli
Version:
CLI for bundling and running bundled frontend or backend TypeScript files.
74 lines • 13.3 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", { value: true });
exports.DEFAULT_BUNDLED_RESOURCES_FILE = exports.DEFAULT_ENTRIES_CONFIG_FILE = void 0;
exports.bundleWebApps = bundleWebApps;
exports.bundleWebAppsAndReturnBundledResources = bundleWebAppsAndReturnBundledResources;
const fs = require("fs");
const path = require("path");
const stream = require("stream");
const util = require("util");
const yaml = require("yaml");
const zlib = require("zlib");
const bundler_1 = require("./bundler");
const file_extension_stripper_1 = require("./file_extension_stripper");
const files_copier_1 = require("./files_copier");
const web_app_entries_def_1 = require("./web_app_entries_def");
const parser_1 = require("@selfage/message/parser");
let pipeline = util.promisify(stream.pipeline);
exports.DEFAULT_ENTRIES_CONFIG_FILE = "web_app_entries.yaml";
exports.DEFAULT_BUNDLED_RESOURCES_FILE = "web_app_resources.yaml";
async function bundleWebApps(entriesConfigFile = exports.DEFAULT_ENTRIES_CONFIG_FILE, bundledResourcesFile = exports.DEFAULT_BUNDLED_RESOURCES_FILE, outDir, options) {
let baseDir = path.posix.dirname(entriesConfigFile);
let allFiles = await bundleWebAppsAndReturnBundledResources(entriesConfigFile, baseDir, options);
let allRelativeFiles = allFiles.map((file) => path.posix.relative(path.posix.dirname(bundledResourcesFile), file));
await fs.promises.writeFile(bundledResourcesFile, yaml.stringify(allRelativeFiles));
if (!outDir ||
path.posix.normalize(outDir) === path.posix.normalize(baseDir)) {
return;
}
await (0, files_copier_1.copyFiles)(allFiles, baseDir, outDir);
}
async function bundleWebAppsAndReturnBundledResources(entriesConfigFile, baseDir, options) {
let webAppEntries = (0, parser_1.parseMessage)(yaml.parse((await fs.promises.readFile(entriesConfigFile)).toString()), web_app_entries_def_1.WEB_APP_ENTRIES);
let configDir = path.posix.dirname(entriesConfigFile);
let promises = new Array();
for (let entry of webAppEntries.entries) {
promises.push(bundleAndGzip(path.posix.join(configDir, entry.source), path.posix.join(configDir, entry.output), baseDir, options), writeHtmlFileAndGZip(path.posix.join(configDir, entry.output), baseDir));
}
let allFiles = await Promise.all(promises);
let flattenedFiles = new Array();
for (let files of allFiles) {
flattenedFiles.push(...files);
}
if (webAppEntries.extraAssets) {
for (let extraAsset of webAppEntries.extraAssets) {
flattenedFiles.push(path.posix.join(configDir, extraAsset));
}
}
return flattenedFiles;
}
async function bundleAndGzip(sourceFile, outputFile, baseDir, options) {
let assetFiles = await (0, bundler_1.bundleForBrowserReturnAssetFiles)(sourceFile, outputFile, baseDir, options);
let jsFile = (0, file_extension_stripper_1.stripFileExtension)(outputFile) + ".js";
let gzFile = await gzipFile(jsFile);
return [...assetFiles, jsFile, gzFile];
}
async function writeHtmlFileAndGZip(binFile, baseDir) {
let binModulePath = (0, file_extension_stripper_1.stripFileExtension)(binFile);
let htmlFile = binModulePath + ".html";
let binJsPath = path.posix.relative(baseDir, binModulePath + ".js");
await fs.promises.writeFile(htmlFile, `<!DOCTYPE html>
<html>
<head><meta charset="UTF-8"></head>
<body>
<script type="text/javascript" src="/${binJsPath}"></script>
</body>
</html>`);
let gzFile = await gzipFile(htmlFile);
return [htmlFile, gzFile];
}
async function gzipFile(file) {
await pipeline(fs.createReadStream(file), zlib.createGzip({ level: 9 }), fs.createWriteStream(file + ".gz"));
return file + ".gz";
}
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoid2ViX2FwcF9idW5kbGVyLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsid2ViX2FwcF9idW5kbGVyLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7OztBQW1CQSxzQ0EyQkM7QUFFRCx3RkFtQ0M7QUFuRkQseUJBQTBCO0FBQzFCLDZCQUE4QjtBQUM5QixpQ0FBa0M7QUFDbEMsNkJBQThCO0FBQzlCLDZCQUE4QjtBQUM5Qiw2QkFBOEI7QUFDOUIsdUNBR21CO0FBQ25CLHVFQUErRDtBQUMvRCxpREFBMkM7QUFDM0MsK0RBQXdEO0FBQ3hELG9EQUF1RDtBQUN2RCxJQUFJLFFBQVEsR0FBRyxJQUFJLENBQUMsU0FBUyxDQUFDLE1BQU0sQ0FBQyxRQUFRLENBQUMsQ0FBQztBQUVwQyxRQUFBLDJCQUEyQixHQUFHLHNCQUFzQixDQUFDO0FBQ3JELFFBQUEsOEJBQThCLEdBQUcsd0JBQXdCLENBQUM7QUFFOUQsS0FBSyxVQUFVLGFBQWEsQ0FDakMsaUJBQWlCLEdBQUcsbUNBQTJCLEVBQy9DLG9CQUFvQixHQUFHLHNDQUE4QixFQUNyRCxNQUFlLEVBQ2YsT0FBNkI7SUFFN0IsSUFBSSxPQUFPLEdBQUcsSUFBSSxDQUFDLEtBQUssQ0FBQyxPQUFPLENBQUMsaUJBQWlCLENBQUMsQ0FBQztJQUNwRCxJQUFJLFFBQVEsR0FBRyxNQUFNLHNDQUFzQyxDQUN6RCxpQkFBaUIsRUFDakIsT0FBTyxFQUNQLE9BQU8sQ0FDUixDQUFDO0lBQ0YsSUFBSSxnQkFBZ0IsR0FBRyxRQUFRLENBQUMsR0FBRyxDQUFDLENBQUMsSUFBSSxFQUFFLEVBQUUsQ0FDM0MsSUFBSSxDQUFDLEtBQUssQ0FBQyxRQUFRLENBQUMsSUFBSSxDQUFDLEtBQUssQ0FBQyxPQUFPLENBQUMsb0JBQW9CLENBQUMsRUFBRSxJQUFJLENBQUMsQ0FDcEUsQ0FBQztJQUNGLE1BQU0sRUFBRSxDQUFDLFFBQVEsQ0FBQyxTQUFTLENBQ3pCLG9CQUFvQixFQUNwQixJQUFJLENBQUMsU0FBUyxDQUFDLGdC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QUFDO0lBQ3ZDLElBQUksU0FBUyxHQUFHLElBQUksQ0FBQyxLQUFLLENBQUMsUUFBUSxDQUFDLE9BQU8sRUFBRSxhQUFhLEdBQUcsS0FBSyxDQUFDLENBQUM7SUFDcEUsTUFBTSxFQUFFLENBQUMsUUFBUSxDQUFDLFNBQVMsQ0FDekIsUUFBUSxFQUNSOzs7OzJDQUl1QyxTQUFTOztRQUU1QyxDQUNMLENBQUM7SUFDRixJQUFJLE1BQU0sR0FBRyxNQUFNLFFBQVEsQ0FBQyxRQUFRLENBQUMsQ0FBQztJQUN0QyxPQUFPLENBQUMsUUFBUSxFQUFFLE1BQU0sQ0FBQyxDQUFDO0FBQzVCLENBQUM7QUFFRCxLQUFLLFVBQVUsUUFBUSxDQUFDLElBQVk7SUFDbEMsTUFBTSxRQUFRLENBQ1osRUFBRSxDQUFDLGdCQUFnQixDQUFDLElBQUksQ0FBQyxFQUN6QixJQUFJLENBQUMsVUFBVSxDQUFDLEVBQUUsS0FBSyxFQUFFLENBQUMsRUFBRSxDQUFDLEVBQzdCLEVBQUUsQ0FBQyxpQkFBaUIsQ0FBQyxJQUFJLEdBQUcsS0FBSyxDQUFDLENBQ25DLENBQUM7SUFDRixPQUFPLElBQUksR0FBRyxLQUFLLENBQUM7QUFDdEIsQ0FBQyIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCBmcyA9IHJlcXVpcmUoXCJmc1wiKTtcbmltcG9ydCBwYXRoID0gcmVxdWlyZShcInBhdGhcIik7XG5pbXBvcnQgc3RyZWFtID0gcmVxdWlyZShcInN0cmVhbVwiKTtcbmltcG9ydCB1dGlsID0gcmVxdWlyZShcInV0aWxcIik7XG5pbXBvcnQgeWFtbCA9IHJlcXVpcmUoXCJ5YW1sXCIpO1xuaW1wb3J0IHpsaWIgPSByZXF1aXJlKFwiemxpYlwiKTtcbmltcG9ydCB7XG4gIENvbW1vbkJ1bmRsZU9wdGlvbnMsXG4gIGJ1bmRsZUZvckJyb3dzZXJSZXR1cm5Bc3NldEZpbGVzLFxufSBmcm9tIFwiLi9idW5kbGVyXCI7XG5pbXBvcnQgeyBzdHJpcEZpbGVFeHRlbnNpb24gfSBmcm9tIFwiLi9maWxlX2V4dGVuc2lvbl9zdHJpcHBlclwiO1xuaW1wb3J0IHsgY29weUZpbGVzIH0gZnJvbSBcIi4vZmlsZXNfY29waWVyXCI7XG5pbXBvcnQgeyBXRUJfQVBQX0VOVFJJRVMgfSBmcm9tIFwiLi93ZWJfYXBwX2VudHJpZXNfZGVmXCI7XG5pbXBvcnQgeyBwYXJzZU1lc3NhZ2UgfSBmcm9tIFwiQHNlbGZhZ2UvbWVzc2FnZS9wYXJzZXJcIjtcbmxldCBwaXBlbGluZSA9IHV0aWwucHJvbWlzaWZ5KHN0cmVhbS5waXBlbGluZSk7XG5cbmV4cG9ydCBsZXQgREVGQVVMVF9FTlRSSUVTX0NPTkZJR19GSUxFID0gXCJ3ZWJfYXBwX2VudHJpZXMueWFtbFwiO1xuZXhwb3J0IGxldCBERUZBVUxUX0JVTkRMRURfUkVTT1VSQ0VTX0ZJTEUgPSBcIndlYl9hcHBfcmVzb3VyY2VzLnlhbWxcIjtcblxuZXhwb3J0IGFzeW5jIGZ1bmN0aW9uIGJ1bmRsZVdlYkFwcHMoXG4gIGVudHJpZXNDb25maWdGaWxlID0gREVGQVVMVF9FTlRSSUVTX0NPTkZJR19GSUxFLFxuICBidW5kbGVkUmVzb3VyY2VzRmlsZSA9IERFRkFVTFRfQlVORExFRF9SRVNPVVJDRVNfRklMRSxcbiAgb3V0RGlyPzogc3RyaW5nLFxuICBvcHRpb25zPzogQ29tbW9uQnVuZGxlT3B0aW9ucyxcbik6IFByb21pc2U8dm9pZD4ge1xuICBsZXQgYmFzZURpciA9IHBhdGgucG9zaXguZGlybmFtZShlbnRyaWVzQ29uZmlnRmlsZSk7XG4gIGxldCBhbGxGaWxlcyA9IGF3YWl0IGJ1bmRsZVdlYkFwcHNBbmRSZXR1cm5CdW5kbGVkUmVzb3VyY2VzKFxuICAgIGVudHJpZXNDb25maWdGaWxlLFxuICAgIGJhc2VEaXIsXG4gICAgb3B0aW9ucyxcbiAgKTtcbiAgbGV0IGFsbFJlbGF0aXZlRmlsZXMgPSBhbGxGaWxlcy5tYXAoKGZpbGUpID0+XG4gICAgcGF0aC5wb3NpeC5yZWxhdGl2ZShwYXRoLnBvc2l4LmRpcm5hbWUoYnVuZGxlZFJlc291cmNlc0ZpbGUpLCBmaWxlKSxcbiAgKTtcbiAgYXdhaXQgZnMucHJvbWlzZXMud3JpdGVGaWxlKFxuICAgIGJ1bmRsZWRSZXNvdXJjZXNGaWxlLFxuICAgIHlhbWwuc3RyaW5naWZ5KGFsbFJlbGF0aXZlRmlsZXMpLFxuICApO1xuXG4gIGlmIChcbiAgICAhb3V0RGlyIHx8XG4gICAgcGF0aC5wb3NpeC5ub3JtYWxpemUob3V0RGlyKSA9PT0gcGF0aC5wb3NpeC5ub3JtYWxpemUoYmFzZURpcilcbiAgKSB7XG4gICAgcmV0dXJuO1xuICB9XG4gIGF3YWl0IGNvcHlGaWxlcyhhbGxGaWxlcywgYmFzZURpciwgb3V0RGlyKTtcbn1cblxuZXhwb3J0IGFzeW5jIGZ1bmN0aW9uIGJ1bmRsZVdlYkFwcHNBbmRSZXR1cm5CdW5kbGVkUmVzb3VyY2VzKFxuICBlbnRyaWVzQ29uZmlnRmlsZTogc3RyaW5nLFxuICBiYXNlRGlyOiBzdHJpbmcsXG4gIG9wdGlvbnM/OiBDb21tb25CdW5kbGVPcHRpb25zLFxuKTogUHJvbWlzZTxBcnJheTxzdHJpbmc+PiB7XG4gIGxldCB3ZWJBcHBFbnRyaWVzID0gcGFyc2VNZXNzYWdlKFxuICAgIHlhbWwucGFyc2UoKGF3YWl0IGZzLnByb21pc2VzLnJlYWRGaWxlKGVudHJpZXNDb25maWdGaWxlKSkudG9TdHJpbmcoKSksXG4gICAgV0VCX0FQUF9FTlRSSUVTLFxuICApO1xuICBsZXQgY29uZmlnRGlyID0gcGF0aC5wb3NpeC5kaXJuYW1lKGVudHJpZXNDb25maWdGaWxlKTtcblxuICBsZXQgcHJvbWlzZXMgPSBuZXcgQXJyYXk8UHJvbWlzZTxBcnJheTxzdHJpbmc+Pj4oKTtcbiAgZm9yIChsZXQgZW50cnkgb2Ygd2ViQXBwRW50cmllcy5lbnRyaWVzKSB7XG4gICAgcHJvbWlzZXMucHVzaChcbiAgICAgIGJ1bmRsZUFuZEd6aXAoXG4gICAgICAgIHBhdGgucG9zaXguam9pbihjb25maWdEaXIsIGVudHJ5LnNvdXJjZSksXG4gICAgICAgIHBhdGgucG9zaXguam9pbihjb25maWdEaXIsIGVudHJ5Lm91dHB1dCksXG4gICAgICAgIGJhc2VEaXIsXG4gICAgICAgIG9wdGlvbnMsXG4gICAgICApLFxuICAgICAgd3JpdGVIdG1sRmlsZUFuZEdaaXAocGF0aC5wb3NpeC5qb2luKGNvbmZpZ0RpciwgZW50cnkub3V0cHV0KSwgYmFzZURpciksXG4gICAgKTtcbiAgfVxuXG4gIGxldCBhbGxGaWxlcyA9IGF3YWl0IFByb21pc2UuYWxsKHByb21pc2VzKTtcbiAgbGV0IGZsYXR0ZW5lZEZpbGVzID0gbmV3IEFycmF5PHN0cmluZz4oKTtcbiAgZm9yIChsZXQgZmlsZXMgb2YgYWxsRmlsZXMpIHtcbiAgICBmbGF0dGVuZWRGaWxlcy5wdXNoKC4uLmZpbGVzKTtcbiAgfVxuICBpZiAod2ViQXBwRW50cmllcy5leHRyYUFzc2V0cykge1xuICAgIGZvciAobGV0IGV4dHJhQXNzZXQgb2Ygd2ViQXBwRW50cmllcy5leHRyYUFzc2V0cykge1xuICAgICAgZmxhdHRlbmVkRmlsZXMucHVzaChwYXRoLnBvc2l4LmpvaW4oY29uZmlnRGlyLCBleHRyYUFzc2V0KSk7XG4gICAgfVxuICB9XG4gIHJldHVybiBmbGF0dGVuZWRGaWxlcztcbn1cblxuYXN5bmMgZnVuY3Rpb24gYnVuZGxlQW5kR3ppcChcbiAgc291cmNlRmlsZTogc3RyaW5nLFxuICBvdXRwdXRGaWxlOiBzdHJpbmcsXG4gIGJhc2VEaXI6IHN0cmluZyxcbiAgb3B0aW9uczogQ29tbW9uQnVuZGxlT3B0aW9ucyxcbik6IFByb21pc2U8QXJyYXk8c3RyaW5nPj4ge1xuICBsZXQgYXNzZXRGaWxlcyA9IGF3YWl0IGJ1bmRsZUZvckJyb3dzZXJSZXR1cm5Bc3NldEZpbGVzKFxuICAgIHNvdXJjZUZpbGUsXG4gICAgb3V0cHV0RmlsZSxcbiAgICBiYXNlRGlyLFxuICAgIG9wdGlvbnMsXG4gICk7XG4gIGxldCBqc0ZpbGUgPSBzdHJpcEZpbGVFeHRlbnNpb24ob3V0cHV0RmlsZSkgKyBcIi5qc1wiO1xuICBsZXQgZ3pGaWxlID0gYXdhaXQgZ3ppcEZpbGUoanNGaWxlKTtcbiAgcmV0dXJuIFsuLi5hc3NldEZpbGVzLCBqc0ZpbGUsIGd6RmlsZV07XG59XG5cbmFzeW5jIGZ1bmN0aW9uIHdyaXRlSHRtbEZpbGVBbmRHWmlwKFxuICBiaW5GaWxlOiBzdHJpbmcsXG4gIGJhc2VEaXI6IHN0cmluZyxcbik6IFByb21pc2U8QXJyYXk8c3RyaW5nPj4ge1xuICBsZXQgYmluTW9kdWxlUGF0aCA9IHN0cmlwRmlsZUV4dGVuc2lvbihiaW5GaWxlKTtcbiAgbGV0IGh0bWxGaWxlID0gYmluTW9kdWxlUGF0aCArIFwiLmh0bWxcIjtcbiAgbGV0IGJpbkpzUGF0aCA9IHBhdGgucG9zaXgucmVsYXRpdmUoYmFzZURpciwgYmluTW9kdWxlUGF0aCArIFwiLmpzXCIpO1xuICBhd2FpdCBmcy5wcm9taXNlcy53cml0ZUZpbGUoXG4gICAgaHRtbEZpbGUsXG4gICAgYDwhRE9DVFlQRSBodG1sPlxuPGh0bWw+XG4gIDxoZWFkPjxtZXRhIGNoYXJzZXQ9XCJVVEYtOFwiPjwvaGVhZD5cbiAgPGJvZHk+XG4gICAgPHNjcmlwdCB0eXBlPVwidGV4dC9qYXZhc2NyaXB0XCIgc3JjPVwiLyR7YmluSnNQYXRofVwiPjwvc2NyaXB0PlxuICA8L2JvZHk+XG48L2h0bWw+YCxcbiAgKTtcbiAgbGV0IGd6RmlsZSA9IGF3YWl0IGd6aXBGaWxlKGh0bWxGaWxlKTtcbiAgcmV0dXJuIFtodG1sRmlsZSwgZ3pGaWxlXTtcbn1cblxuYXN5bmMgZnVuY3Rpb24gZ3ppcEZpbGUoZmlsZTogc3RyaW5nKTogUHJvbWlzZTxzdHJpbmc+IHtcbiAgYXdhaXQgcGlwZWxpbmUoXG4gICAgZnMuY3JlYXRlUmVhZFN0cmVhbShmaWxlKSxcbiAgICB6bGliLmNyZWF0ZUd6aXAoeyBsZXZlbDogOSB9KSxcbiAgICBmcy5jcmVhdGVXcml0ZVN0cmVhbShmaWxlICsgXCIuZ3pcIiksXG4gICk7XG4gIHJldHVybiBmaWxlICsgXCIuZ3pcIjtcbn1cbiJdfQ==