diff --git a/src/index.ts b/src/index.ts index e356947..15dfde9 100644 --- a/src/index.ts +++ b/src/index.ts @@ -8,7 +8,7 @@ import { // keys are NPM, vals are Yarn interface Indexable { - [index: string]: string | Function + [index: string]: string | ((command: string) => string) } var npmToYarnTable: Indexable = { @@ -46,6 +46,59 @@ var npmToYarnTable: Indexable = { }, rebuild: function (command: string) { return command.replace('rebuild', 'add --force') + }, + run: function (command: string) { + return command.replace( + /^run\s?([^\s]+)?(\s--\s--)?(.*)$/, + (_, data?: string, dash?: string, rest?: string): string => { + var result = '' + if (data && !unchangedCLICommands.includes(data) && !yarnCLICommands.includes(data)) { + result += data + } else { + result += 'run ' + (data || '') + } + if (dash) result += dash.replace(/^\s--/, '') + if (rest) result += rest + return result + } + ) + }, + ls: function (command: string) { + return command.replace(/^(ls|list)(.*)$/, function (_1, _2: string, args: string): string { + var result = 'list' + if (args) { + var ended = false + var packages = [] + var items = args.split(' ').filter(Boolean) + for (var item of items) { + if (ended) { + result += ' ' + item + } else if (item.startsWith('-')) { + result += ' --pattern "' + packages.join('|') + '"' + packages = [] + ended = true + result += ' ' + item + } else { + packages.push(item) + } + } + if (packages.length > 0) { + result += ' --pattern "' + packages.join('|') + '"' + } + return result + } else { + return 'list' + } + }) + }, + list: function (command: string) { + return (npmToYarnTable.ls as Function)(command) + }, + init: function (command: string) { + if (/^init (?!-).*$/.test(command)) { + return command.replace('init', 'create') + } + return command.replace(' --scope', '') } } @@ -96,14 +149,23 @@ var yarnToNpmTable: Indexable = { version: function (command: string) { return command.replace(/--(major|minor|patch)/, '$1') }, - install: 'install' -} - -yarnToNpmTable.global = function (command: string) { - if (/^global add/.test(command)) { - return (yarnToNpmTable.add as Function)(command.replace(/^global add/, 'add'), true) - } else if (/^global remove/.test(command)) { - return (yarnToNpmTable.remove as Function)(command.replace(/^global remove/, 'remove'), true) + install: 'install', + list: function (command: string) { + return command + .replace(/--pattern ["']([^"']+)["']/, function (_, packages: string) { + return packages.split('|').join(' ') + }) + .replace(/^list/, 'ls') + }, + init: 'init', + create: 'init', + run: 'run', + global: function (command: string) { + if (/^global add/.test(command)) { + return (yarnToNpmTable.add as Function)(command.replace(/^global add/, 'add'), true) + } else if (/^global remove/.test(command)) { + return (yarnToNpmTable.remove as Function)(command.replace(/^global remove/, 'remove'), true) + } } } diff --git a/src/utils.ts b/src/utils.ts index 74f6fa5..dbd7c54 100644 --- a/src/utils.ts +++ b/src/utils.ts @@ -1,15 +1,8 @@ -export var unchangedCLICommands = [ - 'init', - 'run', - 'test', - 'login', - 'logout', - 'link', - 'publish', - 'cache' -] +export var unchangedCLICommands = ['test', 'login', 'logout', 'link', 'publish', 'cache'] export var yarnCLICommands = [ + 'init', + 'run', 'add', 'audit', 'autoclean', @@ -50,14 +43,12 @@ export var uniqueYarnCLICommands = [ 'add', 'autoclean', 'check', - 'create', 'generate-lock-entry', 'global', 'import', 'info', 'licenses', 'link', - 'list', 'lockfile', 'policies', 'remove', @@ -74,6 +65,8 @@ export var uniqueYarnCLICommands = [ ] export var npmCLICommands = [ + 'init', + 'run', 'access', 'adduser', 'audit', @@ -99,6 +92,7 @@ export var npmCLICommands = [ 'install-test', 'install', 'ls', + 'list', 'npm', 'org', 'outdated', diff --git a/test/index.spec.ts b/test/index.spec.ts index a2f4b68..c7d4669 100644 --- a/test/index.spec.ts +++ b/test/index.spec.ts @@ -47,6 +47,56 @@ describe('NPM to Yarn tests', () => { it("npm whoami can't auto-convert to yarn", () => { expect(convert('npm whoami', 'yarn')).toEqual("yarn whoami\n# couldn't auto-convert command") }) + + it('npm init', () => { + expect(convert('npm init', 'yarn')).toEqual('yarn init') + expect(convert('npm init -y', 'yarn')).toEqual('yarn init -y') + expect(convert('npm init --yes', 'yarn')).toEqual('yarn init --yes') + expect(convert('npm init --scope', 'yarn')).toEqual('yarn init') + expect(convert('npm init --private', 'yarn')).toEqual('yarn init --private') + expect(convert('npm init --unknown-arg', 'yarn')).toEqual('yarn init --unknown-arg') + // create + expect(convert('npm init esm --yes', 'yarn')).toEqual('yarn create esm --yes') + expect(convert('npm init @scope/my-package', 'yarn')).toEqual('yarn create @scope/my-package') + expect(convert('npm init react-app ./my-react-app', 'yarn')).toEqual( + 'yarn create react-app ./my-react-app' + ) + }) + + it('npm run', () => { + expect(convert('npm run custom', 'yarn')).toEqual('yarn custom') + expect(convert('npm run add', 'yarn')).toEqual('yarn run add') + expect(convert('npm run install', 'yarn')).toEqual('yarn run install') + expect(convert('npm run run', 'yarn')).toEqual('yarn run run') + // with args + expect(convert('npm run custom -- --version', 'yarn')).toEqual('yarn custom --version') + }) + + it('npm list', () => { + expect(convert('npm list', 'yarn')).toEqual('yarn list') + expect(convert('npm list package', 'yarn')).toEqual('yarn list --pattern "package"') + expect(convert('npm list package package2', 'yarn')).toEqual( + 'yarn list --pattern "package|package2"' + ) + expect(convert('npm list @scope/package @scope/package2', 'yarn')).toEqual( + 'yarn list --pattern "@scope/package|@scope/package2"' + ) + expect(convert('npm list @scope/package @scope/package2 --depth=2', 'yarn')).toEqual( + 'yarn list --pattern "@scope/package|@scope/package2" --depth=2' + ) + // alias + expect(convert('npm ls', 'yarn')).toEqual('yarn list') + expect(convert('npm ls package', 'yarn')).toEqual('yarn list --pattern "package"') + expect(convert('npm ls package package2', 'yarn')).toEqual( + 'yarn list --pattern "package|package2"' + ) + expect(convert('npm ls @scope/package @scope/package2', 'yarn')).toEqual( + 'yarn list --pattern "@scope/package|@scope/package2"' + ) + expect(convert('npm ls @scope/package @scope/package2 --depth=2', 'yarn')).toEqual( + 'yarn list --pattern "@scope/package|@scope/package2" --depth=2' + ) + }) }) describe('Yarn to NPM tests', () => { @@ -107,4 +157,43 @@ describe('Yarn to NPM tests', () => { "npm upgrade-interactive\n# couldn't auto-convert command" ) }) + + it('yarn init', () => { + expect(convert('yarn init', 'npm')).toEqual('npm init') + expect(convert('yarn init -y', 'npm')).toEqual('npm init -y') + expect(convert('yarn init --yes', 'npm')).toEqual('npm init --yes') + expect(convert('yarn init --private', 'npm')).toEqual('npm init --private') + expect(convert('yarn init --unknown-arg', 'npm')).toEqual('npm init --unknown-arg') + }) + + it('yarn create', () => { + expect(convert('yarn create esm --yes', 'npm')).toEqual('npm init esm --yes') + expect(convert('yarn create @scope/my-package', 'npm')).toEqual('npm init @scope/my-package') + expect(convert('yarn create react-app ./my-react-app', 'npm')).toEqual( + 'npm init react-app ./my-react-app' + ) + }) + + it('yarn run', () => { + expect(convert('yarn custom', 'npm')).toEqual('npm run custom') + expect(convert('yarn run custom', 'npm')).toEqual('npm run custom') + expect(convert('yarn run add', 'npm')).toEqual('npm run add') + expect(convert('yarn run install', 'npm')).toEqual('npm run install') + expect(convert('yarn run run', 'npm')).toEqual('npm run run') + // with args + expect(convert('yarn custom -- --version', 'npm')).toEqual('npm run custom -- --version') + expect(convert('yarn run custom --version', 'npm')).toEqual('npm run custom --version') + expect(convert('yarn run custom -- --version', 'npm')).toEqual('npm run custom -- --version') + }) + + it('yarn list', () => { + expect(convert('yarn list', 'npm')).toEqual('npm ls') + expect(convert('yarn list --pattern "package"', 'npm')).toEqual('npm ls package') + expect(convert('yarn list --pattern "package|package2"', 'npm')).toEqual( + 'npm ls package package2' + ) + expect(convert('yarn list --pattern "@scope/package|@scope/package2"', 'npm')).toEqual( + 'npm ls @scope/package @scope/package2' + ) + }) })