/
config.ts
102 lines (85 loc) · 3.13 KB
/
config.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
import arg from 'arg';
import chalk from 'chalk';
import inquirer from 'inquirer';
const { prompt } = inquirer;
import { basename, dirname, join } from 'path';
import { exit } from 'process';
import { fileURLToPath } from 'url';
import { JobDef } from './job-def.js';
const __dirname = dirname(fileURLToPath(import.meta.url));
// !!! ⚠️ Don't forget to update the section 'bin' of package.json for any change of jobLinks ⚠️ !!!
const jobLinks = Object.freeze({
copy: 'copy',
remove: 'remove',
rimraf: 'remove',
ensureDir: 'ensureDir',
mkdirs: 'ensureDir',
mkdirp: 'ensureDir',
emptyDir: 'emptyDir',
ensureFile: 'ensureFile',
touch: 'ensureFile',
move: 'move',
version: 'version',
help: 'help'
} as { [key: string]: string });
// 'cli' must not be used as task name
const allowedScriptPrefixes = ['fse-cli', 'fse']; // longer first
function extractScriptAndTask(scriptPath: string) {
const scriptName = basename(scriptPath);
if (allowedScriptPrefixes.includes(scriptName)) {
return [scriptPath];
}
const prefixes = allowedScriptPrefixes.map(p => p + '-');
for (const p of prefixes) {
if (scriptName.startsWith(p)) {
const fromEnd = p.length - scriptName.length - 1;
return [scriptPath.slice(0, fromEnd), scriptName.slice(p.length)];
}
}
return [scriptName];
}
async function parseArgumentsIntoOptions(rawArgs: string[]) {
const fullCommand = extractScriptAndTask(rawArgs[1]);
const finalArgs = [rawArgs[0], ...fullCommand, ...rawArgs.splice(2)];
const jobName = finalArgs[2];
if (!jobName) {
console.error("%s: No task specified. Launch %s to get more help.",
chalk.red.bold('ERROR'),
chalk.yellowBright.bold('fse-cli help'));
exit(1);
}
const jobTag = jobLinks[jobName];
if (!jobTag) {
console.error("%s: Unknown task '" + jobName + "'. Launch %s to get more help.",
chalk.red.bold('ERROR'),
chalk.yellowBright.bold('fse-cli help'));
exit(1);
}
const argv = finalArgs.slice(3);
const modulePath = join(__dirname, 'tasks', jobTag + '.js');
const { def: jobDef }: {def: JobDef} = await import(modulePath);
const args = arg(
jobDef.spec,
{ argv }
);
return { jobDef, options: jobDef.options(args) };
}
interface JobOptions {
jobTag: string;
options: Record<string, unknown>;
}
async function promptForMissingOptions({ jobDef, options: partialOptions }:
{ jobDef: JobDef, options: Record<string, unknown> }): Promise<JobOptions> {
const questions = jobDef.questions(partialOptions);
const answers = await prompt<{ [key: string]: unknown }>(questions);
const options = Object.keys(answers).reduce((options, k) => {
options[k] = partialOptions[k] || answers[k];
return options;
}, { ...partialOptions });
return { jobTag: jobDef.name, options };
}
export async function fetchOptionsFrom(args: string[]): Promise<JobOptions> {
const data = await parseArgumentsIntoOptions(args);
const options = await promptForMissingOptions(data);
return options;
}