Skip to content

Commit 1684719

Browse files
authored
Unify CLI and scrubber (#7)
1 parent 638a354 commit 1684719

File tree

12 files changed

+295
-96
lines changed

12 files changed

+295
-96
lines changed

cli/index.ts

Lines changed: 75 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -4,21 +4,39 @@ import figlet from "figlet";
44
import inquirer from "inquirer";
55
import shell from "shelljs";
66
import yargs from "yargs/yargs";
7+
import {
8+
Options,
9+
CommandLineOptions,
10+
UserResponse,
11+
APIType,
12+
BackendType,
13+
DatabaseType,
14+
AuthType,
15+
} from "./optionTypes";
716

817
type CommandLineArgs = Array<string>;
918

10-
type Options = {
11-
[x: string]: unknown;
12-
backend?: string;
13-
api?: string;
14-
database?: string;
15-
auth?: boolean;
16-
output?: string;
17-
_?: (string | number)[];
18-
$0?: string;
19+
type Choice<T> = {
20+
name: string;
21+
value: T;
1922
};
2023

21-
const OPTIONS = {
24+
type OptionConfig<T> = {
25+
id: string;
26+
description: string;
27+
message: string;
28+
choices: ReadonlyArray<Choice<T>>;
29+
};
30+
31+
type OptionConfigs = {
32+
backend: OptionConfig<BackendType>;
33+
api: OptionConfig<APIType>;
34+
database: OptionConfig<DatabaseType>;
35+
auth: OptionConfig<void>;
36+
outputDir: OptionConfig<void>;
37+
};
38+
39+
const OPTIONS: OptionConfigs = {
2240
backend: {
2341
id: "b",
2442
description: "Backend language",
@@ -50,16 +68,18 @@ const OPTIONS = {
5068
id: "au",
5169
description: "Include built-in auth features",
5270
message: "Would you like built-in auth features?",
71+
choices: [],
5372
},
54-
output: {
73+
outputDir: {
5574
id: "o",
5675
description: "Output directory",
5776
message:
5877
"Which directory would you like the starter code folder to be in (default is current directory)?",
78+
choices: [],
5979
},
6080
};
6181

62-
const parseArguments = (args: CommandLineArgs) => {
82+
const parseArguments = (args: CommandLineArgs): CommandLineOptions => {
6383
const { argv } = yargs(args.slice(2)).options({
6484
backend: {
6585
alias: OPTIONS.backend.id,
@@ -84,17 +104,24 @@ const parseArguments = (args: CommandLineArgs) => {
84104
type: "boolean",
85105
description: OPTIONS.auth.description,
86106
},
87-
output: {
88-
alias: OPTIONS.output.id,
107+
outputDir: {
108+
alias: OPTIONS.outputDir.id,
89109
type: "string",
90-
description: OPTIONS.output.description,
110+
description: OPTIONS.outputDir.description,
91111
},
92112
});
93113

94-
return argv;
114+
return {
115+
backend: argv.backend as BackendType,
116+
api: argv.api as APIType,
117+
database: argv.database as DatabaseType,
118+
auth: argv.auth,
119+
};
95120
};
96121

97-
const promptOptions = async (options: Options) => {
122+
const promptOptions = async (
123+
options: CommandLineOptions,
124+
): Promise<UserResponse> => {
98125
const prompts = [];
99126
if (!options.backend) {
100127
prompts.push({
@@ -132,33 +159,37 @@ const promptOptions = async (options: Options) => {
132159
});
133160
}
134161

135-
if (!options.output) {
162+
if (!options.outputDir) {
136163
prompts.push({
137164
type: "output",
138-
name: "output",
139-
message: OPTIONS.output.message,
165+
name: "outputDir",
166+
message: OPTIONS.outputDir.message,
140167
default: ".",
141168
});
142169
}
143170

144171
const answers = await inquirer.prompt(prompts);
145172

146173
return {
147-
backend: options.backend || answers.backend,
148-
api: options.api || answers.api,
149-
database: options.database || answers.database,
150-
auth: options.auth || answers.auth,
151-
output: options.output || answers.output,
174+
appOptions: {
175+
backend: options.backend || answers.backend,
176+
api: options.api || answers.api,
177+
database: options.database || answers.database,
178+
auth: (options.auth || answers.auth ? "auth" : null) as AuthType,
179+
},
180+
outputDir: options.outputDir || answers.outputDir,
152181
};
153182
};
154183

155184
const confirmPrompt = async (options: Options) => {
156185
const backendName = OPTIONS.backend.choices.find(
157186
(choice) => choice.value === options.backend,
158187
)?.name;
188+
159189
const apiName = OPTIONS.api.choices.find(
160190
(choice) => choice.value === options.api,
161191
)?.name;
192+
162193
const databaseName = OPTIONS.database.choices.find(
163194
(choice) => choice.value === options.database,
164195
)?.name;
@@ -179,7 +210,7 @@ const confirmPrompt = async (options: Options) => {
179210
return confirm;
180211
};
181212

182-
const cli = async (args: CommandLineArgs) => {
213+
async function cli(args: CommandLineArgs): Promise<Options | null> {
183214
console.log(
184215
boxen(
185216
chalk.bold(
@@ -193,26 +224,37 @@ const cli = async (args: CommandLineArgs) => {
193224
},
194225
),
195226
);
196-
let options: Options = parseArguments(args);
197-
options = await promptOptions(options);
198-
const confirm = await confirmPrompt(options);
227+
228+
const commandLineOptions: CommandLineOptions = parseArguments(args);
229+
230+
const { appOptions, outputDir } = await promptOptions(commandLineOptions);
231+
232+
const confirm = await confirmPrompt(appOptions);
233+
199234
if (!confirm) {
200235
console.log(chalk.red.bold("Blueprint app creation has been cancelled."));
201-
return;
236+
return null;
202237
}
238+
203239
console.log(chalk.green.bold("Confirmed. Creating blueprint app..."));
204-
const path = options.output;
240+
241+
const path = outputDir;
205242
const changeDirectory = shell.cd(path);
243+
206244
if (changeDirectory.code !== 0) {
207245
console.log("No directory exists. Exiting...");
208-
return;
246+
return null;
209247
}
248+
210249
const clone = shell.exec(
211250
"git clone https://github.com/uwblueprint/starter-code-v2.git",
212251
);
252+
213253
if (clone.code !== 0) {
214254
console.log("Git clone failed. Exiting...");
215255
}
216-
};
256+
257+
return appOptions;
258+
}
217259

218260
export default cli;

cli/optionTypes.ts

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
export type BackendType = "python" | "typescript";
2+
3+
export type APIType = "rest" | "graphql";
4+
5+
export type DatabaseType = "postgresql" | "mongodb";
6+
7+
export type AuthType = "auth";
8+
9+
export type Options = {
10+
backend: BackendType;
11+
api: APIType;
12+
database: DatabaseType;
13+
auth?: AuthType;
14+
};
15+
16+
export type CommandLineOptions = {
17+
backend?: BackendType;
18+
api?: APIType;
19+
database?: DatabaseType;
20+
auth?: boolean;
21+
outputDir?: string;
22+
};
23+
24+
export type UserResponse = {
25+
appOptions: Options;
26+
outputDir: string;
27+
};

index.ts

Lines changed: 13 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,20 +1,26 @@
11
#!/usr/bin/env node
22
import cli from "./cli";
3+
import { Options } from "./cli/optionTypes";
34

45
import Scrubber from "./scrubber/scrubber";
5-
import { ScrubberAction } from "./scrubber/scrubberTypes";
66

7-
async function scrub() {
7+
async function scrub(rootDir: string, options: Options) {
88
try {
9-
const actions: ScrubberAction[] = [{ type: "remove", tags: ["@remove"] }];
109
const scrubber = new Scrubber();
1110

12-
await scrubber.parseConfig("scrubber/scrubberConfig.json");
13-
await scrubber.start(actions);
11+
await scrubber.parseConfig(`${rootDir}/scrubber/scrubberConfig.json`);
12+
await scrubber.start(options);
1413
} catch (err) {
1514
console.log(err);
1615
}
1716
}
1817

19-
cli(process.argv);
20-
scrub();
18+
async function run() {
19+
const rootDir = __dirname;
20+
const options = await cli(process.argv);
21+
if (options) {
22+
await scrub(rootDir, options);
23+
}
24+
}
25+
26+
run();

package.json

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -34,9 +34,12 @@
3434
"boxen": "^5.0.0",
3535
"chalk": "^4.1.0",
3636
"figlet": "^1.5.0",
37+
"glob": "^7.1.6",
3738
"inquirer": "^8.0.0",
3839
"shelljs": "^0.8.4",
3940
"yargs": "^16.2.0"
4041
},
41-
"files": ["bin/"]
42+
"files": [
43+
"bin/"
44+
]
4245
}

0 commit comments

Comments
 (0)