ts-migrate
Version:
A tool for migrating frontend application from JavaScript to TypeScript
199 lines • 9.81 kB
JavaScript
;
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
/* eslint-disable no-await-in-loop, no-restricted-syntax */
const path_1 = __importDefault(require("path"));
const updatable_log_1 = __importDefault(require("updatable-log"));
const yargs_1 = __importDefault(require("yargs"));
const ts_migrate_plugins_1 = require("ts-migrate-plugins");
const ts_migrate_server_1 = require("ts-migrate-server");
const init_1 = __importDefault(require("./commands/init"));
const rename_1 = __importDefault(require("./commands/rename"));
const availablePlugins = [
ts_migrate_plugins_1.addConversionsPlugin,
ts_migrate_plugins_1.declareMissingClassPropertiesPlugin,
ts_migrate_plugins_1.eslintFixPlugin,
ts_migrate_plugins_1.explicitAnyPlugin,
ts_migrate_plugins_1.hoistClassStaticsPlugin,
ts_migrate_plugins_1.jsDocPlugin,
ts_migrate_plugins_1.memberAccessibilityPlugin,
ts_migrate_plugins_1.reactClassLifecycleMethodsPlugin,
ts_migrate_plugins_1.reactClassStatePlugin,
ts_migrate_plugins_1.reactDefaultPropsPlugin,
ts_migrate_plugins_1.reactPropsPlugin,
ts_migrate_plugins_1.reactShapePlugin,
ts_migrate_plugins_1.stripTSIgnorePlugin,
ts_migrate_plugins_1.tsIgnorePlugin,
];
// eslint-disable-next-line no-unused-expressions
yargs_1.default
.scriptName('npm run ts-migrate --')
.version(false)
.usage('Usage: $0 <command> [options]')
.command('init <folder>', 'Initialize tsconfig.json file in <folder>', (cmd) => cmd.positional('folder', { type: 'string' }).require(['folder']), (args) => {
const rootDir = path_1.default.resolve(process.cwd(), args.folder);
(0, init_1.default)({ rootDir, isExtendedConfig: false });
})
.command('init:extended <folder>', 'Initialize tsconfig.json file in <folder>', (cmd) => cmd.positional('folder', { type: 'string' }).require(['folder']), (args) => {
const rootDir = path_1.default.resolve(process.cwd(), args.folder);
(0, init_1.default)({ rootDir, isExtendedConfig: true });
})
.command('rename [options] <folder>', 'Rename files in folder from JS/JSX to TS/TSX', (cmd) => cmd
.positional('folder', { type: 'string' })
.string('sources')
.alias('sources', 's')
.describe('sources', 'Path to a subset of your project to rename.')
.example('$0 rename /frontend/foo', 'Rename all the files in /frontend/foo')
.example('$0 rename /frontend/foo -s "bar/**/*"', 'Rename all the files in /frontend/foo/bar')
.require(['folder']), (args) => {
const rootDir = path_1.default.resolve(process.cwd(), args.folder);
const { sources } = args;
const renamedFiles = (0, rename_1.default)({ rootDir, sources });
if (renamedFiles === null) {
process.exit(-1);
}
})
.command('migrate [options] <folder>', 'Fix TypeScript errors, using codemods', (cmd) => cmd
.positional('folder', { type: 'string' })
.choices('defaultAccessibility', ['private', 'protected', 'public'])
.string('plugin')
.choices('plugin', availablePlugins.map((p) => p.name))
.describe('plugin', 'Run a specific plugin')
.string('privateRegex')
.string('protectedRegex')
.string('publicRegex')
.string('sources')
.alias('sources', 's')
.describe('sources', 'Path to a subset of your project to rename (globs are ok).')
.example('migrate /frontend/foo', 'Migrate all the files in /frontend/foo')
.example('$0 migrate /frontend/foo -s "bar/**/*" -s "node_modules/**/*.d.ts"', 'Migrate all the files in /frontend/foo/bar, accounting for ambient types from node_modules.')
.example('$0 migrate /frontend/foo --plugin jsdoc', 'Migrate JSDoc comments for all the files in /frontend/foo')
.require(['folder']), async (args) => {
const rootDir = path_1.default.resolve(process.cwd(), args.folder);
const { sources } = args;
let config;
const airbnbAnyAlias = '$TSFixMe';
const airbnbAnyFunctionAlias = '$TSFixMeFunction';
// by default, we're not going to use any aliases in ts-migrate
const anyAlias = args.aliases === 'tsfixme' ? airbnbAnyAlias : undefined;
const anyFunctionAlias = args.aliases === 'tsfixme' ? airbnbAnyFunctionAlias : undefined;
if (args.plugin) {
const plugin = availablePlugins.find((cur) => cur.name === args.plugin);
if (!plugin) {
updatable_log_1.default.error(`Could not find a plugin named ${args.plugin}.`);
process.exit(1);
return;
}
if (plugin === ts_migrate_plugins_1.jsDocPlugin) {
const anyAlias = args.aliases === 'tsfixme' ? '$TSFixMe' : undefined;
const typeMap = typeof args.typeMap === 'string' ? JSON.parse(args.typeMap) : undefined;
config = new ts_migrate_server_1.MigrateConfig().addPlugin(ts_migrate_plugins_1.jsDocPlugin, { anyAlias, typeMap });
}
else {
config = new ts_migrate_server_1.MigrateConfig().addPlugin(plugin, {
anyAlias,
anyFunctionAlias,
});
}
}
else {
const useDefaultPropsHelper = args.useDefaultPropsHelper === 'true';
const { defaultAccessibility, privateRegex, protectedRegex, publicRegex } = args;
config = new ts_migrate_server_1.MigrateConfig()
.addPlugin(ts_migrate_plugins_1.stripTSIgnorePlugin, {})
.addPlugin(ts_migrate_plugins_1.hoistClassStaticsPlugin, { anyAlias })
.addPlugin(ts_migrate_plugins_1.reactPropsPlugin, {
anyAlias,
anyFunctionAlias,
shouldUpdateAirbnbImports: true,
})
.addPlugin(ts_migrate_plugins_1.reactClassStatePlugin, { anyAlias })
.addPlugin(ts_migrate_plugins_1.reactClassLifecycleMethodsPlugin, { force: true })
.addPlugin(ts_migrate_plugins_1.reactDefaultPropsPlugin, {
useDefaultPropsHelper,
})
.addPlugin(ts_migrate_plugins_1.reactShapePlugin, {
anyAlias,
anyFunctionAlias,
})
.addPlugin(ts_migrate_plugins_1.declareMissingClassPropertiesPlugin, { anyAlias })
.addPlugin(ts_migrate_plugins_1.memberAccessibilityPlugin, {
defaultAccessibility,
privateRegex,
protectedRegex,
publicRegex,
})
.addPlugin(ts_migrate_plugins_1.explicitAnyPlugin, { anyAlias })
.addPlugin(ts_migrate_plugins_1.addConversionsPlugin, { anyAlias })
// We need to run eslint-fix before ts-ignore because formatting may affect where
// the errors are that need to get ignored.
.addPlugin(ts_migrate_plugins_1.eslintFixPlugin, {})
.addPlugin(ts_migrate_plugins_1.tsIgnorePlugin, {})
// We need to run eslint-fix again after ts-ignore to fix up formatting.
.addPlugin(ts_migrate_plugins_1.eslintFixPlugin, {});
}
const { exitCode } = await (0, ts_migrate_server_1.migrate)({ rootDir, config, sources });
process.exit(exitCode);
})
.command('reignore <folder>', 'Re-run ts-ignore on a project', (cmd) => cmd
.option('p', {
alias: 'messagePrefix',
default: 'FIXME',
type: 'string',
describe: 'A message to add to the ts-expect-error or ts-ignore comments that are inserted.',
})
.positional('folder', { type: 'string' })
.require(['folder']), async (args) => {
const rootDir = path_1.default.resolve(process.cwd(), args.folder);
const changedFiles = new Map();
function withChangeTracking(plugin) {
return {
name: plugin.name,
async run(params) {
const prevText = params.text;
const nextText = await plugin.run(params);
const seen = changedFiles.has(params.fileName);
if (!seen && nextText != null && nextText !== prevText) {
changedFiles.set(params.fileName, prevText);
}
return nextText;
},
};
}
const eslintFixChangedPlugin = {
name: 'eslint-fix-changed',
async run(params) {
if (!changedFiles.has(params.fileName))
return undefined;
if (changedFiles.get(params.fileName) === params.text)
return undefined;
return ts_migrate_plugins_1.eslintFixPlugin.run(params);
},
};
const config = new ts_migrate_server_1.MigrateConfig()
.addPlugin(withChangeTracking(ts_migrate_plugins_1.stripTSIgnorePlugin), {})
.addPlugin(withChangeTracking(ts_migrate_plugins_1.tsIgnorePlugin), {
messagePrefix: args.messagePrefix,
})
.addPlugin(eslintFixChangedPlugin, {});
const { exitCode } = await (0, ts_migrate_server_1.migrate)({ rootDir, config });
process.exit(exitCode);
})
.example('$0 --help', 'Show help')
.example('$0 migrate --help', 'Show help for the migrate command')
.example('$0 init frontend/foo', 'Create tsconfig.json file at frontend/foo/tsconfig.json')
.example('$0 init:extended frontend/foo', 'Create extended from the base tsconfig.json file at frontend/foo/tsconfig.json')
.example('$0 rename frontend/foo', 'Rename files in frontend/foo from JS/JSX to TS/TSX')
.example('$0 rename frontend/foo --s "bar/baz"', 'Rename files in frontend/foo/bar/baz from JS/JSX to TS/TSX')
.demandCommand(1, 'Must provide a command.')
.help('h')
.alias('h', 'help')
.alias('i', 'init')
.alias('m', 'migrate')
.alias('rn', 'rename')
.alias('ri', 'reignore')
.wrap(Math.min(yargs_1.default.terminalWidth(), 100)).argv;
//# sourceMappingURL=cli.js.map