starting to split options by type
This commit is contained in:
		| @@ -1,108 +0,0 @@ | |||||||
| /* |  | ||||||
|  * 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 |  | ||||||
|  */ |  | ||||||
|  |  | ||||||
| import { Persistent } from '@sapphirecode/modelling'; |  | ||||||
| import { TypeValidation } from './Types/TypeValidation'; |  | ||||||
| import { PathType } from './Types/PathType'; |  | ||||||
| import { OptionType } from './OptionType'; |  | ||||||
| import { OptionSource } from './Sources/OptionSource'; |  | ||||||
| import { EnvSource } from './Sources/EnvSource'; |  | ||||||
| import { ArgSource } from './Sources/ArgSource'; |  | ||||||
| import { ConfigSource } from './Sources/ConfigSource'; |  | ||||||
| import { InteractiveSource } from './Sources/InteractiveSource'; |  | ||||||
| import { Option, OptionProcess } from './Option'; |  | ||||||
| import { ErrorCallback } from './Types/ErrorCallback'; |  | ||||||
|  |  | ||||||
| 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'), |  | ||||||
|   array:   new TypeValidation ('array') |  | ||||||
| }; |  | ||||||
|  |  | ||||||
| interface SourceConfig { |  | ||||||
|   env?: boolean; |  | ||||||
|   args?: boolean; |  | ||||||
|   interactive?: boolean; |  | ||||||
|   configs?: string[]; |  | ||||||
|   exit_on_interrupt?: boolean; |  | ||||||
|   error_callback?: ErrorCallback; |  | ||||||
| } |  | ||||||
|  |  | ||||||
| export class InteractiveOptions extends Persistent { |  | ||||||
|   protected options: Array<OptionProcess>; |  | ||||||
|   protected quiet = false; |  | ||||||
|   protected sources: OptionSource[] = []; |  | ||||||
|  |  | ||||||
|   public constructor ( |  | ||||||
|     options: Array<Option>, |  | ||||||
|     source_config: SourceConfig = {} |  | ||||||
|   ) { |  | ||||||
|     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.persistent_type; |  | ||||||
|     } |  | ||||||
|  |  | ||||||
|     const exit_on_interrupt |  | ||||||
|       = typeof source_config.exit_on_interrupt === 'boolean' |  | ||||||
|         ? source_config.exit_on_interrupt |  | ||||||
|         : false; |  | ||||||
|  |  | ||||||
|     if ( |  | ||||||
|       typeof source_config.configs !== 'undefined' |  | ||||||
|       && Array.isArray (source_config.configs) |  | ||||||
|     ) { |  | ||||||
|       this.sources.push (new ConfigSource ( |  | ||||||
|         source_config.configs, |  | ||||||
|         source_config.error_callback |  | ||||||
|       )); |  | ||||||
|     } |  | ||||||
|     if (source_config.env !== false) |  | ||||||
|       this.sources.push (new EnvSource (source_config.error_callback)); |  | ||||||
|     if (source_config.args !== false) |  | ||||||
|       this.sources.push (new ArgSource (source_config.error_callback)); |  | ||||||
|     if (source_config.interactive !== false) { |  | ||||||
|       this.sources.push (new InteractiveSource ( |  | ||||||
|         exit_on_interrupt, |  | ||||||
|         source_config.error_callback |  | ||||||
|       )); |  | ||||||
|     } |  | ||||||
|   } |  | ||||||
|  |  | ||||||
|   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) { |  | ||||||
|       if (!opt.filled) { |  | ||||||
|         opt.value = opt.default; |  | ||||||
|         opt.filled = true; |  | ||||||
|       } |  | ||||||
|       this.set (opt.name, opt.value); |  | ||||||
|     } |  | ||||||
|     return this.to_object (); |  | ||||||
|   } |  | ||||||
| } |  | ||||||
| @@ -5,26 +5,31 @@ | |||||||
|  * Created by Timo Hocker <timo@scode.ovh>, May 2020 |  * Created by Timo Hocker <timo@scode.ovh>, May 2020 | ||||||
|  */ |  */ | ||||||
|  |  | ||||||
| import { TypeValidation } from './Types/TypeValidation'; | interface SourceConfig { | ||||||
| import { OptionType } from './OptionType'; |   console?: boolean, | ||||||
|  |   configs?: string[], | ||||||
|  |   env?: boolean, | ||||||
|  |   interactive?: boolean, | ||||||
|  | } | ||||||
|  |  | ||||||
| interface Option { | interface Option { | ||||||
|   name: string; |   name: string; | ||||||
|   type: OptionType; |  | ||||||
|   required?: boolean; |   required?: boolean; | ||||||
|   default?: unknown; |   default?: unknown; | ||||||
|   alias?: string; |   sources?: SourceConfig; | ||||||
|   env?: string; |  | ||||||
|   description?: string; |   /* | ||||||
|   message?: string; |    * alias?: string; | ||||||
|   preset?: unknown[]; |    * env?: string; | ||||||
|   error?: string; |    * message?: string; | ||||||
|  |    * preset?: unknown[]; | ||||||
|  |    * error?: string; | ||||||
|  |    */ | ||||||
| } | } | ||||||
|  |  | ||||||
| interface OptionProcess extends Option { | interface OptionValue { | ||||||
|   filled: boolean; |   filled: boolean; | ||||||
|   value?: unknown; |   value?: unknown; | ||||||
|   type_validation: TypeValidation; |  | ||||||
| } | } | ||||||
|  |  | ||||||
| export { Option, OptionProcess }; | export { Option, OptionValue }; | ||||||
|   | |||||||
| @@ -1,16 +0,0 @@ | |||||||
| /* |  | ||||||
|  * 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 |  | ||||||
|  */ |  | ||||||
|  |  | ||||||
| export type OptionType = |  | ||||||
|   'string' |  | ||||||
|   | 'number' |  | ||||||
|   | 'boolean' |  | ||||||
|   | 'file' |  | ||||||
|   | 'folder' |  | ||||||
|   | 'path' |  | ||||||
|   | 'array'; |  | ||||||
|  |  | ||||||
							
								
								
									
										0
									
								
								lib/Options/ArrayOption.ts
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										0
									
								
								lib/Options/ArrayOption.ts
									
									
									
									
									
										Normal file
									
								
							
							
								
								
									
										45
									
								
								lib/Options/BaseOption.ts
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										45
									
								
								lib/Options/BaseOption.ts
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,45 @@ | |||||||
|  | import { OptionSource } from '../Sources/OptionSource'; | ||||||
|  | import { Option } from '../Option'; | ||||||
|  | import { EnvSource } from '../Sources/EnvSource'; | ||||||
|  | import { ErrorCallback } from '../ErrorCallback'; | ||||||
|  | import { ArgSource } from '../Sources/ArgSource'; | ||||||
|  | import { ConfigSource } from '../Sources/ConfigSource'; | ||||||
|  | import { TypeValidation } from '../TypeValidation/TypeValidation'; | ||||||
|  |  | ||||||
|  | export abstract class BaseOption<T> { | ||||||
|  |   protected readonly sources: OptionSource[] = []; | ||||||
|  |   private _config: Option; | ||||||
|  |  | ||||||
|  |   public constructor ( | ||||||
|  |     config: Option, | ||||||
|  |     error_callback?: ErrorCallback, | ||||||
|  |     exit_on_interrupt = true | ||||||
|  |   ) { | ||||||
|  |     this._config = config; | ||||||
|  |  | ||||||
|  |     const sources = config.sources || {}; | ||||||
|  |     if (typeof sources.configs !== 'undefined') | ||||||
|  |       this.sources.push (new ConfigSource (sources.configs, error_callback)); | ||||||
|  |  | ||||||
|  |     if (sources.env !== false) | ||||||
|  |       this.sources.push (new EnvSource (error_callback)); | ||||||
|  |  | ||||||
|  |     if (sources.console !== false) | ||||||
|  |       this.sources.push (new ArgSource (error_callback)); | ||||||
|  |  | ||||||
|  |     if (sources.interactive !== false) { | ||||||
|  |       this.sources.push (new InteractiveSource ( | ||||||
|  |         exit_on_interrupt, | ||||||
|  |         error_callback | ||||||
|  |       )); | ||||||
|  |     } | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   protected abstract get validation(): TypeValidation; | ||||||
|  |  | ||||||
|  |   public async parse(): Promise<T> { | ||||||
|  |     for (let source of this.sources) { | ||||||
|  |       source.parse(this._config); | ||||||
|  |     } | ||||||
|  |   }; | ||||||
|  | } | ||||||
							
								
								
									
										0
									
								
								lib/Options/BooleanOption.ts
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										0
									
								
								lib/Options/BooleanOption.ts
									
									
									
									
									
										Normal file
									
								
							
							
								
								
									
										0
									
								
								lib/Options/FileOption.ts
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										0
									
								
								lib/Options/FileOption.ts
									
									
									
									
									
										Normal file
									
								
							
							
								
								
									
										0
									
								
								lib/Options/FolderOption.ts
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										0
									
								
								lib/Options/FolderOption.ts
									
									
									
									
									
										Normal file
									
								
							
							
								
								
									
										0
									
								
								lib/Options/NumberOption.ts
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										0
									
								
								lib/Options/NumberOption.ts
									
									
									
									
									
										Normal file
									
								
							
							
								
								
									
										0
									
								
								lib/Options/PathOption.ts
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										0
									
								
								lib/Options/PathOption.ts
									
									
									
									
									
										Normal file
									
								
							
							
								
								
									
										14
									
								
								lib/Options/StringOption.ts
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										14
									
								
								lib/Options/StringOption.ts
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,14 @@ | |||||||
|  | import { Option } from '../Option'; | ||||||
|  | import { BaseOption } from './BaseOption'; | ||||||
|  |  | ||||||
|  | export class StringOption extends BaseOption<string> { | ||||||
|  |   private _config: Option; | ||||||
|  |  | ||||||
|  |   public constructor (config: Option) { | ||||||
|  |     this._config = config; | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   public async parse (): Promise<string> { | ||||||
|  |  | ||||||
|  |   } | ||||||
|  | } | ||||||
| @@ -11,7 +11,7 @@ import fs from 'fs-extra'; | |||||||
| import { run_regex } from '@sapphirecode/utilities'; | import { run_regex } from '@sapphirecode/utilities'; | ||||||
| import hjson from 'hjson'; | import hjson from 'hjson'; | ||||||
| import { OptionProcess } from '../Option'; | import { OptionProcess } from '../Option'; | ||||||
| import { ErrorCallback } from '../Types/ErrorCallback'; | import { ErrorCallback } from '../ErrorCallback'; | ||||||
| import { OptionSource } from './OptionSource'; | import { OptionSource } from './OptionSource'; | ||||||
|  |  | ||||||
| export class ConfigSource extends OptionSource { | export class ConfigSource extends OptionSource { | ||||||
|   | |||||||
| @@ -9,7 +9,7 @@ | |||||||
| /* eslint-disable no-process-exit */ | /* eslint-disable no-process-exit */ | ||||||
| import { Confirm, Input, List, AutoComplete } from 'enquirer'; | import { Confirm, Input, List, AutoComplete } from 'enquirer'; | ||||||
| import { OptionProcess, Option } from '../Option'; | import { OptionProcess, Option } from '../Option'; | ||||||
| import { ErrorCallback } from '../Types/ErrorCallback'; | import { ErrorCallback } from '../ErrorCallback'; | ||||||
| import { OptionSource } from './OptionSource'; | import { OptionSource } from './OptionSource'; | ||||||
|  |  | ||||||
| export class InteractiveSource extends OptionSource { | export class InteractiveSource extends OptionSource { | ||||||
|   | |||||||
| @@ -5,11 +5,11 @@ | |||||||
|  * Created by Timo Hocker <timo@scode.ovh>, May 2020 |  * Created by Timo Hocker <timo@scode.ovh>, May 2020 | ||||||
|  */ |  */ | ||||||
|  |  | ||||||
| import { OptionProcess } from '../Option'; | import { ErrorCallback } from '../ErrorCallback'; | ||||||
| import { ErrorCallback } from '../Types/ErrorCallback'; | import { OptionValue, Option } from '../Option'; | ||||||
|  |  | ||||||
| export abstract class OptionSource { | export abstract class OptionSource { | ||||||
|   public abstract async parse(opt: OptionProcess[]): Promise<void>; |   public abstract async parse(opt: Option, value: OptionValue): Promise<void>; | ||||||
|  |  | ||||||
|   protected error_callback?: ErrorCallback; |   protected error_callback?: ErrorCallback; | ||||||
|  |  | ||||||
| @@ -18,7 +18,7 @@ export abstract class OptionSource { | |||||||
|   } |   } | ||||||
|  |  | ||||||
|   protected async assign_arg ( |   protected async assign_arg ( | ||||||
|     opt: OptionProcess, |     opt: OptionValue, | ||||||
|     value: unknown |     value: unknown | ||||||
|   ): Promise<void> { |   ): Promise<void> { | ||||||
|     try { |     try { | ||||||
|   | |||||||
							
								
								
									
										12
									
								
								lib/TypeRegister.ts
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										12
									
								
								lib/TypeRegister.ts
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,12 @@ | |||||||
|  | import { TypeValidation } from './TypeValidation/TypeValidation'; | ||||||
|  | import { PathType } from './TypeValidation/PathType'; | ||||||
|  |  | ||||||
|  | export 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'), | ||||||
|  |   array:   new TypeValidation ('array') | ||||||
|  | }; | ||||||
| @@ -6,7 +6,7 @@ | |||||||
|  */ |  */ | ||||||
|  |  | ||||||
| import test from 'ava'; | import test from 'ava'; | ||||||
| import { PathType } from '../lib/Types/PathType'; | import { PathType } from '../lib/TypeValidation/PathType'; | ||||||
|  |  | ||||||
| test ('no file', async (t) => { | test ('no file', async (t) => { | ||||||
|   const validator = new PathType ('file'); |   const validator = new PathType ('file'); | ||||||
|   | |||||||
| @@ -6,7 +6,7 @@ | |||||||
|  */ |  */ | ||||||
|  |  | ||||||
| import test from 'ava'; | import test from 'ava'; | ||||||
| import { TypeValidation } from '../lib/Types/TypeValidation'; | import { TypeValidation } from '../lib/TypeValidation/TypeValidation'; | ||||||
|  |  | ||||||
| test ('string', async (t) => { | test ('string', async (t) => { | ||||||
|   const validator = new TypeValidation ('string'); |   const validator = new TypeValidation ('string'); | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user