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

feat(core): add package manager parsers and stringifiers #11953

Merged
merged 17 commits into from
Sep 20, 2022
Merged
Changes from 1 commit
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
Prev Previous commit
Next Next commit
feat(core): add writer for the pnpm package manager
meeroslav committed Sep 19, 2022
commit aba37c3bf605ccea856fcaf81eb859d6d7abc761
2 changes: 2 additions & 0 deletions .prettierignore
Original file line number Diff line number Diff line change
@@ -21,3 +21,5 @@ packages/**/generators/**/files/**/*.html
/.yarn
/.verdaccio/build/local-registry
/dist

/scripts/lockfile-test/*.*
1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
@@ -295,6 +295,7 @@
"@tailwindcss/typography": "^0.5.0",
"@yarnpkg/lockfile": "^1.1.0",
"@yarnpkg/parsers": "^3.0.0-rc.18",
"@zkochan/js-yaml": "0.0.6",
"axios": "0.21.1",
"classnames": "^2.3.1",
"cliui": "^7.0.2",
2 changes: 1 addition & 1 deletion packages/nx/package.json
Original file line number Diff line number Diff line change
@@ -33,9 +33,9 @@
"homepage": "https://nx.dev",
"dependencies": {
"@parcel/watcher": "2.0.4",
"@pnpm/lockfile-file": "^5.3.4",
"@yarnpkg/lockfile": "^1.1.0",
"@yarnpkg/parsers": "^3.0.0-rc.18",
"@zkochan/js-yaml": "0.0.6",
"chalk": "4.1.0",
"chokidar": "^3.5.1",
"cli-cursor": "3.1.0",
2 changes: 1 addition & 1 deletion packages/nx/src/utils/lock-file/lock-file-type.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
export interface PackageDependency<T> {
version: string;
version?: string;
packageMeta: T[];
dependencies?: Record<string, string>;
dependenciesMeta?: Record<string, { optional: string }>; // todo: THIS IS FOR YARN 2
17 changes: 11 additions & 6 deletions packages/nx/src/utils/lock-file/lock-file.ts
Original file line number Diff line number Diff line change
@@ -1,10 +1,11 @@
import { readFileSync, writeFileSync } from 'fs-extra';
import { join } from 'path';
import { gte } from 'semver';
import {
detectPackageManager,
getPackageManagerVersion,
PackageManager,
} from '../package-manager';
import { gte } from 'semver';
import {
parseLockFile as parseYarn,
stringifyLockFile as stringifyYarn,
@@ -13,9 +14,11 @@ import {
parseLockFile as parseNpm,
stringifyLockFile as stringifyNpm,
} from './npm';
import { parseLockFile as parsePnpm } from './pnpm';
import {
parseLockFile as parsePnpm,
stringifyLockFile as stringifyPnpm,
} from './pnpm';
import { LockFileData } from './lock-file-type';
import { join } from 'path';

export function parseLockFile(
packageManager: PackageManager = detectPackageManager(),
@@ -48,9 +51,11 @@ export function writeLockFile(
writeFileSync(join(root, 'yarn.lock'), content);
return;
}
// if (packageManager === 'pnpm') {
// return await writePnpm('.', lockFile as PnpmLockFile);
// }
if (packageManager === 'pnpm') {
const content = stringifyPnpm(lockFile);
writeFileSync(join(root, 'pnpm-lock.yaml'), content);
return;
}
if (packageManager === 'npm') {
const content = stringifyNpm(lockFile);
writeFileSync(join(root, 'package-lock.json'), content + '\n');
2 changes: 1 addition & 1 deletion packages/nx/src/utils/lock-file/npm.ts
Original file line number Diff line number Diff line change
@@ -44,7 +44,7 @@ export type NpmLockFile = {
* @param lockFile
* @returns
*/
export function parseLockFile(lockFile: string): LockFileData {
export function parseLockFile(lockFile: string): LockFileData<PackageMeta> {
const { packages, dependencies, ...metadata } = JSON.parse(
lockFile
) as NpmLockFile;
134 changes: 124 additions & 10 deletions packages/nx/src/utils/lock-file/pnpm.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,18 @@
import { LockFileData, PackageDependency } from './lock-file-type';
import { load } from 'js-yaml';
import { load, dump } from '@zkochan/js-yaml';

type Dependencies = Record<string, PackageDependency<string>>;
type PackageMeta = {
key: string;
specifier?: string;
isDevDependency?: boolean;
isDependency?: boolean;
dependencyDetails: Record<string, Record<string, string>>;
};

type Dependencies = Record<
string,
Omit<PackageDependency<string>, 'packageMeta'>
>;

export type PnpmLockFile = {
lockfileVersion: number;
@@ -34,25 +45,128 @@ export type PnpmLockFile = {
* @param lockFile
* @returns
*/
export function parseLockFile(lockFile: string): LockFileData {
export function parseLockFile(lockFile: string): LockFileData<PackageMeta> {
const { dependencies, devDependencies, packages, specifiers, ...metadata } =
load(lockFile) as PnpmLockFile;
return {
dependencies: mapPackages(packages),
dependencies: mapPackages(
dependencies,
devDependencies,
specifiers,
packages
),
lockFileMetadata: { ...metadata },
};
}

function mapPackages(packages: Dependencies): Dependencies {
const mappedPackages: Dependencies = {};
const LOCKFILE_YAML_FORMAT = {
blankLines: true,
lineWidth: 1000,
noCompatMode: true,
noRefs: true,
sortKeys: false,
};

/**
* Generates pnpm-lock.yml file from `LockFileData` object
*
* @param lockFile
* @returns
*/
export function stringifyLockFile(
lockFileData: LockFileData<PackageMeta>
): string {
const specifiers: Record<string, string> = {};
const devDependencies: Record<string, string> = {};
const dependencies: Record<string, string> = {};
const packages: Dependencies = {};
Object.entries(lockFileData.dependencies).forEach(
([dependencyKey, { packageMeta, resolution, engines }]) => {
const packageName = dependencyKey.slice(
0,
dependencyKey.lastIndexOf('@')
);
packageMeta.forEach(
({
key,
specifier,
isDependency,
isDevDependency,
dependencyDetails,
}) => {
const metaVersion = key.slice(key.lastIndexOf('/') + 1);
if (isDependency) {
dependencies[packageName] = metaVersion;
}
if (isDevDependency) {
devDependencies[packageName] = metaVersion;
}
if (specifier) {
specifiers[packageName] = specifier;
}
packages[key] = {
resolution,
engines,
...dependencyDetails,
};
}
);
}
);

return dump(
{
...lockFileData.lockFileMetadata,
specifiers: sortObject(specifiers),
...(dependencies && { dependencies: sortObject(dependencies) }),
...(devDependencies && { devDependencies: sortObject(devDependencies) }),
packages: sortObject(packages),
},
LOCKFILE_YAML_FORMAT
);
}

function mapPackages(
dependencies: Record<string, string>,
devDependencies: Record<string, string>,
specifiers: Record<string, string>,
packages: Dependencies
): LockFileData<PackageMeta>['dependencies'] {
const mappedPackages: LockFileData<PackageMeta>['dependencies'] = {};
Object.entries(packages).forEach(([key, value]) => {
const packageName = key.slice(1, key.lastIndexOf('/'));
const version = key.slice(key.lastIndexOf('/') + 1).split('_')[0];
mappedPackages[`${packageName}@${version}`] = {
...value,
const matchingVersion = key.slice(key.lastIndexOf('/') + 1);
const version = matchingVersion.split('_')[0];
const isDependency = dependencies[packageName] === matchingVersion;
const isDevDependency = devDependencies[packageName] === matchingVersion;
const { resolution, engines, ...rest } = value;
const meta = {
key,
isDependency,
isDevDependency,
dependencyDetails: rest,
specifier:
isDependency || isDevDependency ? specifiers[packageName] : undefined,
};
mappedPackages[`${packageName}@${version}`] = mappedPackages[
`${packageName}@${version}`
] || {
resolution,
engines,
version,
requestedKey: [key],
packageMeta: [],
};
mappedPackages[`${packageName}@${version}`].packageMeta.push(meta);
});
return mappedPackages;
}

function sortObject<T = string>(obj: Record<string, T>) {
const result: Record<string, T> = {};
Object.keys(obj)
.sort()
.forEach((key) => {
result[key] = obj[key];
});
return result;
}
2 changes: 1 addition & 1 deletion packages/nx/src/utils/lock-file/yarn.ts
Original file line number Diff line number Diff line change
@@ -78,7 +78,7 @@ export function parseLockFile(lockFile: string): LockFileData {
}

/**
* Generates package-lock.json file from `LockFileData` object
* Generates yarn.lock file from `LockFileData` object
*
* @param lockFile
* @returns
4 changes: 2 additions & 2 deletions scripts/lockfile-test/pmtest.ts
Original file line number Diff line number Diff line change
@@ -3,11 +3,11 @@ import {
writeLockFile,
} from '../../packages/nx/src/utils/lock-file/lock-file';

const pm = 'yarn';
const pm = 'pnpm';

const value = parseLockFile(pm, 'scripts/lockfile-test');

// console.log(value.dependencies['[email protected].1']);
// console.log(value.dependencies['[email protected].1']);
// // console.log(value['importers']);
// console.log(value['lockfileVersion']);
// console.log(value['overrides']);
Loading