import { ActionType , ArgumentType , CLIArgumentType , ParamDefinition , ParamDefinitionsMap , TaskArguments , TaskDefinition } from '../../../types' ; import { RedspotError } from '../errors' ; import { ErrorDescriptor , ERRORS } from '../errors-list' ; import * as types from '../params/argumentTypes' ; import { REDSPOT_PARAM_DEFINITIONS } from '../params/redspot-params' ; function isCLIArgumentType ( type ) { return 'parse' in type ; } /**
 * This class creates a task definition, which consists of:
 * * a name, that should be unique and will be used to call the task.
 * * a description. This is optional.
 * * the action that the task will execute.
 * * a set of parameters that can be used by the action.
 *
 */ export class SimpleTaskDefinition implements TaskDefinition { get description ( ) { return this . _description ; } public readonly paramDefinitions : ParamDefinitionsMap = { } ; public readonly positionalParamDefinitions : Array < ParamDefinition < any > > = [ ] ; public action : ActionType < TaskArguments > ; private _positionalParamNames : Set < string > ; private _hasVariadicParam : boolean ; private _hasOptionalPositionalParam : boolean ; private _description ? : string ; param name param isSubtask constructor ( public readonly name , public readonly isSubtask = false ) { this . _positionalParamNames = new Set ( ) ; this . _hasVariadicParam = false ; this . _hasOptionalPositionalParam = false ; this . action = ( ) => { throw new RedspotError ( ERRORS . TASK_DEFINITIONS . ACTION_NOT_SET , { taskName : name } ) ; } ; } param description public setDescription ( description ) { this . _description = description ; return this ; } param action public setAction < ArgsT extends TaskArguments > ( action ) { this . action = action ; return this ; } remarks param name param description param defaultValue param type param isOptional public addParam < T > ( name , description ? , defaultValue ? , type ? , isOptional = defaultValue !== undefined ) { if ( type === undefined ) { if ( defaultValue === undefined ) { return this . addParam ( name , description , undefined , types . string , isOptional ) ; } if ( typeof defaultValue !== 'string' ) { throw new RedspotError ( ERRORS . TASK_DEFINITIONS . DEFAULT_VALUE_WRONG_TYPE , { paramName : name , taskName : this . name } ) ; } return this . addParam ( name , description , defaultValue , types . string , isOptional ) ; } this . _validateParamNameCasing ( name ) ; this . _validateNameNotUsed ( name ) ; this . _validateNoDefaultValueForMandatoryParam ( defaultValue , isOptional , name ) ; this . _validateCLIArgumentTypesForExternalTasks ( type ) ; this . paramDefinitions [ name ] = { name , defaultValue , type , description , isOptional , isFlag : false , isVariadic : false } ; return this ; } see addParam . param name param description param defaultValue param type public addOptionalParam < T > ( name , description ? , defaultValue ? , type ? ) { return this . addParam ( name , description , defaultValue , type , true ) ; } param name param description public addFlag ( name , description ? ) { this . _validateParamNameCasing ( name ) ; this . _validateNameNotUsed ( name ) ; this . paramDefinitions [ name ] = { name , defaultValue : false , type : types . boolean , description , isFlag : true , isOptional : true , isVariadic : false } ; return this ; } remarks remarks remarks param name param description param defaultValue param type param isOptional public addPositionalParam < T > ( name , description ? , defaultValue ? , type ? , isOptional = defaultValue !== undefined ) { if ( type === undefined ) { if ( defaultValue === undefined ) { return this . addPositionalParam ( name , description , undefined , types . string , isOptional ) ; } if ( typeof defaultValue !== 'string' ) { throw new RedspotError ( ERRORS . TASK_DEFINITIONS . DEFAULT_VALUE_WRONG_TYPE , { paramName : name , taskName : this . name } ) ; } return this . addPositionalParam ( name , description , defaultValue , types . string , isOptional ) ; } this . _validateParamNameCasing ( name ) ; this . _validateNameNotUsed ( name ) ; this . _validateNotAfterVariadicParam ( name ) ; this . _validateNoMandatoryParamAfterOptionalOnes ( name , isOptional ) ; this . _validateNoDefaultValueForMandatoryParam ( defaultValue , isOptional , name ) ; this . _validateCLIArgumentTypesForExternalTasks ( type ) ; const definition = { name , defaultValue , type , description , isVariadic : false , isOptional , isFlag : false } ; this . _addPositionalParamDefinition ( definition ) ; return this ; } see addPositionalParam . param name param description param defaultValue param type public addOptionalPositionalParam < T > ( name , description ? , defaultValue ? , type ? ) { return this . addPositionalParam ( name , description , defaultValue , type , true ) ; } param name param description param defaultValue param type param isOptional public addVariadicPositionalParam < T > ( name , description ? , defaultValue ? , type ? , isOptional = defaultValue !== undefined ) { if ( defaultValue !== undefined && ! Array . isArray ( defaultValue ) ) { defaultValue = [ defaultValue ] ; } if ( type === undefined ) { if ( defaultValue === undefined ) { return this . addVariadicPositionalParam ( name , description , undefined , types . string , isOptional ) ; } if ( ! this . _isStringArray ( defaultValue ) ) { throw new RedspotError ( ERRORS . TASK_DEFINITIONS . DEFAULT_VALUE_WRONG_TYPE , { paramName : name , taskName : this . name } ) ; } return this . addVariadicPositionalParam ( name , description , defaultValue , types . string , isOptional ) ; } this . _validateParamNameCasing ( name ) ; this . _validateNameNotUsed ( name ) ; this . _validateNotAfterVariadicParam ( name ) ; this . _validateNoMandatoryParamAfterOptionalOnes ( name , isOptional ) ; this . _validateNoDefaultValueForMandatoryParam ( defaultValue , isOptional , name ) ; this . _validateCLIArgumentTypesForExternalTasks ( type ) ; const definition = { name , defaultValue , type , description , isVariadic : true , isOptional , isFlag : false } ; this . _addPositionalParamDefinition ( definition ) ; return this ; } param name param description param defaultValue param type public addOptionalVariadicPositionalParam < T > ( name , description ? , defaultValue ? , type ? ) { return this . addVariadicPositionalParam ( name , description , defaultValue , type , true ) ; } param definition private _addPositionalParamDefinition ( definition ) { if ( definition . isVariadic ) { this . _hasVariadicParam = true ; } if ( definition . isOptional ) { this . _hasOptionalPositionalParam = true ; } this . _positionalParamNames . add ( definition . name ) ; this . positionalParamDefinitions . push ( definition ) ; } param name throws private _validateNotAfterVariadicParam ( name ) { if ( this . _hasVariadicParam ) { throw new RedspotError ( ERRORS . TASK_DEFINITIONS . PARAM_AFTER_VARIADIC , { paramName : name , taskName : this . name } ) ; } } param name throws throws private _validateNameNotUsed ( name ) { if ( this . _hasParamDefined ( name ) ) { throw new RedspotError ( ERRORS . TASK_DEFINITIONS . PARAM_ALREADY_DEFINED , { paramName : name , taskName : this . name } ) ; } if ( Object . keys ( REDSPOT_PARAM_DEFINITIONS ) . includes ( name ) ) { throw new RedspotError ( ERRORS . TASK_DEFINITIONS . PARAM_CLASHES_WITH_REDSPOT_PARAM , { paramName : name , taskName : this . name } ) ; } } param name private _hasParamDefined ( name ) { return ( this . paramDefinitions [ name ] !== undefined || this . _positionalParamNames . has ( name ) ) ; } param name param isOptional throws private _validateNoMandatoryParamAfterOptionalOnes ( name , isOptional ) { if ( ! isOptional && this . _hasOptionalPositionalParam ) { throw new RedspotError ( ERRORS . TASK_DEFINITIONS . MANDATORY_PARAM_AFTER_OPTIONAL , { paramName : name , taskName : this . name } ) ; } } private _validateParamNameCasing ( name ) { const pattern = /^[a-z]+([a-zA-Z0-9])*$/ ; const match = pattern . exec ( name ) ; if ( match === null ) { throw new RedspotError ( ERRORS . TASK_DEFINITIONS . INVALID_PARAM_NAME_CASING , { paramName : name , taskName : this . name } ) ; } } private _validateNoDefaultValueForMandatoryParam ( defaultValue , isOptional , name ) { if ( defaultValue !== undefined && ! isOptional ) { throw new RedspotError ( ERRORS . TASK_DEFINITIONS . DEFAULT_IN_MANDATORY_PARAM , { paramName : name , taskName : this . name } ) ; } } private _isStringArray ( values ) { return Array . isArray ( values ) && values . every ( ( v ) => typeof v === 'string' ) ; } private _validateCLIArgumentTypesForExternalTasks ( type ) { if ( this . isSubtask ) { return ; } if ( ! isCLIArgumentType ( type ) ) { throw new RedspotError ( ERRORS . TASK_DEFINITIONS . CLI_ARGUMENT_TYPE_REQUIRED , { task : this . name , type : type . name } ) ; } } } /**
 * Allows you to override a previously defined task.
 *
 * When overriding a task you can:
 *  * flag it as a subtask
 *  * set a new description
 *  * set a new action
 *
 */ export class OverriddenTaskDefinition implements TaskDefinition { private _description ? : string ; private _action ? : ActionType < TaskArguments > ; constructor ( public readonly parentTaskDefinition , public readonly isSubtask = false ) { this . isSubtask = isSubtask ; this . parentTaskDefinition = parentTaskDefinition ; } public setDescription ( description ) { this . _description = description ; return this ; } param action public setAction < ArgsT extends TaskArguments > ( action ) { this . _action = action ; return this ; } /**
     * Retrieves the parent task's name.
     */ get name ( ) { return this . parentTaskDefinition . name ; } /**
     * Retrieves, if defined, the description of the overriden task,
     * otherwise retrieves the description of the parent task.
     */ get description ( ) { if ( this . _description !== undefined ) { return this . _description ; } return this . parentTaskDefinition . description ; } /**
     * Retrieves, if defined, the action of the overriden task,
     * otherwise retrieves the action of the parent task.
     */ get action ( ) { if ( this . _action !== undefined ) { return this . _action ; } return this . parentTaskDefinition . action ; } /**
     * Retrieves the parent task's param definitions.
     */ get paramDefinitions ( ) { return this . parentTaskDefinition . paramDefinitions ; } /**
     * Retrieves the parent task's positional param definitions.
     */ get positionalParamDefinitions ( ) { return this . parentTaskDefinition . positionalParamDefinitions ; } /**
     * Overriden tasks can't add new parameters.
     */ public addParam < T > ( name , description ? , defaultValue ? , type ? , isOptional ? ) { if ( isOptional === undefined || ! isOptional ) { return this . _throwNoParamsOverrideError ( ERRORS . TASK_DEFINITIONS . OVERRIDE_NO_MANDATORY_PARAMS ) ; } return this . addOptionalParam ( name , description , defaultValue , type ) ; } /**
     * Overriden tasks can't add new parameters.
     */ public addOptionalParam < T > ( name , description ? , defaultValue ? , type ? ) { this . parentTaskDefinition . addOptionalParam ( name , description , defaultValue , type ) ; return this ; } /**
     * Overriden tasks can't add new parameters.
     */ public addPositionalParam < T > ( name , description ? , defaultValue ? , type ? , isOptional ? ) { return this . _throwNoParamsOverrideError ( ERRORS . TASK_DEFINITIONS . OVERRIDE_NO_POSITIONAL_PARAMS ) ; } /**
     * Overriden tasks can't add new parameters.
     */ public addOptionalPositionalParam < T > ( name , description ? , defaultValue ? , type ? ) { return this . _throwNoParamsOverrideError ( ERRORS . TASK_DEFINITIONS . OVERRIDE_NO_POSITIONAL_PARAMS ) ; } /**
     * Overriden tasks can't add new parameters.
     */ public addVariadicPositionalParam < T > ( name , description ? , defaultValue ? , type ? , isOptional ? ) { return this . _throwNoParamsOverrideError ( ERRORS . TASK_DEFINITIONS . OVERRIDE_NO_VARIADIC_PARAMS ) ; } /**
     * Overriden tasks can't add new parameters.
     */ public addOptionalVariadicPositionalParam < T > ( name , description ? , defaultValue ? , type ? ) { return this . _throwNoParamsOverrideError ( ERRORS . TASK_DEFINITIONS . OVERRIDE_NO_VARIADIC_PARAMS ) ; } throws throws public addFlag ( name , description ? ) { this . parentTaskDefinition . addFlag ( name , description ) ; return this ; } private _throwNoParamsOverrideError ( errorDescriptor ) { throw new RedspotError ( errorDescriptor , { taskName : this . name } ) ; } }