UNPKG

esbuild-plugin-kaitai

Version:

An esbuild plugin for importing Kaitai Struct files.

99 lines (98 loc) 4.75 kB
"use strict"; var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); } return new (P || (P = Promise))(function (resolve, reject) { function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); } step((generator = generator.apply(thisArg, _arguments || [])).next()); }); }; var __importDefault = (this && this.__importDefault) || function (mod) { return (mod && mod.__esModule) ? mod : { "default": mod }; }; Object.defineProperty(exports, "__esModule", { value: true }); exports.compileKaitaiCli = void 0; const child_process_1 = require("child_process"); const fs_1 = require("fs"); const os_1 = __importDefault(require("os")); const path_1 = __importDefault(require("path")); function runCompiler(compilerPath, flags, timeout) { return new Promise((resolve, reject) => { (0, child_process_1.execFile)(compilerPath, flags, { encoding: 'utf8', timeout: timeout, shell: false }, (error, stdout, stderr) => { if (error) { reject(error); } else if (stderr) { reject(new Error(stderr)); } else { resolve(JSON.parse(stdout)); } }); }); } const buildError = (text, file, detail) => ({ text, location: { file }, detail }); const buildErrorReturn = (text, file, detail) => ({ errors: [buildError(text, file, detail)] }); /** * Compiles a ksy file with the command-line Kaitai Compiler. * @param file The file to compile. * @param options The compilation options. * @returns The results of the compilation. */ function compileKaitaiCli(file, options) { return __awaiter(this, void 0, void 0, function* () { // Make a temp dir for the output const tmpDir = yield fs_1.promises.mkdtemp(path_1.default.join(os_1.default.tmpdir(), 'kaitai-')); try { // Get config options const compilerPath = (options === null || options === void 0 ? void 0 : options.compilerPath) || process.env.KAITAI_PATH || 'kaitai-struct-compiler'; const compilerFlags = (options === null || options === void 0 ? void 0 : options.compilerFlags) || []; const compilerTimeout = (options === null || options === void 0 ? void 0 : options.compilerTimeout) || 10000; // Add required flags compilerFlags.push('--ksc-json-output'); compilerFlags.push('--target', 'javascript'); compilerFlags.push('--outdir', tmpDir); compilerFlags.push(file.path); // Run the compiler const result = yield runCompiler(compilerPath, compilerFlags, compilerTimeout); // Get the result for our input file if (result[file.path]) { const fileResult = result[file.path]; if ('output' in fileResult) { const jsResults = fileResult.output['javascript']; const mainSpec = fileResult.firstSpecName; const mainSpecResults = jsResults[mainSpec]; // Assume the first output file is the only one const outputFileName = mainSpecResults.files[0].fileName; // Read the file from the tmp location const outputFilePath = path_1.default.join(tmpDir, outputFileName); const output = yield fs_1.promises.readFile(outputFilePath, { encoding: 'utf8' }); yield fs_1.promises.writeFile('./debug.js', output); return { contents: output, loader: 'js', resolveDir: path_1.default.dirname(file.path) }; } else { return { errors: fileResult.errors.map(e => buildError(e.message, e.file, e.path)) }; } } else { return buildErrorReturn('The Kaitai Compiler didn\'t return anything for this file.', file.path, result); } } finally { // Clean up the tmp folder fs_1.promises.rm(tmpDir, { maxRetries: 4, retryDelay: 1000, recursive: true, force: true }); } }); } exports.compileKaitaiCli = compileKaitaiCli;