Skip to content

Commit

Permalink
refactor: update code
Browse files Browse the repository at this point in the history
  • Loading branch information
bytemain committed Jun 22, 2024
1 parent ba761a0 commit 4c0fc8d
Show file tree
Hide file tree
Showing 3 changed files with 48 additions and 52 deletions.
90 changes: 43 additions & 47 deletions src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ import * as path from "node:path";
import { Readable } from "node:stream";
import * as urllib from "urllib";
import * as yauzl from "yauzl";
import { awaitEvent, createDeferred, retry } from "./utils";
import { awaitEvent, createPromiseResolvers, retry } from "./utils";

const debug = debugFactory("InstallExtension");

Expand Down Expand Up @@ -306,48 +306,44 @@ export class ExtensionInstaller implements IExtensionInstaller {
}

private async checkExtensionType(tmpZipFile: string): Promise<ExtensionType> {
const deferred = createDeferred<ExtensionType>();
const resolvers = createPromiseResolvers<ExtensionType>();

const zipFile = await this.createZipFile(tmpZipFile);

zipFile.readEntry();
zipFile.on("error", deferred.reject);
zipFile.on("entry", (entry) => {
if (entry.fileName === "extension/package.json") {
deferred.resolve(ExtensionType.OPENSUMI);
resolvers.resolve(ExtensionType.OPENSUMI);
} else {
zipFile.readEntry();
}
});

zipFile.on("close", function() {
deferred.resolve(ExtensionType.JETBRAINS);
resolvers.resolve(ExtensionType.JETBRAINS);
});
zipFile.on("error", resolvers.reject);

return deferred.promise;
return resolvers.promise;
}

private async checkJarExtension(tmpZipFile: string): Promise<boolean> {
const deferred = createDeferred<boolean>();
const resolvers = createPromiseResolvers<boolean>();

const zipFile = await this.createZipFile(tmpZipFile);

zipFile.readEntry();
zipFile.on("error", deferred.reject);
zipFile.on("entry", (entry) => {
// 判断如果文件名是 META-INF,则说明该插件是 jar 文件,应该直接复制
if (entry.fileName === "META-INF/") {
deferred.resolve(true);
resolvers.resolve(true);
} else {
zipFile.readEntry();
}
});

zipFile.on("close", function() {
deferred.resolve(false);
resolvers.resolve(false);
});
zipFile.on("error", resolvers.reject);

return deferred.promise;
return resolvers.promise;
}

