Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Will/lockfile pnpm8 support #4305

Merged
merged 6 commits into from
Sep 14, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion apps/lockfile-explorer-web/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
"license": "MIT",
"scripts": {
"build": "heft test --clean",
"start": "heft build-watch",
"start": "heft start",
"test": "heft test",
"_phase:build": "heft run --only build -- --clean",
"_phase:test": "heft run --only test -- --clean"
Expand Down
93 changes: 76 additions & 17 deletions apps/lockfile-explorer-web/src/parsing/readLockfile.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,11 @@ import { Path } from '@lifaon/path';

const serviceUrl: string = window.appContext.serviceUrl;

export enum PnpmLockfileVersion {
V6,
V5
}

export interface IPackageJsonType {
name: string;
dependencies: {
Expand All @@ -16,22 +21,36 @@ export interface IPackageJsonType {
[key in string]: string;
};
}

export interface ILockfilePackageType {
lockfileVersion: number;
importers?: {
export interface ILockfileImporterV6 {
dependencies?: {
[key in string]: {
specifiers?: {
[key in string]: string;
};
dependencies?: {
[key in string]: string;
};
devDependencies?: {
[key in string]: string;
};
specifier: string;
version: string;
};
};
devDependencies?: {
[key in string]: {
specifier: string;
version: string;
};
};
}
export interface ILockfileImporterV5 {
specifiers?: {
[key in string]: string;
};
dependencies?: {
[key in string]: string;
};
devDependencies?: {
[key in string]: string;
};
}
export interface ILockfilePackageType {
lockfileVersion: number | string;
importers?: {
[key in string]: ILockfileImporterV5 | ILockfileImporterV6;
};
packages?: {
[key in string]: {
resolution: {
Expand All @@ -48,13 +67,48 @@ export interface ILockfilePackageType {
};
}

/**
* Transform any newer lockfile formats to the following format:
* [packageName]:
* specifier: ...
* version: ...
*/
function getImporterValue(
importerValue: ILockfileImporterV5 | ILockfileImporterV6,
pnpmLockfileVersion: PnpmLockfileVersion
): ILockfileImporterV5 {
if (pnpmLockfileVersion === PnpmLockfileVersion.V6) {
const v6ImporterValue = importerValue as ILockfileImporterV6;
const v5ImporterValue: ILockfileImporterV5 = {
specifiers: {},
dependencies: {},
devDependencies: {}
};
for (const [depName, depDetails] of Object.entries(v6ImporterValue.dependencies || {})) {
v5ImporterValue.specifiers![depName] = depDetails.specifier;
v5ImporterValue.dependencies![depName] = depDetails.version;
}
for (const [depName, depDetails] of Object.entries(v6ImporterValue.devDependencies || {})) {
v5ImporterValue.specifiers![depName] = depDetails.specifier;
v5ImporterValue.devDependencies![depName] = depDetails.version;
}
return v5ImporterValue;
} else {
return importerValue as ILockfileImporterV5;
}
}

/**
* Parse through the lockfile and create all the corresponding LockfileEntries and LockfileDependencies
* to construct the lockfile graph.
*
* @returns A list of all the LockfileEntries in the lockfile.
*/
export function generateLockfileGraph(lockfile: ILockfilePackageType): LockfileEntry[] {
let pnpmLockfileVersion: PnpmLockfileVersion = PnpmLockfileVersion.V5;
if (`${lockfile.lockfileVersion}`.startsWith('6')) {
pnpmLockfileVersion = PnpmLockfileVersion.V6;
}
const allEntries: LockfileEntry[] = [];
const allEntriesById: { [key in string]: LockfileEntry } = {};

Expand All @@ -81,7 +135,7 @@ export function generateLockfileGraph(lockfile: ILockfilePackageType): LockfileE
// entryId: normalizedPath,
rawEntryId: importerKey,
kind: LockfileEntryFilter.Project,
rawYamlData: importerValue,
rawYamlData: getImporterValue(importerValue, pnpmLockfileVersion),
duplicates
});
allImporters.push(importer);
Expand All @@ -95,16 +149,21 @@ export function generateLockfileGraph(lockfile: ILockfilePackageType): LockfileE
for (const [dependencyKey, dependencyValue] of Object.entries(lockfile.packages)) {
// const normalizedPath = new Path(dependencyKey).makeAbsolute('/').toString();

let packageDepKey = dependencyKey;
if (pnpmLockfileVersion === PnpmLockfileVersion.V6) {
packageDepKey = dependencyKey.replace('@', '/');
}

const currEntry = new LockfileEntry({
// entryId: normalizedPath,
rawEntryId: dependencyKey,
rawEntryId: packageDepKey,
kind: LockfileEntryFilter.Package,
rawYamlData: dependencyValue
});

allPackages.push(currEntry);
allEntries.push(currEntry);
allEntriesById[dependencyKey] = currEntry;
allEntriesById[packageDepKey] = currEntry;
}
}

Expand All @@ -123,7 +182,7 @@ export function generateLockfileGraph(lockfile: ILockfilePackageType): LockfileE
matchedEntry.referrers.push(entry);
} else {
// Local package
console.error('Could not resolve dependency entryId: ', dependency.entryId);
console.error('Could not resolve dependency entryId: ', dependency.entryId, dependency);
}
}
}
Expand Down
Empty file modified apps/lockfile-explorer/bin/lockfile-explorer
100644 → 100755
Empty file.
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
{
"changes": [
{
"packageName": "@rushstack/lockfile-explorer",
"comment": "Add support for the V6 lockfile used by PNPM 8.",
"type": "minor"
}
],
"packageName": "@rushstack/lockfile-explorer"
}