Skip to content

Commit

Permalink
feat: remove npm alias code
Browse files Browse the repository at this point in the history
  • Loading branch information
mshanemc committed Jan 12, 2024
1 parent 7f6563f commit af66a0a
Show file tree
Hide file tree
Showing 4 changed files with 43 additions and 181 deletions.
5 changes: 2 additions & 3 deletions src/commands/cli/releasenotes.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ import { Messages, SfError } from '@salesforce/core';
import shelljs from 'shelljs';
import semver from 'semver';
import { CLI } from '../../types.js';
import { NpmPackage, parseAliasedPackageName, parsePackageVersion } from '../../package.js';
import { NpmPackage, parsePackageVersion } from '../../package.js';

Messages.importMessagesDirectoryFromMetaUrl(import.meta.url);
const messages = Messages.loadMessages('@salesforce/plugin-release-management', 'cli.releasenotes');
Expand Down Expand Up @@ -227,8 +227,7 @@ const normalizePlugins = (npmPackage: NpmPackage): Map<string, string> => {
if (!version) {
throw new SfError(`Could not find version for ${p}`, 'VersionNotFound');
}
const name = dependencies[p].startsWith('npm:') ? parseAliasedPackageName(dependencies[p]) : p;
return [name, version];
return [p, version];
});
return new Map<string, string>([[npmPackage.name, npmPackage.version], ...pluginsTuples]);
};
Expand Down
109 changes: 26 additions & 83 deletions src/package.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ import { ux } from '@oclif/core';
import shelljs from 'shelljs';
import { SfError } from '@salesforce/core';
import { AsyncOptionalCreatable, findKey, parseJson } from '@salesforce/kit';
import { AnyJson, get, isObject, isPlainObject, Nullable } from '@salesforce/ts-types';
import { AnyJson, isObject, isPlainObject } from '@salesforce/ts-types';
import { Registry } from './registry.js';

export type PackageJson = {
Expand Down Expand Up @@ -63,22 +63,14 @@ interface PinnedPackage {
name: string;
version: string;
tag: string;
alias: Nullable<string>;
}

// Differentiates between dependencyName and packageName to support npm aliases
interface DependencyInfo {
dependencyName: string;
packageName: string;
alias: Nullable<string>;
currentVersion?: string;
finalVersion?: string;
}

export function parseAliasedPackageName(alias: string): string {
return alias.replace('npm:', '').replace(/@(\^|~)?[0-9]{1,3}(?:.[0-9]{1,3})?(?:.[0-9]{1,3})?(.*?)$/, '');
}

export function parsePackageVersion(alias: string): string | undefined {
const regex = /[0-9]{1,3}(?:.[0-9]{1,3})?(?:.[0-9]{1,3})?(.*?)$/;
return regex.exec(alias)?.[0];
Expand Down Expand Up @@ -161,7 +153,7 @@ export class Package extends AsyncOptionalCreatable {
} else {
version = versions[tag];
}
return { name: dep.name, version, tag, alias: dep.alias };
return { name: dep.name, version, tag };
});
}

Expand Down Expand Up @@ -189,48 +181,22 @@ export class Package extends AsyncOptionalCreatable {
}

