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