Files
scrypted/server/src/plugin/runtime/node-worker-common.ts
Koushik Dutta ea606de22f postrelease
2024-06-26 09:43:48 -07:00

103 lines
2.7 KiB
TypeScript

import AdmZip from 'adm-zip';
import fs from 'fs';
import path from 'path';
function createAdmZipHash(hash: string) {
const extractVersion = "1-";
return extractVersion + hash;
}
function prep(pluginVolume: string, hash: string) {
hash = createAdmZipHash(hash);
const zipFilename = `${hash}.zip`;
const zipDir = path.join(pluginVolume, 'zip');
const zipFile = path.join(zipDir, zipFilename);
const unzippedPath = path.join(zipDir, 'unzipped')
const zipDirTmp = zipDir + '.tmp';
const zipDirTmp2 = zipDir + '.tmp2';
return {
unzippedPath,
zipFilename,
zipDir,
zipFile,
zipDirTmp,
zipDirTmp2,
};
}
export async function prepareZip(pluginVolume: string, h: string, getZip: () => Promise<Buffer>) {
const { zipFile, unzippedPath } = prep(pluginVolume, h);
if (fs.existsSync(zipFile)) {
return {
zipFile,
unzippedPath,
}
}
const zipBuffer = await getZip();
return extractZip(pluginVolume, h, zipBuffer);
}
export function prepareZipSync(pluginVolume: string, h: string, getZip: () => Buffer) {
const { zipFile, unzippedPath } = prep(pluginVolume, h);
if (fs.existsSync(zipFile)) {
return {
zipFile,
unzippedPath,
}
}
const zipBuffer = getZip();
return extractZip(pluginVolume, h, zipBuffer);
}
export function extractZip(pluginVolume: string, h: string, zipBuffer: Buffer) {
const { zipDir, zipDirTmp, zipDirTmp2, zipFilename, zipFile, unzippedPath } = prep(pluginVolume, h);
// stage the plugin zip in a tmp directory, then move it to the final location.
// so if the zip extraction is corrupt, it won't be used.
fs.rmSync(zipDirTmp, {
recursive: true,
force: true,
});
let zipDirTmp2Exists = false;
try {
fs.rmSync(zipDirTmp2, {
recursive: true,
force: true,
});
}
catch (e) {
zipDirTmp2Exists = true;
}
try {
fs.rmSync(zipDir, {
recursive: true,
force: true,
});
}
catch (e) {
if (zipDirTmp2Exists)
throw e;
// file lock from dangling plugin process may have prevented the recursive rm from completing.
// try renaming it. it will get cleaned up eventually.
fs.renameSync(zipDir, zipDirTmp2);
}
fs.mkdirSync(zipDirTmp, {
recursive: true,
});
fs.writeFileSync(path.join(zipDirTmp, zipFilename), zipBuffer);
const admZip = new AdmZip(zipBuffer);
admZip.extractAllTo(path.join(zipDirTmp, 'unzipped'), true);
fs.renameSync(zipDirTmp, zipDir);
return {
zipFile,
unzippedPath,
}
}