Skip to content

Commit

Permalink
feat(version): support for updating pnpm-lock.yaml, expand on #168
Browse files Browse the repository at this point in the history
- takes PR #168 and adresses all comments provided in the original PR
- fixed npm lockfile that got broken by original PR, I took the same approach as the pnpm lock file update to fix the npm lock file update. Both updates are now very similar and easier to read
- removed `preferred-pm` since I would prefer to not use any extra dependencies, and I think that also fixed the unit tests since they weren't being detected properly
- added a prettier VSCode setting (setup) and also fixed couple of places where prettier wasn't doing a good job
  • Loading branch information
ghiscoding committed May 26, 2022
1 parent cf35dc6 commit ee1a964
Show file tree
Hide file tree
Showing 9 changed files with 154 additions and 370 deletions.
302 changes: 7 additions & 295 deletions package-lock.json

Large diffs are not rendered by default.

5 changes: 3 additions & 2 deletions package.json
Expand Up @@ -5,8 +5,9 @@
"private": true,
"scripts": {
"clean": "rimraf --maxBusyTries=10 packages/*/dist dist",
"prebuild": "run-s clean lint",
"prebuild": "npm run clean",
"build": "npm run build --ws",
"postbuild": "npm run lint",
"lint": "eslint packages --ext .ts",
"dist-info-cmd": "node ./packages/cli/dist/cli.js info",
"dist-init-cmd": "node ./packages/cli/dist/cli.js init --independent --exact --use-workspaces",
Expand Down Expand Up @@ -103,4 +104,4 @@
"./packages/run",
"./packages/cli"
]
}
}
1 change: 0 additions & 1 deletion packages/version/package.json
Expand Up @@ -43,7 +43,6 @@
"p-pipe": "^3.1.0",
"p-reduce": "^2.1.0",
"path": "^0.12.7",
"preferred-pm": "^3.0.3",
"semver": "^7.3.7",
"slash": "^3.0.0",
"temp-write": "^4.0.0",
Expand Down
@@ -1,6 +1,6 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP

exports[`npm modern lock file updateModernLockfileVersion v2 in project root 1`] = `
exports[`npm modern lock file call updateNpmLockFileVersion2 for npm lock file in project root 1`] = `
Object {
"dependencies": Object {
"@my-workspace/package-1": Object {
Expand All @@ -11,7 +11,7 @@ Object {
},
"@my-workspace/package-2": Object {
"requires": Object {
"@my-workspace/package-1": "^2.3.4",
"@my-workspace/package-1": "^2.4.0",
},
"version": "file:packages/package-2",
},
Expand Down Expand Up @@ -43,22 +43,22 @@ Object {
"resolved": "https://registry.npmjs.org/tiny-tarball/-/tiny-tarball-1.0.0.tgz",
"version": "1.0.0",
},
"version": "2.3.4",
"version": "2.4.0",
},
"packages/package-2": Object {
"dependencies": Object {
"@my-workspace/package-1": "^2.3.4",
"@my-workspace/package-1": "^2.4.0",
},
"license": "MIT",
"name": "@my-workspace/package-2",
"version": "2.3.4",
"version": "2.4.0",
},
},
"requires": true,
}
`;

exports[`pnpm lock file updateModernLockfileVersion v2 on pnpm lock file 1`] = `
exports[`pnpm lock file call updatePnpmLockFile for pnpm lock file in project root 1`] = `
"lockfileVersion: 5.4
importers:
.:
Expand Down
Expand Up @@ -528,7 +528,7 @@ index SHA..SHA 100644
+ \\"package-4\\": \\"^2.0.0\\""
`;

