Skip to content
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
10 changes: 4 additions & 6 deletions packages/pnpm-sync-lib/etc/pnpm-sync-lib.api.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,19 +4,17 @@

```ts

import { Lockfile } from '@pnpm/lockfile-types-pnpm-lock-v6';
import { LockfileObject } from '@pnpm/lockfile.types-pnpm-lock-v9';

// @beta (undocumented)
export interface IDependencyMeta {
// (undocumented)
injected?: boolean;
}

// @beta
export interface ILockfile {
// (undocumented)
importers: Record<string, ILockfileImporter>;
lockfileVersion: number | string;
packages: Record<string, ILockfilePackage>;
}
export type ILockfile = Lockfile | LockfileObject;

// @beta
export interface ILockfileImporter {
Expand Down
9 changes: 6 additions & 3 deletions packages/pnpm-sync-lib/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "pnpm-sync-lib",
"version": "0.3.2",
"version": "0.3.3",
"description": "API library for integrating \"pnpm-sync\" with your toolchain",
"repository": {
"type": "git",
Expand All @@ -17,8 +17,11 @@
"test": "heft test --clean"
},
"dependencies": {
"@pnpm/dependency-path-2": "npm:@pnpm/dependency-path@^2.1.8",
"@pnpm/dependency-path-5": "npm:@pnpm/dependency-path@^5.1.7",
"@pnpm/dependency-path-pnpm-v10": "npm:@pnpm/dependency-path@^1000.0.9",
"@pnpm/dependency-path-pnpm-v8": "npm:@pnpm/dependency-path@^2.1.8",
"@pnpm/dependency-path-pnpm-v9": "npm:@pnpm/dependency-path@^5.1.7",
"@pnpm/lockfile-types-pnpm-lock-v6": "npm:@pnpm/lockfile-types@^5.1.5",
"@pnpm/lockfile.types-pnpm-lock-v9": "npm:@pnpm/lockfile.types@^1001.0.8",
"yaml": "2.4.1"
},
"devDependencies": {
Expand Down
21 changes: 4 additions & 17 deletions packages/pnpm-sync-lib/src/interfaces.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,6 @@
import { Lockfile as LockfileObjectV6 } from '@pnpm/lockfile-types-pnpm-lock-v6';
import { LockfileObject as LockfileObjectV9 } from '@pnpm/lockfile.types-pnpm-lock-v9';

export interface IPnpmSyncCliArgs {
prepare: boolean;
lockfile: string;
Expand Down Expand Up @@ -172,20 +175,4 @@ export interface ILockfilePackage {
*
* @beta
*/
export interface ILockfile {
/**
* The version of the `pnpm-lock.yaml` file format.
*
* Example: `6.0`
*/
lockfileVersion: number | string;
importers: Record<string, ILockfileImporter>;
/**
* The `packages` section stores the installation plan for external (non-workspace)
* packages. The key is a `node_modules/.pnpm` version path, which in lockfile version 6
* encodes the installed package name, package version, and any peer dependency qualifiers.
*
* Example key: `/[email protected]([email protected])`
*/
packages: Record<string, ILockfilePackage>;
}
export type ILockfile = LockfileObjectV6 | LockfileObjectV9;
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@octogonz Because we changed to use the official lockfile type provided by pnpm, this change might be a breaking change to the return value type of the readPnpmLockfile function. P.S. However, I'm not quite sure why we previously defined our own pnpmlock file type instead of using the official one.

38 changes: 26 additions & 12 deletions packages/pnpm-sync-lib/src/pnpmSyncPrepare.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,11 @@ import path from 'path';
import fs from 'fs';
import YAML from 'yaml';
import process from 'node:process';
import { depPathToFilename as depPathToFilename2 } from '@pnpm/dependency-path-2';
import { depPathToFilename as depPathToFilename5 } from '@pnpm/dependency-path-5';
import { depPathToFilename as depPathToFilenameV8 } from '@pnpm/dependency-path-pnpm-v8';
import { depPathToFilename as depPathToFilenameV9 } from '@pnpm/dependency-path-pnpm-v9';
import { depPathToFilename as depPathToFilenameV10 } from '@pnpm/dependency-path-pnpm-v10';
import { ProjectSnapshot as ProjectSnapshotV6 } from '@pnpm/lockfile-types-pnpm-lock-v6';
import { ProjectSnapshot as ProjectSnapshotV9 } from '@pnpm/lockfile.types-pnpm-lock-v9';

import {
ILockfile,
Expand All @@ -14,7 +17,7 @@ import {
IVersionSpecifier,
ITargetFolder
} from './interfaces';
import { pnpmSyncGetJsonVersion } from './utilities';
import { isPnpmV10, isPnpmV8, isPnpmV9, pnpmSyncGetJsonVersion } from './utilities';

/**
* @beta
Expand Down Expand Up @@ -58,6 +61,8 @@ export interface IPnpmSyncPrepareOptions extends IPnpmSyncUpdateFileBaseOptions
/**
* Environment-provided API to avoid an NPM dependency.
* The "pnpm-sync" NPM package provides a reference implementation.
*
* @remarks Use `@pnpm/lockfile-file` for pnpm-lock v6 and `@pnpm/lockfile.fs` for pnpm-lock v9
*/
readPnpmLockfile: (
lockfilePath: string,
Expand Down Expand Up @@ -219,10 +224,9 @@ export async function pnpmSyncPrepareAsync(options: IPnpmSyncPrepareOptions): Pr
const pnpmModulesYaml = YAML.parse(fs.readFileSync(`${pnpmModulesYamlPath}/.modules.yaml`, 'utf8'));
const pnpmVersion: string | undefined = pnpmModulesYaml?.packageManager?.split('@')[1];

// currently, only support pnpm v8 and v9
if (!pnpmVersion || !(pnpmVersion.startsWith('8') || pnpmVersion.startsWith('9'))) {
if (!pnpmVersion || !(isPnpmV8(pnpmVersion) || isPnpmV9(pnpmVersion) || isPnpmV10(pnpmVersion))) {
logMessageCallback({
message: `The pnpm version is not supported; pnpm-sync requires pnpm version 8.x, 9.x`,
message: `The pnpm version is not supported; pnpm-sync requires pnpm version 8.x, 9.x, 10.x`,
messageKind: LogMessageKind.ERROR,
details: {
messageIdentifier: LogMessageIdentifier.PREPARE_ERROR_UNSUPPORTED_PNPM_VERSION,
Expand Down Expand Up @@ -287,11 +291,18 @@ export async function pnpmSyncPrepareAsync(options: IPnpmSyncPrepareOptions): Pr
}

const packageDirname = (() => {
if (pnpmVersion.startsWith('8')) {
return depPathToFilename2(injectedDependencyVersion);
if (isPnpmV8(pnpmVersion)) {
return depPathToFilenameV8(injectedDependencyVersion);
}
if (isPnpmV9(pnpmVersion)) {
return depPathToFilenameV9(injectedDependency + '@' + injectedDependencyVersion, 120);
}
if (pnpmVersion.startsWith('9')) {
return depPathToFilename5(injectedDependency + '@' + injectedDependencyVersion, 120);
if (isPnpmV10(pnpmVersion)) {
return depPathToFilenameV10(
injectedDependency + '@' + injectedDependencyVersion,
// for v10 default is 120 on Linux/MacOS and 60 on Windows https://pnpm.io/next/settings#virtualstoredirmaxlength
process.platform === 'win32' ? 60 : 120
);
}
return '';
})();
Expand Down Expand Up @@ -398,13 +409,16 @@ function processTransitiveInjectedDependency(
}
}

const { packages: lockfilePackages } = pnpmLockfile;
const { packages: lockfilePackages = {} } = pnpmLockfile;

while (potentialTransitiveInjectedDependencyVersionQueue.length > 0) {
const transitiveInjectedDependencyVersion: string | undefined =
potentialTransitiveInjectedDependencyVersionQueue.shift();
if (transitiveInjectedDependencyVersion) {
const { dependencies, optionalDependencies } = lockfilePackages[transitiveInjectedDependencyVersion];
// ProjectSnapshots type in pnpm-lock v9 use a branded type as record key, so we need to cast it to Record<string, ProjectSnapshotV6 | ProjectSnapshotV9>
const { dependencies, optionalDependencies } = (
lockfilePackages as unknown as Record<string, ProjectSnapshotV6 | ProjectSnapshotV9>
)[transitiveInjectedDependencyVersion];
processInjectedDependencies(
dependencies,
injectedDependencyToVersion,
Expand Down
6 changes: 6 additions & 0 deletions packages/pnpm-sync-lib/src/utilities.ts
Original file line number Diff line number Diff line change
Expand Up @@ -37,3 +37,9 @@ async function getFilesInDirectoryHelper(directory: string, returnFileList: ISyn
});
}
}

export const isPnpmV8 = (pnpmVersion: string): boolean => pnpmVersion.startsWith('8.');
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@octogonz I extracted the logic for checking pnpm version into three utility functions.


export const isPnpmV9 = (pnpmVersion: string): boolean => pnpmVersion.startsWith('9.');

export const isPnpmV10 = (pnpmVersion: string): boolean => pnpmVersion.startsWith('10.');
21 changes: 11 additions & 10 deletions packages/pnpm-sync/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "pnpm-sync",
"version": "0.3.2",
"version": "0.3.3",
"description": "Recopy injected dependencies whenever a project is rebuilt in your PNPM workspace",
"keywords": [
"rush",
Expand All @@ -27,17 +27,18 @@
"directory": "packages/pnpm-sync"
},
"license": "MIT",
"bin": {
"pnpm-sync": "bin/pnpm-sync.js"
},
"scripts": {
"build": "heft build --clean",
"test": "heft test --clean",
"lint": "eslint src/**",
"prepublishOnly": "heft build --clean"
},
"bin": {
"pnpm-sync": "bin/pnpm-sync.js"
"prepublishOnly": "heft build --clean",
"test": "heft test --clean"
},
"dependencies": {
"@pnpm/lockfile-file": "~8.1.4",
"@pnpm/lockfile-file-pnpm-lock-v6": "npm:@pnpm/lockfile-file@~8.1.4",
"@pnpm/lockfile.fs-pnpm-lock-v9": "npm:@pnpm/lockfile.fs@^1001.1.11",
"@pnpm/logger": "~5.0.0",
"@rushstack/node-core-library": "^3.61.0",
"@rushstack/package-extractor": "^0.6.12",
Expand All @@ -46,12 +47,12 @@
},
"devDependencies": {
"@rushstack/eslint-config": "^3.6.2",
"@rushstack/heft": "^0.64.3",
"@rushstack/eslint-patch": "^1.7.2",
"@rushstack/heft": "^0.64.3",
"@rushstack/heft-node-rig": "^2.4.5",
"@types/heft-jest": "1.0.6",
"@types/node": "18.17.15",
"typescript": "~5.3.3",
"eslint": "~8.7.0"
"eslint": "~8.7.0",
"typescript": "~5.3.3"
}
}
36 changes: 14 additions & 22 deletions packages/pnpm-sync/src/start.ts
Original file line number Diff line number Diff line change
@@ -1,14 +1,9 @@
import { Command } from 'commander';
import {
type ILockfile,
type ILockfilePackage,
pnpmSyncCopyAsync,
pnpmSyncPrepareAsync,
type ILogMessageCallbackOptions
} from 'pnpm-sync-lib';
import { pnpmSyncCopyAsync, pnpmSyncPrepareAsync, type ILogMessageCallbackOptions } from 'pnpm-sync-lib';
import { FileSystem, Async } from '@rushstack/node-core-library';
import { PackageExtractor } from '@rushstack/package-extractor';
import { readWantedLockfile, Lockfile } from '@pnpm/lockfile-file';
import { readWantedLockfile as readWantedLockfileV6 } from '@pnpm/lockfile-file-pnpm-lock-v6';
import { readWantedLockfile as readWantedLockfileV9 } from '@pnpm/lockfile.fs-pnpm-lock-v9';

const program: Command = new Command();

Expand Down Expand Up @@ -83,22 +78,19 @@ program
) => {
const pnpmLockFolder = lockfilePath.slice(0, lockfilePath.length - 'pnpm-lock.yaml'.length);

const lockfile: Lockfile | null = await readWantedLockfile(pnpmLockFolder, options);
const lockfileV6 = await readWantedLockfileV6(pnpmLockFolder, options);

if (lockfile === null) {
return undefined;
} else {
const lockfilePackages: Record<string, ILockfilePackage> = lockfile.packages as Record<
string,
ILockfilePackage
>;
const result: ILockfile = {
lockfileVersion: lockfile.lockfileVersion,
importers: lockfile.importers,
packages: lockfilePackages
};
return result;
if (lockfileV6?.lockfileVersion.toString().startsWith('6')) {
return lockfileV6;
}

const lockfileV9 = await readWantedLockfileV9(pnpmLockFolder, options);

if (lockfileV9?.lockfileVersion.toString().startsWith('9')) {
return lockfileV9;
}

return undefined;
},
logMessageCallback: logMessage
});
Expand Down
Loading