Skip to content

Commit

Permalink
Add support for "@yarnpkg/fslib" and "@yarnpkg/libzip", and implement…
Browse files Browse the repository at this point in the history
… "getPackageVersion" method in all package managers
  • Loading branch information
valentinpalkovic committed May 19, 2023
1 parent 50ad585 commit e954f4b
Show file tree
Hide file tree
Showing 7 changed files with 181 additions and 1 deletion.
2 changes: 2 additions & 0 deletions code/lib/cli/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,8 @@
"@storybook/telemetry": "7.1.0-alpha.19",
"@storybook/types": "7.1.0-alpha.19",
"@types/semver": "^7.3.4",
"@yarnpkg/fslib": "^2.10.3",
"@yarnpkg/libzip": "^2.3.0",
"boxen": "^5.1.2",
"chalk": "^4.1.0",
"commander": "^6.2.1",
Expand Down
5 changes: 5 additions & 0 deletions code/lib/cli/src/js-package-manager/JsPackageManager.ts
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,11 @@ export abstract class JsPackageManager {

public readonly cwd?: string;

public abstract getPackageVersion(
packageName: string,
basePath?: string
): Promise<string | undefined>;

// NOTE: for some reason yarn prefers the npm registry in
// local development, so always use npm
async setRegistryURL(url: string) {
Expand Down
20 changes: 20 additions & 0 deletions code/lib/cli/src/js-package-manager/NPMProxy.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,9 @@
import sort from 'semver/functions/sort';
import { platform } from 'os';
import dedent from 'ts-dedent';
import { sync as findUpSync } from 'find-up';
import { existsSync, readFileSync } from 'fs';
import path from 'path';
import { JsPackageManager } from './JsPackageManager';
import type { PackageJson } from './PackageJson';
import type { InstallationMetadata, PackageMetadata } from './types';
Expand Down Expand Up @@ -77,6 +80,23 @@ export class NPMProxy extends JsPackageManager {
return this.executeCommand({ command: 'npm', args: ['--version'] });
}

public async getPackageVersion(packageName: string, basePath = process.cwd()): Promise<string> {
const packageJsonPath = await findUpSync(
(dir) => {
const possiblePath = path.join(dir, 'node_modules', packageName, 'package.json');
return existsSync(possiblePath) ? possiblePath : undefined;
},
{ cwd: basePath }
);

if (!packageJsonPath) {
return null;
}

const packageJson = JSON.parse(readFileSync(packageJsonPath, 'utf-8')) as Record<string, any>;
return packageJson.version;
}

getInstallArgs(): string[] {
if (!this.installArgs) {
this.installArgs = [];
Expand Down
46 changes: 46 additions & 0 deletions code/lib/cli/src/js-package-manager/PNPMProxy.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,8 @@
import { pathExistsSync } from 'fs-extra';
import dedent from 'ts-dedent';
import { sync as findUpSync } from 'find-up';
import path from 'path';
import fs from 'fs';
import { JsPackageManager } from './JsPackageManager';
import type { PackageJson } from './PackageJson';
import type { InstallationMetadata, PackageMetadata } from './types';
Expand Down Expand Up @@ -107,6 +110,49 @@ export class PNPMProxy extends JsPackageManager {
}
}

async getPackageVersion(packageName: string, basePath = process.cwd()): Promise<string | null> {
const pnpapiPath = findUpSync(['.pnp.js', '.pnp.cjs'], { cwd: basePath });

if (pnpapiPath) {
try {
// eslint-disable-next-line import/no-dynamic-require, global-require
const pnpApi = require(pnpapiPath);

const resolvedPath = await pnpApi.resolveToUnqualified(packageName, basePath, {
considerBuiltins: false,
});

const pkgLocator = pnpApi.findPackageLocator(resolvedPath);
const pkg = pnpApi.getPackageInformation(pkgLocator);

const packageJSON = fs.readFileSync(
path.join(pkg.packageLocation, 'package.json'),
'utf-8'
);

return JSON.parse(packageJSON).version;
} catch (error) {
console.error('Error while fetching package version in Yarn PnP mode:', error);
}
}

const packageJsonPath = await findUpSync(
(dir) => {
const possiblePath = path.join(dir, 'node_modules', packageName, 'package.json');
return fs.existsSync(possiblePath) ? possiblePath : undefined;
},
{ cwd: basePath }
);

if (!packageJsonPath) {
return null;
}

const packageJson = JSON.parse(fs.readFileSync(packageJsonPath, 'utf-8'));

return packageJson.version;
}

protected getResolutions(packageJson: PackageJson, versions: Record<string, string>) {
return {
overrides: {
Expand Down
20 changes: 20 additions & 0 deletions code/lib/cli/src/js-package-manager/Yarn1Proxy.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,7 @@
import dedent from 'ts-dedent';
import { sync as findUpSync } from 'find-up';
import { existsSync, readFileSync } from 'fs';
import path from 'path';
import { createLogStream } from '../utils';
import { JsPackageManager } from './JsPackageManager';
import type { PackageJson } from './PackageJson';
Expand Down Expand Up @@ -59,6 +62,23 @@ export class Yarn1Proxy extends JsPackageManager {
return this.executeCommand({ command: `yarn`, args: [command, ...args], cwd });
}

public async getPackageVersion(packageName: string, basePath = process.cwd()): Promise<string> {
const packageJsonPath = await findUpSync(
(dir) => {
const possiblePath = path.join(dir, 'node_modules', packageName, 'package.json');
return existsSync(possiblePath) ? possiblePath : undefined;
},
{ cwd: basePath }
);

if (!packageJsonPath) {
return null;
}

const packageJson = JSON.parse(readFileSync(packageJsonPath, 'utf-8')) as Record<string, any>;
return packageJson.version;
}

public async findInstallations(pattern: string[]) {
const commandResult = await this.executeCommand({
command: 'yarn',
Expand Down
58 changes: 58 additions & 0 deletions code/lib/cli/src/js-package-manager/Yarn2Proxy.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,9 @@
import dedent from 'ts-dedent';
import { sync as findUpSync, sync as syncFindUp } from 'find-up';
import fs, { existsSync, readFileSync } from 'fs';
import path from 'path';
import { NodeFS, VirtualFS, ZipOpenFS } from '@yarnpkg/fslib';
import { getLibzipSync } from '@yarnpkg/libzip';
import { createLogStream } from '../utils';
import { JsPackageManager } from './JsPackageManager';
import type { PackageJson } from './PackageJson';
Expand Down Expand Up @@ -117,6 +122,59 @@ export class Yarn2Proxy extends JsPackageManager {
}
}

async getPackageVersion(packageName: string, basePath = process.cwd()): Promise<string | null> {
const pnpapiPath = findUpSync(['.pnp.js', '.pnp.cjs'], { cwd: basePath });

if (pnpapiPath) {
try {
// eslint-disable-next-line import/no-dynamic-require, global-require
const pnpApi = require(pnpapiPath);

const resolvedPath = await pnpApi.resolveToUnqualified(packageName, basePath, {
considerBuiltins: false,
});

const pkgLocator = pnpApi.findPackageLocator(resolvedPath);
const pkg = pnpApi.getPackageInformation(pkgLocator);

const localFs: typeof fs = { ...fs };
const nodeFs = new NodeFS(localFs);

const zipOpenFs = new ZipOpenFS({
libzip: getLibzipSync(),
baseFs: nodeFs,
readOnlyArchives: true,
});

const virtualFs = new VirtualFS({
baseFs: zipOpenFs,
});

const virtualFile = virtualFs.readJsonSync(
path.join(pkg.packageLocation, 'package.json') as any
);
return virtualFile.version;
} catch (error) {
console.error('Error while fetching package version in Yarn PnP mode:', error);
}
}

const packageJsonPath = await syncFindUp(
(dir) => {
const possiblePath = path.join(dir, 'node_modules', packageName, 'package.json');
return existsSync(possiblePath) ? possiblePath : undefined;
},
{ cwd: basePath }
);

if (!packageJsonPath) {
return null;
}

const packageJson = JSON.parse(readFileSync(packageJsonPath, 'utf-8'));
return packageJson.version;
}

protected getResolutions(packageJson: PackageJson, versions: Record<string, string>) {
return {
resolutions: {
Expand Down
31 changes: 30 additions & 1 deletion code/yarn.lock
Original file line number Diff line number Diff line change
Expand Up @@ -5726,6 +5726,8 @@ __metadata:
"@types/semver": ^7.3.4
"@types/shelljs": ^0.8.7
"@types/util-deprecate": ^1.0.0
"@yarnpkg/fslib": ^2.10.3
"@yarnpkg/libzip": ^2.3.0
boxen: ^5.1.2
chalk: ^4.1.0
commander: ^6.2.1
Expand Down Expand Up @@ -7929,6 +7931,13 @@ __metadata:
languageName: node
linkType: hard

"@types/emscripten@npm:^1.39.6":
version: 1.39.6
resolution: "@types/emscripten@npm:1.39.6"
checksum: cb1ea8ccddada1d304bdf11a54daa0d1e87f29cea947eceff54c1e0a752d2cc185eeffdcf52042f24420aa8e1fa9bbfdbab1231fb2531eefcfdc788199fee2de
languageName: node
linkType: hard

"@types/escodegen@npm:^0.0.6":
version: 0.0.6
resolution: "@types/escodegen@npm:0.0.6"
Expand Down Expand Up @@ -9621,6 +9630,26 @@ __metadata:
languageName: node
linkType: hard

"@yarnpkg/fslib@npm:^2.10.3":
version: 2.10.3
resolution: "@yarnpkg/fslib@npm:2.10.3"
dependencies:
"@yarnpkg/libzip": ^2.3.0
tslib: ^1.13.0
checksum: c4fbbed99e801f17c381204e9699d9ea4fb51b14e99968985f477bdbc7b02b61e026860173f3f46bd60d9f46ae6a06f420a3edb3c02c3a45ae83779095928094
languageName: node
linkType: hard

"@yarnpkg/libzip@npm:^2.3.0":
version: 2.3.0
resolution: "@yarnpkg/libzip@npm:2.3.0"
dependencies:
"@types/emscripten": ^1.39.6
tslib: ^1.13.0
checksum: 0c2361ccb002e28463ed98541f3bdaab54f52aad6a2080666c2a9ea605ebd9cdfb7b0340b1db6f105820d05bcb803cdfb3ce755a8f6034657298c291bf884f81
languageName: node
linkType: hard

"@yarnpkg/lockfile@npm:1.1.0, @yarnpkg/lockfile@npm:^1.1.0":
version: 1.1.0
resolution: "@yarnpkg/lockfile@npm:1.1.0"
Expand Down Expand Up @@ -29062,7 +29091,7 @@ __metadata:
languageName: node
linkType: hard

"tslib@npm:^1.10.0, tslib@npm:^1.8.1, tslib@npm:^1.9.0, tslib@npm:^1.9.3":
"tslib@npm:^1.10.0, tslib@npm:^1.13.0, tslib@npm:^1.8.1, tslib@npm:^1.9.0, tslib@npm:^1.9.3":
version: 1.14.1
resolution: "tslib@npm:1.14.1"
checksum: 69ae09c49eea644bc5ebe1bca4fa4cc2c82b7b3e02f43b84bd891504edf66dbc6b2ec0eef31a957042de2269139e4acff911e6d186a258fb14069cd7f6febce2
Expand Down

0 comments on commit e954f4b

Please sign in to comment.