feat: enhance plugin download handling with validation and extraction improvements
This commit is contained in:
@@ -956,6 +956,11 @@ ipcMain.handle('plugin:download', async (event, { pluginId, downloadUrl, name })
|
|||||||
return { success: false, error: 'Plugin already installed' };
|
return { success: false, error: 'Plugin already installed' };
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Validate downloadUrl
|
||||||
|
if (!downloadUrl || typeof downloadUrl !== 'string' || downloadUrl.trim() === '') {
|
||||||
|
return { success: false, error: 'Plugin metadata missing downloadUrl field' };
|
||||||
|
}
|
||||||
|
|
||||||
// Download the zip file
|
// Download the zip file
|
||||||
const tempZipPath = path.join(app.getPath('temp'), `${pluginId}.zip`);
|
const tempZipPath = path.join(app.getPath('temp'), `${pluginId}.zip`);
|
||||||
|
|
||||||
@@ -986,13 +991,43 @@ ipcMain.handle('plugin:download', async (event, { pluginId, downloadUrl, name })
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
// Extract the zip file
|
// Extract the zip file to temp location first
|
||||||
const zip = new AdmZip(tempZipPath);
|
const tempExtractDir = path.join(app.getPath('temp'), `${pluginId}-extract`);
|
||||||
zip.extractAllTo(pluginDir, true);
|
if (fs.existsSync(tempExtractDir)) {
|
||||||
|
fs.rmSync(tempExtractDir, { recursive: true, force: true });
|
||||||
|
}
|
||||||
|
fs.mkdirSync(tempExtractDir, { recursive: true });
|
||||||
|
|
||||||
// Clean up temp file
|
const zip = new AdmZip(tempZipPath);
|
||||||
|
zip.extractAllTo(tempExtractDir, true);
|
||||||
|
|
||||||
|
// Clean up temp zip
|
||||||
fs.unlinkSync(tempZipPath);
|
fs.unlinkSync(tempZipPath);
|
||||||
|
|
||||||
|
// GitHub archives extract to repo-name-branch/ folder, flatten it
|
||||||
|
const extractedContents = fs.readdirSync(tempExtractDir);
|
||||||
|
let sourceDir = tempExtractDir;
|
||||||
|
|
||||||
|
// If single folder exists, move contents up one level
|
||||||
|
if (extractedContents.length === 1) {
|
||||||
|
const singleItem = path.join(tempExtractDir, extractedContents[0]);
|
||||||
|
if (fs.statSync(singleItem).isDirectory()) {
|
||||||
|
sourceDir = singleItem;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Move contents to final plugin directory
|
||||||
|
fs.mkdirSync(pluginDir, { recursive: true });
|
||||||
|
const files = fs.readdirSync(sourceDir);
|
||||||
|
for (const file of files) {
|
||||||
|
const srcPath = path.join(sourceDir, file);
|
||||||
|
const destPath = path.join(pluginDir, file);
|
||||||
|
fs.renameSync(srcPath, destPath);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Clean up temp extract dir
|
||||||
|
fs.rmSync(tempExtractDir, { recursive: true, force: true });
|
||||||
|
|
||||||
// Store metadata
|
// Store metadata
|
||||||
const metadataPath = path.join(pluginDir, 'plugin-metadata.json');
|
const metadataPath = path.join(pluginDir, 'plugin-metadata.json');
|
||||||
fs.writeFileSync(metadataPath, JSON.stringify({
|
fs.writeFileSync(metadataPath, JSON.stringify({
|
||||||
|
|||||||
Reference in New Issue
Block a user