@sheetxl/models
Version:
Models - A Headless javascript spreadsheet library.
196 lines • 8.74 kB
TypeScript
import { RemoveListener } from "@sheetxl/common";
/**
* Used for transactional state.
* This represents a single record change.
* This is used by transactional operations, undo/redo, version control, and distributed state.
* This also includes eventing but this is only for eventing for the final writes to the transaction
* store any local eventing needs to be handled by the record itself.
*/
export interface ChangeSet<STATE, INPUTS> {
state: STATE;
/**
* Inputs are values that are not part of the state but were used to calculate the state.
* This is done because we want to allow different for inputs. For example
* selection is considered an input because in a multi view environment we may
* not want to selection to change if another view updates the data/state.
*/
inputs?: INPUTS;
prevState: STATE | null;
/**Unique Identifier for the change */
uuid: string;
}
export interface TransactionalUpdateStateOptions<STATE = any, INPUTS = undefined> {
uuid?: string;
description?: string;
isUndo?: boolean;
record: any;
/**
* The previous state will be:
* The state of a previous transaction + any child transactions.
*/
state: ((prev: STATE) => STATE) | STATE;
/**
* The previous input will be:
* The inputs from child transactions. (but not from previous transactions)
*/
inputs?: ((prev: INPUTS) => INPUTS) | INPUTS;
}
export interface TransactionStoreListener<STATE = any, INPUTS = undefined> {
/**
* Called when a change set is committed to the global changeset.
* This is a map of unique ids to change sets.
*
* @param changes
* @param description
*/
onChange(changes: Map<any, ChangeSet<STATE, INPUTS>>, description: string): void;
/**
* Called when all transactions are cleared. Handlers should clear their state.
* For example undo should clear the undo stack.
*/
onClear?(uuid: string): void;
}
export interface ChangeSetListener<STATE = any, INPUTS = undefined> {
/**
* Called during a transaction this is when changes should be applied
*/
onRecordChange?(change: ChangeSet<STATE, INPUTS>, description: string, record: any, isUndo?: boolean): void;
/**
* Called at the end of a transaction.
*/
onAfterRecordChange?(change: ChangeSet<STATE, INPUTS>, description: string, record: any): void;
/**
* Called synchronously at the beginning of a transaction before a record is changed.
*
* If this throws an exception then all records within the transaction will not
* be applied.
*/
onBeforeRecordChange?(uuid: string, description: string, record: any, newInputs: INPUTS): void;
/**
* Called when all transactions are cleared. Handlers should clear their state.
* For example undo should clear the undo stack.
*/
onClear?(uuid: string): void;
}
/**
* Objects that support interfacing with a transactional store implement this interface.
*/
export interface ITransactionStack {
/**
* Begins a transaction but puts it onto a global stack.
* This will batch all 'transactional' changes until they have all be committed or rolled back.
*
* @remarks
* Any changes that are made to this object will be reflected in the local sheet but
* not committed to the transactional store until the batch is popped.
*
* @param description
*/
pushTransaction(description?: string): ITransaction;
}
export declare const setTransactionStoreSync: (isSync: boolean) => void;
export interface ITransaction {
/**
* Begin a transaction with self contained, non-eventing updates
* @remarks
*
* Context is useful for debugging and logging.
* This is treated as a stack so it's fifo. This means
* that when finally committed to global changeset
* that only the final context will be maintained.
* @param description The description of the transaction
* @param onClose A callback for when the transaction is closed (due to either a commit or rollback)
* @param isUndo A hint to indicate if the transaction should be support undo.
*/
beginTransaction(description?: string, onClose?: (transaction: ITransaction) => void, isUndo?: boolean): ITransaction;
/**
* Commit the transaction and all children transactions to the parent changeset.
*/
commit(): ITransaction;
/**
* Discard all changes and children transaction changes.
*/
rollback(): ITransaction;
/**
* If root transaction will return self
*/
parent(): ITransaction;
/**
* unique id for this transaction. This will be the same id for all sub transactions.
*/
readonly uuid: string;
readonly depth: number;
readonly description: string;
readonly isUndo: boolean;
updateState<STATE = any, INPUTS = undefined>(options: TransactionalUpdateStateOptions<STATE, INPUTS>): ChangeSet<STATE, INPUTS>;
getChangeSet<STATE = any, INPUTS = undefined>(record: any): ChangeSet<STATE, INPUTS>;
getState<STATE = any>(record: any): STATE;
}
declare abstract class AbstractTransaction implements ITransaction {
protected _mapRecordToChanges: Map<any, ChangeSet<any, any>>;
protected _children: Set<AbstractTransaction>;
protected _updatingStates: any[];
protected _depth: number;
protected _lookupCache: any;
protected _description: string;
protected _isUndo: boolean;
constructor(description?: string, isUndo?: boolean);
get depth(): number;
/**
* Creates a child transaction
*/
beginTransaction(description?: string, onClose?: (transaction: ITransaction) => void, isUndo?: boolean): ITransaction;
protected _removeChild(child: AbstractTransaction): void;
updateStates<STATE = any, INPUTS = undefined>(uuid: string, recordsToChanges: Map<any, ChangeSet<any, any>>, options: Omit<TransactionalUpdateStateOptions<STATE, INPUTS>, 'record' | 'state'>): Map<any, ChangeSet<any, any>>;
updateState<STATE = any, INPUTS = undefined>(options: TransactionalUpdateStateOptions<STATE, INPUTS>): ChangeSet<STATE, INPUTS>;
getState<STATE = any>(record: any): STATE;
abstract getChangeSet<STATE = any, INPUTS = undefined>(record: any): ChangeSet<STATE, INPUTS>;
abstract commit(): ITransaction;
abstract rollback(): ITransaction;
/**
* If root transaction will return self
*/
abstract parent(): ITransaction;
abstract get uuid(): string;
get description(): string;
get isUndo(): boolean;
}
/**
* Events are never fired on sub transactions. Only when making changes to the root
* either directly or through a final commit. Any models that want to fire non transactional
* events should do this directly.
*/
export default class TransactionStore extends AbstractTransaction implements ITransaction {
private _listeners;
private _listenersChangeSet;
private _transactionStack;
private _isSync;
constructor(isSync?: boolean);
peekTransaction(): ITransaction;
get uuid(): string;
/**
* calls beginTransaction but adds to a shared stack
*/
pushTransaction(description: string, onClose?: (transaction: ITransaction) => void, isUndo?: boolean): ITransaction;
clear(record: any): void;
commit(): ITransaction;
rollback(): ITransaction;
parent(): ITransaction;
getChangeSet<STATE = any, INPUTS = undefined>(record: any): ChangeSet<STATE, INPUTS>;
updateState<STATE = any, INPUTS = undefined>(options: TransactionalUpdateStateOptions<STATE, INPUTS>): ChangeSet<STATE, INPUTS>;
updateStates<STATE = any, INPUTS = undefined>(uuid: string, recordsToChanges: Map<any, ChangeSet<any, any>>, options: TransactionalUpdateStateOptions<STATE, INPUTS>): Map<any, ChangeSet<any, any>>;
addListener(listener: TransactionStoreListener): RemoveListener;
/**
* Fired when information at a specific record is changed.
* This will be fired both during a commit and during a change to the global store
*/
addChangeSetListener<STATE = any, INPUTS = undefined>(record: any, listener: ChangeSetListener<STATE, INPUTS>): RemoveListener;
private dispatchEvents;
notifyRecordChange(changes: ChangeSet<any, any>, description: string, record: any, isUndo: boolean): void;
notifyBeforeChange(uuid: string, description: string, record: any, newInputs: any): void;
notifyAfterChange(changes: ChangeSet<any, any>, description: string, record: any): void;
notifyChange(changes: Map<any, ChangeSet<any, any>>, description: string): void;
notifyClear(uuid: string, record: any): void;
}
export { TransactionStore };
//# sourceMappingURL=Transaction.d.ts.map