Skip to content

Commit 5b7e843

Browse files
authored
fix: explore zip method and improved stuffs
- give proper error message - use paths from plugin.json for icon, readme, etc
1 parent e41acde commit 5b7e843

File tree

1 file changed

+57
-10
lines changed

1 file changed

+57
-10
lines changed

server/apis/plugin.js

Lines changed: 57 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -473,10 +473,11 @@ router.put('/', async (req, res) => {
473473
}
474474

475475
const { pluginJson, icon, readme, changelogs } = await exploreZip(pluginZip.data);
476-
const errorMessage = validatePlugin(pluginJson, icon, readme);
477-
478-
if (errorMessage) {
479-
res.status(400).send({ error: errorMessage });
476+
477+
try {
478+
validatePlugin(pluginJson, icon, readme);
479+
} catch (error) {
480+
res.status(400).send({ error: error.message });
480481
return;
481482
}
482483

@@ -637,11 +638,54 @@ router.delete('/:id', async (req, res) => {
637638
});
638639

639640
async function exploreZip(file) {
640-
const zip = await jsZip.loadAsync(file);
641-
const pluginJson = JSON.parse(await zip.file('plugin.json')?.async('string'));
642-
const icon = await zip.file('icon.png')?.async('base64');
643-
const readme = await zip.file('readme.md')?.async('string');
644-
const changelogs = await zip.file(pluginJson.changelogs || 'changelogs.md')?.async('string');
641+
// Create a new JSZip instance for each request to avoid caching issues
642+
const zip = new JSZip();
643+
await zip.loadAsync(file);
644+
645+
const pluginJsonFile = zip.file('plugin.json');
646+
if (!pluginJsonFile) {
647+
throw new Error('Missing plugin.json file in the zip.');
648+
}
649+
const pluginJson = JSON.parse(await pluginJsonFile.async('string'));
650+
651+
const iconPath = pluginJson.icon || 'icon.png';
652+
const iconFile = zip.file(iconPath);
653+
let icon = null;
654+
if (iconFile) {
655+
icon = await iconFile.async('base64');
656+
} else if (iconPath !== 'icon.png') {
657+
// If custom path failed, try the default path
658+
const defaultIconFile = zip.file('icon.png');
659+
if (defaultIconFile) {
660+
icon = await defaultIconFile.async('base64');
661+
}
662+
}
663+
664+
const readmePath = pluginJson.readme || 'readme.md';
665+
let readmeFile = zip.file(readmePath);
666+
if (!readmeFile && readmePath !== 'readme.md') {
667+
// If custom path failed, try the default path
668+
readmeFile = zip.file('readme.md');
669+
}
670+
671+
let readme = null;
672+
if (readmeFile) {
673+
const readmeContent = await readmeFile.async('string');
674+
readme = readmeContent && readmeContent.trim() ? readmeContent.trim() : null;
675+
}
676+
677+
const changelogsPath = pluginJson.changelogs || 'changelogs.md';
678+
let changelogsFile = zip.file(changelogsPath);
679+
if (!changelogsFile && changelogsPath !== 'changelogs.md') {
680+
// If custom path failed, try the default path
681+
changelogsFile = zip.file('changelogs.md');
682+
}
683+
684+
let changelogs = null;
685+
if (changelogsFile) {
686+
const changelogsContent = await changelogsFile.async('string');
687+
changelogs = changelogsContent && changelogsContent.trim() ? changelogsContent.trim() : null;
688+
}
645689

646690
return { pluginJson, icon, readme, changelogs };
647691
}
@@ -676,7 +720,10 @@ function validatePlugin(json, icon, readmeFile) {
676720
throw new Error('Invalid version number, version should be in the format <major>.<minor>.<patch> (e.g. 0.0.1)');
677721
}
678722

679-
const missingFields = [name, version, id, main].filter((field) => !field);
723+
const requiredFields = { name, version, id, main };
724+
const missingFields = Object.entries(requiredFields)
725+
.filter(([_, value]) => !value)
726+
.map(([key]) => key);
680727
if (missingFields.length) {
681728
throw new Error(`Missing fields in plugin.json: ${missingFields.join(', ')}`);
682729
}

0 commit comments

Comments
 (0)