1// @ts-check 2const stream = require("stream"); 3const Vinyl = require("vinyl"); 4const ts = require("../../lib/typescript"); 5const fs = require("fs"); 6const { base64VLQFormatEncode } = require("./sourcemaps"); 7 8/** 9 * @param {string | ((file: import("vinyl")) => string)} data 10 */ 11function prepend(data) { 12 return new stream.Transform({ 13 objectMode: true, 14 /** 15 * @param {string | Buffer | import("vinyl")} input 16 * @param {(error: Error, data?: any) => void} cb 17 */ 18 transform(input, _, cb) { 19 if (typeof input === "string" || Buffer.isBuffer(input)) return cb(new Error("Only Vinyl files are supported.")); 20 if (!input.isBuffer()) return cb(new Error("Streams not supported.")); 21 try { 22 const output = input.clone(); 23 const prependContent = typeof data === "function" ? data(input) : data; 24 output.contents = Buffer.concat([Buffer.from(prependContent, "utf8"), input.contents]); 25 if (input.sourceMap) { 26 if (typeof input.sourceMap === "string") input.sourceMap = /**@type {import("./sourcemaps").RawSourceMap}*/(JSON.parse(input.sourceMap)); 27 const lineStarts = /**@type {*}*/(ts).computeLineStarts(prependContent); 28 let prependMappings = ""; 29 for (let i = 1; i < lineStarts.length; i++) { 30 prependMappings += ";"; 31 } 32 const offset = prependContent.length - lineStarts[lineStarts.length - 1]; 33 if (offset > 0) { 34 prependMappings += base64VLQFormatEncode(offset) + ","; 35 } 36 output.sourceMap = { 37 version: input.sourceMap.version, 38 file: input.sourceMap.file, 39 sources: input.sourceMap.sources, 40 sourceRoot: input.sourceMap.sourceRoot, 41 mappings: prependMappings + input.sourceMap.mappings, 42 names: input.names, 43 sourcesContent: input.sourcesContent 44 }; 45 } 46 return cb(null, output); 47 } 48 catch (e) { 49 return cb(e); 50 } 51 } 52 }) 53} 54exports.prepend = prepend; 55 56/** 57 * @param {string | ((file: import("vinyl")) => string)} file 58 */ 59function prependFile(file) { 60 const data = typeof file === "string" ? fs.readFileSync(file, "utf8") : 61 vinyl => fs.readFileSync(file(vinyl), "utf8"); 62 return prepend(data) 63} 64exports.prependFile = prependFile;