import * as plugins from './plugins.js'; import * as paths from '../paths.js'; import * as interfaces from '../interfaces/index.js'; export class Base64TsOutput { private files: interfaces.IBase64File[] = []; private cwd: string; constructor(cwd: string = paths.cwd) { this.cwd = cwd; } /** * Add a file with its content to the output */ public addFile(filePath: string, content: Buffer | string): void { const contentBuffer = typeof content === 'string' ? Buffer.from(content, 'utf-8') : content; const contentBase64 = contentBuffer.toString('base64'); this.files.push({ path: filePath, contentBase64, }); } /** * Add files matching a glob pattern */ public async addFilesFromGlob(pattern: string): Promise { const absolutePattern = plugins.smartpath.transform.toAbsolute(pattern, this.cwd) as string; const patternDir = plugins.path.dirname(absolutePattern); const patternBase = plugins.path.basename(absolutePattern); // Check if it's a directory pattern or file pattern const isGlobPattern = patternBase.includes('*'); if (isGlobPattern) { // Handle glob patterns const dirPath = patternDir.replace(/\/\*\*$/, ''); const dirExists = await plugins.fs.directory(dirPath).exists(); if (!dirExists) { console.log(`Directory does not exist: ${dirPath}`); return; } const isRecursive = pattern.includes('**'); let entries; if (isRecursive) { entries = await plugins.fs.directory(dirPath).recursive().list(); } else { entries = await plugins.fs.directory(dirPath).list(); } // Filter by pattern if needed const filePattern = patternBase.replace('*', '.*'); const regex = new RegExp(filePattern); for (const entry of entries) { if (!entry.isDirectory && regex.test(entry.name)) { const fullPath = plugins.path.join(dirPath, entry.path); const relativePath = plugins.path.relative(this.cwd, fullPath); const content = await plugins.fs.file(fullPath).read(); this.addFile(relativePath, content); } } } else { // Handle single file path const fileExists = await plugins.fs.file(absolutePattern).exists(); if (!fileExists) { console.log(`File does not exist: ${absolutePattern}`); return; } const relativePath = plugins.path.relative(this.cwd, absolutePattern); const content = await plugins.fs.file(absolutePattern).read(); this.addFile(relativePath, content); } } /** * Generate TypeScript file content * @param maxLineLength - Max chars per line for base64 strings. 0 or undefined = unlimited (default) */ public generateTypeScript(maxLineLength?: number): string { // Default behavior: no line splitting (unlimited) if (!maxLineLength || maxLineLength <= 0) { const filesJson = JSON.stringify(this.files, null, 2); return `// Auto-generated by tsbundle - do not edit export const files: { path: string; contentBase64: string }[] = ${filesJson}; `; } // Split base64 strings into chunks when maxLineLength is specified const formatBase64 = (base64: string): string => { if (base64.length <= maxLineLength) { return `"${base64}"`; } const chunks: string[] = []; for (let i = 0; i < base64.length; i += maxLineLength) { chunks.push(base64.slice(i, i + maxLineLength)); } return `"" +\n "${chunks.join('" +\n "')}"`; }; const filesFormatted = this.files.map(file => { return ` { "path": "${file.path}", "contentBase64": ${formatBase64(file.contentBase64)} }`; }).join(',\n'); return `// Auto-generated by tsbundle - do not edit export const files: { path: string; contentBase64: string }[] = [ ${filesFormatted} ]; `; } /** * Write the TypeScript file to disk * @param outputPath - Output file path * @param maxLineLength - Max chars per line for base64 strings. 0 or undefined = unlimited (default) */ public async writeToFile(outputPath: string, maxLineLength?: number): Promise { const absolutePath = plugins.smartpath.transform.toAbsolute(outputPath, this.cwd) as string; const outputDir = plugins.path.dirname(absolutePath); await plugins.fs.directory(outputDir).create(); const content = this.generateTypeScript(maxLineLength); await plugins.fs.file(absolutePath).encoding('utf8').write(content); console.log(`Generated base64ts output: ${outputPath}`); } /** * Get all collected files */ public getFiles(): interfaces.IBase64File[] { return this.files; } /** * Clear all collected files */ public clear(): void { this.files = []; } }