UNPKG

@knennigtri/merge-markdown

Version:

Prepare input files to merge together and optionally output html/pdf/word presentation

924 lines (904 loc) 46.7 kB
"use strict"; function _typeof(o) { "@babel/helpers - typeof"; return _typeof = "function" == typeof Symbol && "symbol" == typeof Symbol.iterator ? function (o) { return typeof o; } : function (o) { return o && "function" == typeof Symbol && o.constructor === Symbol && o !== Symbol.prototype ? "symbol" : typeof o; }, _typeof(o); } function _regeneratorRuntime() { "use strict"; var r = _regenerator(), e = r.m(_regeneratorRuntime), t = (Object.getPrototypeOf ? Object.getPrototypeOf(e) : e.__proto__).constructor; function n(r) { var e = "function" == typeof r && r.constructor; return !!e && (e === t || "GeneratorFunction" === (e.displayName || e.name)); } var o = { "throw": 1, "return": 2, "break": 3, "continue": 3 }; function a(r) { var e, t; return function (n) { e || (e = { stop: function stop() { return t(n.a, 2); }, "catch": function _catch() { return n.v; }, abrupt: function abrupt(r, e) { return t(n.a, o[r], e); }, delegateYield: function delegateYield(r, o, a) { return e.resultName = o, t(n.d, _regeneratorValues(r), a); }, finish: function finish(r) { return t(n.f, r); } }, t = function t(r, _t, o) { n.p = e.prev, n.n = e.next; try { return r(_t, o); } finally { e.next = n.n; } }), e.resultName && (e[e.resultName] = n.v, e.resultName = void 0), e.sent = n.v, e.next = n.n; try { return r.call(this, e); } finally { n.p = e.prev, n.n = e.next; } }; } return (_regeneratorRuntime = function _regeneratorRuntime() { return { wrap: function wrap(e, t, n, o) { return r.w(a(e), t, n, o && o.reverse()); }, isGeneratorFunction: n, mark: r.m, awrap: function awrap(r, e) { return new _OverloadYield(r, e); }, AsyncIterator: _regeneratorAsyncIterator, async: function async(r, e, t, o, u) { return (n(e) ? _regeneratorAsyncGen : _regeneratorAsync)(a(r), e, t, o, u); }, keys: _regeneratorKeys, values: _regeneratorValues }; })(); } function _regeneratorValues(e) { if (null != e) { var t = e["function" == typeof Symbol && Symbol.iterator || "@@iterator"], r = 0; if (t) return t.call(e); if ("function" == typeof e.next) return e; if (!isNaN(e.length)) return { next: function next() { return e && r >= e.length && (e = void 0), { value: e && e[r++], done: !e }; } }; } throw new TypeError(_typeof(e) + " is not iterable"); } function _regeneratorKeys(e) { var n = Object(e), r = []; for (var t in n) r.unshift(t); return function e() { for (; r.length;) if ((t = r.pop()) in n) return e.value = t, e.done = !1, e; return e.done = !0, e; }; } function _regeneratorAsync(n, e, r, t, o) { var a = _regeneratorAsyncGen(n, e, r, t, o); return a.next().then(function (n) { return n.done ? n.value : a.next(); }); } function _regeneratorAsyncGen(r, e, t, o, n) { return new _regeneratorAsyncIterator(_regenerator().w(r, e, t, o), n || Promise); } function _regeneratorAsyncIterator(t, e) { function n(r, o, i, f) { try { var c = t[r](o), u = c.value; return u instanceof _OverloadYield ? e.resolve(u.v).then(function (t) { n("next", t, i, f); }, function (t) { n("throw", t, i, f); }) : e.resolve(u).then(function (t) { c.value = t, i(c); }, function (t) { return n("throw", t, i, f); }); } catch (t) { f(t); } } var r; this.next || (_regeneratorDefine2(_regeneratorAsyncIterator.prototype), _regeneratorDefine2(_regeneratorAsyncIterator.prototype, "function" == typeof Symbol && Symbol.asyncIterator || "@asyncIterator", function () { return this; })), _regeneratorDefine2(this, "_invoke", function (t, o, i) { function f() { return new e(function (e, r) { n(t, i, e, r); }); } return r = r ? r.then(f, f) : f(); }, !0); } function _regenerator() { /*! regenerator-runtime -- Copyright (c) 2014-present, Facebook, Inc. -- license (MIT): https://github.com/babel/babel/blob/main/packages/babel-helpers/LICENSE */ var e, t, r = "function" == typeof Symbol ? Symbol : {}, n = r.iterator || "@@iterator", o = r.toStringTag || "@@toStringTag"; function i(r, n, o, i) { var c = n && n.prototype instanceof Generator ? n : Generator, u = Object.create(c.prototype); return _regeneratorDefine2(u, "_invoke", function (r, n, o) { var i, c, u, f = 0, p = o || [], y = !1, G = { p: 0, n: 0, v: e, a: d, f: d.bind(e, 4), d: function d(t, r) { return i = t, c = 0, u = e, G.n = r, a; } }; function d(r, n) { for (c = r, u = n, t = 0; !y && f && !o && t < p.length; t++) { var o, i = p[t], d = G.p, l = i[2]; r > 3 ? (o = l === n) && (u = i[(c = i[4]) ? 5 : (c = 3, 3)], i[4] = i[5] = e) : i[0] <= d && ((o = r < 2 && d < i[1]) ? (c = 0, G.v = n, G.n = i[1]) : d < l && (o = r < 3 || i[0] > n || n > l) && (i[4] = r, i[5] = n, G.n = l, c = 0)); } if (o || r > 1) return a; throw y = !0, n; } return function (o, p, l) { if (f > 1) throw TypeError("Generator is already running"); for (y && 1 === p && d(p, l), c = p, u = l; (t = c < 2 ? e : u) || !y;) { i || (c ? c < 3 ? (c > 1 && (G.n = -1), d(c, u)) : G.n = u : G.v = u); try { if (f = 2, i) { if (c || (o = "next"), t = i[o]) { if (!(t = t.call(i, u))) throw TypeError("iterator result is not an object"); if (!t.done) return t; u = t.value, c < 2 && (c = 0); } else 1 === c && (t = i["return"]) && t.call(i), c < 2 && (u = TypeError("The iterator does not provide a '" + o + "' method"), c = 1); i = e; } else if ((t = (y = G.n < 0) ? u : r.call(n, G)) !== a) break; } catch (t) { i = e, c = 1, u = t; } finally { f = 1; } } return { value: t, done: y }; }; }(r, o, i), !0), u; } var a = {}; function Generator() {} function GeneratorFunction() {} function GeneratorFunctionPrototype() {} t = Object.getPrototypeOf; var c = [][n] ? t(t([][n]())) : (_regeneratorDefine2(t = {}, n, function () { return this; }), t), u = GeneratorFunctionPrototype.prototype = Generator.prototype = Object.create(c); function f(e) { return Object.setPrototypeOf ? Object.setPrototypeOf(e, GeneratorFunctionPrototype) : (e.__proto__ = GeneratorFunctionPrototype, _regeneratorDefine2(e, o, "GeneratorFunction")), e.prototype = Object.create(u), e; } return GeneratorFunction.prototype = GeneratorFunctionPrototype, _regeneratorDefine2(u, "constructor", GeneratorFunctionPrototype), _regeneratorDefine2(GeneratorFunctionPrototype, "constructor", GeneratorFunction), GeneratorFunction.displayName = "GeneratorFunction", _regeneratorDefine2(GeneratorFunctionPrototype, o, "GeneratorFunction"), _regeneratorDefine2(u), _regeneratorDefine2(u, o, "Generator"), _regeneratorDefine2(u, n, function () { return this; }), _regeneratorDefine2(u, "toString", function () { return "[object Generator]"; }), (_regenerator = function _regenerator() { return { w: i, m: f }; })(); } function _regeneratorDefine2(e, r, n, t) { var i = Object.defineProperty; try { i({}, "", {}); } catch (e) { i = 0; } _regeneratorDefine2 = function _regeneratorDefine(e, r, n, t) { if (r) i ? i(e, r, { value: n, enumerable: !t, configurable: !t, writable: !t }) : e[r] = n;else { var o = function o(r, n) { _regeneratorDefine2(e, r, function (e) { return this._invoke(r, n, e); }); }; o("next", 0), o("throw", 1), o("return", 2); } }, _regeneratorDefine2(e, r, n, t); } function _OverloadYield(e, d) { this.v = e, this.k = d; } function _toConsumableArray(r) { return _arrayWithoutHoles(r) || _iterableToArray(r) || _unsupportedIterableToArray(r) || _nonIterableSpread(); } function _nonIterableSpread() { throw new TypeError("Invalid attempt to spread non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method."); } function _unsupportedIterableToArray(r, a) { if (r) { if ("string" == typeof r) return _arrayLikeToArray(r, a); var t = {}.toString.call(r).slice(8, -1); return "Object" === t && r.constructor && (t = r.constructor.name), "Map" === t || "Set" === t ? Array.from(r) : "Arguments" === t || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(t) ? _arrayLikeToArray(r, a) : void 0; } } function _iterableToArray(r) { if ("undefined" != typeof Symbol && null != r[Symbol.iterator] || null != r["@@iterator"]) return Array.from(r); } function _arrayWithoutHoles(r) { if (Array.isArray(r)) return _arrayLikeToArray(r); } function _arrayLikeToArray(r, a) { (null == a || a > r.length) && (a = r.length); for (var e = 0, n = Array(a); e < a; e++) n[e] = r[e]; return n; } function asyncGeneratorStep(n, t, e, r, o, a, c) { try { var i = n[a](c), u = i.value; } catch (n) { return void e(n); } i.done ? t(u) : Promise.resolve(u).then(r, o); } function _asyncToGenerator(n) { return function () { var t = this, e = arguments; return new Promise(function (r, o) { var a = n.apply(t, e); function _next(n) { asyncGeneratorStep(a, r, o, _next, _throw, "next", n); } function _throw(n) { asyncGeneratorStep(a, r, o, _next, _throw, "throw", n); } _next(void 0); }); }; } var packageInfo = require("../package.json"); var dockerode = require("dockerode"); var fs = require("fs"); var path = require("path"); var tar = require("tar"); var manifestUtil = require("./manifest.js"); var presentationUtil = require("./presentation.js"); var mergeUtil = require("./merge.js"); var _require = require("child_process"), exec = _require.exec; var debug = require("debug"); var debugDocker = debug("docker"); var debugDockerPaths = debug("docker:paths"); exports.debbugOptions = { docker: "docker", dockerPaths: "docker:paths" }; var docker = new dockerode(); var IMAGE_NAME = "node"; var IMAGE_TAG = "mergemarkdown"; var CONTAINER_NAME = "mergemarkdown"; var WORKING_DIR = "/home/runner/workspace/cli"; var TAR_NAME = "archive.tar.gz"; var EXCLUDE_PATHS = [/node_modules/, // Matches any path containing 'node_modules' /quickstart.md/, /merged/, // Matches any path containing 'merged' /target/, // Matches any path containing 'target' ".git/", ".vscode/", "archive.tar.gz"]; function runMergeMarkdownInDocker(_x, _x2) { return _runMergeMarkdownInDocker.apply(this, arguments); } /* Starts a docker container or returns the running container */ function _runMergeMarkdownInDocker() { _runMergeMarkdownInDocker = _asyncToGenerator(/*#__PURE__*/_regeneratorRuntime().mark(function _callee(manifestFileStr, cmdArgs) { var _manifest$docker; var manifest, manifestOutputName, excludePaths, manifestRelDir, dockerRunning, imageExists, needsRebuild, rebuildReason, hasCompatibleNodeVersion, hasMatchingVersion, versionToUse, command, output, fallbackOutput, container, info, cleanCommand, extractCommand, isDevelopment, _commands, checkCommand, versionToInstall, installCommand, fallbackCommand, npmModuleName, requestedCMD, envPrefix, commands, dockerCMD, relManifestOutputName, absManifestOutputName_inDocker, absManifestOutputName_parsed, absManifestOutputName_name, absManifestOutputName_dir, outputPaths, destPath, fileToDel; return _regeneratorRuntime().wrap(function _callee$(_context) { while (1) switch (_context.prev = _context.next) { case 0: manifest = manifestUtil.getJSON_withABSPaths(manifestFileStr); manifestOutputName = manifest.output.name; excludePaths = [].concat(EXCLUDE_PATHS, _toConsumableArray(Array.isArray((_manifest$docker = manifest.docker) === null || _manifest$docker === void 0 ? void 0 : _manifest$docker.excludePaths) ? manifest.docker.excludePaths : [])); debugDocker("excludePaths:\n".concat(excludePaths.map(function (regex) { return " ".concat(regex.toString()); }).join("\n"))); // relDir given in -m dir/manifest.yml to help build docker upload/download paths manifestRelDir = path.parse(manifestFileStr).dir || "./"; debugDocker("manifestDir: ".concat(manifestRelDir)); _context.prev = 6; _context.next = 9; return isDockerRunning(); case 9: dockerRunning = _context.sent; if (dockerRunning) { _context.next = 13; break; } console.error("Docker is not running. Start the Docker engine and retry."); return _context.abrupt("return"); case 13: _context.next = 15; return dockerImageExists("".concat(IMAGE_NAME, ":").concat(IMAGE_TAG)); case 15: imageExists = _context.sent; needsRebuild = false; rebuildReason = ""; if (imageExists) { _context.next = 24; break; } console.log("Docker Image DNE. Creating..."); needsRebuild = true; rebuildReason = "Image does not exist"; _context.next = 37; break; case 24: _context.next = 26; return checkDockerImageNodeVersion("".concat(IMAGE_NAME, ":").concat(IMAGE_TAG)); case 26: hasCompatibleNodeVersion = _context.sent; if (hasCompatibleNodeVersion) { _context.next = 33; break; } console.log("Docker Image exists but has incompatible Node.js version. Rebuilding with Node.js 20+..."); needsRebuild = true; rebuildReason = "Incompatible Node.js version"; _context.next = 37; break; case 33: _context.next = 35; return checkDockerImageMergeMarkdownVersion("".concat(IMAGE_NAME, ":").concat(IMAGE_TAG)); case 35: hasMatchingVersion = _context.sent; if (!hasMatchingVersion) { console.log("Docker Image exists but merge-markdown version doesn't match local version (".concat(packageInfo.version, "). Rebuilding...")); needsRebuild = true; rebuildReason = "Version mismatch"; } else { debugDocker("Docker Image exists with compatible Node.js version and matching merge-markdown version"); } case 37: if (!needsRebuild) { _context.next = 75; break; } debugDocker("Rebuilding Docker image. Reason: ".concat(rebuildReason)); // Set environment variable for docker-compose to use the correct version _context.next = 41; return getValidMergeMarkdownVersion(packageInfo.version); case 41: versionToUse = _context.sent; process.env.MERGE_MARKDOWN_VERSION = versionToUse; if (versionToUse !== packageInfo.version) { console.log("Warning: Local version ".concat(packageInfo.version, " not available on npm registry. Using ").concat(versionToUse, " instead.")); } command = "docker compose -f ".concat(path.join(__dirname, "../docker/docker-compose.yml"), " up -d --build"); console.log(command); _context.prev = 46; _context.next = 49; return runExecCommands(command, manifestRelDir); case 49: output = _context.sent; console.log("Docker build completed successfully."); debugDocker(output); _context.next = 75; break; case 54: _context.prev = 54; _context.t0 = _context["catch"](46); console.error("Error executing:", _context.t0); // If build fails, try with latest as fallback if (!(versionToUse !== "latest")) { _context.next = 74; break; } console.log("Build failed, attempting fallback to latest version..."); process.env.MERGE_MARKDOWN_VERSION = "latest"; _context.prev = 60; _context.next = 63; return runExecCommands(command, manifestRelDir); case 63: fallbackOutput = _context.sent; console.log("Fallback build completed successfully."); debugDocker(fallbackOutput); _context.next = 72; break; case 68: _context.prev = 68; _context.t1 = _context["catch"](60); console.error("Fallback build also failed:", _context.t1); throw _context.t1; case 72: _context.next = 75; break; case 74: throw _context.t0; case 75: console.log("--------Docker Container START--------"); _context.prev = 76; _context.next = 79; return getContainer(); case 79: container = _context.sent; _context.next = 82; return container.inspect(); case 82: info = _context.sent; if (info.State.Running) { _context.next = 87; break; } _context.next = 86; return startContainer(container); case 86: container = _context.sent; case 87: // Clean working directory console.log("Cleaning the docker working directory."); cleanCommand = "rm -rf ".concat(WORKING_DIR, "/*"); debugDocker(cleanCommand); _context.next = 92; return execContainer(container, cleanCommand); case 92: container = _context.sent; // Create and copy archive console.log("Copying this project to the docker container."); console.log("Exclude Copying These Paths:\n".concat(excludePaths.map(function (regex) { return " ".concat(regex.toString()); }).join("\n"))); _context.next = 97; return createTarArchive("./", TAR_NAME, excludePaths); case 97: console.log("Tar archive created successfully"); _context.next = 100; return copyIntoContainer(container, TAR_NAME, WORKING_DIR); case 100: container = _context.sent; // Extract files console.log("Extracting files into the container."); extractCommand = "tar xzf ".concat(WORKING_DIR, "/").concat(TAR_NAME, " -C ").concat(WORKING_DIR); debugDocker(extractCommand); _context.next = 106; return execContainer(container, extractCommand); case 106: container = _context.sent; // Install merge-markdown debugDocker("Running container is ".concat(container.id)); isDevelopment = process.env.NODE_ENV === "dev"; if (!isDevelopment) { _context.next = 118; break; } // Development mode: Install from local source console.log("🔧 Development mode: Installing from local source..."); _commands = ["cd ".concat(WORKING_DIR), "npm install --silent", "npm link --silent"].join(" && "); debugDocker("Dev install command: ".concat(_commands)); _context.next = 115; return execContainer(container, ["/bin/sh", "-c", "export NODE_ENV=dev && ".concat(_commands)], true); case 115: container = _context.sent; _context.next = 154; break; case 118: // Production mode: Install from npm registry console.log("Verifying merge-markdown installation in container..."); checkCommand = "npm list -g @knennigtri/merge-markdown"; debugDocker("Checking installation: ".concat(checkCommand)); _context.prev = 121; _context.next = 124; return execContainer(container, checkCommand, false); case 124: container = _context.sent; debugDocker("merge-markdown is already installed"); _context.next = 154; break; case 128: _context.prev = 128; _context.t2 = _context["catch"](121); console.log("merge-markdown not found in container, installing..."); _context.next = 133; return getValidMergeMarkdownVersion(packageInfo.version); case 133: versionToInstall = _context.sent; if (versionToInstall !== packageInfo.version) { console.log("Warning: Local version ".concat(packageInfo.version, " not available on npm registry. Installing ").concat(versionToInstall, " instead.")); } installCommand = "npm install -g @knennigtri/merge-markdown@".concat(versionToInstall, " --silent"); console.log("Installing: ".concat(installCommand)); _context.prev = 137; _context.next = 140; return execContainer(container, installCommand, true); case 140: container = _context.sent; _context.next = 154; break; case 143: _context.prev = 143; _context.t3 = _context["catch"](137); if (!(versionToInstall !== "latest")) { _context.next = 153; break; } console.log("Installation failed, trying latest version as fallback..."); fallbackCommand = "npm install -g @knennigtri/merge-markdown@latest --silent"; _context.next = 150; return execContainer(container, fallbackCommand, true); case 150: container = _context.sent; _context.next = 154; break; case 153: throw _context.t3; case 154: // Run merge-markdown command debugDocker("Running container is ".concat(container.id)); npmModuleName = packageInfo.name.replace(/@[^/]+\//, ""); requestedCMD = "".concat(npmModuleName, " ").concat(cmdArgs); requestedCMD = requestedCMD.replace("--docker", ""); envPrefix = isDevelopment ? "export NODE_ENV=dev && " : ""; commands = ["cd ".concat(WORKING_DIR), "".concat(envPrefix).concat(requestedCMD)].join(" && "); dockerCMD = ["/bin/sh", "-c", commands]; debugDocker(dockerCMD); debugDocker("Merging in Docker"); _context.next = 165; return execContainer(container, dockerCMD, true); case 165: container = _context.sent; // Download results debugDocker("Downloading locally"); debugDockerPaths("WORKING_DIR: ".concat(WORKING_DIR)); debugDockerPaths("manifestOutputName: ".concat(manifestOutputName)); debugDockerPaths("manifestRelDir: ".concat(manifestRelDir)); debugDockerPaths("process.cwd(): ".concat(process.cwd())); relManifestOutputName = path.relative(process.cwd(), manifestOutputName); absManifestOutputName_inDocker = path.join(WORKING_DIR, relManifestOutputName); absManifestOutputName_parsed = path.parse(absManifestOutputName_inDocker); absManifestOutputName_name = absManifestOutputName_parsed.name; absManifestOutputName_dir = absManifestOutputName_parsed.dir; debugDockerPaths("Downloading merged Files from: ".concat(absManifestOutputName_dir)); outputPaths = [absManifestOutputName_inDocker].concat(_toConsumableArray(Object.values(presentationUtil.EXTS).map(function (ext) { return path.join(absManifestOutputName_dir, "".concat(absManifestOutputName_name).concat(ext)); })), _toConsumableArray(Object.values(mergeUtil.EXTS).map(function (ext) { return path.join(absManifestOutputName_dir, "".concat(absManifestOutputName_name).concat(ext)); })), [path.join(absManifestOutputName_dir, "temp.html")]); debugDockerPaths("Downloading files if they exist:\n".concat(outputPaths.map(function (p) { return " ".concat(p); }).join("\n"))); destPath = path.parse(manifestOutputName).dir; debugDockerPaths("Downloading to ".concat(destPath)); // Ensure destination directory exists if (!fs.existsSync(destPath)) { fs.mkdirSync(destPath, { recursive: true }); debugDockerPaths("Created directory: ".concat(destPath)); } else { debugDockerPaths("Directory already exists: ".concat(destPath)); } _context.next = 184; return downloadFromContainer(container, outputPaths, destPath); case 184: // Cleanup if (debug.enabled("docker")) { debugDocker("Skipping ".concat(TAR_NAME, " file deletion in debug mode")); } else { fileToDel = path.join("./", TAR_NAME); fs.unlink(fileToDel, function (err) { if (err) { console.error("Could not delete ".concat(fileToDel)); } }); } console.log("--------Docker Container END--------"); _context.next = 192; break; case 188: _context.prev = 188; _context.t4 = _context["catch"](76); console.error("Error in Docker container workflow:", _context.t4); throw _context.t4; case 192: _context.next = 198; break; case 194: _context.prev = 194; _context.t5 = _context["catch"](6); console.error("Error getting or creating container:", _context.t5); throw _context.t5; case 198: case "end": return _context.stop(); } }, _callee, null, [[6, 194], [46, 54], [60, 68], [76, 188], [121, 128], [137, 143]]); })); return _runMergeMarkdownInDocker.apply(this, arguments); } function startContainer(container) { return new Promise(function (resolve, reject) { debugDocker("Starting container: ".concat(container.id)); container.start(function (err) { if (err) { if (err.statusCode === 304) { debugDocker("304. Container already running."); resolve(container); } else { console.error("Error starting container:", err); reject(err); } } else { debugDocker("Container started successfully"); resolve(container); } }); }); } /* Gets the running container or starts and returns it */ function getContainer(containerName) { var name = containerName || CONTAINER_NAME; debugDocker("Getting containter: ".concat(name)); return new Promise(function (resolve, reject) { docker.getContainer(name).inspect(function (err, data) { if (err) { if (err.statusCode === 404) { debugDocker("404. Container doesn't exist. Creating..."); resolve(createContainer()); } else reject(err); } else { debugDocker("Found container ".concat(name, " with ID: ").concat(data.Id)); resolve(docker.getContainer(data.Id)); //returns a container } }); }); } /* Function to create a container based on an existing image */ function createContainer(containerName, imageName) { var name = containerName || CONTAINER_NAME; var img = imageName || "".concat(IMAGE_NAME, ":").concat(IMAGE_TAG); debugDocker("Creating container ".concat(name, " from image ").concat(img)); return new Promise(function (resolve, reject) { docker.createContainer({ Image: img, Tty: true, name: name }, function (err, container) { if (err) reject(err); // Failed to create container debugDocker("Container created: ".concat(container.id)); resolve(startContainer(container)); }); }); } /* execute commands within the running container */ function execContainer(_x3, _x4, _x5) { return _execContainer.apply(this, arguments); } function _execContainer() { _execContainer = _asyncToGenerator(/*#__PURE__*/_regeneratorRuntime().mark(function _callee2(container, command, attachStd) { var execOptions; return _regeneratorRuntime().wrap(function _callee2$(_context2) { while (1) switch (_context2.prev = _context2.next) { case 0: execOptions = { Cmd: typeof command === "string" ? command.split(" ") : Array.isArray(command) ? command : [], AttachStdout: attachStd, AttachStderr: attachStd }; return _context2.abrupt("return", new Promise(function (resolve, reject) { container.exec(execOptions, function (err, exec) { console.log("Executing command: ", execOptions.Cmd.join(" ")); var dockerConsole = " "; var rawOutput = ""; // Buffer all output first if (err) { console.error("Error creating exec instance:", err); reject(err); } else { exec.start(function (err, stream) { if (err) { console.error("Error starting exec instance:", err); reject(err); } else { stream.on("data", function (chunk) { // Docker streams include an 8-byte header, skip it if present var data = chunk; if (chunk.length > 8) { // Header format: [stream_type, 0, 0, 0, size1, size2, size3, size4] // Check if this looks like a Docker multiplexed stream header var isHeader = (chunk[0] === 0 || chunk[0] === 1 || chunk[0] === 2) && chunk[1] === 0 && chunk[2] === 0 && chunk[3] === 0; if (isHeader) { data = chunk.slice(8); } } rawOutput += data.toString(); }); stream.on("end", function () { // Clean the complete output after all chunks received /* eslint-disable no-control-regex */ var cleanOutput = rawOutput // Remove ALL ANSI escape sequences (most comprehensive approach) .replace(/\x1b\[[0-9;?]*[a-zA-Z]/g, "") // CSI sequences (including ? for private modes) .replace(/\x1b\][0-9;]*\x07/g, "") // OSC sequences ending with BEL .replace(/\x1b\][0-9;]*\x1b\\/g, "") // OSC sequences ending with ST .replace(/\x1b[=>()]/g, "") // Set modes and character sets .replace(/\x1b[78]/g, "") // Save/restore cursor .replace(/\x1b[HM]/g, "") // Home and reverse index .replace(/\x1b[c]/g, "") // Reset .replace(/\x1b\[[0-9;]*m/g, "") // SGR (color/style) sequences .replace(/\x1b[PX^_]/g, "") // Various escape sequences // Remove ALL control characters except newline and tab .replace(/[\x00-\x08\x0B-\x0C\x0E-\x1F\x7F-\x9F]/g, ""); /* eslint-enable no-control-regex */ // Split into lines and indent var lines = cleanOutput.split("\n").map(function (line) { return line.trim(); }).filter(function (line) { return line.length > 0; }).map(function (line) { return dockerConsole + line; }).join("\n"); if (lines.trim()) { console.log(lines); } resolve(container); }); } }); } }); })); case 2: case "end": return _context2.stop(); } }, _callee2); })); return _execContainer.apply(this, arguments); } function dockerImageExists(imageName) { var img = imageName || "".concat(IMAGE_NAME, ":").concat(IMAGE_TAG); return new Promise(function (resolve) { docker.listImages({ filters: { reference: [img] } }, function (err, images) { if (images.length > 0) { resolve(true); } else { resolve(false); } }); }); } /* Validate that a specific version exists on npm registry, fallback to latest if not */ function getValidMergeMarkdownVersion(_x6) { return _getValidMergeMarkdownVersion.apply(this, arguments); } /* Check if the Docker image has the correct merge-markdown version */ function _getValidMergeMarkdownVersion() { _getValidMergeMarkdownVersion = _asyncToGenerator(/*#__PURE__*/_regeneratorRuntime().mark(function _callee3(requestedVersion) { var _require2, _exec, checkCommand; return _regeneratorRuntime().wrap(function _callee3$(_context3) { while (1) switch (_context3.prev = _context3.next) { case 0: debugDocker("Validating merge-markdown version: ".concat(requestedVersion)); _context3.prev = 1; // Check if the requested version exists on npm registry _require2 = require("child_process"), _exec = _require2.exec; checkCommand = "npm view @knennigtri/merge-markdown@".concat(requestedVersion, " version"); return _context3.abrupt("return", new Promise(function (resolve) { _exec(checkCommand, { timeout: 10000 }, function (error, stdout, stderr) { if (error || stderr) { debugDocker("Version ".concat(requestedVersion, " not found on npm registry: ").concat((error === null || error === void 0 ? void 0 : error.message) || stderr)); debugDocker("Falling back to latest version"); resolve("latest"); } else { var foundVersion = stdout.trim(); if (foundVersion === requestedVersion) { debugDocker("Version ".concat(requestedVersion, " confirmed on npm registry")); resolve(requestedVersion); } else { debugDocker("Version mismatch. Requested: ".concat(requestedVersion, ", Found: ").concat(foundVersion, ". Using latest.")); resolve("latest"); } } }); })); case 7: _context3.prev = 7; _context3.t0 = _context3["catch"](1); debugDocker("Error validating version: ".concat(_context3.t0.message, ". Using latest.")); return _context3.abrupt("return", "latest"); case 11: case "end": return _context3.stop(); } }, _callee3, null, [[1, 7]]); })); return _getValidMergeMarkdownVersion.apply(this, arguments); } function checkDockerImageMergeMarkdownVersion(_x7) { return _checkDockerImageMergeMarkdownVersion.apply(this, arguments); } /* Check if the Docker image has a compatible Node.js version */ function _checkDockerImageMergeMarkdownVersion() { _checkDockerImageMergeMarkdownVersion = _asyncToGenerator(/*#__PURE__*/_regeneratorRuntime().mark(function _callee4(imageName) { var img, localVersion, container, stream, output, versionMatch, dockerVersion, versionsMatch; return _regeneratorRuntime().wrap(function _callee4$(_context4) { while (1) switch (_context4.prev = _context4.next) { case 0: img = imageName || "".concat(IMAGE_NAME, ":").concat(IMAGE_TAG); localVersion = packageInfo.version; debugDocker("Checking merge-markdown version in image: ".concat(img, ", local version: ").concat(localVersion)); _context4.prev = 3; _context4.next = 6; return docker.createContainer({ Image: img, Cmd: ["npm", "list", "-g", "--depth=0", "@knennigtri/merge-markdown"], AttachStdout: true, AttachStderr: true }); case 6: container = _context4.sent; _context4.next = 9; return container.attach({ stream: true, stdout: true, stderr: true }); case 9: stream = _context4.sent; output = ""; stream.on("data", function (chunk) { output += chunk.toString(); }); _context4.next = 14; return container.start(); case 14: _context4.next = 16; return container.wait(); case 16: _context4.next = 18; return container.remove(); case 18: // Extract version number from npm list output versionMatch = output.match(/@knennigtri\/merge-markdown@(\d+\.\d+\.\d+)/); if (!versionMatch) { _context4.next = 25; break; } dockerVersion = versionMatch[1]; debugDocker("Found Docker merge-markdown version: ".concat(dockerVersion)); // Check if versions match versionsMatch = dockerVersion === localVersion; debugDocker("Version match: ".concat(versionsMatch, " (Docker: ").concat(dockerVersion, ", Local: ").concat(localVersion, ")")); return _context4.abrupt("return", versionsMatch); case 25: debugDocker("Could not parse merge-markdown version from: ".concat(output)); return _context4.abrupt("return", false); case 29: _context4.prev = 29; _context4.t0 = _context4["catch"](3); debugDocker("Error checking merge-markdown version: ".concat(_context4.t0.message)); // If we can't check the version, assume it needs rebuild return _context4.abrupt("return", false); case 33: case "end": return _context4.stop(); } }, _callee4, null, [[3, 29]]); })); return _checkDockerImageMergeMarkdownVersion.apply(this, arguments); } function checkDockerImageNodeVersion(_x8) { return _checkDockerImageNodeVersion.apply(this, arguments); } function _checkDockerImageNodeVersion() { _checkDockerImageNodeVersion = _asyncToGenerator(/*#__PURE__*/_regeneratorRuntime().mark(function _callee5(imageName) { var img, container, stream, output, versionMatch, majorVersion; return _regeneratorRuntime().wrap(function _callee5$(_context5) { while (1) switch (_context5.prev = _context5.next) { case 0: img = imageName || "".concat(IMAGE_NAME, ":").concat(IMAGE_TAG); debugDocker("Checking Node.js version in image: ".concat(img)); _context5.prev = 2; _context5.next = 5; return docker.createContainer({ Image: img, Cmd: ["node", "--version"], AttachStdout: true, AttachStderr: true }); case 5: container = _context5.sent; _context5.next = 8; return container.attach({ stream: true, stdout: true, stderr: true }); case 8: stream = _context5.sent; output = ""; stream.on("data", function (chunk) { output += chunk.toString(); }); _context5.next = 13; return container.start(); case 13: _context5.next = 15; return container.wait(); case 15: _context5.next = 17; return container.remove(); case 17: // Extract version number (e.g., "v20.1.0" -> 20) versionMatch = output.match(/v(\d+)\./); if (!versionMatch) { _context5.next = 22; break; } majorVersion = parseInt(versionMatch[1]); debugDocker("Found Node.js version: ".concat(majorVersion)); // Require Node.js 20 or higher for proper Web API support return _context5.abrupt("return", majorVersion >= 20); case 22: debugDocker("Could not parse Node.js version from: ".concat(output)); return _context5.abrupt("return", false); case 26: _context5.prev = 26; _context5.t0 = _context5["catch"](2); debugDocker("Error checking Node.js version: ".concat(_context5.t0.message)); // If we can't check the version, assume it's outdated and needs rebuild return _context5.abrupt("return", false); case 30: case "end": return _context5.stop(); } }, _callee5, null, [[2, 26]]); })); return _checkDockerImageNodeVersion.apply(this, arguments); } function isDockerRunning() { return new Promise(function (resolve) { docker.ping(function (err) { if (err) { resolve(false); // Docker is not running or not accessible } else { resolve(true); // Docker is running } }); }); } /* Run command line arguments with exec */ function runExecCommands(command, cwd) { return new Promise(function (resolve, reject) { exec(command, { cwd: cwd }, function (error, stdout, stderr) { if (error) { reject(error); return; } // Docker Compose writes status messages to stderr, but these aren't errors // Only reject if stderr contains actual error indicators if (stderr && (stderr.includes("ERROR") || stderr.includes("FAILED") || stderr.includes("Error"))) { reject(stderr); return; } // Return both stdout and stderr as Docker Compose uses both for status resolve(stdout + (stderr ? "\n" + stderr : "")); }); }); } /* Copy the local tarFilePath into the destDir in the container */ function copyIntoContainer(container, tarFilePath, destDir) { debugDocker("Copying ".concat(tarFilePath, " to ").concat(destDir)); return new Promise(function (resolve, reject) { var tarStream = fs.createReadStream(tarFilePath); container.putArchive(tarStream, { path: destDir }, function (err) { if (err) { reject(err); return; } resolve(container); }); }); } /* Takes the sourceDir and compresses it into a tar at tarFilePath, excluding specified paths using regex */ function createTarArchive(sourceDir, tarFilePath) { var excludedPaths = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : []; debugDocker("".concat(sourceDir, " to tarball ").concat(tarFilePath)); return new Promise(function (resolve, reject) { var includedCount = 0; var tarStream = tar.c({ gzip: true, cwd: sourceDir, filter: function filter(filePath) { var relativePath = path.relative(sourceDir, filePath); // Normalize path separators to forward slashes for consistent regex matching var normalizedPath = relativePath.replace(/\\/g, "/"); // Check if this path or any parent path should be excluded var shouldExclude = excludedPaths.some(function (excludedPath) { var regex = typeof excludedPath === "string" ? new RegExp(excludedPath) : excludedPath; // Check if the current path matches if (regex.test(normalizedPath)) { debugDockerPaths("Excluding: ".concat(normalizedPath, " (matched: ").concat(regex.toString(), ")")); return true; } // Check if this path is inside an excluded directory var pathParts = normalizedPath.split("/"); for (var i = 0; i < pathParts.length; i++) { var partialPath = pathParts.slice(0, i + 1).join("/"); if (regex.test(partialPath)) { debugDockerPaths("Excluding: ".concat(normalizedPath, " (parent matched: ").concat(regex.toString(), ")")); return true; } } return false; }); if (!shouldExclude) { includedCount++; debugDockerPaths("Including: ".concat(normalizedPath)); } return !shouldExclude; } }, ["."]); var fileStream = fs.createWriteStream(tarFilePath); tarStream.pipe(fileStream); tarStream.on("end", function () { debugDocker("Archive created with ".concat(includedCount, " files")); if (includedCount === 0) { console.warn("Warning: No files were included in the archive. Check exclude patterns."); } resolve(); }); tarStream.on("error", function (err) { console.error("Error creating tar archive:", err); reject(err); }); fileStream.on("error", function (err) { console.error("Error writing tar file:", err); reject(err); }); }); } /* Downloads the srcPath in the container to the local destPath */ function downloadFromContainer(_x9, _x10, _x11) { return _downloadFromContainer.apply(this, arguments); } function _downloadFromContainer() { _downloadFromContainer = _asyncToGenerator(/*#__PURE__*/_regeneratorRuntime().mark(function _callee7(container, srcPaths, destPath) { var downloadPromises; return _regeneratorRuntime().wrap(function _callee7$(_context7) { while (1) switch (_context7.prev = _context7.next) { case 0: if (!Array.isArray(srcPaths)) { srcPaths = [srcPaths]; } if (!destPath) destPath = "./"; // Ensure the destination directory exists if (!fs.existsSync(destPath)) { fs.mkdirSync(destPath, { recursive: true }); } console.log("Downloading files to ".concat(destPath)); downloadPromises = srcPaths.map(/*#__PURE__*/function () { var _ref = _asyncToGenerator(/*#__PURE__*/_regeneratorRuntime().mark(function _callee6(srcPath) { var stream; return _regeneratorRuntime().wrap(function _callee6$(_context6) { while (1) switch (_context6.prev = _context6.next) { case 0: _context6.prev = 0; _context6.next = 3; return container.getArchive({ path: srcPath }); case 3: stream = _context6.sent; return _context6.abrupt("return", new Promise(function (resolve, reject) { stream.pipe(tar.extract({ cwd: destPath })); stream.on("end", function () { debugDocker("Output ".concat(srcPath.replace(WORKING_DIR, "."), " downloading..")); resolve(); }); stream.on("error", function (err) { reject(err); }); })); case 7: _context6.prev = 7; _context6.t0 = _context6["catch"](0); debugDocker("File ".concat(srcPath, " not found, skipping")); return _context6.abrupt("return", null); case 11: case "end": return _context6.stop(); } }, _callee6, null, [[0, 7]]); })); return function (_x12) { return _ref.apply(this, arguments); }; }()); _context7.next = 7; return Promise.all(downloadPromises); case 7: return _context7.abrupt("return", container); case 8: case "end": return _context7.stop(); } }, _callee7); })); return _downloadFromContainer.apply(this, arguments); } exports.runMergeMarkdownInDocker = runMergeMarkdownInDocker;