forked from webhintio/hint
/
create-hintrc.ts
212 lines (169 loc) · 6.7 KB
/
create-hintrc.ts
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
/**
* @fileoverview Generates a valid `.hintrc` file based on user responses.
*/
/*
* ------------------------------------------------------------------------------
* Requirements
* ------------------------------------------------------------------------------
*/
import * as fs from 'fs';
import * as path from 'path';
import { promisify } from 'util';
import * as inquirer from 'inquirer';
import { NpmPackage, UserConfig } from 'hint/dist/src/lib/types';
import { debug as d } from 'hint/dist/src/lib/utils/debug';
import * as logger from 'hint/dist/src/lib/utils/logging';
import cwd from 'hint/dist/src/lib/utils/fs/cwd';
import { getInstalledResources, getCoreResources } from 'hint/dist/src/lib/utils/resource-loader';
import { ResourceType } from 'hint/dist/src/lib/enums/resource-type';
import { generateBrowserslistConfig } from './browserslist';
import { getOfficialPackages, installPackages } from 'hint/dist/src/lib/utils/npm';
import { sendPendingData, trackEvent } from 'hint/dist/src/lib/utils/app-insights';
const debug: debug.IDebugger = d(__filename);
const defaultFormatter = 'summary';
type InitUserConfig = {
config: UserConfig;
packages?: string[];
};
/** Validates if the given array is not empty and if so, prints an error message. */
const anyResources = (resources: any[], type: string) => {
/* istanbul ignore else */
if (resources.length > 0) {
return true;
}
logger.error(`Couldn't find any installed ${type}s. Visit https://www.npmjs.com/search?q=%hint%2F${type}.`);
return false;
};
const getConfigurationName = (pkgName: string): string => {
const nameSplitted = pkgName.split('/');
return nameSplitted[1].replace('configuration-', '');
};
/** Shwos the user a list of official configuration packages available in npm to install. */
const extendConfig = async (): Promise<InitUserConfig | null> => {
const configPackages: NpmPackage[] = await getOfficialPackages(ResourceType.configuration);
if (!anyResources(configPackages, ResourceType.configuration)) {
return null;
}
const choices = configPackages.map((pkg) => {
return {
name: getConfigurationName(pkg.name),
value: pkg.name
};
});
const questions: inquirer.Questions = [{
choices,
message: 'Choose the configuration you want to extend from',
name: 'configuration',
pageSize: 15,
type: 'list'
}];
const answers: inquirer.Answers = await inquirer.prompt(questions);
const hintConfig = { extends: [getConfigurationName(answers.configuration)] };
return {
config: hintConfig,
packages: [answers.configuration]
};
};
/** Prompts a series of questions to create a new configuration object based on the installed packages. */
const customConfig = async (): Promise<InitUserConfig | null> => {
const connectorKeys: inquirer.ChoiceType[] = getInstalledResources(ResourceType.connector).concat(getCoreResources(ResourceType.connector));
const formattersKeys: inquirer.ChoiceType[] = getInstalledResources(ResourceType.formatter).concat(getCoreResources(ResourceType.formatter));
const parsersKeys: inquirer.ChoiceType[] = getInstalledResources(ResourceType.parser).concat(getCoreResources(ResourceType.parser));
const hintsKeys: inquirer.ChoiceType[] = getInstalledResources(ResourceType.hint).concat(getCoreResources(ResourceType.hint));
if (!anyResources(connectorKeys, ResourceType.connector) ||
!anyResources(formattersKeys, ResourceType.formatter) ||
!anyResources(hintsKeys, ResourceType.hint)) {
return null;
}
const customQuestions: inquirer.Question[] = [
{
choices: connectorKeys,
message: 'What connector do you want to use?',
name: 'connector',
type: 'list'
},
{
choices: formattersKeys,
default: defaultFormatter,
message: 'What formatter do you want to use?',
name: 'formatters',
pageSize: 15,
type: 'checkbox'
},
{
choices: hintsKeys,
message: 'Choose the hints you want to add to your configuration',
name: 'hints',
pageSize: 15,
type: 'checkbox',
when: (answers: inquirer.Answers) => {
return !answers.default;
}
}
];
// Parsers are not mandatory
if (parsersKeys.length > 0) {
customQuestions.push({
choices: parsersKeys,
message: 'What parsers do you want to use?',
name: 'parsers',
pageSize: 15,
type: 'checkbox'
});
}
const results: inquirer.Answers = await inquirer.prompt(customQuestions);
const hintConfig = {
browserslist: [],
connector: {
name: '',
options: { waitFor: 1000 }
},
extends: [],
formatters: [defaultFormatter],
hints: {},
hintsTimeout: 120000,
ignoredUrls: []
};
hintConfig.connector.name = results.connector;
hintConfig.formatters = results.formatters;
results.hints.forEach((hint: string) => {
(hintConfig.hints as any)[hint] = 'error';
});
(hintConfig.browserslist as string[]) = await generateBrowserslistConfig();
return { config: hintConfig };
};
/**
* Initiates a wizard to generate a valid `.hintrc` file based on:
* * an existing published configuration package
* * the installed resources
*/
export default async (): Promise<boolean> => {
debug('Starting --init');
logger.log('Welcome to hint configuration generator');
const initialQuestion: inquirer.Questions = [{
choices: ['predefined', 'custom'],
default: 'predefined',
message: 'Do you want to use a predefined configuration or create your own based on your installed packages?',
name: 'configType',
type: 'list'
}];
const initialAnswer: inquirer.Answers = await inquirer.prompt(initialQuestion);
const result = initialAnswer.configType === 'predefined' ?
await extendConfig() :
await customConfig();
if (!result) {
return false;
}
const filePath: string = path.join(cwd(), '.hintrc');
await promisify(fs.writeFile)(filePath, JSON.stringify(result.config, null, 4), 'utf8');
if (Array.isArray(result.packages) && result.packages.length > 0) {
const isInstalled = getInstalledResources(ResourceType.configuration).includes(getConfigurationName(result.packages[0]));
if (isInstalled) {
return true;
}
await installPackages(result.packages);
}
trackEvent('new-hintrc', result.config);
await sendPendingData();
return true;
};