Skip to content

Commit 5ad3393

Browse files
committed
fixes #619
1 parent 5deecb0 commit 5ad3393

File tree

1 file changed

+48
-53
lines changed

1 file changed

+48
-53
lines changed

src/zip.ts

+48-53
Original file line numberDiff line numberDiff line change
@@ -1,70 +1,65 @@
1-
import { Entry, open, ZipFile } from 'yauzl';
1+
import { Entry, open, Options, ZipFile } from 'yauzl';
22
import { Manifest } from './manifest';
33
import { parseXmlManifest, XMLManifest } from './xml';
4+
import { promisify } from 'util';
5+
import { Readable } from 'stream';
46

5-
function readEntryString(zipfile: ZipFile, entry: Entry, cb: (err: Error, result?: string) => void): void {
6-
zipfile.openReadStream(entry, (err, stream) => {
7-
if (err) {
8-
return cb(err);
9-
}
10-
7+
async function bufferStream(stream: Readable): Promise<Buffer> {
8+
return await new Promise((c, e) => {
119
const buffers = [];
1210
stream.on('data', buffer => buffers.push(buffer));
13-
stream.once('error', cb);
14-
stream.once('end', () => {
15-
try {
16-
cb(null, Buffer.concat(buffers).toString('utf8'));
17-
} catch (err) {
18-
cb(err);
19-
}
20-
});
11+
stream.once('error', e);
12+
stream.once('end', () => c(Buffer.concat(buffers)));
2113
});
2214
}
2315

24-
export function readVSIXPackage(packagePath: string): Promise<{ manifest: Manifest; xmlManifest: XMLManifest }> {
25-
return new Promise<{ manifest: Manifest; xmlManifest: XMLManifest }>((c, e) => {
26-
open(packagePath, (err, zipfile) => {
27-
if (err) {
28-
return e(err);
29-
}
16+
export async function readZip(packagePath: string, filter: (name: string) => boolean): Promise<Map<string, Buffer>> {
17+
const zipfile = await promisify<string, Options, ZipFile>(open)(packagePath, { lazyEntries: true });
3018

31-
let manifest: Manifest | undefined;
32-
let xmlManifest: XMLManifest | undefined;
19+
return await new Promise((c, e) => {
20+
const result = new Map<string, Buffer>();
3321

34-
zipfile.once('close', () => {
35-
if (!manifest) {
36-
e(new Error('Manifest not found'));
37-
} else if (!xmlManifest) {
38-
e(new Error('VSIX manifest not found'));
39-
} else {
40-
c({ manifest, xmlManifest });
41-
}
42-
});
22+
zipfile.once('close', () => c(result));
4323

44-
zipfile.on('entry', (entry: Entry) => {
45-
switch (entry.fileName.toLowerCase()) {
46-
case 'extension/package.json': {
47-
return readEntryString(zipfile, entry, (err, result) => {
48-
if (err) {
49-
zipfile.close();
50-
return e(err);
51-
}
24+
zipfile.readEntry();
25+
zipfile.on('entry', (entry: Entry) => {
26+
const name = entry.fileName.toLowerCase();
5227

53-
manifest = JSON.parse(result);
54-
});
28+
if (filter(name)) {
29+
zipfile.openReadStream(entry, (err, stream) => {
30+
if (err) {
31+
zipfile.close();
32+
return e(err);
5533
}
56-
case 'extension.vsixmanifest': {
57-
return readEntryString(zipfile, entry, (err, result) => {
58-
if (err) {
59-
zipfile.close();
60-
return e(err);
61-
}
6234

63-
parseXmlManifest(result).then(r => (xmlManifest = r));
64-
});
65-
}
66-
}
67-
});
35+
bufferStream(stream).then(buffer => {
36+
result.set(name, buffer);
37+
zipfile.readEntry();
38+
});
39+
});
40+
} else {
41+
zipfile.readEntry();
42+
}
6843
});
6944
});
7045
}
46+
47+
export async function readVSIXPackage(packagePath: string): Promise<{ manifest: Manifest; xmlManifest: XMLManifest }> {
48+
const map = await readZip(packagePath, name => /^extension\/package\.json$|^extension\.vsixmanifest$/i.test(name));
49+
const rawManifest = map.get('extension/package.json');
50+
51+
if (!rawManifest) {
52+
throw new Error('Manifest not found');
53+
}
54+
55+
const rawXmlManifest = map.get('extension.vsixmanifest');
56+
57+
if (!rawXmlManifest) {
58+
throw new Error('VSIX manifest not found');
59+
}
60+
61+
return {
62+
manifest: JSON.parse(rawManifest.toString('utf8')),
63+
xmlManifest: await parseXmlManifest(rawXmlManifest.toString('utf8')),
64+
};
65+
}

0 commit comments

Comments
 (0)