private async unzip(dist: string, targetDirName: string, tmpZipFile: string): Promise<string[]> {
Expand Down Expand Up @@ -383,31 +379,19 @@ export class ExtensionInstaller implements IExtensionInstaller {
targetDirName: string,
tmpZipFile: string,
): Promise<string> {
const deferred = createDeferred<string>();
const resolvers = createPromiseResolvers<string>();

const isJarExtension = await this.checkJarExtension(tmpZipFile);
// 如果是 jar 插件,则直接复制
if (isJarExtension) {
const dest = path.join(dist, path.basename(tmpZipFile, ".zip") + ".jar");
await fsp.cp(tmpZipFile, dest, { recursive: true });
deferred.resolve(dest);
resolvers.resolve(dest);
} else {
let readFirst = false;
let extensionDirName = "";
const zipFile = await this.createZipFile(tmpZipFile);
zipFile.readEntry();
zipFile.on("error", deferred.reject);
zipFile.on("close", () => {
if (!extensionDirName) {
deferred.reject(new Error("Download Error: cannot get extension dir name from zip file"));
return;
}

fsp.rm(tmpZipFile)
.then(() => deferred.resolve(path.join(dist, extensionDirName)))
.catch(deferred.reject);
});

zipFile.on("entry", (entry) => {
const targetFileName = path.join(dist, entry.fileName);
if (/\/$/.test(entry.fileName)) {
Expand All @@ -418,24 +402,35 @@ export class ExtensionInstaller implements IExtensionInstaller {
}
mkdirp(targetFileName)
.then(() => zipFile.readEntry())
.catch(deferred.reject);
.catch(resolvers.reject);
} else {
zipFile.openReadStream(entry, (err, readStream) => {
if (err) {
deferred.reject(err);
resolvers.reject(err);
return;
}
readStream.on("end", () => {
zipFile.readEntry();
});
mkdirp(path.dirname(targetFileName))
.then(() => readStream.pipe(fs.createWriteStream(targetFileName)))
.catch(deferred.reject);
.catch(resolvers.reject);
});
}
});
zipFile.on("error", resolvers.reject);
zipFile.on("close", () => {
if (!extensionDirName) {
resolvers.reject(new Error("Download Error: cannot get extension dir name from zip file"));
return;
}

fsp.rm(tmpZipFile)
.then(() => resolvers.resolve(path.join(dist, extensionDirName)))
.catch(resolvers.reject);
});
}
return deferred.promise;
return resolvers.promise;
}

private async _installByRelease(release: ExtensionRelease): Promise<string[]> {
Expand Down Expand Up @@ -521,24 +516,25 @@ export class ExtensionInstaller implements IExtensionInstaller {

private async unzipFile(dist: string, targetDirName: string, tmpZipFile: string): Promise<string> {
const sourcePathRegex = new RegExp("^extension");
const deferred = createDeferred<string>();
const resolvers = createPromiseResolvers<string>();

const extensionDir = path.join(dist, targetDirName);
// 创建插件目录
await fsp.mkdir(extensionDir, { recursive: true });

const zipFile = await createZipFile(tmpZipFile);
zipFile.readEntry();
zipFile.on("error", deferred.reject);
zipFile.on("error", resolvers.reject);

zipFile.on("close", () => {
if (!fs.existsSync(path.join(extensionDir, "package.json"))) {
deferred.reject(new Error(`Download Error: ${extensionDir}/package.json`));
return;
}
fsp.rm(tmpZipFile).then(() => deferred.resolve(extensionDir)).catch(err => {
deferred.reject(err);
});
fsp.access(path.join(extensionDir, "package.json"))
.then(() => {
resolvers.resolve(extensionDir);
})
.catch(err => {
resolvers.reject(new Error(`Download Error: ${extensionDir}/package.json can not access: ` + err.message));
});
fsp.rm(tmpZipFile);
});

zipFile.on("entry", (entry) => {
Expand All @@ -551,7 +547,7 @@ export class ExtensionInstaller implements IExtensionInstaller {
if (/\/$/.test(fileName)) {
const targetFileName = path.join(extensionDir, fileName);
mkdirp(targetFileName).then(() => zipFile.readEntry()).catch(err => {
deferred.reject(err);
resolvers.reject(err);
});
return;
}
Expand Down Expand Up @@ -582,16 +578,16 @@ export class ExtensionInstaller implements IExtensionInstaller {
if (originalFileName) {
// rename .asar, if filename has been modified
fsp.rename(targetFileName, path.join(extensionDir, originalFileName))
.catch(deferred.reject);
.catch(resolvers.reject);
}
zipFile.readEntry();
});
stream.on("error", deferred.reject);
stream.on("error", resolvers.reject);
stream.pipe(writeStream);
}).catch(deferred.reject);
}).catch(resolvers.reject);
});
});

return deferred.promise;
return resolvers.promise;
}
}
2 changes: 1 addition & 1 deletion src/utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -79,7 +79,7 @@ export interface IDeferred<T> {
promise: Promise<T>;
}

export const createDeferred = <T>(): IDeferred<T> => {
export const createPromiseResolvers = <T>(): IDeferred<T> => {
let resolve: (value: T) => void;
let reject: (error: Error) => void;
const promise = new Promise<T>((res, rej) => {
Expand Down
8 changes: 4 additions & 4 deletions tests/utils.test.ts
Original file line number Diff line number Diff line change
@@ -1,17 +1,17 @@
import { describe, it } from "vitest";
import { createDeferred, sleep } from "../src/utils";
import { createPromiseResolvers, sleep } from "../src/utils";

describe("utils", () => {
describe("Deferred", () => {
describe("PromiseResolvers", () => {
it("can throw error", async ({ expect }) => {
const errorThrow = async () => {
await sleep(1000);
throw new Error("error");
};
const fn = async () => {
const deferred = createDeferred();
const resolvers = createPromiseResolvers();
await errorThrow();
return deferred.promise;
return resolvers.promise;
};

await expect(fn()).rejects.toThrow("error");
Expand Down

0 comments on commit 4c0fc8d

Please sign in to comment.