import type { CTAState, } from '../types/CTAState'; import type { DefaultActionsRecord, } from '../types/DefaultActionsRecord'; /** * Options for configuring action type behavior * @prop {boolean} [useDefault=] - When true, bypasses the use of an overridden action. */ export type ActionTypeOptions = { useDefault?: boolean }; export type ActionTypeConstructParam< Payload extends CTAState, Type extends keyof DefaultActionsRecord, > = { actionTypeOptions?: ActionTypeOptions hasAugmentedAction: boolean payload: Parameters[Type]>[1] type: Type }; export class ActionType< Payload extends CTAState, Type extends keyof DefaultActionsRecord, > { readonly type: ActionTypeConstructParam['type']; readonly payload: Readonly['payload']>; readonly actionTypeOptions: ActionTypeOptions; constructor( param: ActionTypeConstructParam, ) { this.type = param.type; this.payload = param.payload; this.actionTypeOptions = param.hasAugmentedAction ? { ...param?.actionTypeOptions, } : { useDefault: true, }; } } function _hasAugmentedAction( actions: Actions, type: keyof DefaultActionsRecord>, ) { return Boolean( actions && typeof actions === 'object' && type in actions, ); } export class UpdateInitialActionType< Payload extends CTAState, > extends ActionType { constructor( param: Pick, 'actionTypeOptions' | 'payload' | 'hasAugmentedAction'>, ) { super( { ...param, type: 'updateInitial', }, ); } } export function createUpdateInitialActionType< Payload extends CTAState, Actions, >( actions: Actions, ) { const hasAction = _hasAugmentedAction( actions, 'updateInitial', ); return function updateActionType( payload: ActionTypeConstructParam['payload'], actionTypeOptions?: ActionTypeOptions, ) { return new UpdateInitialActionType( { actionTypeOptions, hasAugmentedAction: hasAction, payload, }, ); }; } export class ResetActionType< Payload extends CTAState, > extends ActionType { constructor( param: Pick, 'actionTypeOptions' | 'payload' | 'hasAugmentedAction'>, ) { super( { ...param, type: 'reset', }, ); } } export function createResetActionType< Payload extends CTAState, Actions, >( actions: Actions, ) { const hasAction = _hasAugmentedAction( actions, 'reset', ); return function resetActionType( payload?: ActionTypeConstructParam['payload'], actionTypeOptions?: ActionTypeOptions, ) { return new ResetActionType( { actionTypeOptions, hasAugmentedAction: hasAction, payload, }, ); }; } export class UpdateActionType< Payload extends CTAState, > extends ActionType { constructor( param: Pick< ActionTypeConstructParam< Payload, 'update' >, 'actionTypeOptions' | 'payload' | 'hasAugmentedAction' >, ) { super( { ...param, type: 'update', }, ); } } export function createUpdateActionType< Payload extends CTAState, Actions, >( actions: Actions, ) { const hasAugmentedAction = _hasAugmentedAction( actions, 'update', ); return function updateActionType( payload: ActionTypeConstructParam['payload'], actionTypeOptions?: ActionTypeOptions, ) { return new UpdateActionType( { actionTypeOptions, hasAugmentedAction, payload, }, ); }; } export class ReplaceActionType< Payload extends CTAState, > extends ActionType { constructor( param: Pick< ActionTypeConstructParam< Payload, 'replace' >, 'actionTypeOptions' | 'payload' | 'hasAugmentedAction' >, ) { super( { ...param, type: 'replace', }, ); } } export function createReplaceActionType< Payload extends CTAState, Actions, >( actions: Actions, ) { const hasAugmentedAction = _hasAugmentedAction( actions, 'replace', ); return function replaceActionType( payload: ActionTypeConstructParam['payload'], actionTypeOptions?: ActionTypeOptions, ) { return new ReplaceActionType( { actionTypeOptions, hasAugmentedAction, payload, }, ); }; } export class ReplaceInitialActionType< Payload extends CTAState, > extends ActionType { constructor( param: Pick< ActionTypeConstructParam< Payload, 'replaceInitial' >, 'actionTypeOptions' | 'payload' | 'hasAugmentedAction' >, ) { super( { ...param, type: 'replaceInitial', }, ); } } export function createReplaceInitialActionType< Payload extends CTAState, Actions, >( actions: Actions, ) { const hasAugmentedAction = _hasAugmentedAction( actions, 'replaceInitial', ); return function replaceInitialActionType( payload: ActionTypeConstructParam['payload'], actionTypeOptions?: ActionTypeOptions, ) { return new ReplaceInitialActionType( { actionTypeOptions, hasAugmentedAction, payload, }, ); }; }