diff --git a/README.md b/README.md index 1ccbd64..8810ca6 100644 --- a/README.md +++ b/README.md @@ -30,8 +30,7 @@ const reader = new InteractiveOptions([ description: 'the switch foo', // description in the help page (optional) message: 'should foo be true?', // message when asking interactively (optional) preset: [], // preset choices for string and path types (optional) - error: 'wrong input', // message to display when the user gives invalid input - error_callback: (opt, val, err)=>{...} // function to call when an option value could not be read + error: 'wrong input' // message to display when the user gives invalid input }, ]); @@ -78,7 +77,8 @@ const reader = new InteractiveOptions([], { env: true, interactive: true, configs: ['json files to search for options'], - exit_on_interrupt: true, + exit_on_interrupt: true, // exit when user cancels prompt + error_callback: (opt, val, err)=>{...} // function to call when an option value could not be read }); ``` diff --git a/lib/InteractiveOptions.ts b/lib/InteractiveOptions.ts index 64cb584..76fb21e 100644 --- a/lib/InteractiveOptions.ts +++ b/lib/InteractiveOptions.ts @@ -15,6 +15,7 @@ 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 = { string: new TypeValidation ('string'), @@ -32,6 +33,7 @@ interface SourceConfig { interactive?: boolean; configs?: string[]; exit_on_interrupt?: boolean; + error_callback?: ErrorCallback; } export class InteractiveOptions extends Persistent { @@ -71,14 +73,22 @@ export class InteractiveOptions extends Persistent { if ( typeof source_config.configs !== 'undefined' && Array.isArray (source_config.configs) - ) - this.sources.push (new ConfigSource (source_config.configs)); + ) { + this.sources.push (new ConfigSource ( + source_config.error_callback, + source_config.configs + )); + } if (source_config.env !== false) - this.sources.push (new EnvSource); + this.sources.push (new EnvSource (source_config.error_callback)); if (source_config.args !== false) - this.sources.push (new ArgSource); - if (source_config.interactive !== false) - this.sources.push (new InteractiveSource (exit_on_interrupt)); + this.sources.push (new ArgSource (source_config.error_callback)); + if (source_config.interactive !== false) { + this.sources.push (new InteractiveSource ( + source_config.error_callback, + exit_on_interrupt + )); + } } public async parse (): Promise> { diff --git a/lib/Option.ts b/lib/Option.ts index 621fe8b..2d5a77e 100644 --- a/lib/Option.ts +++ b/lib/Option.ts @@ -19,11 +19,6 @@ interface Option { message?: string; preset?: unknown[]; error?: string; - error_callback?: ( - option: string, - value: unknown, - e: Error - ) => unknown; } interface OptionProcess extends Option { diff --git a/lib/Sources/ConfigSource.ts b/lib/Sources/ConfigSource.ts index 2970c37..697eb6c 100644 --- a/lib/Sources/ConfigSource.ts +++ b/lib/Sources/ConfigSource.ts @@ -11,13 +11,14 @@ import fs from 'fs-extra'; import { run_regex } from '@sapphirecode/utilities'; import hjson from 'hjson'; import { OptionProcess } from '../Option'; +import { ErrorCallback } from '../Types/ErrorCallback'; import { OptionSource } from './OptionSource'; export class ConfigSource extends OptionSource { private _config_files: string[]; - public constructor (config_files: string[]) { - super (); + public constructor (error_callback?:ErrorCallback, config_files: string[]) { + super (error_callback); this._config_files = config_files; } @@ -53,7 +54,8 @@ export class ConfigSource extends OptionSource { for (const key of Object.keys (json)) data[key] = json[key]; } - catch { + catch (e) { + this.error_callback ('*', `config file: ${f}`, e); continue; } } diff --git a/lib/Sources/InteractiveSource.ts b/lib/Sources/InteractiveSource.ts index d3d2368..1823562 100644 --- a/lib/Sources/InteractiveSource.ts +++ b/lib/Sources/InteractiveSource.ts @@ -14,8 +14,11 @@ import { OptionSource } from './OptionSource'; export class InteractiveSource extends OptionSource { private _exit_on_interrupt: boolean; - public constructor (exit_on_interrupt: boolean) { - super (); + public constructor ( + error_callback?:ErrorCallback, + exit_on_interrupt: boolean + ) { + super (error_callback); this._exit_on_interrupt = exit_on_interrupt; } diff --git a/lib/Sources/OptionSource.ts b/lib/Sources/OptionSource.ts index 2214329..47a55bc 100644 --- a/lib/Sources/OptionSource.ts +++ b/lib/Sources/OptionSource.ts @@ -6,10 +6,17 @@ */ import { OptionProcess } from '../Option'; +import { ErrorCallback } from '../Types/ErrorCallback'; export abstract class OptionSource { public abstract async parse(opt: OptionProcess[]): Promise; + protected error_callback?: ErrorCallback; + + public constructor (error_callback?: ErrorCallback) { + this.error_callback = error_callback; + } + protected async assign_arg ( opt: OptionProcess, value: unknown @@ -19,8 +26,8 @@ export abstract class OptionSource { opt.filled = true; } catch (e) { - if (typeof opt.error_callback !== 'undefined') - opt.error_callback (opt.name, value, e); + if (typeof this.error_callback !== 'undefined') + this.error_callback (opt.name, value, e); } } } diff --git a/lib/Types/ErrorCallback.ts b/lib/Types/ErrorCallback.ts new file mode 100644 index 0000000..6207da9 --- /dev/null +++ b/lib/Types/ErrorCallback.ts @@ -0,0 +1,5 @@ +export type ErrorCallback = ( + option: string, + value: unknown, + e: Error +) => unknown;