1 | import { parse } from 'path';
|
2 | import { constants, filter, fs, inquirer, listr, loadSettings, log, value as valueUtil, } from '../common';
|
3 | export const name = 'tsconfig';
|
4 | export const alias = 'ts';
|
5 | export const description = `Common transformations across typescript configuration files.`;
|
6 | export const args = {
|
7 | '-i': 'Include ignored modules.',
|
8 | };
|
9 | export async function cmd(args) {
|
10 | const options = (args && args.options) || {};
|
11 | const includeIgnored = options.i || false;
|
12 | const settings = await loadSettings();
|
13 | if (!settings) {
|
14 | log.warn.yellow(constants.CONFIG_NOT_FOUND_ERROR);
|
15 | return;
|
16 | }
|
17 | const response = (await inquirer.prompt([
|
18 | {
|
19 | type: 'list',
|
20 | name: 'type',
|
21 | message: 'Change?',
|
22 | choices: ['noUnusedLocals: true', 'noUnusedLocals: false'],
|
23 | },
|
24 | ]));
|
25 | log.info();
|
26 | const paths = await getTsconfigPaths(settings, { includeIgnored });
|
27 | const parts = toChoiceParts(response.type);
|
28 | switch (response.type) {
|
29 | case 'noUnusedLocals: true':
|
30 | case 'noUnusedLocals: false':
|
31 | await saveChangesWithPrompt(paths, { noUnusedLocals: parts.value });
|
32 | break;
|
33 | default:
|
34 | log.error(`'${response.type}' not supported.`);
|
35 | break;
|
36 | }
|
37 | log.info();
|
38 | }
|
39 | async function getTsconfigPaths(settings, options) {
|
40 | const { includeIgnored = false } = options;
|
41 | const paths = settings.modules
|
42 | .filter((pkg) => filter.includeIgnored(pkg, includeIgnored))
|
43 | .map((m) => m.dir)
|
44 | .map((dir) => fs.join(dir, 'tsconfig.json'));
|
45 | return filter.fileExists(paths);
|
46 | }
|
47 | async function saveChangesWithPrompt(paths, changes) {
|
48 | if (paths.length === 0) {
|
49 | log.info.gray('No files to change.');
|
50 | return false;
|
51 | }
|
52 | log.info.cyan(`\nChange files:`);
|
53 | paths.forEach((path) => {
|
54 | log.info(` ${toDisplayPath(path)}`);
|
55 | });
|
56 | log.info();
|
57 | const response = (await inquirer.prompt([
|
58 | {
|
59 | type: 'list',
|
60 | name: 'confirm',
|
61 | message: 'Are you sure?',
|
62 | choices: ['No', 'Yes'],
|
63 | },
|
64 | ]));
|
65 | switch (response.confirm) {
|
66 | case 'No':
|
67 | log.info.gray(`Nothing changed.`);
|
68 | return false;
|
69 | case 'Yes':
|
70 | await saveChanges(paths, changes);
|
71 | return true;
|
72 | default:
|
73 | return false;
|
74 | }
|
75 | }
|
76 | function toDisplayPath(path) {
|
77 | const root = parse(path);
|
78 | const dir = parse(root.dir);
|
79 | return log.gray(`${dir.dir}/${log.magenta(dir.base)}/${log.cyan(root.base)}`);
|
80 | }
|
81 | async function saveChanges(paths, changes) {
|
82 | const saveChange = async (path) => {
|
83 | const json = await fs.readJson(path);
|
84 | const compilerOptions = Object.assign(Object.assign({}, json.compilerOptions), changes);
|
85 | const tsConfig = Object.assign(Object.assign({}, json), { compilerOptions });
|
86 | const text = `${JSON.stringify(tsConfig, null, ' ')}\n`;
|
87 | await fs.writeFile(path, text);
|
88 | };
|
89 | const tasks = paths.map((path) => {
|
90 | return {
|
91 | title: `${log.cyan('Updated')} ${toDisplayPath(path)}`,
|
92 | task: async () => saveChange(path),
|
93 | };
|
94 | });
|
95 | try {
|
96 | await listr(tasks, { concurrent: true, exitOnError: false }).run();
|
97 | }
|
98 | catch (error) {
|
99 | }
|
100 | }
|
101 | function toChoiceParts(choice) {
|
102 | const parts = choice.split(':');
|
103 | const key = parts[0].trim();
|
104 | const value = valueUtil.toType(parts[1].trim());
|
105 | return { key, value };
|
106 | }
|