exports[`VersionCommand with lockfile version 2 should have updated project root lockfile version 2 for every necessary properties 1`] = `
exports[`VersionCommand with npm lockfile version 2 should have updated npm project root lockfile version 2 for every necessary properties 1`] = `
Object {
"dependencies": Object {
"@my-workspace/package-1": Object {
Expand Down Expand Up @@ -585,3 +585,38 @@ Object {
"requires": true,
}
`;

exports[`VersionCommand with pnpm lockfile should have updated pnpm project root lockfile for every necessary properties 1`] = `
Object {
"importers": Object {
".": Object {
"specifiers": Object {},
},
"packages/package-1": Object {
"dependencies": Object {
"tiny-tarball": "1.0.0",
},
"specifiers": Object {
"tiny-tarball": "^1.0.0",
},
},
"packages/package-2": Object {
"dependencies": Object {
"@my-workspace/package-1": "link:../package-1",
},
"specifiers": Object {
"@my-workspace/package-1": "workspace:^3.0.0",
},
},
},
"lockfileVersion": 5.4,
"packages": Object {
"/tiny-tarball/1.0.0": Object {
"dev": false,
"resolution": Object {
"integrity": "sha1-u/EC1a5zr+LFUyleD7AiMCFvZbE=",
},
},
},
}
`;
Expand Up @@ -14,8 +14,8 @@ const initFixture = require('@lerna-test/init-fixture')(__dirname);
const {
updateClassicLockfileVersion,
updateTempModernLockfileVersion,
loadLockfile,
saveLockfile,
loadLockfile
} = require('../lib/update-lockfile-version');

describe('npm classic lock file', () => {
Expand Down Expand Up @@ -63,7 +63,7 @@ describe('npm classic lock file', () => {
});

describe('npm modern lock file', () => {
test('updateModernLockfileVersion v2 in project root', async () => {
test('call updateNpmLockFileVersion2 for npm lock file in project root', async () => {
const mockVersion = '2.4.0';
const cwd = await initFixture('lockfile-version2');
const rootLockFilePath = path.join(cwd, 'package-lock.json');
Expand All @@ -81,14 +81,14 @@ describe('npm modern lock file', () => {
expect(Array.from(loadJsonFile.registry.keys())).toStrictEqual([
'/packages/package-1',
'/packages/package-2',
'/'
'/',
]);
expect(fs.readJSONSync(rootLockFilePath)).toMatchSnapshot();
});
});

describe('pnpm lock file', () => {
test('updateModernLockfileVersion v2 on pnpm lock file', async () => {
test('call updatePnpmLockFile for pnpm lock file in project root', async () => {
const mockVersion = '2.5.0';
const cwd = await initFixture('lockfile-pnpm');
const packages = await getPackages(cwd);
Expand All @@ -105,6 +105,7 @@ describe('pnpm lock file', () => {
expect(Array.from(loadJsonFile.registry.keys())).toStrictEqual([
'/packages/package-1',
'/packages/package-2',
'/',
]);

expect(`${fs.readFileSync(lockFileOutput.path)}`).toMatchSnapshot();
Expand Down
40 changes: 32 additions & 8 deletions packages/version/src/__tests__/version-command.spec.ts
Expand Up @@ -57,6 +57,7 @@ const lernaVersion = require('@lerna-test/command-runner')(
require('../../../cli/src/cli-commands/cli-version-commands')
);
import { loadLockfile, NpmLockfile } from '../lib/update-lockfile-version';
import { Lockfile as PnpmLockfile } from '@pnpm/lockfile-types';

// file under test
const yargParser = require('yargs-parser');
Expand Down Expand Up @@ -811,8 +812,8 @@ describe('VersionCommand', () => {
});
});

describe('with lockfile version 2', () => {
it('should have updated project root lockfile version 2 for every necessary properties', async () => {
describe('with npm lockfile version 2', () => {
it('should have updated npm project root lockfile version 2 for every necessary properties', async () => {
const cwd = await initFixture('lockfile-version2');
await new VersionCommand(createArgv(cwd, '--bump', 'major', '--yes'));

Expand All @@ -821,15 +822,12 @@ describe('VersionCommand', () => {
'@my-workspace/package-2': '3.0.0',
});

const lockfileResponse = await loadLockfile(cwd);

console.log(lockfileResponse)

const json = (lockfileResponse.json as NpmLockfile);
const lockfileResponse: any = await loadLockfile(cwd);
const json = lockfileResponse.json as NpmLockfile;

expect(lockfileResponse.packageManager).toBe('npm');
expect(lockfileResponse.json.lockfileVersion).toBe(2);
expect(json.dependencies['@my-workspace/package-2'].requires).toMatchObject({
expect(json.dependencies!['@my-workspace/package-2'].requires).toMatchObject({
'@my-workspace/package-1': '^3.0.0',
});
expect(json.packages['packages/package-1'].version).toBe('3.0.0');
Expand All @@ -842,6 +840,32 @@ describe('VersionCommand', () => {
});
});

describe('with pnpm lockfile', () => {
it('should have updated pnpm project root lockfile for every necessary properties', async () => {
const cwd = await initFixture('lockfile-pnpm');
await new VersionCommand(createArgv(cwd, '--bump', 'major', '--yes'));

expect(writePkg.updatedVersions()).toEqual({
'@my-workspace/package-1': '3.0.0',
'@my-workspace/package-2': '3.0.0',
});

const lockfileResponse: any = await loadLockfile(cwd);
const json = lockfileResponse.json as PnpmLockfile;

expect(lockfileResponse.packageManager).toBe('pnpm');
expect(lockfileResponse.json.lockfileVersion).toBe(5.4);
expect(json.importers['packages/package-2'].dependencies).toMatchObject({
'@my-workspace/package-1': 'link:../package-1',
});
expect(json.importers['packages/package-2'].specifiers).toMatchObject({
'@my-workspace/package-1': 'workspace:^3.0.0',
});

expect(lockfileResponse.json).toMatchSnapshot();
});
});

describe('with spurious -- arguments', () => {
it('ignores the extra arguments with cheesy parseConfiguration()', async () => {
const cwd = await initFixture('lifecycle');
Expand Down
100 changes: 54 additions & 46 deletions packages/version/src/lib/update-lockfile-version.ts
Expand Up @@ -3,7 +3,6 @@ import { PackageLock, LockDependency } from '@npm/types';
import fs from 'fs';
import yaml from 'js-yaml';
import path from 'path';
import preferredPM from 'preferred-pm';
import loadJsonFile from 'load-json-file';
import writeJsonFile from 'write-json-file';
import { Package } from '@lerna-lite/core';
Expand Down Expand Up @@ -49,43 +48,43 @@ async function writeYamlFile(filePath: string, data: unknown) {
} catch (e) {}
}

async function loadNpmLockfile(cwd: string): Promise<LockfileInformation> {
const lockfilePath = path.join(cwd, 'package-lock.json');
const json = await loadJsonFile<NpmLockfile>(lockfilePath);
const version = +(json?.['lockfileVersion'] ?? 1);

return {
json,
version,
path: lockfilePath,
packageManager: 'npm',
};
async function loadNpmLockfile(cwd: string): Promise<LockfileInformation | undefined> {
try {
const lockfilePath = path.join(cwd, 'package-lock.json');
const json = await loadJsonFile<NpmLockfile>(lockfilePath);
const version = +(json?.['lockfileVersion'] ?? 1);

return {
json,
version,
path: lockfilePath,
packageManager: 'npm',
};
} catch (error) {} // eslint-disable-line
}

async function loadPnpmLockfile(cwd: string): Promise<LockfileInformation> {
const lockfilePath = path.join(cwd, 'pnpm-lock.yaml');
const json = (await loadYamlFile(lockfilePath)) as PnpmLockfile;
const version = +(json?.['lockfileVersion'] ?? 1);

return {
json,
version,
path: lockfilePath,
packageManager: 'pnpm',
};
async function loadPnpmLockfile(cwd: string): Promise<LockfileInformation | undefined> {
try {
const lockfilePath = path.join(cwd, 'pnpm-lock.yaml');
const json = (await loadYamlFile(lockfilePath)) as PnpmLockfile;
const version = +(json?.['lockfileVersion'] ?? 1);

return {
json,
version,
path: lockfilePath,
packageManager: 'pnpm',
};
} catch (error) {} // eslint-disable-line
}

export async function loadLockfile(cwd: string) {
const pm = await preferredPM(cwd);

switch (pm?.name) {
case 'npm':
return loadNpmLockfile(cwd);
case 'pnpm':
return loadPnpmLockfile(cwd);
default:
return undefined;
export async function loadLockfile(cwd: string): Promise<LockfileInformation | undefined> {
let lockFile = await loadNpmLockfile(cwd);
if (!lockFile) {
lockFile = await loadPnpmLockfile(cwd);
}

return lockFile;
}

/**
Expand Down Expand Up @@ -151,32 +150,41 @@ export function updateNpmLockFileVersion2(
pkgName: string,
newVersion: string
) {
if (typeof lockfile.json === 'object' && pkgName && newVersion) {
for (const k in lockfile.json) {
if (typeof lockfile.json[k] === 'object' && lockfile.json[k] !== null) {
updateNpmLockFileVersion2(lockfile.json[k], pkgName, newVersion);
if (!lockfile.json || !pkgName || !newVersion || !isNpmLockfile(lockfile)) {
return;
}

const updateNpmLockPart = (part: unknown) => {
if (typeof part !== 'object') {
return;
}

for (const k in part) {
if (typeof part[k] === 'object' && part[k] !== null) {
updateNpmLockPart(part[k]);
} else {
if (k === pkgName) {
// e.g.: "@lerna-lite/core": "^0.1.2",
const [_, versionPrefix, _versionStr] = lockfile.json[k].match(/^([\^~])?(.*)$/);
lockfile.json[k] = `${versionPrefix}${newVersion}`;
} else if (k === 'name' && lockfile.json[k] === pkgName && lockfile.json['version'] !== undefined) {
const [_, versionPrefix, _versionStr] = part[k].match(/^([\^~])?(.*)$/);
part[k] = `${versionPrefix}${newVersion}`;
} else if (k === 'name' && part[k] === pkgName && part['version'] !== undefined) {
// e.g. "packages/version": { "name": "@lerna-lite/version", "version": "0.1.2" }
if (lockfile.json['version'] !== undefined) {
lockfile.json['version'] = newVersion;
if (part['version'] !== undefined) {
part['version'] = newVersion;
}
}
}
}
}
};
updateNpmLockPart(lockfile.json);
}

export function updatePnpmLockFile(lockfile: LockfileInformation, pkgName: string, newVersion: string) {
if (!lockfile.json || !pkgName || !newVersion || !isPnpmLockfile(lockfile)) {
return;
}

const updatePart = (part: unknown) => {
const updatePnpmLockPart = (part: unknown) => {
if (typeof part !== 'object') {
return;
}
Expand All @@ -192,10 +200,10 @@ export function updatePnpmLockFile(lockfile: LockfileInformation, pkgName: strin
k !== 'specifiers' &&
k !== 'dependencies'
) {
updatePart(part[k]);
updatePnpmLockPart(part[k]);
}
}
};

updatePart(lockfile.json.importers);
updatePnpmLockPart(lockfile.json.importers);
}

0 comments on commit ee1a964

Please sign in to comment.