85 lines
		
	
	
		
			2.6 KiB
		
	
	
	
		
			TypeScript
		
	
	
	
	
	
			
		
		
	
	
			85 lines
		
	
	
		
			2.6 KiB
		
	
	
	
		
			TypeScript
		
	
	
	
	
	
| /* eslint-disable no-process-exit */
 | |
| /* eslint-disable no-console */
 | |
| /*
 | |
|  * 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
 | |
|  */
 | |
| 
 | |
| /* eslint-disable max-lines-per-function */
 | |
| /* eslint-disable complexity */
 | |
| /* eslint-disable max-statements */
 | |
| /* eslint-disable no-process-env */
 | |
| import { Persistent } from '@sapphirecode/modelling';
 | |
| import { TypeValidation } from './Types/TypeValidation';
 | |
| import { PathType } from './Types/PathType';
 | |
| import { Option, OptionProcess, OptionType } from './Types';
 | |
| import { OptionSource } from './Sources/OptionSource';
 | |
| import { EnvSource } from './Sources/EnvSource';
 | |
| import { ArgSource } from './Sources/ArgSource';
 | |
| import { InteractiveSource } from './Sources/InteractiveSource';
 | |
| 
 | |
| 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'),
 | |
|   path:    new PathType ('path')
 | |
| };
 | |
| 
 | |
| interface SourceConfig {
 | |
|   env: boolean;
 | |
|   args: boolean;
 | |
|   interactive: boolean;
 | |
| }
 | |
| 
 | |
| export class InteractiveOptions extends Persistent {
 | |
|   protected options: Array<OptionProcess>;
 | |
|   protected quiet = false;
 | |
|   protected sources: OptionSource[] = [];
 | |
| 
 | |
|   public constructor (
 | |
|     options: Array<Option>,
 | |
|     source_config: SourceConfig = { args: true, env: true, interactive: true }
 | |
|   ) {
 | |
|     super ();
 | |
|     this.options = options
 | |
|       .map ((v) => ({
 | |
|         filled:          false,
 | |
|         type_validation: types[v.type],
 | |
|         ...v
 | |
|       } as OptionProcess));
 | |
|     for (const option of this.options) {
 | |
|       if (
 | |
|         typeof option.default !== 'undefined'
 | |
|         && typeof option.default !== option.type_validation.string_type
 | |
|       ) {
 | |
|         throw new Error (
 | |
|           `default does not match option type on ${option.name}`
 | |
|         );
 | |
|       }
 | |
| 
 | |
|       this.properties[option.name] = option.type_validation.string_type;
 | |
|     }
 | |
| 
 | |
|     if (source_config.env)
 | |
|       this.sources.push (new EnvSource);
 | |
|     if (source_config.args)
 | |
|       this.sources.push (new ArgSource);
 | |
|     if (source_config.interactive)
 | |
|       this.sources.push (new InteractiveSource);
 | |
|   }
 | |
| 
 | |
|   public async parse (): Promise<Record<string, unknown>> {
 | |
|     for (const src of this.sources)
 | |
|       // eslint-disable-next-line no-await-in-loop
 | |
|       await src.parse (this.options);
 | |
|     for (const opt of this.options)
 | |
|       this.set (opt.name, opt.value);
 | |
| 
 | |
|     return this.to_object ();
 | |
|   }
 | |
| }
 |