vsix-utils
Version:
utilities for working with VSIX packages
151 lines (143 loc) • 4.41 kB
JavaScript
;
var buffer = require('buffer');
var fs = require('fs');
var promises = require('fs/promises');
var fastXmlParser = require('fast-xml-parser');
var yauzl = require('yauzl');
var yazl = require('yazl');
require('path');
require('process');
require('ignore');
require('mime');
require('package-manager-detector');
require('tinyglobby');
require('remark');
require('remark-transform-links');
function _interopDefault (e) { return e && e.__esModule ? e : { default: e }; }
var yauzl__default = /*#__PURE__*/_interopDefault(yauzl);
var yazl__default = /*#__PURE__*/_interopDefault(yazl);
// src/zip.ts
// src/files.ts
function isInMemoryFile(file) {
return file.type === "in-memory";
}
// src/zip.ts
async function writeVsix(options) {
const { files, packagePath, force, epoch } = options;
if (!files || files.length === 0) {
throw new Error("no files specified to package");
}
if (!packagePath) {
throw new Error("no package path specified");
}
if (fs.existsSync(packagePath)) {
if (!force) {
throw new Error(`package already exists at ${packagePath}`);
}
await promises.unlink(packagePath);
}
const zip = new yazl__default.default.ZipFile();
const zipOptions = {};
if (epoch != null) {
zipOptions.mtime = new Date(epoch * 1e3);
files.sort((a, b) => a.path.localeCompare(b.path));
}
try {
for (const f of files) {
if (isInMemoryFile(f)) {
zip.addBuffer(
typeof f.contents === "string" ? buffer.Buffer.from(f.contents, "utf8") : f.contents,
f.path,
{ ...zipOptions }
);
continue;
}
zip.addFile(f.localPath, f.path, { ...zipOptions });
}
zip.end();
const zipStream = fs.createWriteStream(packagePath, {
mode: promises.constants.S_IRWXU | promises.constants.S_IRGRP | promises.constants.S_IXGRP | promises.constants.S_IROTH | promises.constants.S_IXOTH
});
zip.outputStream.pipe(zipStream);
await new Promise((resolve, reject) => {
zipStream.once("finish", resolve);
zipStream.once("error", reject);
zip.once("error", (err) => {
zipStream.destroy();
reject(err);
});
});
return true;
} catch (err) {
if (fs.existsSync(packagePath)) {
await promises.unlink(packagePath);
}
if (err instanceof Error) {
throw new TypeError(`failed to create package: ${err.message}`);
}
throw new Error(`failed to create package: ${err}`);
}
}
async function readVsix(options) {
const { packagePath } = options;
const zip = await new Promise((resolve, reject) => {
yauzl__default.default.open(packagePath, { lazyEntries: true }, (err, zip2) => {
if (err) {
reject(err);
} else {
resolve(zip2);
}
});
});
const files = await new Promise((resolve, reject) => {
const fileMap = /* @__PURE__ */ new Map();
zip.once("close", () => resolve(fileMap));
zip.on("entry", async (entry) => {
try {
const buffer = await new Promise((resolve2, reject2) => {
zip.openReadStream(entry, (err, stream) => {
if (err) reject2(err);
stream.once("error", reject2);
stream.once("end", () => {
if (stream.readable) {
reject2(new Error("Stream ended before all data was read"));
}
});
return resolve2(bufferStream(stream));
});
});
fileMap.set(entry.fileName, buffer);
zip.readEntry();
} catch (err) {
zip.close();
reject(err);
}
});
zip.readEntry();
});
if (!files.has("extension.vsixmanifest")) {
throw new Error("extension.vsixmanifest file is missing");
}
const rawManifest = files.get("extension.vsixmanifest").toString("utf8");
const parser = new fastXmlParser.XMLParser({
preserveOrder: false,
transformTagName(tagName) {
return tagName.toLowerCase();
}
});
const manifest = parser.parse(rawManifest);
return {
files,
manifest
};
}
async function bufferStream(stream) {
return await new Promise((resolve, reject) => {
const buffers = [];
stream.on("data", (buffer) => buffers.push(buffer));
stream.once("error", reject);
stream.once("end", () => resolve(buffer.Buffer.concat(buffers)));
});
}
exports.readVsix = readVsix;
exports.writeVsix = writeVsix;