polymech-astro/packages/imagetools_3/integration/utils/saveAndCopyAsset.js
2025-12-31 12:21:55 +01:00

82 lines
2.2 KiB
JavaScript

import fs from "node:fs/promises";
import { posix as path } from "node:path";
import { fsCachePath } from "../../utils/runtimeChecks.js";
const copied = new Set();
const dirsCreated = new Set();
export async function saveAndCopyAsset(
hash,
image,
buffer,
outDir,
assetsDir,
assetPath,
isSsrBuild
) {
// Use Set for O(1) lookup instead of O(n) array search
if (copied.has(assetPath)) return;
const src = fsCachePath + hash;
const dest = path.join(outDir, isSsrBuild ? "/client" : "", assetPath);
const destDir = path.dirname(dest);
// Check if destination already exists and is valid (skip copy)
try {
const stats = await fs.stat(dest);
if (stats.size > 0) {
copied.add(assetPath);
console.log(`[skip] ${assetPath} (already exists)`);
return;
}
} catch {
// File doesn't exist, continue with copy
}
// Ensure destination directory exists (but only create once per unique dir)
if (!dirsCreated.has(destDir)) {
await fs.mkdir(destDir, { recursive: true });
dirsCreated.add(destDir);
}
// Try hardlink first (instant, no disk usage), fallback to copy
let linked = false;
try {
await fs.link(src, dest);
linked = true;
} catch (linkError) {
// Hardlink failed, try copy
try {
await fs.copyFile(src, dest);
} catch (copyError) {
if (copyError.code === "ENOENT") {
// Source doesn't exist, regenerate from buffer/image
const imageBuffer = buffer || (await image.toBuffer());
await Promise.all([
fs.writeFile(src, imageBuffer),
fs.writeFile(dest, imageBuffer)
]);
console.log(`[regen] ${src} -> ${dest}`);
} else {
throw copyError;
}
}
}
copied.add(assetPath);
}
// Helper to pre-create directories in batch (call before processing)
export async function preCreateDirectories(assetPaths, outDir, isSsrBuild) {
const uniqueDirs = new Set(
assetPaths.map(assetPath =>
path.dirname(path.join(outDir, isSsrBuild ? "/client" : "", assetPath))
)
);
await Promise.all(
[...uniqueDirs].map(dir => fs.mkdir(dir, { recursive: true }))
);
uniqueDirs.forEach(dir => dirsCreated.add(dir));
}