1
0
mirror of https://github.com/lensapp/lens.git synced 2025-05-20 05:10:56 +00:00
lens/src/extensions/extension-installer/extension-installer.ts
Sebastian Malton 4c75b43007
Release 6.1.18 (#6544)
* Release 6.1.18

Signed-off-by: Sebastian Malton <sebastian@malton.name>

* Fix non-bundled extensions not working (#6543)

- Stop omitting the optional dependencies (which happens to also
  just remove them)

Signed-off-by: Sebastian Malton <sebastian@malton.name>

Signed-off-by: Sebastian Malton <sebastian@malton.name>

Signed-off-by: Sebastian Malton <sebastian@malton.name>
2022-11-09 15:40:53 -05:00

105 lines
2.9 KiB
TypeScript

/**
* Copyright (c) OpenLens Authors. All rights reserved.
* Licensed under MIT License. See LICENSE in root directory for more information.
*/
import AwaitLock from "await-lock";
import child_process from "child_process";
import fs from "fs-extra";
import path from "path";
import logger from "../../main/logger";
import type { PackageJson } from "type-fest";
const logModule = "[EXTENSION-INSTALLER]";
interface Dependencies {
extensionPackageRootDirectory: string;
}
const baseNpmInstallArgs = [
"install",
"--audit=false",
"--fund=false",
// NOTE: we do not omit the `optional` dependencies because that is how we specify the non-bundled extensions
"--omit=dev",
"--omit=peer",
"--prefer-offline",
];
/**
* Installs dependencies for extensions
*/
export class ExtensionInstaller {
private installLock = new AwaitLock();
constructor(private dependencies: Dependencies) {}
get npmPath() {
return __non_webpack_require__.resolve("npm");
}
/**
* Write package.json to the file system and execute npm install for it.
*/
installPackages = async (packageJsonPath: string, packagesJson: PackageJson): Promise<void> => {
// Mutual exclusion to install packages in sequence
await this.installLock.acquireAsync();
try {
// Write the package.json which will be installed in .installDependencies()
await fs.writeFile(path.join(packageJsonPath), JSON.stringify(packagesJson, null, 2), {
mode: 0o600,
});
logger.info(`${logModule} installing dependencies at ${this.dependencies.extensionPackageRootDirectory}`);
await this.npm(...baseNpmInstallArgs);
logger.info(`${logModule} dependencies installed at ${this.dependencies.extensionPackageRootDirectory}`);
} finally {
this.installLock.release();
}
};
/**
* Install single package using npm
*/
installPackage = async (name: string): Promise<void> => {
// Mutual exclusion to install packages in sequence
await this.installLock.acquireAsync();
try {
logger.info(`${logModule} installing package from ${name} to ${this.dependencies.extensionPackageRootDirectory}`);
await this.npm(...baseNpmInstallArgs, name);
logger.info(`${logModule} package ${name} installed to ${this.dependencies.extensionPackageRootDirectory}`);
} finally {
this.installLock.release();
}
};
private npm(...args: string[]): Promise<void> {
return new Promise((resolve, reject) => {
const child = child_process.fork(this.npmPath, args, {
cwd: this.dependencies.extensionPackageRootDirectory,
silent: true,
env: {},
});
let stderr = "";
child.stderr?.on("data", data => {
stderr += String(data);
});
child.on("close", (code) => {
if (code !== 0) {
reject(new Error(stderr));
} else {
resolve();
}
});
child.on("error", error => {
reject(error);
});
});
}
}