Skip to content

Commit f6902d8

Browse files
committed
feat: support resolutions
1 parent d30032c commit f6902d8

File tree

3 files changed

+64
-26
lines changed

3 files changed

+64
-26
lines changed

src/commands/cli/latestrc/build.ts

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ import { ensureString } from '@salesforce/ts-types';
1212
import { Env } from '@salesforce/kit';
1313
import { Octokit } from '@octokit/core';
1414
import { bold } from 'chalk';
15-
import { Messages } from '@salesforce/core';
15+
import { Messages, SfdxError } from '@salesforce/core';
1616
import { SinglePackageRepo } from '../../../repository';
1717

1818
Messages.importMessagesDirectory(__dirname);
@@ -82,7 +82,13 @@ export default class build extends SfdxCommand {
8282

8383
if (only) {
8484
this.ux.log(`bumping the following dependencies only: ${only.join(', ')}`);
85-
repo.package.bumpDependencyVersions(only);
85+
const bumped = repo.package.bumpDependencyVersions(only);
86+
87+
if (!bumped.length) {
88+
throw new SfdxError(
89+
'No version changes made. Confirm you are passing the correct dependency and version to --only.'
90+
);
91+
}
8692
} else {
8793
// bump resolution deps
8894
if (this.flags.resolutions) {

src/package.ts

Lines changed: 32 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -180,9 +180,8 @@ export class Package extends AsyncOptionalCreatable {
180180

181181
// Lookup dependency info by package name or npm alias
182182
// Examples: @salesforce/plugin-info or @sf/info
183-
public getDependencyInfo(name: string): DependencyInfo {
184-
const { dependencies } = this.packageJson;
185-
183+
// Pass in the dependencies you want to search through (dependencies, devDependencies, resolutions, etc)
184+
public getDependencyInfo(name: string, dependencies: Record<string, string>): DependencyInfo {
186185
for (const [key, value] of Object.entries(dependencies)) {
187186
if (key === name) {
188187
if (value.startsWith('npm:')) {
@@ -217,28 +216,41 @@ export class Package extends AsyncOptionalCreatable {
217216
cli.error(`${name} was not found in the dependencies section of the package.json`);
218217
}
219218

220-
public bumpDependencyVersions(dependencies: string[]): DependencyInfo[] {
221-
return dependencies.map((dep) => {
222-
// regex for npm package with optional namespace and version
223-
// https://regex101.com/r/HmIu3N/1
224-
const npmPackageRegex = /^((?:@[^/]+\/)?[^@/]+)(?:@([^@/]+))?$/;
225-
const [, name, version] = npmPackageRegex.exec(dep);
219+
public bumpDependencyVersions(targetDependencies: string[]): DependencyInfo[] {
220+
return targetDependencies
221+
.map((dep) => {
222+
// regex for npm package with optional namespace and version
223+
// https://regex101.com/r/HmIu3N/1
224+
const npmPackageRegex = /^((?:@[^/]+\/)?[^@/]+)(?:@([^@/]+))?$/;
225+
const [, name, version] = npmPackageRegex.exec(dep);
226226

227-
// find dependency in package.json (could be an npm alias)
228-
const depInfo = this.getDependencyInfo(name);
227+
// We will look for packages in dependencies and resolutions
228+
const { dependencies, resolutions } = this.packageJson;
229229

230-
// If a version is not provided, we'll look up the "latest" version
231-
depInfo.finalVersion = version ?? this.getDistTags(depInfo.packageName).latest;
230+
// find dependency in package.json (could be an npm alias)
231+
const depInfo = this.getDependencyInfo(name, { ...dependencies, ...resolutions });
232232

233-
// override final version if npm alias is used
234-
if (depInfo.alias) {
235-
depInfo.finalVersion = `npm:${depInfo.packageName}@${depInfo.finalVersion}`;
236-
}
233+
// if a version is not provided, we'll look up the "latest" version
234+
depInfo.finalVersion = version ?? this.getDistTags(depInfo.packageName).latest;
237235

238-
this.packageJson.dependencies[depInfo.dependencyName] = depInfo.finalVersion;
236+
// return if version did not change
237+
if (depInfo.currentVersion === depInfo.finalVersion) return;
239238

240-
return depInfo;
241-
});
239+
// override final version if npm alias is used
240+
if (depInfo.alias) {
241+
depInfo.finalVersion = `npm:${depInfo.packageName}@${depInfo.finalVersion}`;
242+
}
243+
244+
// update dependency (or resolution) in package.json
245+
if (dependencies[depInfo.dependencyName]) {
246+
this.packageJson.dependencies[depInfo.dependencyName] = depInfo.finalVersion;
247+
} else {
248+
this.packageJson.resolutions[depInfo.dependencyName] = depInfo.finalVersion;
249+
}
250+
251+
return depInfo;
252+
})
253+
.filter(Boolean); // remove falsy values, in this case the `undefined` if version did not change
242254
}
243255

244256
public getNextRCVersion(tag: string, isPatch = false): string {

test/package.test.ts

Lines changed: 24 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -167,7 +167,8 @@ describe('Package', () => {
167167

168168
it('should find dependency using an npm alias', async () => {
169169
const pkg = await Package.create();
170-
const dependency = pkg.getDependencyInfo('@sf/info');
170+
const deps = pkg.packageJson.dependencies;
171+
const dependency = pkg.getDependencyInfo('@sf/info', deps);
171172

172173
expect(dependency).to.deep.equal({
173174
dependencyName: '@sf/info',
@@ -179,7 +180,8 @@ describe('Package', () => {
179180

180181
it('should find an npm alias with a package name', async () => {
181182
const pkg = await Package.create();
182-
const dependency = pkg.getDependencyInfo('@salesforce/plugin-info');
183+
const deps = pkg.packageJson.dependencies;
184+
const dependency = pkg.getDependencyInfo('@salesforce/plugin-info', deps);
183185

184186
expect(dependency).to.deep.equal({
185187
dependencyName: '@sf/info',
@@ -191,7 +193,8 @@ describe('Package', () => {
191193

192194
it('should find a dependency using a package name', async () => {
193195
const pkg = await Package.create();
194-
const dependency = pkg.getDependencyInfo('@salesforce/plugin-config');
196+
const deps = pkg.packageJson.dependencies;
197+
const dependency = pkg.getDependencyInfo('@salesforce/plugin-config', deps);
195198

196199
expect(dependency).to.deep.equal({
197200
dependencyName: '@salesforce/plugin-config',
@@ -213,6 +216,9 @@ describe('Package', () => {
213216
'@salesforce/plugin-config': '1.2.3',
214217
'left-pad': '1.1.1',
215218
},
219+
resolutions: {
220+
'@salesforce/source-deploy-retrieve': '1.0.0',
221+
},
216222
})
217223
);
218224
stubMethod($$.SANDBOX, Package.prototype, 'getDistTags').returns({
@@ -272,12 +278,26 @@ describe('Package', () => {
272278
]);
273279
});
274280

275-
it('should update package.json', async () => {
281+
it('should return an empty array if all versions are already up to date', async () => {
282+
const pkg = await Package.create();
283+
const results = pkg.bumpDependencyVersions(['@sf/info@2.0.1', '@salesforce/plugin-config@1.2.3']);
284+
285+
expect(results).to.deep.equal([]);
286+
});
287+
288+
it('should update dependencies in package.json', async () => {
276289
const pkg = await Package.create();
277290
pkg.bumpDependencyVersions(['@sf/info@2.2.2', '@salesforce/plugin-config@3.3.3']);
278291

279292
expect(pkg.packageJson.dependencies['@sf/info']).to.equal('npm:@salesforce/plugin-info@2.2.2');
280293
expect(pkg.packageJson.dependencies['@salesforce/plugin-config']).to.equal('3.3.3');
281294
});
295+
296+
it('should update resolutions in package.json', async () => {
297+
const pkg = await Package.create();
298+
pkg.bumpDependencyVersions(['@salesforce/source-deploy-retrieve@1.0.1']);
299+
300+
expect(pkg.packageJson.resolutions['@salesforce/source-deploy-retrieve']).to.equal('1.0.1');
301+
});
282302
});
283303
});

0 commit comments

Comments
 (0)