-
Notifications
You must be signed in to change notification settings - Fork 216
/
Copy pathzip.ts
76 lines (63 loc) · 2.25 KB
/
zip.ts
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
import { Entry, open, ZipFile } from 'yauzl';
import { ManifestPackage, UnverifiedManifest } from './manifest';
import { parseXmlManifest, XMLManifest } from './xml';
import { Readable } from 'stream';
import { filePathToVsixPath } from './util';
import { validateManifestForPackaging } from './package';
async function bufferStream(stream: Readable): Promise<Buffer> {
return await new Promise((c, e) => {
const buffers: Buffer[] = [];
stream.on('data', buffer => buffers.push(buffer));
stream.once('error', e);
stream.once('end', () => c(Buffer.concat(buffers)));
});
}
export async function readZip(packagePath: string, filter: (name: string) => boolean): Promise<Map<string, Buffer>> {
const zipfile = await new Promise<ZipFile>((c, e) =>
open(packagePath, { lazyEntries: true }, (err, zipfile) => (err ? e(err) : c(zipfile!)))
);
return await new Promise((c, e) => {
const result = new Map<string, Buffer>();
zipfile.once('close', () => c(result));
zipfile.readEntry();
zipfile.on('entry', (entry: Entry) => {
const name = entry.fileName.toLowerCase();
if (filter(name)) {
zipfile.openReadStream(entry, (err, stream) => {
if (err) {
zipfile.close();
return e(err);
}
bufferStream(stream!).then(buffer => {
result.set(name, buffer);
zipfile.readEntry();
});
});
} else {
zipfile.readEntry();
}
});
});
}
export async function readVSIXPackage(packagePath: string): Promise<{ manifest: ManifestPackage; xmlManifest: XMLManifest }> {
const map = await readZip(packagePath, name => /^extension\/package\.json$|^extension\.vsixmanifest$/i.test(name));
const rawManifest = map.get(filePathToVsixPath('package.json'));
if (!rawManifest) {
throw new Error('Manifest not found');
}
const rawXmlManifest = map.get('extension.vsixmanifest');
if (!rawXmlManifest) {
throw new Error('VSIX manifest not found');
}
const manifest = JSON.parse(rawManifest.toString('utf8')) as UnverifiedManifest;
let manifestValidated;
try {
manifestValidated = validateManifestForPackaging(manifest);
} catch (error) {
throw new Error(`Invalid extension VSIX manifest: ${error}`);
}
return {
manifest: manifestValidated,
xmlManifest: await parseXmlManifest(rawXmlManifest.toString('utf8')),
};
}