2020-05-05 13:32:40 +02:00
|
|
|
/*
|
|
|
|
* Copyright (C) Sapphirecode - All Rights Reserved
|
|
|
|
* This file is part of console-app which is released under MIT.
|
|
|
|
* See file 'LICENSE' for full license details.
|
|
|
|
* Created by Timo Hocker <timo@scode.ovh>, May 2020
|
|
|
|
*/
|
|
|
|
|
2020-05-06 08:34:21 +02:00
|
|
|
import { Persistent } from '@sapphirecode/modelling';
|
2020-05-09 19:51:43 +02:00
|
|
|
import { TypeValidation } from './Types/TypeValidation';
|
|
|
|
import { PathType } from './Types/PathType';
|
2020-05-09 21:30:37 +02:00
|
|
|
import { OptionType } from './OptionType';
|
2020-05-09 19:51:43 +02:00
|
|
|
import { OptionSource } from './Sources/OptionSource';
|
|
|
|
import { EnvSource } from './Sources/EnvSource';
|
|
|
|
import { ArgSource } from './Sources/ArgSource';
|
2020-05-18 19:18:02 +02:00
|
|
|
import { ConfigSource } from './Sources/ConfigSource';
|
2020-05-09 19:51:43 +02:00
|
|
|
import { InteractiveSource } from './Sources/InteractiveSource';
|
2020-05-09 21:30:37 +02:00
|
|
|
import { Option, OptionProcess } from './Option';
|
2020-05-09 19:51:43 +02:00
|
|
|
|
|
|
|
const types: Record<OptionType, TypeValidation> = {
|
|
|
|
string: new TypeValidation ('string'),
|
|
|
|
number: new TypeValidation ('number'),
|
|
|
|
boolean: new TypeValidation ('boolean'),
|
|
|
|
file: new PathType ('file'),
|
|
|
|
folder: new PathType ('folder'),
|
2020-05-09 21:30:37 +02:00
|
|
|
path: new PathType ('path'),
|
|
|
|
array: new TypeValidation ('array')
|
2020-05-09 19:51:43 +02:00
|
|
|
};
|
|
|
|
|
|
|
|
interface SourceConfig {
|
2020-05-18 19:18:02 +02:00
|
|
|
env?: boolean;
|
|
|
|
args?: boolean;
|
|
|
|
interactive?: boolean;
|
|
|
|
configs?: string[];
|
2020-05-22 11:50:07 +02:00
|
|
|
exit_on_interrupt?: boolean;
|
2020-05-07 12:19:19 +02:00
|
|
|
}
|
|
|
|
|
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-07 12:19:19 +02:00
|
|
|
protected quiet = false;
|
2020-05-09 19:51:43 +02:00
|
|
|
protected sources: OptionSource[] = [];
|
2020-05-05 12:17:48 +02:00
|
|
|
|
2020-05-09 19:51:43 +02:00
|
|
|
public constructor (
|
|
|
|
options: Array<Option>,
|
2020-05-18 19:18:02 +02:00
|
|
|
source_config: SourceConfig = {}
|
2020-05-09 19:51:43 +02:00
|
|
|
) {
|
2020-05-05 11:56:36 +02:00
|
|
|
super ();
|
2020-05-05 12:17:48 +02:00
|
|
|
this.options = options
|
2020-05-09 19:51:43 +02:00
|
|
|
.map ((v) => ({
|
|
|
|
filled: false,
|
|
|
|
type_validation: types[v.type],
|
|
|
|
...v
|
|
|
|
} as OptionProcess));
|
2020-05-05 12:17:48 +02:00
|
|
|
for (const option of this.options) {
|
2020-05-07 12:19:19 +02:00
|
|
|
if (
|
|
|
|
typeof option.default !== 'undefined'
|
2020-05-09 19:51:43 +02:00
|
|
|
&& typeof option.default !== option.type_validation.string_type
|
2020-05-07 12:19:19 +02:00
|
|
|
) {
|
|
|
|
throw new Error (
|
|
|
|
`default does not match option type on ${option.name}`
|
|
|
|
);
|
|
|
|
}
|
|
|
|
|
2020-05-09 21:30:37 +02:00
|
|
|
this.properties[option.name] = option.type_validation.persistent_type;
|
2020-05-05 11:56:36 +02:00
|
|
|
}
|
2020-05-09 19:51:43 +02:00
|
|
|
|
2020-05-22 11:50:07 +02:00
|
|
|
const exit_on_interrupt
|
|
|
|
= typeof source_config.exit_on_interrupt === 'boolean'
|
|
|
|
? source_config.exit_on_interrupt
|
|
|
|
: false;
|
|
|
|
|
2020-05-18 19:18:02 +02:00
|
|
|
if (
|
|
|
|
typeof source_config.configs !== 'undefined'
|
|
|
|
&& Array.isArray (source_config.configs)
|
|
|
|
)
|
|
|
|
this.sources.push (new ConfigSource (source_config.configs));
|
|
|
|
if (source_config.env !== false)
|
2020-05-09 19:51:43 +02:00
|
|
|
this.sources.push (new EnvSource);
|
2020-05-18 19:18:02 +02:00
|
|
|
if (source_config.args !== false)
|
2020-05-09 19:51:43 +02:00
|
|
|
this.sources.push (new ArgSource);
|
2020-05-18 19:18:02 +02:00
|
|
|
if (source_config.interactive !== false)
|
2020-05-22 11:50:07 +02:00
|
|
|
this.sources.push (new InteractiveSource (exit_on_interrupt));
|
2020-05-05 11:56:36 +02:00
|
|
|
}
|
2020-05-05 12:17:48 +02:00
|
|
|
|
2020-05-07 13:16:41 +02:00
|
|
|
public async parse (): Promise<Record<string, unknown>> {
|
2020-05-09 21:30:37 +02:00
|
|
|
for (const src of this.sources) {
|
2020-05-09 19:51:43 +02:00
|
|
|
// eslint-disable-next-line no-await-in-loop
|
|
|
|
await src.parse (this.options);
|
2020-05-09 21:30:37 +02:00
|
|
|
}
|
2020-05-07 14:00:52 +02:00
|
|
|
for (const opt of this.options)
|
|
|
|
this.set (opt.name, opt.value);
|
|
|
|
|
2020-05-07 13:16:41 +02:00
|
|
|
return this.to_object ();
|
2020-05-05 12:17:48 +02:00
|
|
|
}
|
2020-05-05 11:56:36 +02:00
|
|
|
}
|