console-app/lib/InteractiveOptions.ts

120 lines
2.8 KiB
TypeScript
Raw Normal View History

2020-05-05 12:48:36 +02:00
/* eslint-disable complexity */
/* eslint-disable max-statements */
/* eslint-disable no-process-env */
2020-05-05 11:56:36 +02:00
import { Persistent } from '@scode/modelling';
2020-05-05 12:48:36 +02:00
import fs from 'fs-extra';
2020-05-05 11:56:36 +02:00
enum OptionType {
string = 'string',
number = 'number',
2020-05-05 12:48:36 +02:00
boolean = 'boolean',
file = 'file',
folder = 'folder',
path = 'path'
2020-05-05 11:56:36 +02:00
}
interface Option {
name: string;
type: OptionType;
required?: boolean;
2020-05-05 12:48:36 +02:00
default?: unknown;
alias?: string;
env?: string;
2020-05-05 12:17:48 +02:00
}
interface OptionProcess extends Option {
filled: boolean;
2020-05-05 12:48:36 +02:00
value?: unknown;
2020-05-05 11:56:36 +02:00
}
export class InteractiveOptions extends Persistent {
2020-05-05 12:17:48 +02:00
protected options: Array<OptionProcess>;
2020-05-05 11:56:36 +02:00
public constructor (options: Array<Option>) {
super ();
2020-05-05 12:17:48 +02:00
this.options = options
.map ((v) => ({ filled: false, ...v } as OptionProcess));
for (const option of this.options) {
2020-05-05 11:56:36 +02:00
if (typeof option.default !== option.type) {
throw new Error (
`default does not match option type on ${option.name}`
);
}
this.properties[option.name] = option.type;
}
}
2020-05-05 12:17:48 +02:00
public async parse (): Promise<void> {
this.get_env_options ();
this.get_args_options ();
await this.get_interactive_options ();
}
2020-05-05 12:48:36 +02:00
private get unfilled (): Array<OptionProcess> {
return this.options.filter ((o) => !o.filled);
}
private async assign_arg (opt: OptionProcess, value: unknown): Promise<void> {
if (opt.type === OptionType.string) {
opt.value = value;
opt.filled = true;
return;
}
if (opt.type === OptionType.number) {
const as_num = parseInt (value);
const is_num = !isNaN (as_num);
if (is_num) {
opt.value = as_num;
opt.filled = true;
}
return;
}
if (opt.type === OptionType.boolean) {
const is_boo = (/^(?:true|false)$/ui).test (value);
if (is_boo) {
const as_boo = (/true/ui).test (value);
opt.value = as_boo;
opt.filled = true;
}
return;
}
if (
opt.type === OptionType.path
|| opt.type === OptionType.file
|| opt.type === OptionType.folder
) {
if (!await fs.pathExists (value))
return;
if (opt.type === OptionType.path) {
opt.value = value;
opt.filled = true;
return;
}
const stat = await fs.stat (value);
if (stat.isDirectory () === (opt.type === OptionType.folder)) {
opt.value = value;
opt.filled = true;
}
}
}
2020-05-05 12:17:48 +02:00
2020-05-05 12:48:36 +02:00
private async get_env_options (): void {
await Promise.all (this.options.map ((opt) => {
if (
typeof opt.env !== 'undefined'
&& typeof process.env[opt.env] !== 'undefined'
)
return this.assign_arg (opt, process.env[opt.env]);
return Promise.resolve ();
}));
2020-05-05 12:17:48 +02:00
}
2020-05-05 12:48:36 +02:00
private async get_args_options (): void {
2020-05-05 12:17:48 +02:00
}
private async get_interactive_options (): Promise<void> {
}
2020-05-05 11:56:36 +02:00
}