/**
* Lookup dependency info by package name or npm alias
* Examples: @salesforce/plugin-info or @sf/info
* Lookup dependency info by package name
* Examples: @salesforce/plugin-info
* Pass in the dependencies you want to search through (dependencies, devDependencies, resolutions, etc)
*/
// eslint-disable-next-line class-methods-use-this
public getDependencyInfo(name: string, dependencies: Record<string, string>): DependencyInfo {
for (const [key, value] of Object.entries(dependencies)) {
if (key === name) {
if (value.startsWith('npm:')) {
// npm alias was passed in as name, so we need to parse package name and version
// e.g. passed in: "@sf/login"
// dependency: "@sf/login": "npm:@salesforce/[email protected]"
return {
dependencyName: key,
packageName: parseAliasedPackageName(value),
alias: value,
currentVersion: parsePackageVersion(value),
};
} else {
// package name was passed, so we can use key and value directly
return {
dependencyName: key,
packageName: key,
alias: null,
currentVersion: value,
};
}
}
if (value.startsWith(`npm:${name}`)) {
// package name was passed in as name, but an alias is used for the dependency
// e.g. passed in: "@salesforce/plugin-login"
// dependency: "@sf/login": "npm:@salesforce/[email protected]"
return {
dependencyName: key,
packageName: name,
alias: value,
currentVersion: parsePackageVersion(value),
};
}
const match = Object.entries(dependencies).find(([key]) => key === name);
if (match) {
const [matchingName, value] = match;
return {
packageName: matchingName,
currentVersion: value,
};
} else {
ux.error(`${name} was not found in the dependencies section of the package.json`);
}

ux.error(`${name} was not found in the dependencies section of the package.json`);
}

public bumpDependencyVersions(targetDependencies: string[]): DependencyInfo[] {
Expand All @@ -254,18 +220,13 @@ export class Package extends AsyncOptionalCreatable {
// return if version did not change
if (depInfo.currentVersion === depInfo.finalVersion) return;

// override final version if npm alias is used
if (depInfo.alias) {
depInfo.finalVersion = `npm:${depInfo.packageName}@${depInfo.finalVersion}`;
}

// update dependency (or resolution) in package.json
if (dependencies[depInfo.dependencyName]) {
this.packageJson.dependencies[depInfo.dependencyName] = depInfo.finalVersion;
} else if (resolutions?.[depInfo.dependencyName] && this.packageJson.resolutions) {
this.packageJson.resolutions[depInfo.dependencyName] = depInfo.finalVersion;
if (dependencies[depInfo.packageName]) {
this.packageJson.dependencies[depInfo.packageName] = depInfo.finalVersion;
} else if (resolutions?.[depInfo.packageName] && this.packageJson.resolutions) {
this.packageJson.resolutions[depInfo.packageName] = depInfo.finalVersion;
} else if (this.packageJson.oclif?.jitPlugins) {
this.packageJson.oclif.jitPlugins[depInfo.dependencyName] = depInfo.finalVersion;
this.packageJson.oclif.jitPlugins[depInfo.packageName] = depInfo.finalVersion;
}

return depInfo;
Expand Down Expand Up @@ -311,11 +272,7 @@ export class Package extends AsyncOptionalCreatable {
const updatedDeps = this.calculatePinnedPackageUpdates(deps);

updatedDeps.forEach((pp) => {
if (pp.alias) {
this.packageJson.dependencies[pp.alias] = `npm:${pp.name}@${pp.version}`;
} else {
this.packageJson.dependencies[pp.name] = pp.version;
}
this.packageJson.dependencies[pp.name] = pp.version;
});
return updatedDeps;
}
Expand Down Expand Up @@ -349,9 +306,7 @@ export class Package extends AsyncOptionalCreatable {
// side effect: mutate package.json reference
updatedDeps.forEach((pp) => {
if (this.packageJson.oclif?.jitPlugins) {
if (pp.alias) {
this.packageJson.oclif.jitPlugins[pp.alias] = `npm:${pp.name}@${pp.version}`;
} else if (this.packageJson.oclif?.jitPlugins) {
if (this.packageJson.oclif?.jitPlugins) {
this.packageJson.oclif.jitPlugins[pp.name] = pp.version;
}
}
Expand All @@ -369,7 +324,7 @@ export class Package extends AsyncOptionalCreatable {
}

public hasScript(scriptName: string): boolean {
return !!get(this.packageJson, `scripts.${scriptName}`, null);
return typeof this.packageJson.scripts[scriptName] === 'string';
}

protected async init(): Promise<void> {
Expand Down Expand Up @@ -406,20 +361,8 @@ const getPinnedPackage = ({
version: string;
tag?: string;
targetTag: string;
}): PinnedPackage => {
if (version.startsWith('npm:')) {
return {
name: parseAliasedPackageName(version),
version: version.split('@').reverse()[0].replace('^', '').replace('~', ''),
alias: name,
tag: tag ?? targetTag,
};
} else {
return {
name,
version: version.split('@').reverse()[0].replace('^', '').replace('~', ''),
alias: null,
tag: tag ?? targetTag,
};
}
};
}): PinnedPackage => ({
name,
version: version.split('@').reverse()[0].replace('^', '').replace('~', ''),
tag: tag ?? targetTag,
});
39 changes: 7 additions & 32 deletions test/commands/dependencies.pin.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -33,22 +33,15 @@ describe('dependencies:pin', () => {
sandbox.restore();
});

function setupStub(alias?: string): void {
function setupStub(): void {
// prevent it from writing back to the package.json
stubMethod(sandbox, fs, 'writeFileSync');
const pJson = alias
? {
name: 'test',
version: '1.0.0',
dependencies: { [alias]: 'npm:@salesforce/plugin-auth@^1.4.0' },
pinnedDependencies: [alias],
}
: {
name: 'test',
version: '1.0.0',
dependencies: { '@salesforce/plugin-auth': '^1.4.0' },
pinnedDependencies: ['@salesforce/plugin-auth'],
};
const pJson = {
name: 'test',
version: '1.0.0',
dependencies: { '@salesforce/plugin-auth': '^1.4.0' },
pinnedDependencies: ['@salesforce/plugin-auth'],
};

stubMethod(sandbox, fs.promises, 'readFile').resolves(JSON.stringify(pJson));
// we don't need all members of what exec returns, just the stdout
Expand All @@ -64,23 +57,6 @@ describe('dependencies:pin', () => {
name: '@salesforce/plugin-auth',
tag: 'latest',
version: '1.4.4',
alias: null,
},
];

expect(result).to.deep.equal(expected);
});

it('should update the package.json with pinned versions for an aliased package', async () => {
setupStub('auth');
const result = await runNpmDependenciesPinCmd(['--json']);

const expected = [
{
name: '@salesforce/plugin-auth',
tag: 'latest',
version: '1.4.4',
alias: 'auth',
},
];

Expand All @@ -96,7 +72,6 @@ describe('dependencies:pin', () => {
name: '@salesforce/plugin-auth',
tag: 'latest-rc',
version: '1.5.0',
alias: null,
},
];

Expand Down
Loading

0 comments on commit af66a0a

Please sign in to comment.