Skip to content

Commit

Permalink
Merge pull request #18510 from storybookjs/tom/sb-372-sb18298-set-leg…
Browse files Browse the repository at this point in the history
…acy-peer-deps=true-in

CLI: Add npm7 migration for legacy peer deps
  • Loading branch information
shilman authored Jun 20, 2022
2 parents 3863591 + 10afa9e commit e5c2bb6
Show file tree
Hide file tree
Showing 3 changed files with 108 additions and 2 deletions.
47 changes: 47 additions & 0 deletions lib/cli/src/automigrate/fixes/npm7.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
import { NPMProxy } from '../../js-package-manager/NPMProxy';
import { npm7 } from './npm7';

const mockExecuteCommand = jest.fn();
class MockedNPMProxy extends NPMProxy {
executeCommand(...args) {
return mockExecuteCommand(...args);
}
}

function mockExecuteResults(map: Record<string, string>) {
mockExecuteCommand.mockImplementation((command, args) => {
const commandString = `${command} ${args.join(' ')}`;
if (map[commandString]) return map[commandString];

throw new Error(`Unexpected execution of '${commandString}'`);
});
}

describe('npm7 fix', () => {
describe('npm < 7', () => {
it('does not match', async () => {
mockExecuteResults({ 'npm --version': '6.0.0' });
expect(await npm7.check({ packageManager: new MockedNPMProxy() })).toEqual(null);
});
});

describe('npm 7+', () => {
it('matches if config is not installed', async () => {
mockExecuteResults({
'npm --version': '7.0.0',
'npm config get legacy-peer-deps --location=project': 'false',
});
expect(await npm7.check({ packageManager: new MockedNPMProxy() })).toEqual({
npmVersion: '7.0.0',
});
});

it('does not match if config is installed', async () => {
mockExecuteResults({
'npm --version': '7.0.0',
'npm config get legacy-peer-deps --location=project': 'true',
});
expect(await npm7.check({ packageManager: new MockedNPMProxy() })).toEqual(null);
});
});
});
41 changes: 41 additions & 0 deletions lib/cli/src/automigrate/fixes/npm7.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
import chalk from 'chalk';
import dedent from 'ts-dedent';
import { Fix } from '../types';
import { NPMProxy } from '../../js-package-manager/NPMProxy';

interface Npm7RunOptions {
npmVersion: string;
}

/**
* Is the user using npm7+? If so create a .npmrc with legacy-peer-deps=true
*/
export const npm7: Fix<Npm7RunOptions> = {
id: 'npm7',

async check({ packageManager }) {
if (packageManager.type !== 'npm') return null;

const npmVersion = (packageManager as NPMProxy).getNpmVersion();
if ((packageManager as NPMProxy).needsLegacyPeerDeps(npmVersion)) {
return { npmVersion };
}
return null;
},

prompt({ npmVersion }) {
const npmFormatted = chalk.cyan(`npm ${npmVersion}`);
return dedent`
We've detected you are running ${npmFormatted} which has peer dependency semantics which Storybook is incompatible with.
In order to work with Storybook's package structure, you'll need to run \`npm\` with the
\`--legacy-peer-deps=true\` flag. We can generate an \`.npmrc\` which will do that automatically.
More info: ${chalk.yellow('https://github.com/storybookjs/storybook/issues/18298')}
`;
},

async run({ packageManager }) {
(packageManager as NPMProxy).setLegacyPeerDeps();
},
};
22 changes: 20 additions & 2 deletions lib/cli/src/js-package-manager/NPMProxy.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,10 +18,28 @@ export class NPMProxy extends JsPackageManager {
return `npm run ${command}`;
}

getNpmVersion(): string {
return this.executeCommand('npm', ['--version']);
}

hasLegacyPeerDeps() {
return (
this.executeCommand('npm', ['config', 'get', 'legacy-peer-deps', '--location=project']) ===
'true'
);
}

setLegacyPeerDeps() {
this.executeCommand('npm', ['config', 'set', 'legacy-peer-deps=true', '--location=project']);
}

needsLegacyPeerDeps(version: string) {
return semver.gte(version, '7.0.0') && !this.hasLegacyPeerDeps();
}

getInstallArgs(): string[] {
if (!this.installArgs) {
const version = this.executeCommand('npm', ['--version']);
this.installArgs = semver.gte(version, '7.0.0')
this.installArgs = this.needsLegacyPeerDeps(this.getNpmVersion())
? ['install', '--legacy-peer-deps']
: ['install'];
}
Expand Down

0 comments on commit e5c2bb6

Please sign in to comment.