Skip to content

Commit d4c2bf0

Browse files
Merge pull request #5217 from farfromrefug/pnpm
This PR add pnpm full support
2 parents bb8e816 + 8d6b32f commit d4c2bf0

9 files changed

+120
-0
lines changed

lib/bootstrap.ts

+1
Original file line numberDiff line numberDiff line change
@@ -112,6 +112,7 @@ $injector.requireCommand(["setup|cloud", "cloud|setup"], "./commands/setup");
112112
$injector.requirePublic("packageManager", "./package-manager");
113113
$injector.requirePublic("npm", "./node-package-manager");
114114
$injector.requirePublic("yarn", "./yarn-package-manager");
115+
$injector.requirePublic("pnpm", "./pnpm-package-manager");
115116
$injector.requireCommand("package-manager|set", "./commands/package-manager-set");
116117
$injector.requireCommand("package-manager|get", "./commands/package-manager-get");
117118

lib/common/commands/package-manager-set.ts

+2
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,8 @@ export class PackageManagerCommand implements ICommand {
1010
public execute(args: string[]): Promise<void> {
1111
if (args[0] === 'yarn') {
1212
return this.$userSettingsService.saveSetting("packageManager", "yarn");
13+
} else if (args[0] === 'pnpm') {
14+
return this.$userSettingsService.saveSetting("packageManager", "pnpm");
1315
} else if (args[0] === 'npm') {
1416
return this.$userSettingsService.saveSetting("packageManager", "npm");
1517
}

lib/declarations.d.ts

+1
Original file line numberDiff line numberDiff line change
@@ -554,6 +554,7 @@ interface IOptions extends IRelease, IDeviceIdentifier, IJustLaunch, IAvd, IAvai
554554
frameworkName: string;
555555
frameworkVersion: string;
556556
yarn: string,
557+
pnpm: string,
557558
ipa: string;
558559
tsc: boolean;
559560
ts: boolean;

lib/options.ts

+1
Original file line numberDiff line numberDiff line change
@@ -100,6 +100,7 @@ export class Options {
100100
ts: { type: OptionType.Boolean, hasSensitiveValue: false },
101101
typescript: { type: OptionType.Boolean, hasSensitiveValue: false },
102102
yarn: { type: OptionType.Boolean, hasSensitiveValue: false },
103+
pnpm: { type: OptionType.Boolean, hasSensitiveValue: false },
103104
androidTypings: { type: OptionType.Boolean, hasSensitiveValue: false },
104105
bundle: { type: OptionType.String, hasSensitiveValue: false },
105106
all: { type: OptionType.Boolean, hasSensitiveValue: false },

lib/package-manager.ts

+3
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ export class PackageManager implements IPackageManager {
99
private $npm: INodePackageManager,
1010
private $options: IOptions,
1111
private $yarn: INodePackageManager,
12+
private $pnpm: INodePackageManager,
1213
private $logger: ILogger,
1314
private $userSettingsService: IUserSettingsService
1415
) { }
@@ -98,6 +99,8 @@ export class PackageManager implements IPackageManager {
9899

99100
if (pm === 'yarn' || this.$options.yarn) {
100101
return this.$yarn;
102+
} else if (pm === 'pnpm' || this.$options.pnpm) {
103+
return this.$pnpm;
101104
} else {
102105
return this.$npm;
103106
}

lib/pnpm-package-manager.ts

+106
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,106 @@
1+
import * as path from "path";
2+
import { BasePackageManager } from "./base-package-manager";
3+
import { exported } from './common/decorators';
4+
import { CACACHE_DIRECTORY_NAME } from "./constants";
5+
6+
export class PnpmPackageManager extends BasePackageManager {
7+
8+
constructor(
9+
$childProcess: IChildProcess,
10+
private $errors: IErrors,
11+
$fs: IFileSystem,
12+
$hostInfo: IHostInfo,
13+
private $httpClient: Server.IHttpClient,
14+
private $logger: ILogger,
15+
$pacoteService: IPacoteService
16+
) {
17+
super($childProcess, $fs, $hostInfo, $pacoteService, 'pnpm');
18+
}
19+
20+
@exported("pnpm")
21+
public async install(packageName: string, pathToSave: string, config: INodePackageManagerInstallOptions): Promise<INpmInstallResultInfo> {
22+
if (config.disableNpmInstall) {
23+
return;
24+
}
25+
if (config.ignoreScripts) {
26+
config['ignore-scripts'] = true;
27+
}
28+
29+
const packageJsonPath = path.join(pathToSave, 'package.json');
30+
const jsonContentBefore = this.$fs.readJson(packageJsonPath);
31+
32+
const flags = this.getFlagsString(config, true);
33+
// With pnpm we need to install as "flat" or some imports wont be found
34+
let params = ['i', '--shamefully-hoist'];
35+
const isInstallingAllDependencies = packageName === pathToSave;
36+
if (!isInstallingAllDependencies) {
37+
params.push(packageName);
38+
}
39+
40+
params = params.concat(flags);
41+
const cwd = pathToSave;
42+
43+
try {
44+
const result = await this.processPackageManagerInstall(packageName, params, { cwd, isInstallingAllDependencies });
45+
return result;
46+
} catch (e) {
47+
this.$fs.writeJson(packageJsonPath, jsonContentBefore);
48+
throw e;
49+
}
50+
}
51+
52+
@exported("pnpm")
53+
public uninstall(packageName: string, config?: IDictionary<string | boolean>, cwd?: string): Promise<string> {
54+
// pnpm does not want save option in remove. It saves it by default
55+
delete config['save'];
56+
const flags = this.getFlagsString(config, false);
57+
return this.$childProcess.exec(`pnpm remove ${packageName} ${flags}`, { cwd });
58+
}
59+
60+
@exported("pnpm")
61+
public async view(packageName: string, config: Object): Promise<any> {
62+
const wrappedConfig = _.extend({}, config, { json: true });
63+
64+
const flags = this.getFlagsString(wrappedConfig, false);
65+
let viewResult: any;
66+
try {
67+
viewResult = await this.$childProcess.exec(`pnpm info ${packageName} ${flags}`);
68+
} catch (e) {
69+
this.$errors.fail(e.message);
70+
}
71+
const result = JSON.parse(viewResult);
72+
return result;
73+
}
74+
75+
@exported("pnpm")
76+
public search(filter: string[], config: IDictionary<string | boolean>): Promise<string> {
77+
const flags = this.getFlagsString(config, false);
78+
return this.$childProcess.exec(`pnpm search ${filter.join(" ")} ${flags}`);
79+
}
80+
81+
public async searchNpms(keyword: string): Promise<INpmsResult> {
82+
const httpRequestResult = await this.$httpClient.httpRequest(`https://api.npms.io/v2/search?q=keywords:${keyword}`);
83+
const result: INpmsResult = JSON.parse(httpRequestResult.body);
84+
return result;
85+
}
86+
87+
@exported("pnpm")
88+
public async getRegistryPackageData(packageName: string): Promise<any> {
89+
const registry = await this.$childProcess.exec(`pnpm config get registry`);
90+
const url = `${registry.trim()}/${packageName}`;
91+
this.$logger.trace(`Trying to get data from pnpm registry for package ${packageName}, url is: ${url}`);
92+
const responseData = (await this.$httpClient.httpRequest(url)).body;
93+
this.$logger.trace(`Successfully received data from pnpm registry for package ${packageName}. Response data is: ${responseData}`);
94+
const jsonData = JSON.parse(responseData);
95+
this.$logger.trace(`Successfully parsed data from pnpm registry for package ${packageName}.`);
96+
return jsonData;
97+
}
98+
99+
@exported("pnpm")
100+
public async getCachePath(): Promise<string> {
101+
const cachePath = await this.$childProcess.exec(`pnpm config get cache`);
102+
return path.join(cachePath.trim(), CACACHE_DIRECTORY_NAME);
103+
}
104+
}
105+
106+
$injector.register("pnpm", PnpmPackageManager);

test/package-installation-manager.ts

+2
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ import * as HostInfoLib from "../lib/common/host-info";
66
import * as LoggerLib from "../lib/common/logger/logger";
77
import * as NpmLib from "../lib/node-package-manager";
88
import * as YarnLib from "../lib/yarn-package-manager";
9+
import * as PnpmLib from "../lib/pnpm-package-manager";
910
import * as PackageManagerLib from "../lib/package-manager";
1011
import * as PackageInstallationManagerLib from "../lib/package-installation-manager";
1112
import * as OptionsLib from "../lib/options";
@@ -43,6 +44,7 @@ function createTestInjector(): IInjector {
4344
});
4445
testInjector.register("npm", NpmLib.NodePackageManager);
4546
testInjector.register("yarn", YarnLib.YarnPackageManager);
47+
testInjector.register("pnpm", PnpmLib.PnpmPackageManager);
4648
testInjector.register("packageManager", PackageManagerLib.PackageManager);
4749
testInjector.register("packageInstallationManager", PackageInstallationManagerLib.PackageInstallationManager);
4850

test/plugins-service.ts

+2
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ import { PackageManager } from "../lib/package-manager";
44
import { PackageInstallationManager } from "../lib/package-installation-manager";
55
import { NodePackageManager } from "../lib/node-package-manager";
66
import { YarnPackageManager } from "../lib/yarn-package-manager";
7+
import { PnpmPackageManager } from "../lib/pnpm-package-manager";
78
import { FileSystem } from "../lib/common/file-system";
89
import { ProjectData } from "../lib/project-data";
910
import { ChildProcess } from "../lib/common/child-process";
@@ -58,6 +59,7 @@ function createTestInjector() {
5859
testInjector.register("packageManager", PackageManager);
5960
testInjector.register("npm", NodePackageManager);
6061
testInjector.register("yarn", YarnPackageManager);
62+
testInjector.register("pnpm", PnpmPackageManager);
6163
testInjector.register("fs", FileSystem);
6264
testInjector.register("adb", {});
6365
testInjector.register("androidDebugBridgeResultHandler", {});

test/services/extensibility-service.ts

+2
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ import { assert } from "chai";
55
import { NodePackageManager } from "../../lib/node-package-manager";
66
import { PackageManager } from "../../lib/package-manager";
77
import { YarnPackageManager } from "../../lib/yarn-package-manager";
8+
import { PnpmPackageManager } from "../../lib/pnpm-package-manager";
89
import * as constants from "../../lib/constants";
910
import { ChildProcess } from "../../lib/common/child-process";
1011
import { CommandsDelimiters } from "../../lib/common/constants";
@@ -58,6 +59,7 @@ describe("extensibilityService", () => {
5859
});
5960
testInjector.register("npm", NodePackageManager);
6061
testInjector.register("yarn", YarnPackageManager);
62+
testInjector.register("pnpm", PnpmPackageManager);
6163
testInjector.register("settingsService", SettingsService);
6264
testInjector.register("requireService", {
6365
require: (pathToRequire: string): any => undefined

0 commit comments

Comments
 (0)