import { LoadingState } from "../reusable/states/LoadingState"; import { ErrorState } from "../reusable/states/ErrorState"; import { SkeletosTransaction } from "../base/SkeletosTransaction"; import { SkeletosCursor } from "../base/SkeletosCursor"; import { ISkeletosCommand } from "./ISkeletosCommand"; import { AbstractSkeletosState } from "./AbstractSkeletosState"; import { AbstractProgressAction } from "./AbstractProgressAction"; /** * A Skeletos action is the place where you would modify any Skeletos state. For example, you can * modify state based on some user interaction, or you can modify state as a result of retrieving data from the server. * You can even modify state "in anticipation" of modification calls to the server before the calls are returned (a * technique known as optimistic updates). * * 1. An action is composed of multiple commands. The action can execute these commands in parallel, sequentially or * in some defined order. Under the covers, the action uses async.auto(..) to determine the pipeline of commands * that need to be executed. See getCommands(..). * * 2. Each action gets a unique SkeletosTransaction which it uses to perform all state modifications under. Whenever * an error occurs as part of the action's commands, this transaction is rolled back. * * 3. Every action can have some loading or error state that you can set. When set, the action will set loading in * loading state at the beginning of the action, and will unset loading in the loading state at the end of the action. * Additionally, if error state is set, the action will use error state to post details of the errorMessage. */ export declare abstract class AbstractSkeletosAction extends AbstractProgressAction { protected _loadingState: LoadingState; protected _errorState: ErrorState; private _transaction; private _rootCursor; /** * Creates a new action. * * If you have attributes/variables that you want to initialize, do it in the * AbstractSkeletosAction#doBeforeExecute(). That function is a good chance to initialize variables instead of * initializing variables in the constructor. The problem with initializing variables in the constructor is that if * this action is encapsulated within another action, then you may not currently have all the data to initialize * variables with. * * @param dbOrTransaction Supply the database on top of which you want to performance the action or the transaction * you want to use. If you supply a database, a new transaction will be created for you. * @param loadingState * @param errorState */ constructor(rootCursor: SkeletosCursor, loadingState?: LoadingState, errorState?: ErrorState); /** * This method gets called right before the action is executed. It is a good chance to initialize variables instead * of initializing variables in the constructor. The problem with initializing variables in the constructor is that * if this action is encapsulated within another action, then you may not currently have all the data to initialize * variables with. For example, you may not have the proper SkeletosTransaction to reconstruct the SkeletosStates * with. * * For this reason, this overridden method goes through each field of type AbstractSkeletosState and makes sure * that it is constructed with the transaction this action was supplied with. * * This action also shows the loading action. * * Make sure you call super.doBeforExecute(..) in your subclass overridden method. */ protected doBeforeExecute(): void; /** * Gets the root cursor of the database we are operating on. * * For example, if you need to get a new RootStateWeb, you can do: * `const rootState: RootStateWeb = new RootStateWeb(this.rootCursor(), ... );` * * @returns {SkeletosCursor} */ protected readonly rootCursor: SkeletosCursor; /** * Returns the Root State as per the supplied stateClass constructor. * * @param stateClass * @returns {any} */ protected getRootState(stateClass: typeof AbstractSkeletosState): RootStateType; /** * Returns a mutable root state that can stay mutated even after there is an error in this action that incurs a * rollback for the transaction. Hence why the mutation is "sticky". * * Use this mutable root state only when you want to modify the root state before you throw an error, and if you * want this mutation to not be part of the rollback of this action's transaction. * * @param {typeof AbstractSkeletosState} stateClass * @returns {RootStateType} */ protected getStickyMutableRootState(stateClass: typeof AbstractSkeletosState): RootStateType; /** * That transaction that is used to track all the modifications. */ protected readonly transaction: SkeletosTransaction; /** * Function that gets called when the action completes either successfully or with an error. * * @param err */ protected doAfterExecute(err?: Error): void; /** * Override this to provide a custom loading message. The message will be inserted into loadingState if it was * defined. * * @returns {string} */ protected getLoadingMessage(): string; /** * When specifying the command map in getCommands(..), use this function to wrap another action within this action. * * @param action */ protected callAnotherAction(action: AbstractSkeletosAction): ISkeletosCommand; /** * Display loading errorMessage and increases the loading count. * * @param message * @param executeAsCommand whether this action is being executed as a command of another action * @returns {function(ErrorCallback=): void} */ private showLoading; }