Skip to content

Commit 89a6efe

Browse files
committed
Extract PlantUML jar from asar before running
1 parent 51d346f commit 89a6efe

1 file changed

Lines changed: 53 additions & 2 deletions

File tree

electron/main.ts

Lines changed: 53 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -546,6 +546,56 @@ function derivePlantumlFriendlyError(details?: string | null, exitCode?: number)
546546
return 'Local PlantUML renderer failed to produce output.';
547547
}
548548

549+
function isPackagedAsarPath(filePath: string): boolean {
550+
return /\.asar($|[\\/])/.test(filePath);
551+
}
552+
553+
async function ensurePlantumlJarExtracted(sourcePath: string): Promise<string> {
554+
if (!isPackagedAsarPath(sourcePath)) {
555+
return sourcePath;
556+
}
557+
558+
const tempDir = path.join(app.getPath('temp'), 'docforge-plantuml');
559+
const destinationPath = path.join(tempDir, 'plantuml.jar');
560+
561+
await fs.mkdir(tempDir, { recursive: true });
562+
563+
let needsExtraction = true;
564+
try {
565+
const [sourceStats, destStats] = await Promise.all([fs.stat(sourcePath), fs.stat(destinationPath)]);
566+
if (sourceStats.size === destStats.size) {
567+
needsExtraction = false;
568+
}
569+
} catch {
570+
// Either the destination does not exist yet or we could not stat one of the files.
571+
needsExtraction = true;
572+
}
573+
574+
if (!needsExtraction) {
575+
return destinationPath;
576+
}
577+
578+
const pipeline = promisify(stream.pipeline);
579+
580+
try {
581+
await pipeline(createReadStream(sourcePath), createWriteStream(destinationPath));
582+
} catch (error) {
583+
try {
584+
await fs.unlink(destinationPath);
585+
} catch {
586+
// Ignore cleanup failures; we'll retry extraction later if needed.
587+
}
588+
589+
const message =
590+
error instanceof Error
591+
? error.message
592+
: 'Failed to extract bundled PlantUML renderer from application archive.';
593+
throw new Error(`Unable to prepare PlantUML renderer: ${message}`);
594+
}
595+
596+
return destinationPath;
597+
}
598+
549599
async function resolvePlantUmlJar(): Promise<string> {
550600
if (cachedPlantumlJarPath) {
551601
return cachedPlantumlJarPath;
@@ -571,8 +621,9 @@ async function resolvePlantUmlJar(): Promise<string> {
571621
for (const candidate of candidates) {
572622
try {
573623
await fs.access(candidate);
574-
cachedPlantumlJarPath = candidate;
575-
return candidate;
624+
const usablePath = await ensurePlantumlJarExtracted(candidate);
625+
cachedPlantumlJarPath = usablePath;
626+
return usablePath;
576627
} catch {
577628
// Continue searching
578629
}

0 commit comments

Comments
 (0)