tinybase
Version:
A reactive data store and sync engine.
7,599 lines • 268 kB
TypeScript
/**
* The store module is the core of the TinyBase project and contains the types,
* interfaces, and functions to work with Store objects.
*
* The main entry point to this module is the createStore function, which
* returns a new Store. From there, you can set and get data, register
* listeners, and use other modules to build an entire app around the state and
* tabular data within.
* @packageDocumentation
* @module store
* @since v1.0.0
*/
import type {StoreAlias} from '../_internal/store/index.d.ts';
import type {Id, IdOrNull, Ids, Json} from '../common/index.d.ts';
/**
* The TablesSchema type describes the tabular structure of a Store in terms of
* valid Table Ids and the types of Cell that can exist within them.
*
* A TablesSchema comprises a JavaScript object describing each Table, in turn a
* nested JavaScript object containing information about each Cell and its
* CellSchema. It is provided to the setTablesSchema method.
* @example
* When applied to a Store, this TablesSchema only allows one Table called
* `pets`, in which each Row may contain a string `species` Cell, and is
* guaranteed to contain a boolean `sold` Cell that defaults to `false`.
*
* ```js
* import type {TablesSchema} from 'tinybase';
*
* export const tableSchema: TablesSchema = {
* pets: {
* species: {type: 'string'},
* sold: {type: 'boolean', default: false},
* },
* };
* ```
* @category Schema
* @since v1.0.0
*/
export type TablesSchema = {[tableId: Id]: {[cellId: Id]: CellSchema}};
/**
* The CellSchema type describes what values are allowed for each Cell in a
* Table.
*
* A CellSchema specifies the type of the Cell (`string`, `boolean`, or
* `number`), and what the default value can be when an explicit value is not
* specified.
*
* If a default value is provided (and its type is correct), you can be certain
* that that Cell will always be present in a Row.
*
* If the default value is _not_ provided (or its type is incorrect), the Cell
* may be missing from the Row, but when present you can be guaranteed it is of
* the correct type.
* @example
* When applied to a Store, this CellSchema ensures a boolean Cell is always
* present, and defaults it to `false`.
*
* ```js
* import type {CellSchema} from 'tinybase';
*
* export const requiredBoolean: CellSchema = {
* type: 'boolean',
* default: false,
* };
* ```
* @category Schema
* @since v1.0.0
*/
export type CellSchema =
| {type: 'string'; default?: string}
| {type: 'number'; default?: number}
| {type: 'boolean'; default?: boolean};
/**
* The ValuesSchema type describes the keyed Values that can be set in a Store
* and their types.
*
* A ValuesSchema comprises a JavaScript object describing each Value and its
* ValueSchema. It is provided to the setValuesSchema method.
* @example
* When applied to a Store, this ValuesSchema only allows one boolean Value
* called `open`, that defaults to `false`.
*
* ```js
* import type {ValuesSchema} from 'tinybase';
*
* export const valuesSchema: ValuesSchema = {
* open: {type: 'boolean', default: false},
* };
* ```
* @category Schema
* @since v3.0.0
*/
export type ValuesSchema = {[valueId: Id]: ValueSchema};
/**
* The ValueSchema type describes what values are allowed for keyed Values in a
* Store.
*
* A ValueSchema specifies the type of the Value (`string`, `boolean`, or
* `number`), and what the default value can be when an explicit value is not
* specified.
*
* If a default value is provided (and its type is correct), you can be certain
* that the Value will always be present in a Store.
*
* If the default value is _not_ provided (or its type is incorrect), the Value
* may not be present in the Store, but when present you can be guaranteed it is
* of the correct type.
* @example
* When applied to a Store, this ValueSchema ensures a boolean Value is always
* present, and defaults it to `false`.
*
* ```js
* import type {ValueSchema} from 'tinybase';
*
* export const requiredBoolean: ValueSchema = {
* type: 'boolean',
* default: false,
* };
* ```
* @category Schema
* @since v3.0.0
*/
export type ValueSchema =
| {type: 'string'; default?: string}
| {type: 'number'; default?: number}
| {type: 'boolean'; default?: boolean};
/**
* The NoTablesSchema type is a TablesSchema-like type for when one has not been
* provided.
* @category Schema
* @since v1.0.0
*/
export type NoTablesSchema = {[tableId: Id]: {[cellId: Id]: {type: 'any'}}};
/**
* The NoValuesSchema type is a ValuesSchema-like type for when one has not been
* provided.
* @category Schema
* @since v1.0.0
*/
export type NoValuesSchema = {[valueId: Id]: {type: 'any'}};
/**
* The OptionalTablesSchema type is used by generic types that can optionally
* take a TablesSchema.
* @category Schema
* @since v1.0.0
*/
export type OptionalTablesSchema = TablesSchema | NoTablesSchema;
/**
* The OptionalValuesSchema type is used by generic types that can optionally
* take a ValuesSchema.
* @category Schema
* @since v1.0.0
*/
export type OptionalValuesSchema = ValuesSchema | NoValuesSchema;
/**
* The OptionalSchemas type is used by generic types that can optionally take
* either or both of a TablesSchema and ValuesSchema.
* @category Schema
* @since v1.0.0
*/
export type OptionalSchemas = [OptionalTablesSchema, OptionalValuesSchema];
/**
* The NoSchemas type is used as a default by generic types that can optionally
* take either or both of a TablesSchema and ValuesSchema.
* @category Schema
* @since v1.0.0
*/
export type NoSchemas = [NoTablesSchema, NoValuesSchema];
/**
* The Content type describes both the Tables and Values in a Store.
*
* It is an array of two objects, representing tabular and keyed value content.
* @example
* The following is a valid Content array:
* ```json
* [
* {
* "pets": {
* "fido": {
* "sold": false,
* "price": 4,
* },
* "felix": {
* "sold": true,
* "price": 5,
* },
* },
* },
* {
* open: true,
* employees: 3,
* },
* ]
* ```
* @category Store
* @since v5.0.0
*/
export type Content = [Tables, Values];
/**
* The Tables type is the data structure representing all of the data in a
* Store.
*
* A Tables object is used when setting all of the tables together with the
* setTables method, and when getting them back out again with the getTables
* method. A Tables object is a regular JavaScript object containing individual
* Table objects, keyed by their Id.
* @example
* ```js
* import type {Tables} from 'tinybase';
*
* export const tables: Tables = {
* pets: {
* fido: {species: 'dog', color: 'brown'},
* felix: {species: 'cat'},
* },
* species: {
* dog: {price: 5},
* cat: {price: 4},
* },
* };
* ```
* @category Store
* @since v1.0.0
*/
export type Tables = {[tableId: Id]: Table};
/**
* The Table type is the data structure representing the data in a single table.
*
* A Table is used when setting a table with the setTable method, and when
* getting it back out again with the getTable method. A Table object is a
* regular JavaScript object containing individual Row objects, keyed by their
* Id.
* @example
* ```js
* import type {Table} from 'tinybase';
*
* export const table: Table = {
* fido: {species: 'dog', color: 'brown'},
* felix: {species: 'cat'},
* };
* ```
* @category Store
* @since v1.0.0
*/
export type Table = {[rowId: Id]: Row};
/**
* The Row type is the data structure representing the data in a single row.
*
* A Row is used when setting a row with the setRow method, and when getting it
* back out again with the getRow method. A Row object is a regular JavaScript
* object containing individual Cell objects, keyed by their Id.
* @example
* ```js
* import type {Row} from 'tinybase';
*
* export const row: Row = {species: 'dog', color: 'brown'};
* ```
* @category Store
* @since v1.0.0
*/
export type Row = {[cellId: Id]: Cell};
/**
* The Cell type is the data structure representing the data in a single cell.
*
* A Cell is used when setting a cell with the setCell method, and when getting
* it back out again with the getCell method. A Cell is a JavaScript string,
* number, or boolean.
* @example
* ```js
* import type {Cell} from 'tinybase';
*
* export const cell: Cell = 'dog';
* ```
* @category Store
* @since v1.0.0
*/
export type Cell = string | number | boolean;
/**
* The CellOrUndefined type is a data structure representing the data in a
* single cell, or the value `undefined`.
*
* This is used when describing a Cell that is present _or_ that is not present,
* such as when it has been deleted, or when describing a previous state where
* the Cell value has since been added.
* @category Store
* @since v1.0.0
*/
export type CellOrUndefined = Cell | undefined;
/**
* The Values type is the data structure representing all the keyed values in a
* Store.
*
* A Values object is used when setting values with the setValues method, and
* when getting them back out again with the getValues method. A Values object
* is a regular JavaScript object containing individual Value objects, keyed by
* their Id.
* @example
* ```js
* import type {Values} from 'tinybase';
*
* export const values: Values = {open: true, employees: 4};
* ```
* @category Store
* @since v3.0.0
*/
export type Values = {[valueId: Id]: Value};
/**
* The Value type is the data structure representing the data in a single keyed
* value.
*
* A Value is used when setting a value with the setValue method, and when
* getting it back out again with the getValue method. A Value is a JavaScript
* string, number, or boolean.
* @example
* ```js
* import type {Value} from 'tinybase';
*
* export const value: Value = 'dog';
* ```
* @category Store
* @since v3.0.0
*/
export type Value = string | number | boolean;
/**
* The ValueOrUndefined type is a data structure representing the data in a
* single value, or the value `undefined`.
*
* This is used when describing a Value that is present _or_ that is not
* present, such as when it has been deleted, or when describing a previous
* state where the Value has since been added.
* @category Store
* @since v3.0.0
*/
export type ValueOrUndefined = Value | undefined;
/**
* The TableCallback type describes a function that takes a Table's Id and a
* callback to loop over each Row within it.
*
* A TableCallback is provided when using the forEachTable method, so that you
* can do something based on every Table in the Store. See that method for
* specific examples.
* @param tableId The Id of the Table that the callback can operate on.
* @param forEachRow A function that will let you iterate over the Row objects
* in this Table.
* @category Callback
* @since v1.0.0
*/
export type TableCallback = (
tableId: Id,
forEachRow: (rowCallback: RowCallback) => void,
) => void;
/**
* The TableCellCallback type describes a function that takes a Cell's Id and
* the count of times it appears across a whole Table.
*
* A TableCellCallback is provided when using the forEachTableCell method, so
* that you can do something based on every Cell used across a Table. See that
* method for specific examples.
* @param cellId The Id of the Cell that the callback can operate on.
* @param count The number of times this Cell is used across a whole Table.
* @category Callback
* @since v1.0.0
*/
export type TableCellCallback = (cellId: Id, count: number) => void;
/**
* The RowCallback type describes a function that takes a Row's Id and a
* callback to loop over each Cell within it.
*
* A RowCallback is provided when using the forEachRow method, so that you can
* do something based on every Row in a Table. See that method for specific
* examples.
* @param rowId The Id of the Row that the callback can operate on.
* @param forEachCell A function that will let you iterate over the Cell values
* in this Row.
* @category Callback
* @since v1.0.0
*/
export type RowCallback = (
rowId: Id,
forEachCell: (cellCallback: CellCallback) => void,
) => void;
/**
* The CellCallback type describes a function that takes a Cell's Id and its
* value.
*
* A CellCallback is provided when using the forEachCell method, so that you can
* do something based on every Cell in a Row. See that method for specific
* examples.
* @param cellId The Id of the Cell that the callback can operate on.
* @param cell The value of the Cell.
* @category Callback
* @since v1.0.0
*/
export type CellCallback = (cellId: Id, cell: Cell) => void;
/**
* The ValueCallback type describes a function that takes a Value's Id and its
* actual value.
*
* A ValueCallback is provided when using the forEachValue method, so that you
* can do something based on every Value in a Store. See that method for
* specific examples.
* @param valueId The Id of the Value that the callback can operate on.
* @param value The Value itself.
* @category Callback
* @since v3.0.0
*/
export type ValueCallback = (valueId: Id, value: Value) => void;
/**
* The MapCell type describes a function that takes an existing Cell value and
* returns another.
*
* A MapCell can be provided in the setCell method to map an existing value to a
* new one, such as when incrementing a number. See that method for specific
* examples.
* @param cell The current value of the Cell to map to a new value.
* @category Callback
* @since v1.0.0
*/
export type MapCell = (cell: CellOrUndefined) => Cell;
/**
* The MapValue type describes a function that takes an existing Value and
* returns another.
*
* A MapValue can be provided in the setValue method to map an existing Value to
* a new one, such as when incrementing a number. See that method for specific
* examples.
* @param value The current Value to map to a new Value.
* @category Callback
* @since v3.0.0
*/
export type MapValue = (value: ValueOrUndefined) => Value;
/**
* The GetCell type describes a function that takes a Id and returns the Cell
* value for a particular Row.
*
* A GetCell can be provided when setting definitions, as in the
* setMetricDefinition method of a Metrics object, or the setIndexDefinition
* method of an Indexes object. See those methods for specific examples.
* @param cellId The Id of the Cell to fetch the value for.
* @category Callback
* @since v1.0.0
*/
export type GetCell = (cellId: Id) => CellOrUndefined;
/**
* The IdAddedOrRemoved type describes a change made to an Id in either the
* tabular or keyed-value part of the Store (or in other TinyBase modules).
*
* This type is used in other types like ChangedTableIds, ChangedRowIds,
* ChangedCellIds, and ChangedValueIds, as well as in other events or listeners
* where a list of Ids has changed.
*
* It is a simple number: a 1 indicates that a given Id was added to a list of
* Ids, and a -1 indicates that it was removed.
* @category Transaction
* @since v4.0.0
*/
export type IdAddedOrRemoved = 1 | -1;
/**
* The ChangedTableIds type describes the Table Ids that were added or removed
* during a transaction.
*
* It is available to the DoRollback function and to a TransactionListener
* function via the TransactionLog object.
*
* It is a simple object that has Table Id as key, and an IdAddedOrRemoved
* number indicating whether the Table Id was added (1) or removed (-1).
*
* Note that there will be no entry if the content of the Table itself changed.
* For that you should consult the ChangedRowIds, ChangedCellIds, or
* ChangedCells types.
* @category Transaction
* @since v4.0.0
*/
export type ChangedTableIds = {[tableId: Id]: IdAddedOrRemoved};
/**
* The ChangedRowIds type describes the Row Ids that were added or removed
* during a transaction.
*
* It is available to the DoRollback function and to a TransactionListener
* function via the TransactionLog object.
*
* It is a nested object that has Table Id as a top-level key, and then Row Id
* as an inner key. The values of the inner objects are IdAddedOrRemoved numbers
* indicating whether the Row Id was added (1) or removed (-1) to the given
* Table.
*
* Note that there will be no entry if the content of the Row itself changed.
* For that you should consult the ChangedCellIds or ChangedCells types.
* @category Transaction
* @since v4.0.0
*/
export type ChangedRowIds = {[tableId: Id]: {[rowId: Id]: IdAddedOrRemoved}};
/**
* The ChangedCellIds type describes the Cell Ids that were added or removed
* during a transaction.
*
* It is available to the DoRollback function and to a TransactionListener
* function via the TransactionLog object.
*
* It is a nested object that has Table Id as a top-level key, and Row Id, and
* then CellId as inner keys. The values of the inner objects are
* IdAddedOrRemoved numbers indicating whether the Cell Id was added (1) or
* removed (-1) to the given Row.
*
* Note that there will be no entry if the content of the Cell itself changed.
* For that you should consult the ChangedCells type.
* @category Transaction
* @since v4.0.0
*/
export type ChangedCellIds = {
[tableId: Id]: {[rowId: Id]: {[cellId: Id]: IdAddedOrRemoved}};
};
/**
* The ChangedValueIds type describes the Value Ids that were added or removed
* during a transaction.
*
* It is available to the DoRollback function and to a TransactionListener
* function via the TransactionLog object.
*
* It is a simple object that has Value Id as key, and an IdAddedOrRemoved
* number indicating whether the Value Id was added (1) or removed (-1).
*
* Note that there will be no entry if the content of the Value itself changed.
* For that you should consult the ChangedValues type.
* @category Transaction
* @since v4.0.0
*/
export type ChangedValueIds = {[valueId: Id]: IdAddedOrRemoved};
/**
* The DoRollback type describes a function that you can use to rollback the
* transaction if it did not complete to your satisfaction.
*
* A DoRollback can be provided when calling the transaction method or the
* finishTransaction method. See those methods for specific examples.
*
* Since v5.0, this function is called with the Store as a single argument. You
* can use the getTransactionChanges method and getTransactionLog method of the
* Store directly to decide whether to do the rollback.
* @param store A reference to the Store that is completing a transaction.
* @category Callback
* @since v1.0.0
*/
export type DoRollback = (store: Store) => boolean;
/**
* The TransactionListener type describes a function that is used to listen to
* the completion of a transaction for the Store.
*
* A TransactionListener is provided when using the
* addWillFinishTransactionListener and addDidFinishTransactionListener methods.
* See those methods for specific examples.
*
* Since v5.0, this listener is called with no arguments other than the Store.
* You can use the getTransactionChanges method and getTransactionLog method of
* the Store directly to get information about the changes made within the
* transaction.
* @param store A reference to the Store that is completing a transaction.
* @category Listener
* @since v1.0.0
*/
export type TransactionListener<Store extends StoreAlias = StoreAlias> = (
store: Store,
) => void;
/**
* The HasTablesListener type describes a function that is used to listen to
* Tables as a whole being added to or removed from the Store.
*
* A HasTablesListener is provided when using the addHasTablesListener method.
* See that method for specific examples.
*
* When called, a HasTablesListener is given a reference to the Store. It is
* also given a flag to indicate whether Tables now exist (having not done
* previously), or do not (having done so previously).
* @param store A reference to the Store that changed.
* @param hasTables Whether Tables now exist or not.
* @category Listener
* @since v4.4.0
*/
export type HasTablesListener<Store extends StoreAlias = StoreAlias> = (
store: Store,
hasTables: boolean,
) => void;
/**
* The TablesListener type describes a function that is used to listen to
* changes to the tabular part of the Store.
*
* A TablesListener is provided when using the addTablesListener method. See
* that method for specific examples.
*
* When called, a TablesListener is given a reference to the Store and a
* GetCellChange function that can be used to query Cell values before and after
* the current transaction.
*
* Note that if the listener was manually forced to be called (with the
* callListener method rather than due to a real change in the Store), the
* GetCellChange function will not be present.
* @param store A reference to the Store that changed.
* @param getCellChange A function that returns information about any Cell's
* changes.
* @category Listener
* @since v1.0.0
*/
export type TablesListener<Store extends StoreAlias = StoreAlias> = (
store: Store,
getCellChange: GetCellChange | undefined,
) => void;
/**
* The TableIdsListener type describes a function that is used to listen to
* changes to the Table Ids in the Store.
*
* A TableIdsListener is provided when using the addTableIdsListener method. See
* that method for specific examples.
*
* When called, a TableIdsListener is given a reference to the Store.
*
* Since v3.3, the listener is also passed a GetIdChanges function that can be
* used to query which Ids changed during the transaction.
* @param store A reference to the Store that changed.
* @param getIdChanges A function that returns information about the Id changes,
* since v3.3.
* @category Listener
* @since v1.0.0
*/
export type TableIdsListener<Store extends StoreAlias = StoreAlias> = (
store: Store,
getIdChanges: GetIdChanges | undefined,
) => void;
/**
* The HasTableListener type describes a function that is used to listen to a
* Table being added to or removed from the Store.
*
* A HasTableListener is provided when using the addHasTableListener method. See
* that method for specific examples.
*
* When called, a HasTableListener is given a reference to the Store, and the Id
* of the Table that changed. It is also given a flag to indicate whether the
* Table now exists (having not done previously), or does not (having done so
* previously).
* @param store A reference to the Store that changed.
* @param tableId The Id of the Table that changed.
* @param hasTable Whether the Table now exists or not.
* @category Listener
* @since v4.4.0
*/
export type HasTableListener<Store extends StoreAlias = StoreAlias> = (
store: Store,
tableId: Id,
hasTable: boolean,
) => void;
/**
* The TableListener type describes a function that is used to listen to changes
* to a Table.
*
* A TableListener is provided when using the addTableListener method. See that
* method for specific examples.
*
* When called, a TableListener is given a reference to the Store, the Id of the
* Table that changed, and a GetCellChange function that can be used to query
* Cell values before and after the current transaction.
*
* Note that if the listener was manually forced to be called (with the
* callListener method rather than due to a real change in the Store), the
* GetCellChange function will not be present.
* @param store A reference to the Store that changed.
* @param tableId The Id of the Table that changed.
* @param getCellChange A function that returns information about any Cell's
* changes.
* @category Listener
* @since v1.0.0
*/
export type TableListener<Store extends StoreAlias = StoreAlias> = (
store: Store,
tableId: Id,
getCellChange: GetCellChange | undefined,
) => void;
/**
* The TableCellIdsListener type describes a function that is used to listen to
* changes to the Cell Ids that appear anywhere in a Table.
*
* A TableCellIdsListener is provided when using the addTableCellIdsListener
* method. See that method for specific examples.
*
* When called, a TableCellIdsListener is given a reference to the Store, the Id
* of the Table whose Cell Ids changed, and a GetIdChanges function that can be
* used to query which Ids changed during the transaction.
* @param store A reference to the Store that changed.
* @param tableId The Id of the Table that changed.
* @param getIdChanges A function that returns information about the Id changes.
* @category Listener
* @since v3.3.0
*/
export type TableCellIdsListener<Store extends StoreAlias = StoreAlias> = (
store: Store,
tableId: Id,
getIdChanges: GetIdChanges | undefined,
) => void;
/**
* The HasTableCellListener type describes a function that is used to listen to
* a Cell being added to or removed from a Table as a whole.
*
* A HasTableCellListener is provided when using the addHasTableCellListener
* method. See that method for specific examples.
*
* When called, a HasTableCellListener is given a reference to the Store, the Id
* of the Table that changed, and the Id of the Cell that changed. It is also
* given a flag to indicate whether the Cell now exists anywhere in the Table
* (having not done previously), or does not (having done so previously).
* @param store A reference to the Store that changed.
* @param tableId The Id of the Table that changed.
* @param cellId The Id of the Table Cell that changed.
* @param hasTableCell Whether the Cell now exists anywhere in the Table or not.
* @category Listener
* @since v4.4.0
*/
export type HasTableCellListener<Store extends StoreAlias = StoreAlias> = (
store: Store,
tableId: Id,
cellId: Id,
hasTableCell: boolean,
) => void;
/**
* The RowCountListener type describes a function that is used to listen to
* changes to the number of Row objects in a Table.
*
* A RowCountListener is provided when using the addRowCountListener method. See
* that method for specific examples.
*
* When called, a RowCountListener is given a reference to the Store, the Id of
* the Table whose Row Ids changed, and the number of Row objects in the Table.
* @param store A reference to the Store that changed.
* @param tableId The Id of the Table that changed.
* @param count The number of Row objects in the Table.
* @category Listener
* @since v4.1.0
*/
export type RowCountListener<Store extends StoreAlias = StoreAlias> = (
store: Store,
tableId: Id,
count: number,
) => void;
/**
* The RowIdsListener type describes a function that is used to listen to
* changes to the Row Ids in a Table.
*
* A RowIdsListener is provided when using the addRowIdsListener method. See
* that method for specific examples.
*
* When called, a RowIdsListener is given a reference to the Store, and the Id
* of the Table whose Row Ids changed.
*
* Since v3.3, the listener is also passed a GetIdChanges function that can be
* used to query which Ids changed during the transaction.
* @param store A reference to the Store that changed.
* @param tableId The Id of the Table that changed.
* @param getIdChanges A function that returns information about the Id changes,
* since v3.3.
* @category Listener
* @since v1.0.0
*/
export type RowIdsListener<Store extends StoreAlias = StoreAlias> = (
store: Store,
tableId: Id,
getIdChanges: GetIdChanges | undefined,
) => void;
/**
* The SortedRowIdsListener type describes a function that is used to listen to
* changes to sorted Row Ids in a Table.
*
* A SortedRowIdsListener is provided when using the addSortedRowIdsListener
* method. See that method for specific examples.
*
* When called, a SortedRowIdsListener is given a reference to the Store, the Id
* of the Table whose Row Ids sorting changed, the Cell Id being used to sort
* them, whether descending or not, and the offset and limit of the number of
* Ids returned, for pagination purposes. It also receives the sorted array of
* Ids itself, so that you can use them in the listener without the additional
* cost of an explicit call to getSortedRowIds.
* @param store A reference to the Store that changed.
* @param tableId The Id of the Table whose sorted Row Ids changed.
* @param cellId The Id of the Cell whose values were used for the sorting.
* @param descending Whether the sorting was in descending order.
* @param offset The number of Row Ids skipped.
* @param limit The maximum number of Row Ids returned.
* @param sortedRowIds The sorted Row Ids themselves.
* @category Listener
* @since v2.0.0
*/
export type SortedRowIdsListener<Store extends StoreAlias = StoreAlias> = (
store: Store,
tableId: Id,
cellId: Id | undefined,
descending: boolean,
offset: number,
limit: number | undefined,
sortedRowIds: Ids,
) => void;
/**
* The HasRowListener type describes a function that is used to listen to a Row
* being added to or removed from the Store.
*
* A HasRowListener is provided when using the addHasRowListener method. See
* that method for specific examples.
*
* When called, a HasRowListener is given a reference to the Store, the Id of
* the Table that changed, and the Id of the Row that changed. It is also given
* a flag to indicate whether the Row now exists (having not done previously),
* or does not (having done so previously).
* @param store A reference to the Store that changed.
* @param tableId The Id of the Table that changed.
* @param rowId The Id of the Row that changed.
* @param hasRow Whether the Row now exists or not.
* @category Listener
* @since v4.4.0
*/
export type HasRowListener<Store extends StoreAlias = StoreAlias> = (
store: Store,
tableId: Id,
rowId: Id,
hasRow: boolean,
) => void;
/**
* The RowListener type describes a function that is used to listen to changes
* to a Row.
*
* A RowListener is provided when using the addRowListener method. See that
* method for specific examples.
*
* When called, a RowListener is given a reference to the Store, the Id of the
* Table that changed, the Id of the Row that changed, and a GetCellChange
* function that can be used to query Cell values before and after the current
* transaction.
*
* Note that if the listener was manually forced to be called (with the
* callListener method rather than due to a real change in the Store), the
* GetCellChange function will not be present.
* @param store A reference to the Store that changed.
* @param tableId The Id of the Table that changed.
* @param rowId The Id of the Row that changed.
* @param getCellChange A function that returns information about any Cell's
* changes.
* @category Listener
* @since v1.0.0
*/
export type RowListener<Store extends StoreAlias = StoreAlias> = (
store: Store,
tableId: Id,
rowId: Id,
getCellChange: GetCellChange | undefined,
) => void;
/**
* The CellIdsListener type describes a function that is used to listen to
* changes to the Cell Ids in a Row.
*
* A CellIdsListener is provided when using the addCellIdsListener method. See
* that method for specific examples.
*
* When called, a CellIdsListener is given a reference to the Store, the Id of
* the Table that changed, and the Id of the Row whose Cell Ids changed.
*
* Since v3.3, the listener is also passed a GetIdChanges function that can be
* used to query which Ids changed during the transaction.
* @param store A reference to the Store that changed.
* @param tableId The Id of the Table that changed.
* @param rowId The Id of the Row that changed.
* @param getIdChanges A function that returns information about the Id changes,
* since v3.3.
* @category Listener
* @since v1.0.0
*/
export type CellIdsListener<Store extends StoreAlias = StoreAlias> = (
store: Store,
tableId: Id,
rowId: Id,
getIdChanges: GetIdChanges | undefined,
) => void;
/**
* The HasCellListener type describes a function that is used to listen to a
* Cell being added to or removed from the Store.
*
* A HasCellListener is provided when using the addHasCellListener method. See
* that method for specific examples.
*
* When called, a HasCellListener is given a reference to the Store, the Id of
* the Table that changed, the Id of the Row that changed, and the Id of Cell
* that changed. It is also given a flag to indicate whether the Cell now exists
* (having not done previously), or does not (having done so previously).
* @param store A reference to the Store that changed.
* @param tableId The Id of the Table that changed.
* @param rowId The Id of the Row that changed.
* @param cellId The Id of the Cell that changed.
* @param hasCell Whether the Cell now exists or not.
* @category Listener
* @since v4.4.0
*/
export type HasCellListener<Store extends StoreAlias = StoreAlias> = (
store: Store,
tableId: Id,
rowId: Id,
cellId: Id,
hasCell: boolean,
) => void;
/**
* The CellListener type describes a function that is used to listen to changes
* to a Cell.
*
* A CellListener is provided when using the addCellListener method. See that
* method for specific examples.
*
* When called, a CellListener is given a reference to the Store, the Id of the
* Table that changed, the Id of the Row that changed, and the Id of Cell that
* changed. It is also given the new value of the Cell, the old value of the
* Cell, and a GetCellChange function that can be used to query Cell values
* before and after the current transaction.
*
* Note that if the listener was manually forced to be called (with the
* callListener method rather than due to a real change in the Store), the
* GetCellChange function will not be present and the new and old values of the
* Cell will be the same.
* @param store A reference to the Store that changed.
* @param tableId The Id of the Table that changed.
* @param rowId The Id of the Row that changed.
* @param cellId The Id of the Cell that changed.
* @param newCell The new value of the Cell that changed.
* @param oldCell The old value of the Cell that changed.
* @param getCellChange A function that returns information about any Cell's
* changes.
* @category Listener
* @since v1.0.0
*/
export type CellListener<Store extends StoreAlias = StoreAlias> = (
store: Store,
tableId: Id,
rowId: Id,
cellId: Id,
newCell: Cell,
oldCell: Cell,
getCellChange: GetCellChange | undefined,
) => void;
/**
* The HasValuesListener type describes a function that is used to listen to
* Values as a whole being added to or removed from the Store.
*
* A HasValuesListener is provided when using the addHasValuesListener method.
* See that method for specific examples.
*
* When called, a HasValuesListener is given a reference to the Store. It is
* also given a flag to indicate whether Values now exist (having not done
* previously), or do not (having done so previously).
* @param store A reference to the Store that changed.
* @param hasValues Whether Values now exist or not.
* @category Listener
* @since v4.4.0
*/
export type HasValuesListener<Store extends StoreAlias = StoreAlias> = (
store: Store,
hasValues: boolean,
) => void;
/**
* The ValuesListener type describes a function that is used to listen to
* changes to all the Values in a Store.
*
* A ValuesListener is provided when using the addValuesListener method. See
* that method for specific examples.
*
* When called, a ValuesListener is given a reference to the Store and a
* GetValueChange function that can be used to query Values before and after the
* current transaction.
*
* Note that if the listener was manually forced to be called (with the
* callListener method rather than due to a real change in the Store), the
* GetValueChange function will not be present.
* @param store A reference to the Store that changed.
* @param getValueChange A function that returns information about any Value's
* changes.
* @category Listener
* @since v1.0.0
*/
export type ValuesListener<Store extends StoreAlias = StoreAlias> = (
store: Store,
getValueChange: GetValueChange | undefined,
) => void;
/**
* The ValueIdsListener type describes a function that is used to listen to
* changes to the Value Ids in a Store.
*
* A ValueIdsListener is provided when using the addValueIdsListener method. See
* that method for specific examples.
*
* When called, a ValueIdsListener is given a reference to the Store.
*
* Since v3.3, the listener is also passed a GetIdChanges function that can be
* used to query which Ids changed during the transaction.
* @param store A reference to the Store that changed.
* @param getIdChanges A function that returns information about the Id changes,
* since v3.3.
* @category Listener
* @since v1.0.0
*/
export type ValueIdsListener<Store extends StoreAlias = StoreAlias> = (
store: Store,
getIdChanges: GetIdChanges | undefined,
) => void;
/**
* The HasValueListener type describes a function that is used to listen to a
* Value being added to or removed from the Store.
*
* A HasValueListener is provided when using the addHasValueListener method. See
* that method for specific examples.
*
* When called, a HasValueListener is given a reference to the Store and the Id
* of Value that changed. It is also given a flag to indicate whether the Value
* now exists (having not done previously), or does not (having done so
* previously).
* @param store A reference to the Store that changed.
* @param valueId The Id of the Value that changed.
* @param hasValue Whether the Value now exists or not.
* @category Listener
* @since v4.4.0
*/
export type HasValueListener<Store extends StoreAlias = StoreAlias> = (
store: Store,
valueId: Id,
hasValue: boolean,
) => void;
/**
* The ValueListener type describes a function that is used to listen to changes
* to a Value.
*
* A ValueListener is provided when using the addValueListener method. See that
* method for specific examples.
*
* When called, a ValueListener is given a reference to the Store and the Id of
* Value that changed. It is also given the new value of the Value, the old
* value of the Value, and a GetValueChange function that can be used to query
* Values before and after the current transaction.
*
* Note that if the listener was manually forced to be called (with the
* callListener method rather than due to a real change in the Store), the
* GetValueChange function will not be present and the new and old values of the
* Value will be the same.
* @param store A reference to the Store that changed.
* @param valueId The Id of the Value that changed.
* @param newValue The new value of the Value that changed.
* @param oldValue The old value of the Value that changed.
* @param getValueChange A function that returns information about any Value's
* changes.
* @category Listener
* @since v3.0.0
*/
export type ValueListener<Store extends StoreAlias = StoreAlias> = (
store: Store,
valueId: Id,
newValue: Value,
oldValue: Value,
getValueChange: GetValueChange | undefined,
) => void;
/**
* The InvalidCellListener type describes a function that is used to listen to
* attempts to set invalid data to a Cell.
*
* An InvalidCellListener is provided when using the addInvalidCellListener
* method. See that method for specific examples.
*
* When called, an InvalidCellListener is given a reference to the Store, the Id
* of the Table, the Id of the Row, and the Id of Cell that was being attempted
* to be changed. It is also given the invalid value of the Cell, which could
* have been of absolutely any type. Since there could have been multiple failed
* attempts to set the Cell within a single transaction, this is an array
* containing each attempt, chronologically.
* @param store A reference to the Store that was being changed.
* @param tableId The Id of the Table that was being changed.
* @param rowId The Id of the Row that was being changed.
* @param cellId The Id of the Cell that was being changed.
* @param invalidCells An array of the values of the Cell that were invalid.
* @category Listener
* @since v1.1.0
*/
export type InvalidCellListener<Store extends StoreAlias = StoreAlias> = (
store: Store,
tableId: Id,
rowId: Id,
cellId: Id,
invalidCells: any[],
) => void;
/**
* The InvalidValueListener type describes a function that is used to listen to
* attempts to set invalid data to a Value.
*
* An InvalidValueListener is provided when using the addInvalidValueListener
* method. See that method for specific examples.
*
* When called, an InvalidValueListener is given a reference to the Store and
* the Id of Value that was being attempted to be changed. It is also given the
* invalid value of the Value, which could have been of absolutely any type.
* Since there could have been multiple failed attempts to set the Value within
* a single transaction, this is an array containing each attempt,
* chronologically.
* @param store A reference to the Store that was being changed.
* @param valueId The Id of the Value that was being changed.
* @param invalidValues An array of the Values that were invalid.
* @category Listener
* @since v3.0.0
*/
export type InvalidValueListener<Store extends StoreAlias = StoreAlias> = (
store: Store,
valueId: Id,
invalidValues: any[],
) => void;
/**
* The GetIdChanges type describes a function that returns information about the
* changes to a set of Ids during a transaction.
*
* A GetIdChanges function is provided to every listener when called due Ids in
* the Store changing. It returns an object where each key is an Id that
* changed. The listener can then easily identify which Ids have been added
* (those with the value `1`), and which have been removed (those with the value
* `-1`).
* @returns An object keyed by Id with a numerical value. 1 means the Id was
* added, and 1 means it was removed.
* @category Listener
* @since v3.3.0
*/
export type GetIdChanges = () => {[id: Id]: 1 | -1};
/**
* The GetCellChange type describes a function that returns information about
* any Cell's changes during a transaction.
*
* A GetCellChange function is provided to every listener when called due the
* Store changing. The listener can then fetch the previous value of a Cell
* before the current transaction, the new value after it, and a convenience
* flag that indicates that the value has changed.
* @param tableId The Id of the Table to inspect.
* @param rowId The Id of the Row to inspect.
* @param cellId The Id of the Cell to inspect.
* @returns A CellChange array containing information about the Cell's changes.
* @category Listener
* @since v1.0.0
*/
export type GetCellChange = (tableId: Id, rowId: Id, cellId: Id) => CellChange;
/**
* The CellChange type describes a Cell's changes during a transaction.
*
* This is returned by the GetCellChange function that is provided to every
* listener when called. This array contains the previous value of a Cell before
* the current transaction, the new value after it, and a convenience flag that
* indicates that the value has changed.
* @category Listener
* @since v1.0.0
*/
export type CellChange = [
changed: boolean,
oldCell: CellOrUndefined,
newCell: CellOrUndefined,
];
/**
* The GetValueChange type describes a function that returns information about
* any Value's changes during a transaction.
*
* A GetValueChange function is provided to every listener when called due the
* Store changing. The listener can then fetch the previous value of a Value
* before the current transaction, the new value after it, and a convenience
* flag that indicates that the value has changed.
* @param valueId The Id of the Value to inspect.
* @returns A ValueChange array containing information about the Value's
* changes.
* @category Listener
* @since v1.0.0
*/
export type GetValueChange = (valueId: Id) => ValueChange;
/**
* The ValueChange type describes a Value's changes during a transaction.
*
* This is returned by the GetValueChange function that is provided to every
* listener when called. This array contains the previous value of a Value
* before the current transaction, the new value after it, and a convenience
* flag that indicates that the value has changed.
* @category Listener
* @since v1.0.0
*/
export type ValueChange = [
changed: boolean,
oldValue: ValueOrUndefined,
newValue: ValueOrUndefined,
];
/**
* The ChangedCells type describes the Cell values that have been changed during
* a transaction, primarily used so that you can indicate whether the
* transaction should be rolled back.
*
* A ChangedCells object is provided to the `doRollback` callback when using the
* transaction method and the finishTransaction method. See those methods for
* specific examples.
*
* This type is a nested structure of Table, Row, and Cell objects, much like
* the Tables object, but one which provides both the old and new Cell values in
* a two-part array. These are describing the state of each changed Cell in
* Store at the _start_ of the transaction, and by the _end_ of the transaction.
*
* Hence, an `undefined` value for the first item in the array means that the
* Cell was added during the transaction. An `undefined` value for the second
* item in the array means that the Cell was removed during the transaction. An
* array with two different Cell values indicates that it was changed. The
* two-part array will never contain two items of the same value (including two
* `undefined` values), even if, during the transaction, a Cell was changed to a
* different value and then changed back.
* @category Transaction
* @since v1.2.0
*/
export type ChangedCells = {
[tableId: Id]: {[rowId: Id]: {[cellId: Id]: ChangedCell}};
};
/**
* The ChangedCell type describes a Cell that has been changed during a
* transaction, primarily used so that you can indicate whether the transaction
* should be rolled back.
*
* It provides both the old and new Cell values in a two-part array. These are
* describing the state of the changed Cell in the Store at the _start_ of the
* transaction, and by the _end_ of the transaction.
*
* Hence, an `undefined` value for the first item in the array means that the
* Cell was added during the transaction. An `undefined` value for the second
* item in the array means that the Cell was removed during the transaction. An
* array with two different Cell values indicates that it was changed. The
* two-part array will never contain two items of the same value (including two
* `undefined` values), even if, during the transaction, a Cell was changed to a
* different value and then changed back.
* @category Transaction
* @since v1.2.0
*/
export type ChangedCell = [oldCell: CellOrUndefined, newCell: CellOrUndefined];
/**
* The InvalidCells type describes the invalid Cell values that have been
* attempted during a transaction, primarily used so that you can indicate
* whether the transaction should be rolled back.
*
* An InvalidCells object is provided to the `doRollback` callback when using
* the transaction method and the finishTransaction method. See those methods
* for specific examples.
*
* This type is a nested structure of Table, Row, and Cell objects, much like
* the Tables object, but one for which Cell values are listed in array (much
* like the InvalidCellListener type) so that multiple failed attempts to change
* a Cell during the transaction are described.
* @category Transaction
* @since v1.2.0
*/
export type InvalidCells = {
[tableId: Id]: {[rowId: Id]: {[cellId: Id]: any[]}};
};
/**
* The ChangedValues type describes the Values that have been changed during a
* transaction, primarily used so that you can indicate whether the transaction
* should be rolled back.
*
* A ChangedValues object is provided to the `doRollback` callback when using
* the transaction method and the finishTransaction method. See those methods
* for specific examples.
*
* This type is an object containing the old and new Values in two-part arrays.
* These are describing the state of each changed Value in Store at the _start_
* of the transaction, and by the _end_ of the transaction.
*
* Hence, an `undefined` value for the first item in the array means that the
* Value was added during the transaction. An `undefined` value for the second
* item in the array means that the Value was removed during the transaction. An
* array with two different Values indicates that it was changed. The two-part
* array will never contain two items of the same value (including two
* `undefined` values), even if, during the transaction, a Value was changed to
* a different value and then changed back.
* @category Transaction
* @since v3.0.0
*/
export type ChangedValues = {
[valueId: Id]: ChangedValue;
};
/**
* The ChangedValue type describes a Value that has been changed during a
* transaction, primarily used so that you can indicate whether the transaction
* should be rolled back.
*
* It provides both the the old and new Values in a two-part array. These
* describe the state of the changed Value in the Store at the _start_ of the
* transaction, and by the _end_ of the transaction.
*
* Hence, an `undefined` value for the first item in the array means that the
* Value was added during the transaction. An `undefined` value for the second
* item in the array means that the Value was removed during the transaction. An
* array with two different Values indicates that it was changed. The two-part
* array will never contain two items of the same value (including two
* `undefined` values), even if, during the transaction, a Value was changed to
* a different value and then changed back.
* @category Transaction
* @since v3.0.0
*/
export type ChangedValue = [
oldValue: ValueOrUndefined,
newValue: ValueOrUndefined,
];
/**
* The InvalidValues type describes the invalid Values that have been attempted
* during a transaction, primarily used so that you can indicate whether the
* transaction should be rolled back.
*
* An InvalidValues object is provided to the `doRollback` callback when using
* the transaction method and the finishTransaction method. See those methods
* for specific examples.
*
* This type is an object containing each invalid Value's attempt listed in
* array (much like the InvalidValueListener type) so that multiple failed
* attempts to change a Value during the transaction are described.
* @category Transaction
* @since v3.0.0
*/
export type InvalidValues = {[valueId: Id]: any[]};
/**
* The Changes type describes the net meaningful changes that were made to a
* Store during a transaction.
*
* This contains mostly equivalent information to a TransactionLog, but in a
* form that can be more efficiently parsed and serialized (for example in the
* case of synchronization between systems).
*
* It is an array of two objects, representing tabular and keyed value changes.
* If the first item is an empty object, it means no tabular changes were made.
* If the second item is an empty object, it means no keyed value changes were
* made.
*
* If not empty, the first object has an entry for each Table in a Store that
* has had a change within it. If the entry is null, it means that whole Table
* was deleted. Otherwise, the entry will be an object with an entry for each
* Row in that Table that had a change within it. In turn, if that entry is
* null, it means the Row was deleted. Otherwise, the entry will be an object
* with an entry for each Cell in that Row that had a change within it. If the
* entry is null, the Cell was deleted, otherwise it will contain the new value
* the Cell was changed to during the transaction.
*
* If not empty, the second object has an entry for each Value in a Store that
* has had a change. If the entry is null, the Value was deleted, otherwise it
* will contain the new Value it was changed to during the transaction.
*
* A third, required, item in the array is the digit `1`, so that instances of
* Content and Changes types can be disambiguated.
* @example
* The following is a valid Changes array that conveys the following:
* ```json
* [
* { // changes to tabular data in the Store
* "pets": { // this Table was changed
* "fido": null, // this Row was deleted
* "felix": { // this Row was changed
* "sold": true, // this Cell was changed
* "price": null, // this Cell was deleted
* },
* },
* "pendingSales": null, // this Table was deleted
* },
* {}, // no changes to keyed value data in the Store
* 1, // indicates that this is a Changes array
* ]
* ```
* @category Transaction
* @since v4.0.0
*/
export type Changes = [
changedTables: {
[tableId: Id]:
| {[rowId: Id]: {[cellId: Id]: CellOrUndefined} | undefined}
| undefined;
},
changedValues: {[valueId: Id]: ValueOrUndefined},
isChanges: 1,
];
/**
* The TransactionLog type describes the changes that were made to a Store
* during a transaction in detail.
*
* This contains equivalent information to a Changes object, but also
* information about what the previous state of the Store was. The changedCells
* and changedValues entries contain information about all changes to those
* parts of the Store, with their before and after values, for example.
*
* `cellsTouched` and `valuesTouched` indicate whether Cell or Value data has
* been touched during the transaction. The two flags are intended as a hint
* about whether non-mutating listeners might be being called at the end of the
* transaction.
*
* Here, 'touched' means that Cell or Value data has either been changed, or
* changed and then changed back to its original value during the transaction.
* The exception is a transaction that has been rolled back, for which the value
* of `cellsTouched` and `valuesTouched` in the listener will be `false` because
* all changes have been reverted.
*
* In v5.0, this type changed from an object to an array, but still contains the
* same values.
*
* See the documentation for the types of the inner objects for other details.
* @category Transaction
* @since v4.0.0
*/
export type TransactionLog = [
cellsTouched: boolean,
valuesTouched: boolean,
changedCells: ChangedCells,
invalidCells: InvalidCells,
changedValues: ChangedValues,
invalidValues: InvalidValues,
changedTableIds: ChangedTableIds,
changedRowIds: ChangedRowIds,
changedCellIds: ChangedCellIds,
changedValueIds: ChangedValueIds,
];
/**
* The StoreListenerStats type describes the number of listeners registered with
* the Store, and can be used for debugging purposes.
*
* The StoreListenerStats object contains a breakdown of the different types of
* listener. Totals include both mutator and non-mutator listeners. A
* StoreListenerStats object is returned from the getListenerStats method.
* @category Development
* @since v1.0.0
*/
export type StoreListenerStats = {
/**
* The number of HasTablesListener functions registered with the Store, since
* v4.4.
* @category Stat
* @since v1.0.0
*/
hasTables: number;
/**
* The number of TablesListener functions registered with the Store.
* @category Stat
* @since v1.0.0
*/
tables: number;
/**
* The number of TableIdsListener functions registered with the Store.
* @category Stat
* @since v1.0.0
*/
tableIds: number;
/**
* The number of HasTableListener functions registered with the Store, since
* v4.4.
* @category Stat
* @since v1.0.0
*/
hasTable: number;
/**
* The number of TableListener functions registered with the Store.
* @category Stat
* @since v1.0.0
*/
table: number;
/**
* The number of TableCellIdsListener functions registered with the Store,
* since v3.3.
* @category Stat
* @since v1.0.0
*/
tableCellIds: number;
/**
* The number of HasTableCellListener functions registered with the Store,
* since v4.4.
* @category Stat
* @since v1.0.0
*/
hasTableCell: number;
/**
* The number of RowCountListener functions registered with the Store, since
* v4.1.0.
* @category Stat
* @since v1.0.0
*/
rowCount: number;
/**
* The number of RowIdsListener functions registered with the Store.
* @category Stat
* @since v1.0.0
*/
rowIds: number;
/**
* The number of SortedRowIdsListener functions registered with the Store.
* @category Stat
* @since v1.0.0
*/
sortedRowIds: number;
/**
* The number of HasRowListener functions registered with the Store, since
* v4.4.
* @category Stat
* @since v1.0.0
*/
hasRow: number;
/**
* The number of RowListener functions registered with the Store.
* @category Stat
* @since v1.0.0
*/
row: number;
/**
* The number of CellIdsListener functions registered with the Store.
* @category Stat
* @since v1.0.0
*/
cellIds: number;
/**
* The number of HasCellListener functions registered with the Store, since
* v4.4.
* @category Stat
* @since v1.0.0
*/
hasCell: number;
/**
* The number of CellListener functions registered with the Store.
* @category Stat
* @since v1.0.0
*/
cell: number;
/**
* The number of InvalidCellListener functions registered with the Store.
* @category Stat
* @since v1.0.0
*/
invalidCell: number;
/**
* The number of HasValuesListener functions registered with the Store, since
* v4.4.
* @category Stat
* @since v1.0.0
*/
hasValues: number;
/**
* The number of ValuesListener functions registered with the Store, since
* v3.0.
* @category Stat
* @since v1.0.0
*/
values: number;
/**
* The number of ValueIdsListener functions registered with the Store, since
* v3.0.
* @category Stat
* @since v1.0.0
*/
valueIds: number;
/**
* The number of HasValueListener functions registered with the Store, since
* v4.4.
* @category Stat
* @since v1.0.0
*/
hasValue: number;
/**
* The number of ValueListener functions registered with the Store, since
* v3.0.
* @category Stat
* @since v1.0.0
*/
value: number;
/**
* The number of InvalidValueListener functions registered with the Store,
* since v3.0.
* @category Stat
* @since v1.0.0
*/
invalidValue: number;
/**
* The number of TransactionListener functions registered with the Store.
* @category Stat
* @since v1.0.0
*/
transaction: number;
};
/**
* A Store is the main location for keeping both tabular data and keyed values.
*
* Create a Store easily with the createStore function. From there, you can set
* and get data, add listeners for when the data changes, set schemas, and so
* on.
*
* A Store has two facets. It can contain keyed Values, and independently, it
* can contain tabular Tables data. These two facets have similar APIs but can
* be used entirely independently: you can use only tables, only keyed Values,
* or both tables _and_ keyed Values - all in a single Store.
*
* # Keyed values
*
* The keyed value support is best thought of as a flat JavaScript object. The
* Store contains a number of Value objects, each with a unique ID, and which is
* a string, boolean, or number.
*
* ```json
* { // Store
* "value1": "one", // Value (string)
* "value2": true, // Value (boolean)
* "value3": 3, // Value (number)
* ...
* }
* ```
*
* In its default form, a Store has no sense of a structured schema for the
* Values. However, you _can_ optionally specify a ValuesSchema for a Store,
* which then usefully constrains and defaults the Values you can use.
*
* # Tabular data
*
* The tabular data exists in a simple hierarchical structure:
*
* - The Store contains a number of Table objects.
* - Each Table contains a number of Row objects.
* - Each Row contains a number of Cell objects.
*
* A Cell is a string, boolean, or number value.
*
* The members of each level of this hierarchy are identified with a unique Id
* (which is a string). In other words you can naively think of a Store as a
* three-level-deep JavaScript object, keyed with strings:
*
* ```json
* { // Store
* "table1": { // Table
* "row1": { // Row
* "cell1": "one", // Cell (string)
* "cell2": true, // Cell (boolean)
* "cell3": 3, // Cell (number)
* ...
* },
* ...
* },
* ...
* }
* ```
*
* Again, by default Store has no sense of a structured schema. As long as they
* are unique within their own parent, the Id keys can each be any string you
* want. However, as you _can_ optionally specify a TablesSchema for the tabular
* data in a Store, which then usefully constrains the Table and Cell Ids (and
* Cell values) you can use.
*
* # Setting and getting data
*
* Every part of the Store can be accessed with getter methods. When you
* retrieve data from the Store, you are receiving a copy - rather than a
* reference - of it. This means that manipulating the data in the Store must be
* performed with the equivalent setter and deleter methods.
*
* To benefit from the reactive behavior of the Store, you can also subscribe to
* changes on any part of it with 'listeners'. Registering a listener returns a
* listener Id (that you can use later to remove it with the delListener
* method), and it will then be called every time there is a change within the
* part of the hierarchy you're listening to.
*
* This table shows the main ways you can set, get, and listen to, different
* types of data in a Store:
*
* |Type|Get data|Set data|Delete data|Add a listener|
* |-|-|-|-|-|
* |Values|getValues|setValues|delValues|addValuesListener|
* |Value Ids|getValueIds|-|-|addValueIdsListener|
* |Value|getValue|setValue|delValue|addValueListener|
* |Tables|getTables|setTables|delTables|addTablesListener|
* |Table Ids|getTableIds|-|-|addTableIdsListener|
* |Table|getTable|setTable|delTable|addTableListener|
* |Table Cell Ids|getTableCellIds|-|-|addTableCellIdsListener|
* |Row Ids|getRowIds|-|-|addRowIdsListener|
* |Row Ids (sorted)|getSortedRowIds|-|-|addSortedRowIdsListener|
* |Row|getRow|setRow|delRow|addRowListener|
* |Cell Ids|getCellIds|-|-|addCellIdsListener|
* |Cell|getCell|setCell|delCell|addCellListener|
*
* There are two extra methods to manipulate Row objects. The addRow method is
* like the setRow method but automatically assigns it a new unique Id. And the
* setPartialRow method lets you update multiple Cell values in a Row without
* affecting the others. There is a similar setPartialValues method to do the
* same for the Values in a Store.
*
* You can listen to attempts to write invalid data to a Value or Cell with the
* addInvalidValueListener method or addInvalidCellListener method.
*
* The transaction method is used to wrap multiple changes to the Store so that
* the relevant listeners only fire once.
*
* The setJson method and the getJson method allow you to work with a
* JSON-encoded representation of the entire Store, which is useful for
* persisting it.
*
* Finally, the callListener method provides a way for you to manually provoke a
* listener to be called, even if the underlying data hasn't changed. This is
* useful when you are using mutator listeners to guarantee that data conforms
* to programmatic conditions, and those conditions change such that you need to
* update the Store in bulk.
*
* Read more about setting and changing data in The Basics guides, and about
* listeners in the Listening to Stores guide.
*
* # Creating a schema
*
* You can set a ValuesSchema and a TablesSchema with the setValuesSchema method
* and setTablesSchema method respectively. A TablesSchema constrains the Table
* Ids the Store can have, and the types of Cell data in each Table. Each Cell
* requires its type to be specified, and can also take a default value for when
* it's not specified.
*
* You can also get a serialization of the schemas out of the Store with the
* getSchemaJson method, and remove the schemas altogether with the
* delValuesSchema method and delTablesSchema method.
*
* Read more about schemas in the Using Schemas guide.
*
* # Convenience methods
*
* There are a few additional helper methods to make it easier to work with a
* Store. There are methods for easily checking the existence of a Table, Row,
* or Cell, and iterators that let you act on the children of a common parent:
*
* ||Checking existence|Iterator|
* |-|-|-|
* |Value|hasValue|forEachValue|
* |Table|hasTable|forEachTable|
* |Row|hasRow|forEachRow|
* |Cell|hasCell|forEachCell|
*
* Since v4.3.23, you can add listeners for the change of existence of part of a
* Store. For example, the addHasValueListener method lets you listen for a
* Value being added or removed.
*
* Finally, the getListenerStats method describes the current state of the
* Store's listeners for debugging purposes.
* @example
* This example shows a very simple lifecycle of a Store: from creation, to
* adding and getting some data, and then registering and removing a listener.
*
* ```js
* import {createStore} from 'tinybase';
*
* const store = createStore().setTables({pets: {fido: {species: 'dog'}}});
* console.log(store.getRow('pets', 'fido'));
* // -> {species: 'dog'}
*
* store.setCell('pets', 'fido', 'color', 'brown');
* console.log(store.getCell('pets', 'fido', 'color'));
* // -> 'brown'
*
* const listenerId = store.addTableListener('pets', () => {
* console.log('changed');
* });
*
* store.setCell('pets', 'fido', 'sold', false);
* // -> 'changed'
*
* store.delListener(listenerId);
* ```
* @see The Basics guides
* @see Using Schemas guides
* @see Hello World demos
* @see Todo App demos
* @category Store
* @since v1.0.0
*/
export interface Store {
//
/**
* The getContent method returns a Tables object and a Values object in an
* array, representing the entire content of the Store.
*
* Note that this returns a copy of, rather than a reference to the underlying
* data, so changes made to the returned objects are not made to the Store
* itself.
* @returns An array of a Tables object and a Values object.
* @example
* This example retrieves the content of a Store.
*
* ```js
* import {createStore} from 'tinybase';
*
* const store = createStore()
* .setTables({pets: {fido: {species: 'dog'}}})
* .setValues({open: true, employees: 3});
* console.log(store.getContent());
* // -> [{pets: {fido: {species: 'dog'}}}, {open: true, employees: 3}]
* ```
* @example
* This example retrieves the Tables and Values of an empty Store, returning
* empty objects.
*
* ```js
* import {createStore} from 'tinybase';
*
* const store = createStore();
* console.log(store.getContent());
* // -> [{}, {}]
* ```
* @category Getter
* @since v4.0.0
*/
getContent(): Content;
/**
* The getTables method returns a Tables object containing the entire tabular
* data of the Store.
*
* Note that this returns a copy of, rather than a reference to the underlying
* data, so changes made to the returned object are not made to the Store
* itself.
* @returns A Tables object containing the tabular data of the Store.
* @example
* This example retrieves the tabular data in a Store.
*
* ```js
* import {createStore} from 'tinybase';
*
* const store = createStore().setTables({
* pets: {fido: {species: 'dog'}},
* species: {dog: {price: 5}},
* });
* console.log(store.getTables());
* // -> {pets: {fido: {species: 'dog'}}, species: {dog: {price: 5}}}
* ```
* @example
* This example retrieves the Tables of an empty Store, returning an empty
* object.
*
* ```js
* import {createStore} from 'tinybase';
*
* const store = createStore();
* console.log(store.getTables());
* // -> {}
* ```
* @category Getter
* @since v1.0.0
*/
getTables(): Tables;
/**
* The getTableIds method returns the Ids of every Table in the Store.
*
* Note that this returns a copy of, rather than a reference, to the list of
* Ids, so changes made to the list are not made to the Store itself.
* @returns An array of the Ids of every Table in the Store.
* @example
* This example retrieves the Table Ids in a Store.
*
* ```js
* import {createStore} from 'tinybase';
*
* const store = createStore().setTables({
* pets: {fido: {species: 'dog'}},
* species: {dog: {price: 5}},
* });
* console.log(store.getTableIds());
* // -> ['pets', 'species']
* ```
* @example
* This example retrieves the Table Ids of an empty Store, returning an empty
* array.
*
* ```js
* import {createStore} from 'tinybase';
*
* const store = createStore();
* console.log(store.getTableIds());
* // -> []
* ```
* @category Getter
* @since v1.0.0
*/
getTableIds(): Ids;
/**
* The getTable method returns an object containing the entire data of a
* single Table in the Store.
*
* Note that this returns a copy of, rather than a reference to the underlying
* data, so changes made to the returned object are not made to the Store
* itself.
* @param tableId The Id of the Table in the Store.
* @returns An object containing the entire data of the Table.
* @example
* This example retrieves the data in a single Table.
*
* ```js
* import {createStore} from 'tinybase';
*
* const store = createStore().setTables({
* pets: {fido: {species: 'dog'}},
* species: {dog: {price: 5}},
* });
* console.log(store.getTable('pets'));
* // -> {fido: {species: 'dog'}}
* ```
* @example
* This example retrieves a Table that does not exist, returning an empty
* object.
*
* ```js
* import {createStore} from 'tinybase';
*
* const store = createStore().setTables({pets: {fido: {species: 'dog'}}});
* console.log(store.getTable('employees'));
* // -> {}
* ```
* @category Getter
* @since v1.0.0
*/
getTable(tableId: Id): Table;
/**
* The getTableCellIds method returns the Ids of every Cell used across the
* whole Table.
*
* Note that this returns a copy of, rather than a reference, to the list of
* Ids, so changes made to the list are not made to the Store itself.
* @param tableId The Id of the Table in the Store.
* @returns An array of the Ids of every Cell used across the whole Table.
* @example
* This example retrieves the Cell Ids used across a whole Table.
*
* ```js
* import {createStore} from 'tinybase';
*
* const store = createStore().setTables({
* pets: {
* fido: {species: 'dog', color: 'brown'},
* felix: {species: 'cat', legs: 4},
* cujo: {dangerous: true},
* },
* });
* console.log(store.getTableCellIds('pets'));
* // -> ['species', 'color', 'legs', 'dangerous']
* ```
* @example
* This example retrieves the Cell Ids used across a Table that does not
* exist, returning an empty array.
*
* ```js
* import {createStore} from 'tinybase';
*
* const store = createStore().setTables({pets: {fido: {species: 'dog'}}});
* console.log(store.getTableCellIds('species'));
* // -> []
* ```
* @category Getter
* @since v3.3.0
*/
getTableCellIds(tableId: Id): Ids;
/**
* The getRowCount method returns the count of the Row objects in a given
* Table.
*
* While this provides the same result as the length of Ids array returned
* from the getRowIds method, it is somewhat faster, and useful for efficient
* pagination.
* @param tableId The Id of the Table in the Store.
* @returns The number of Row objects in the Table.
* @example
* This example retrieves the number of Row objects in the Table.
*
* ```js
* import {createStore} from 'tinybase';
*
* const store = createStore().setTables({
* pets: {
* fido: {species: 'dog'},
* felix: {species: 'cat'},
* },
* });
* console.log(store.getRowCount('pets'));
* // -> 2
* ```
* @example
* This example retrieves the Row Ids of a Table that does not exist,
* returning zero.
*
* ```js
* import {createStore} from 'tinybase';
*
* const store = createStore().setTables({pets: {fido: {species: 'dog'}}});
* console.log(store.getRowCount('employees'));
* // -> 0
* ```
* @category Getter
* @since v4.1.0
*/
getRowCount(tableId: Id): number;
/**
* The getRowIds method returns the Ids of every Row in a given Table.
*
* Note that this returns a copy of, rather than a reference, to the list of
* Ids, so changes made to the list are not made to the Store itself.
* @param tableId The Id of the Table in the Store.
* @returns An array of the Ids of every Row in the Table.
* @example
* This example retrieves the Row Ids in a Table.
*
* ```js
* import {createStore} from 'tinybase';
*
* const store = createStore().setTables({
* pets: {
* fido: {species: 'dog'},
* felix: {species: 'cat'},
* },
* });
* console.log(store.getRowIds('pets'));
* // -> ['fido', 'felix']
* ```
* @example
* This example retrieves the Row Ids of a Table that does not exist,
* returning an empty array.
*
* ```js
* import {createStore} from 'tinybase';
*
* const store = createStore().setTables({pets: {fido: {species: 'dog'}}});
* console.log(store.getRowIds('employees'));
* // -> []
* ```
* @category Getter
* @since v1.0.0
*/
getRowIds(tableId: Id): Ids;
/**
* The getSortedRowIds method returns the Ids of every Row in a given Table,
* sorted according to the values in a specified Cell.
*
* The sorting of the rows is alphanumeric, and you can indicate whether it
* should be in descending order. The `offset` and `limit` parameters are used
* to paginate results, but default to `0` and `undefined` to return all
* available Row Ids if not specified.
*
* Note that every call to this method will perform the sorting afresh - there
* is no caching of the results - and so you are advised to memoize the
* results yourself, especially when the Table is large. For a performant
* approach to tracking the sorted Row Ids when they change, use the
* addSortedRowIdsListener method.
*
* If the Table does not exist, an empty array is returned.
* @param tableId The Id of the Table in the Store.
* @param cellId The Id of the Cell whose values are used for the sorting, or
* `undefined` to sort by the Row Id itself.
* @param descending Whether the sorting should be in descending order.
* @param offset The number of Row Ids to skip for pagination purposes, if
* any.
* @param limit The maximum number of Row Ids to return, or `undefined` for
* all.
* @returns An array of the sorted Ids of every Row in the Table.
* @example
* This example retrieves sorted Row Ids in a Table.
*
* ```js
* import {createStore} from 'tinybase';
*
* const store = createStore().setTables({
* pets: {
* fido: {species: 'dog'},
* felix: {species: 'cat'},
* },
* });
* console.log(store.getSortedRowIds('pets', 'species'));
* // -> ['felix', 'fido']
* ```
* @example
* This example retrieves sorted Row Ids in a Table in reverse order.
*
* ```js
* import {createStore} from 'tinybase';
*
* const store = createStore().setTables({
* pets: {
* fido: {species: 'dog'},
* felix: {species: 'cat'},
* cujo: {species: 'wolf'},
* },
* });
* console.log(store.getSortedRowIds('pets', 'species', true));
* // -> ['cujo', 'fido', 'felix']
* ```
* @example
* This example retrieves two pages of Row Ids in a Table.
*
* ```js
* import {createStore} from 'tinybase';
*
* const store = createStore().setTables({
* pets: {
* fido: {price: 6},
* felix: {price: 5},
* mickey: {price: 2},
* tom: {price: 4},
* carnaby: {price: 3},
* lowly: {price: 1},
* },
* });
* console.log(store.getSortedRowIds('pets', 'price', false, 0, 2));
* // -> ['lowly', 'mickey']
* console.log(store.getSortedRowIds('pets', 'price', false, 2, 2));
* // -> ['carnaby', 'tom']
* ```
* @example
* This example retrieves Row Ids sorted by their own value, since the
* `cellId` parameter is undefined.
*
* ```js
* import {createStore} from 'tinybase';
*
* const store = createStore().setTables({
* pets: {
* fido: {species: 'dog'},
* felix: {species: 'cat'},
* cujo: {species: 'wolf'},
* },
* });
* console.log(store.getSortedRowIds('pets'));
* // -> ['cujo', 'felix', 'fido']
* ```
* @example
* This example retrieves the sorted Row Ids of a Table that does not exist,
* returning an empty array.
*
* ```js
* import {createStore} from 'tinybase';
*
* const store = createStore().setTables({pets: {fido: {species: 'dog'}}});
* console.log(store.getSortedRowIds('employees'));
* // -> []
* ```
* @category Getter
* @since v2.0.0
*/
getSortedRowIds(
tableId: Id,
cellId?: Id,
descending?: boolean,
offset?: number,
limit?: number,
): Ids;
/**
* The getRow method returns an object containing the entire data of a single
* Row in a given Table.
*
* Note that this returns a copy of, rather than a reference to the underlying
* data, so changes made to the returned object are not made to the Store
* itself.
* @param tableId The Id of the Table in the Store.
* @param rowId The Id of the Row in the Table.
* @returns An object containing the entire data of the Row.
* @example
* This example retrieves the data in a single Row.
*
* ```js
* import {createStore} from 'tinybase';
*
* const store = createStore().setTables({
* pets: {
* fido: {species: 'dog'},
* felix: {species: 'cat'},
* },
* });
* console.log(store.getRow('pets', 'fido'));
* // -> {species: 'dog'}
* ```
* @example
* This example retrieves a Row that does not exist, returning an empty
* object.
*
* ```js
* import {createStore} from 'tinybase';
*
* const store = createStore().setTables({pets: {fido: {species: 'dog'}}});
* console.log(store.getRow('pets', 'felix'));
* // -> {}
* ```
* @category Getter
* @since v1.0.0
*/
getRow(tableId: Id, rowId: Id): Row;
/**
* The getCellIds method returns the Ids of every Cell in a given Row in a
* given Table.
*
* Note that this returns a copy of, rather than a reference, to the list of
* Ids, so changes made to the list are not made to the Store itself.
* @param tableId The Id of the Table in the Store.
* @param rowId The Id of the Row in the Table.
* @returns An array of the Ids of every Cell in the Row.
* @example
* This example retrieves the Cell Ids in a Row.
*
* ```js
* import {createStore} from 'tinybase';
*
* const store = createStore().setTables({
* pets: {
* fido: {species: 'dog', color: 'brown'},
* },
* });
* console.log(store.getCellIds('pets', 'fido'));
* // -> ['species', 'color']
* ```
* @example
* This example retrieves the Cell Ids of a Row that does not exist, returning
* an empty array.
*
* ```js
* import {createStore} from 'tinybase';
*
* const store = createStore().setTables({pets: {fido: {species: 'dog'}}});
* console.log(store.getCellIds('pets', 'felix'));
* // -> []
* ```
* @category Getter
* @since v1.0.0
*/
getCellIds(tableId: Id, rowId: Id): Ids;
/**
* The getCell method returns the value of a single Cell in a given Row, in a
* given Table.
* @param tableId The Id of the Table in the Store.
* @param rowId The Id of the Row in the Table.
* @param cellId The Id of the Cell in the Row.
* @returns The value of the Cell, or `undefined`.
* @example
* This example retrieves a single Cell.
*
* ```js
* import {createStore} from 'tinybase';
*
* const store = createStore().setTables({
* pets: {fido: {species: 'dog', color: 'brown'}},
* });
* console.log(store.getCell('pets', 'fido', 'species'));
* // -> 'dog'
* ```
* @example
* This example retrieves a Cell that does not exist, returning `undefined`.
*
* ```js
* import {createStore} from 'tinybase';
*
* const store = createStore().setTables({pets: {fido: {species: 'dog'}}});
* console.log(store.getCell('pets', 'fido', 'color'));
* // -> undefined
* ```
* @category Getter
* @since v1.0.0
*/
getCell(tableId: Id, rowId: Id, cellId: Id): CellOrUndefined;
/**
* The getValues method returns an object containing the entire set of keyed
* Values in the Store.
*
* Note that this returns a copy of, rather than a reference to the underlying
* data, so changes made to the returned object are not made to the Store
* itself.
* @returns An object containing the set of keyed Values in the Store.
* @example
* This example retrieves the set of keyed Values in the Store.
*
* ```js
* import {createStore} from 'tinybase';
*
* const store = createStore().setValues({open: true, employees: 3});
* console.log(store.getValues());
* // -> {open: true, employees: 3}
* ```
* @example
* This example retrieves Values from a Store that has none, returning an
* empty object.
*
* ```js
* import {createStore} from 'tinybase';
*
* const store = createStore();
* console.log(store.getValues());
* // -> {}
* ```
* @category Getter
* @since v3.0.0
*/
getValues(): Values;
/**
* The getValueIds method returns the Ids of every Value in a Store.
*
* Note that this returns a copy of, rather than a reference, to the list of
* Ids, so changes made to the list are not made to the Store itself.
* @returns An array of the Ids of every Value in the Store.
* @example
* This example retrieves the Value Ids in a Store.
*
* ```js
* import {createStore} from 'tinybase';
*
* const store = createStore().setValues({open: true, employees: 3});
* console.log(store.getValueIds());
* // -> ['open', 'employees']
* ```
* @example
* This example retrieves the Value Ids of a Store that has had none set,
* returning an empty array.
*
* ```js
* import {createStore} from 'tinybase';
*
* const store = createStore();
* console.log(store.getValueIds());
* // -> []
* ```
* @category Getter
* @since v3.0.0
*/
getValueIds(): Ids;
/**
* The getValue method returns a single keyed Value in the Store.
* @param valueId The Id of the Value in the Store.
* @returns The Value, or `undefined`.
* @example
* This example retrieves a single Value.
*
* ```js
* import {createStore} from 'tinybase';
*
* const store = createStore().setValues({open: true, employees: 3});
* console.log(store.getValue('employees'));
* // -> 3
* ```
* @example
* This example retrieves a Value that does not exist, returning `undefined`.
*
* ```js
* import {createStore} from 'tinybase';
*
* const store = createStore().setValues({open: true, employees: 3});
* console.log(store.getValue('website'));
* // -> undefined
* ```
* @category Getter
* @since v3.0.0
*/
getValue(valueId: Id): ValueOrUndefined;
/**
* The hasTables method returns a boolean indicating whether any Table objects
* exist in the Store.
* @returns Whether any Tables exist.
* @example
* This example shows simple existence checks.
*
* ```js
* import {createStore} from 'tinybase';
*
* const store = createStore();
* console.log(store.hasTables());
* // -> false
* store.setTables({pets: {fido: {species: 'dog'}}});
* console.log(store.hasTables());
* // -> true
* ```
* @category Getter
* @since v1.0.0
*/
hasTables(): boolean;
/**
* The hasTable method returns a boolean indicating whether a given Table
* exists in the Store.
* @param tableId The Id of a possible Table in the Store.
* @returns Whether a Table with that Id exists.
* @example
* This example shows two simple Table existence checks.
*
* ```js
* import {createStore} from 'tinybase';
*
* const store = createStore().setTables({pets: {fido: {species: 'dog'}}});
* console.log(store.hasTable('pets'));
* // -> true
* console.log(store.hasTable('employees'));
* // -> false
* ```
* @category Getter
* @since v1.0.0
*/
hasTable(tableId: Id): boolean;
/**
* The hasTableCell method returns a boolean indicating whether a given Cell
* exists anywhere in a Table, not just in a specific Row.
* @param tableId The Id of a possible Table in the Store.
* @param cellId The Id of a possible Cell in the Table.
* @returns Whether a Cell with that Id exists anywhere in that Table.
* @example
* This example shows two simple Cell existence checks.
*
* ```js
* import {createStore} from 'tinybase';
*
* const store = createStore().setTables({
* pets: {fido: {species: 'dog'}, felix: {legs: 4}},
* });
* console.log(store.hasTableCell('pets', 'species'));
* // -> true
* console.log(store.hasTableCell('pets', 'legs'));
* // -> true
* console.log(store.hasTableCell('pets', 'color'));
* // -> false
* ```
* @category Getter
* @since v3.3.0
*/
hasTableCell(tableId: Id, cellId: Id): boolean;
/**
* The hasRow method returns a boolean indicating whether a given Row exists
* in the Store.
* @param tableId The Id of a possible Table in the Store.
* @param rowId The Id of a possible Row in the Table.
* @returns Whether a Row with that Id exists in that Table.
* @example
* This example shows two simple Row existence checks.
*
* ```js
* import {createStore} from 'tinybase';
*
* const store = createStore().setTables({pets: {fido: {species: 'dog'}}});
* console.log(store.hasRow('pets', 'fido'));
* // -> true
* console.log(store.hasRow('pets', 'felix'));
* // -> false
* ```
* @category Getter
* @since v1.0.0
*/
hasRow(tableId: Id, rowId: Id): boolean;
/**
* The hasCell method returns a boolean indicating whether a given Cell exists
* in a given Row in a given Table.
* @param tableId The Id of a possible Table in the Store.
* @param rowId The Id of a possible Row in the Table.
* @param cellId The Id of a possible Cell in the Row.
* @returns Whether a Cell with that Id exists in that Row in that Table.
* @example
* This example shows two simple Cell existence checks.
*
* ```js
* import {createStore} from 'tinybase';
*
* const store = createStore().setTables({pets: {fido: {species: 'dog'}}});
* console.log(store.hasCell('pets', 'fido', 'species'));
* // -> true
* console.log(store.hasCell('pets', 'fido', 'color'));
* // -> false
* ```
* @category Getter
* @since v1.0.0
*/
hasCell(tableId: Id, rowId: Id, cellId: Id): boolean;
/**
* The hasValues method returns a boolean indicating whether any Values exist
* in the Store.
* @returns Whether any Values exist.
* @example
* This example shows simple existence checks.
*
* ```js
* import {createStore} from 'tinybase';
*
* const store = createStore();
* console.log(store.hasValues());
* // -> false
* store.setValues({open: true});
* console.log(store.hasValues());
* // -> true
* ```
* @category Getter
* @since v3.0.0
*/
hasValues(): boolean;
/**
* The hasValue method returns a boolean indicating whether a given Value
* exists in the Store.
* @param valueId The Id of a possible Value in the Store.
* @returns Whether a Value with that Id exists in the Store.
* @example
* This example shows two simple Value existence checks.
*
* ```js
* import {createStore} from 'tinybase';
*
* const store = createStore().setValues({open: true});
* console.log(store.hasValue('open'));
* // -> true
* console.log(store.hasValue('employees'));
* // -> false
* ```
* @category Getter
* @since v3.0.0
*/
hasValue(valueId: Id): boolean;
/**
* The getTablesJson method returns a string serialization of all of the
* Tables in the Store.
* @returns A string serialization of all of the Tables in the Store.
* @example
* This example serializes the contents of a Store.
*
* ```js
* import {createStore} from 'tinybase';
*
* const store = createStore().setTables({pets: {fido: {species: 'dog'}}});
* console.log(store.getTablesJson());
* // -> '{"pets":{"fido":{"species":"dog"}}}'
* ```
* @example
* This example serializes the contents of an empty Store.
*
* ```js
* import {createStore} from 'tinybase';
*
* const store = createStore();
* console.log(store.getTablesJson());
* // -> '{}'
* ```
* @category Getter
* @since v3.0.0
*/
getTablesJson(): Json;
/**
* The getValuesJson method returns a string serialization of all of the keyed
* Values in the Store.
* @returns A string serialization of all of the Values in the Store.
* @example
* This example serializes the keyed value contents of a Store.
*
* ```js
* import {createStore} from 'tinybase';
*
* const store = createStore().setValues({open: true});
* console.log(store.getValuesJson());
* // -> '{"open":true}'
* ```
* @example
* This example serializes the contents of an empty Store.
*
* ```js
* import {createStore} from 'tinybase';
*
* const store = createStore();
* console.log(store.getValuesJson());
* // -> '{}'
* ```
* @category Getter
* @since v3.0.0
*/
getValuesJson(): Json;
/**
* The getJson method returns a string serialization of all the Store content:
* both the Tables and the keyed Values.
*
* From v3.0 onwards, the serialization is of an array with two entries. The
* first is the Tables object, the second the Values. In previous versions
* (before the existence of the Values data structure), it was a sole object
* of Tables.
* @returns A string serialization of the Tables and Values in the Store.
* @example
* This example serializes the tabular and keyed value contents of a Store.
*
* ```js
* import {createStore} from 'tinybase';
*
* const store = createStore()
* .setTables({pets: {fido: {species: 'dog'}}})
* .setValues({open: true});
* console.log(store.getJson());
* // -> '[{"pets":{"fido":{"species":"dog"}}},{"open":true}]'
* ```
* @example
* This example serializes the contents of an empty Store.
*
* ```js
* import {createStore} from 'tinybase';
*
* const store = createStore();
* console.log(store.getJson());
* // -> '[{},{}]'
* ```
* @category Getter
* @since v1.0.0
*/
getJson(): Json;
/**
* The getTablesSchemaJson method returns a string serialization of the
* TablesSchema of the Store.
*
* If no TablesSchema has been set on the Store (or if it has been removed
* with the delTablesSchema method), then it will return the serialization of
* an empty object, `{}`.
* @returns A string serialization of the TablesSchema of the Store.
* @example
* This example serializes the TablesSchema of a Store.
*
* ```js
* import {createStore} from 'tinybase';
*
* const store = createStore().setTablesSchema({
* pets: {
* species: {type: 'string'},
* sold: {type: 'boolean'},
* },
* });
* console.log(store.getTablesSchemaJson());
* // -> '{"pets":{"species":{"type":"string"},"sold":{"type":"boolean"}}}'
* ```
* @example
* This example serializes the TablesSchema of an empty Store.
*
* ```js
* import {createStore} from 'tinybase';
*
* const store = createStore();
* console.log(store.getTablesSchemaJson());
* // -> '{}'
* ```
* @category Getter
* @since v3.0.0
*/
getTablesSchemaJson(): Json;
/**
* The getValuesSchemaJson method returns a string serialization of the
* ValuesSchema of the Store.
*
* If no ValuesSchema has been set on the Store (or if it has been removed
* with the delValuesSchema method), then it will return the serialization of
* an empty object, `{}`.
* @returns A string serialization of the ValuesSchema of the Store.
* @example
* This example serializes the ValuesSchema of a Store.
*
* ```js
* import {createStore} from 'tinybase';
*
* const store = createStore().setValuesSchema({
* open: {type: 'boolean', default: false},
* });
* console.log(store.getValuesSchemaJson());
* // -> '{"open":{"type":"boolean","default":false}}'
* ```
* @example
* This example serializes the ValuesSchema of an empty Store.
*
* ```js
* import {createStore} from 'tinybase';
*
* const store = createStore();
* console.log(store.getValuesSchemaJson());
* // -> '{}'
* ```
* @category Getter
* @since v3.0.0
*/
getValuesSchemaJson(): Json;
/**
* The getSchemaJson method returns a string serialization of both the
* TablesSchema and ValuesSchema of the Store.
*
* From v3.0 onwards, the serialization is of an array with two entries. The
* first is the TablesSchema object, the second the ValuesSchema. In previous
* versions (before the existence of the ValuesSchema data structure), it was
* a sole object of TablesSchema.
* @returns A string serialization of the TablesSchema and ValuesSchema of the
* Store.
* @example
* This example serializes the TablesSchema and ValuesSchema of a Store.
*
* ```js
* import {createStore} from 'tinybase';
*
* const store = createStore()
* .setTablesSchema({
* pets: {
* price: {type: 'number'},
* },
* })
* .setValuesSchema({
* open: {type: 'boolean'},
* });
* console.log(store.getSchemaJson());
* // -> '[{"pets":{"price":{"type":"number"}}},{"open":{"type":"boolean"}}]'
* ```
* @example
* This example serializes the TablesSchema and ValuesSchema of an empty
* Store.
*
* ```js
* import {createStore} from 'tinybase';
*
* const store = createStore();
* console.log(store.getSchemaJson());
* // -> '[{},{}]'
* ```
* @category Getter
* @since v1.0.0
*/
getSchemaJson(): Json;
/**
* The hasTablesSchema method returns a boolean indicating whether the Store
* currently has a TablesSchema applied to it.
* @returns Whether the Store has a TablesSchema applied to it.
* @example
* This example sets a TablesSchema and checks that it is present.
*
* ```js
* import {createStore} from 'tinybase';
*
* const store = createStore().setTablesSchema({
* pets: {
* price: {type: 'number'},
* },
* });
* console.log(store.hasTablesSchema());
* // -> true
*
* store.delTablesSchema();
* console.log(store.hasTablesSchema());
* // -> false
* ```
* @category Getter
* @since v4.1.1
*/
hasTablesSchema(): boolean;
/**
* The hasValuesSchema method returns a boolean indicating whether the Store
* currently has a ValuesSchema applied to it.
* @returns Whether the Store has a ValuesSchema applied to it.
* @example
* This example sets a ValuesSchema and checks that it is present.
*
* ```js
* import {createStore} from 'tinybase';
*
* const store = createStore().setValuesSchema({open: {type: 'boolean'}});
* console.log(store.hasValuesSchema());
* // -> true
*
* store.delValuesSchema();
* console.log(store.hasValuesSchema());
* // -> false
* ```
* @category Getter
* @since v4.1.1
*/
hasValuesSchema(): boolean;
/**
* The setContent method takes an array of two objects and sets the entire
* data of the Store.
*
* This method will cause listeners to be called for any Table, Row, Cell,
* Value, or Id changes resulting from it.
*
* Any part of the provided objects that are invalid (either according to the
* Tables or Values type, or because it does not match a TablesSchema or
* ValuesSchema associated with the Store), will be ignored silently.
*
* Assuming that at least some of the provided Tables object or Values object
* is valid, any data that was already present in that part of the Store will
* be completely overwritten. If either object is completely invalid, no
* change will be made to the corresponding part of the Store.
*
* The method returns a reference to the Store so that subsequent operations
* can be chained in a fluent style.
*
* Since v5.4.2, this method can also take a function that returns the
* content.
* @param content An array containing the tabular and keyed-value data of the
* Store to be set, or a function that returns the array.
* @returns A reference to the Store.
* @example
* This example sets the data of a Store.
*
* ```js
* import {createStore} from 'tinybase';
*
* const store = createStore().setContent([
* {pets: {fido: {species: 'dog'}}},
* {open: true, employees: 3},
* ]);
* console.log(store.getTables());
* // -> {pets: {fido: {species: 'dog'}}}
* console.log(store.getValues());
* // -> {open: true, employees: 3}
* ```
* @example
* This example sets the data of a Store with the results of a function.
*
* ```js
* import {createStore} from 'tinybase';
*
* const store = createStore().setContent(() => [
* {pets: {fido: {species: 'dog'}}},
* {open: true, employees: 3},
* ]);
* console.log(store.getTables());
* // -> {pets: {fido: {species: 'dog'}}}
* console.log(store.getValues());
* // -> {open: true, employees: 3}
* ```
* @example
* This example attempts to set the data of an existing Store with partly
* invalid, and then completely invalid objects.
*
* ```js
* import {createStore} from 'tinybase';
*
* const store = createStore().setContent([
* {pets: {fido: {species: 'dog'}}},
* {open: true, employees: 3},
* ]);
*
* store.setContent([{pets: {felix: {species: 'cat', bug: []}}}, '']);
* console.log(store.getTables());
* // -> {pets: {felix: {species: 'cat'}}}
* console.log(store.getValues());
* // -> {open: true, employees: 3}
*
* store.setContent([{meaning: 42}]);
* console.log(store.getTables());
* // -> {pets: {felix: {species: 'cat'}}}
* ```
* @category Setter
* @since v4.0.0
*/
setContent(content: Content | (() => Content)): this;
/**
* The setTables method takes an object and sets the entire tabular data of
* the Store.
*
* This method will cause listeners to be called for any Table, Row, Cell, or
* Id changes resulting from it.
*
* Any part of the provided object that is invalid (either according to the
* Tables type, or because it does not match a TablesSchema associated with
* the Store), will be ignored silently.
*
* Assuming that at least some of the provided Tables object is valid, any
* data that was already present in the Store will be completely overwritten.
* If the object is completely invalid, no change will be made to the Store.
*
* The method returns a reference to the Store so that subsequent operations
* can be chained in a fluent style.
* @param tables The data of the Store to be set.
* @returns A reference to the Store.
* @example
* This example sets the tabular data of a Store.
*
* ```js
* import {createStore} from 'tinybase';
*
* const store = createStore().setTables({
* pets: {fido: {species: 'dog'}},
* species: {dog: {price: 5}},
* });
* console.log(store.getTables());
* // -> {pets: {fido: {species: 'dog'}}, species: {dog: {price: 5}}}
* ```
* @example
* This example attempts to set the tabular data of an existing Store with
* partly invalid, and then completely invalid, Tables objects.
*
* ```js
* import {createStore} from 'tinybase';
*
* const store = createStore().setTables({pets: {fido: {species: 'dog'}}});
*
* store.setTables({pets: {felix: {species: 'cat', bug: []}}});
* console.log(store.getTables());
* // -> {pets: {felix: {species: 'cat'}}}
*
* store.setTables({meaning: 42});
* console.log(store.getTables());
* // -> {pets: {felix: {species: 'cat'}}}
* ```
* @category Setter
* @since v1.0.0
*/
setTables(tables: Tables): this;
/**
* The setTable method takes an object and sets the entire data of a single
* Table in the Store.
*
* This method will cause listeners to be called for any Table, Row, Cell, or
* Id changes resulting from it.
*
* Any part of the provided object that is invalid (either according to the
* Table type, or because it does not match a TablesSchema associated with the
* Store), will be ignored silently.
*
* Assuming that at least some of the provided Table object is valid, any data
* that was already present in the Store for that Table will be completely
* overwritten. If the object is completely invalid, no change will be made to
* the Store.
*
* The method returns a reference to the Store so that subsequent operations
* can be chained in a fluent style.
* @param tableId The Id of the Table in the Store.
* @param table The data of a single Table to be set.
* @returns A reference to the Store.
* @example
* This example sets the data of a single Table.
*
* ```js
* import {createStore} from 'tinybase';
*
* const store = createStore().setTable('pets', {
* fido: {species: 'dog'},
* felix: {species: 'cat'},
* });
* console.log(store.getTables());
* // -> {pets: {fido: {species: 'dog'}, felix: {species: 'cat'}}}
* ```
* @example
* This example attempts to set the data of an existing Store with partly
* invalid, and then completely invalid, Table objects.
*
* ```js
* import {createStore} from 'tinybase';
*
* const store = createStore().setTables({pets: {fido: {species: 'dog'}}});
*
* store.setTable('pets', {felix: {species: 'cat', bug: []}});
* console.log(store.getTables());
* // -> {pets: {felix: {species: 'cat'}}}
*
* store.setTable('pets', {meaning: 42});
* console.log(store.getTables());
* // -> {pets: {felix: {species: 'cat'}}}
* ```
* @category Setter
* @since v1.0.0
*/
setTable(tableId: Id, table: Table): this;
/**
* The setRow method takes an object and sets the entire data of a single Row
* in the Store.
*
* This method will cause listeners to be called for any Table, Row, Cell, or
* Id changes resulting from it.
*
* Any part of the provided object that is invalid (either according to the
* Row type, or because it does not match a TablesSchema associated with the
* Store), will be ignored silently.
*
* Assuming that at least some of the provided Row object is valid, any data
* that was already present in the Store for that Row will be completely
* overwritten. If the object is completely invalid, no change will be made to
* the Store.
*
* The method returns a reference to the Store so that subsequent operations
* can be chained in a fluent style.
* @param tableId The Id of the Table in the Store.
* @param rowId The Id of the Row in the Table.
* @param row The data of a single Row to be set.
* @returns A reference to the Store.
* @example
* This example sets the data of a single Row.
*
* ```js
* import {createStore} from 'tinybase';
*
* const store = createStore().setRow('pets', 'fido', {species: 'dog'});
* console.log(store.getTables());
* // -> {pets: {fido: {species: 'dog'}}}
* ```
* @example
* This example attempts to set the data of an existing Store with partly
* invalid, and then completely invalid, Row objects.
*
* ```js
* import {createStore} from 'tinybase';
*
* const store = createStore().setTables({pets: {fido: {species: 'dog'}}});
*
* store.setRow('pets', 'fido', {color: 'brown', bug: []});
* console.log(store.getTables());
* // -> {pets: {fido: {color: 'brown'}}}
*
* store.setRow('pets', 'fido', 42);
* console.log(store.getTables());
* // -> {pets: {fido: {color: 'brown'}}}
* ```
* @category Setter
* @since v1.0.0
*/
setRow(tableId: Id, rowId: Id, row: Row): this;
/**
* The addRow method takes an object and creates a new Row in the Store,
* returning the unique Id assigned to it.
*
* This method will cause listeners to be called for any Table, Row, Cell, or
* Id changes resulting from it.
*
* Any part of the provided object that is invalid (either according to the
* Row type, or because it does not match a TablesSchema associated with the
* Store), will be ignored silently.
*
* Assuming that at least some of the provided Row object is valid, a new Row
* will be created. If the object is completely invalid, no change will be
* made to the Store and the method will return `undefined`.
*
* You should not guarantee the form of the unique Id that is generated when a
* Row is added to the Table. However it is likely to be a string
* representation of an increasing integer.
*
* The `reuseRowIds` parameter defaults to `true`, which means that if you
* delete a Row and then add another, the Id will be re-used - unless you
* delete the entire Table, in which case all Row Ids will reset. Otherwise,
* if you specify `reuseRowIds` to be `false`, then the Id will be a
* monotonically increasing string representation of an increasing integer,
* regardless of any you may have previously deleted.
* @param tableId The Id of the Table in the Store.
* @param row The data of a single Row to be added.
* @param reuseRowIds Whether Ids should be recycled from previously deleted
* Row objects, defaulting to `true`.
* @returns A reference to the Store.
* @example
* This example adds a single Row.
*
* ```js
* import {createStore} from 'tinybase';
*
* const store = createStore();
* console.log(store.addRow('pets', {species: 'dog'}));
* // -> '0'
* console.log(store.getTables());
* // -> {pets: {'0': {species: 'dog'}}}
* ```
* @example
* This example attempts to add Rows to an existing Store with partly invalid,
* and then completely invalid, Row objects.
*
* ```js
* import {createStore} from 'tinybase';
*
* const store = createStore().setTables({pets: {'0': {species: 'dog'}}});
*
* console.log(store.addRow('pets', {species: 'cat', bug: []}));
* // -> '1'
* console.log(store.getTables());
* // -> {pets: {'0': {species: 'dog'}, '1': {species: 'cat'}}}
*
* console.log(store.addRow('pets', 42));
* // -> undefined
* console.log(store.getTables());
* // -> {pets: {'0': {species: 'dog'}, '1': {species: 'cat'}}}
* ```
* @category Setter
* @since v1.0.0
*/
addRow(tableId: Id, row: Row, reuseRowIds?: boolean): Id | undefined;
/**
* The setPartialRow method takes an object and sets partial data of a single
* Row in the Store, leaving other Cell values unaffected.
*
* This method will cause listeners to be called for any Table, Row, Cell, or
* Id changes resulting from it.
*
* Any part of the provided object that is invalid (either according to the
* Row type, or because, when combined with the current Row data, it does not
* match a TablesSchema associated with the Store), will be ignored silently.
*
* Assuming that at least some of the provided Row object is valid, it will be
* merged with the data that was already present in the Store. If the object
* is completely invalid, no change will be made to the Store.
*
* The method returns a reference to the Store so that subsequent operations
* can be chained in a fluent style.
* @param tableId The Id of the Table in the Store.
* @param rowId The Id of the Row in the Table.
* @param partialRow The partial data of a single Row to be set.
* @returns A reference to the Store.
* @example
* This example sets some of the data of a single Row.
*
* ```js
* import {createStore} from 'tinybase';
*
* const store = createStore().setTables({
* pets: {fido: {species: 'dog', color: 'brown'}},
* });
* store.setPartialRow('pets', 'fido', {color: 'walnut', visits: 1});
* console.log(store.getTables());
* // -> {pets: {fido: {species: 'dog', color: 'walnut', visits: 1}}}
* ```
* @example
* This example attempts to set some of the data of an existing Store with
* partly invalid, and then completely invalid, Row objects.
*
* ```js
* import {createStore} from 'tinybase';
*
* const store = createStore().setTables({pets: {fido: {species: 'dog'}}});
*
* store.setPartialRow('pets', 'fido', {color: 'brown', bug: []});
* console.log(store.getTables());
* // -> {pets: {fido: {species: 'dog', color: 'brown'}}}
*
* store.setPartialRow('pets', 'fido', 42);
* console.log(store.getTables());
* // -> {pets: {fido: {species: 'dog', color: 'brown'}}}
* ```
* @category Setter
* @since v1.0.0
*/
setPartialRow(tableId: Id, rowId: Id, partialRow: Row): this;
/**
* The setCell method sets the value of a single Cell in the Store.
*
* This method will cause listeners to be called for any Table, Row, Cell, or
* Id changes resulting from it.
*
* If the Cell value is invalid (either because of its type, or because it
* does not match a TablesSchema associated with the Store), will be ignored
* silently.
*
* As well as string, number, or boolean Cell types, this method can also take
* a MapCell function that takes the current Cell value as a parameter and
* maps it. This is useful if you want to efficiently increment a value
* without fetching it first, for example.
*
* The method returns a reference to the Store so that subsequent operations
* can be chained in a fluent style.
* @param tableId The Id of the Table in the Store.
* @param rowId The Id of the Row in the Table.
* @param cellId The Id of the Cell in the Row.
* @param cell The value of the Cell to be set, or a MapCell function to
* update it.
* @returns A reference to the Store.
* @example
* This example sets the value of a single Cell.
*
* ```js
* import {createStore} from 'tinybase';
*
* const store = createStore().setCell('pets', 'fido', 'species', 'dog');
* console.log(store.getTables());
* // -> {pets: {fido: {species: 'dog'}}}
* ```
* @example
* This example sets the data of a single Cell by mapping the existing value.
*
* ```js
* import {createStore} from 'tinybase';
*
* const increment = (cell) => cell + 1;
* const store = createStore().setTables({pets: {fido: {visits: 1}}});
*
* store.setCell('pets', 'fido', 'visits', increment);
* console.log(store.getCell('pets', 'fido', 'visits'));
* // -> 2
* ```
* @example
* This example attempts to set the data of an existing Store with an invalid
* Cell value.
*
* ```js
* import {createStore} from 'tinybase';
*
* const store = createStore().setTables({pets: {fido: {species: 'dog'}}});
*
* store.setCell('pets', 'fido', 'bug', []);
* console.log(store.getTables());
* // -> {pets: {fido: {species: 'dog'}}}
* ```
* @category Setter
* @since v1.0.0
*/
setCell(tableId: Id, rowId: Id, cellId: Id, cell: Cell | MapCell): this;
/**
* The setValues method takes an object and sets all the Values in the Store.
*
* This method will cause listeners to be called for any Value or Id changes
* resulting from it.
*
* Any part of the provided object that is invalid (either according to the
* Values type, or because it does not match a ValuesSchema associated with
* the Store), will be ignored silently.
*
* Assuming that at least some of the provided Values object is valid, any
* data that was already present in the Store for that Values will be
* completely overwritten. If the object is completely invalid, no change will
* be made to the Store.
*
* The method returns a reference to the Store so that subsequent operations
* can be chained in a fluent style.
* @param values The Values object to be set.
* @returns A reference to the Store.
* @example
* This example sets the Values of a Store.
*
* ```js
* import {createStore} from 'tinybase';
*
* const store = createStore().setValues({open: true, employees: 3});
* console.log(store.getValues());
* // -> {open: true, employees: 3}
* ```
* @example
* This example attempts to set the data of an existing Store with partly
* invalid, and then completely invalid, Values objects.
*
* ```js
* import {createStore} from 'tinybase';
*
* const store = createStore().setValues({open: true});
*
* store.setValues({employees: 3, bug: []});
* console.log(store.getValues());
* // -> {employees: 3}
*
* store.setValues(42);
* console.log(store.getValues());
* // -> {employees: 3}
* ```
* @category Setter
* @since v3.0.0
*/
setValues(values: Values): this;
/**
* The setPartialValues method takes an object and sets its Values in the
* Store, but leaving existing Values unaffected.
*
* This method will cause listeners to be called for any Values or Id changes
* resulting from it.
*
* Any part of the provided object that is invalid (either according to the
* Values type, or because, when combined with the current Values data, it
* does not match a ValuesSchema associated with the Store), will be ignored
* silently.
*
* Assuming that at least some of the provided Values object is valid, it will
* be merged with the data that was already present in the Store. If the
* object is completely invalid, no change will be made to the Store.
*
* The method returns a reference to the Store so that subsequent operations
* can be chained in a fluent style.
* @param partialValues The Values to be set.
* @returns A reference to the Store.
* @example
* This example sets some of the keyed value data in a Store.
*
* ```js
* import {createStore} from 'tinybase';
*
* const store = createStore().setValues({open: true});
* store.setPartialValues({employees: 3});
* console.log(store.getValues());
* // -> {open: true, employees: 3}
* ```
* @example
* This example attempts to set some of the data of an existing Store with
* partly invalid, and then completely invalid, Values objects.
*
* ```js
* import {createStore} from 'tinybase';
*
* const store = createStore().setValues({open: true});
*
* store.setPartialValues({employees: 3, bug: []});
* console.log(store.getValues());
* // -> {open: true, employees: 3}
*
* store.setPartialValues(42);
* console.log(store.getValues());
* // -> {open: true, employees: 3}
* ```
* @category Setter
* @since v3.0.0
*/
setPartialValues(partialValues: Values): this;
/**
* The setValue method sets a single keyed Value in the Store.
*
* This method will cause listeners to be called for any Value, or Id changes
* resulting from it.
*
* If the Value is invalid (either because of its type, or because it does not
* match a ValuesSchema associated with the Store), will be ignored silently.
*
* As well as string, number, or boolean Value types, this method can also
* take a MapValue function that takes the current Value as a parameter and
* maps it. This is useful if you want to efficiently increment a value
* without fetching it first, for example.
*
* The method returns a reference to the Store so that subsequent operations
* can be chained in a fluent style.
* @param valueId The Id of the Value in the Store.
* @param value The Value to be set, or a MapValue function to update it.
* @returns A reference to the Store.
* @example
* This example sets a single Value.
*
* ```js
* import {createStore} from 'tinybase';
*
* const store = createStore().setValue('open', true);
* console.log(store.getValues());
* // -> {open: true}
* ```
* @example
* This example sets the data of a single Value by mapping the existing Value.
*
* ```js
* import {createStore} from 'tinybase';
*
* const increment = (value) => value + 1;
* const store = createStore().setValues({employees: 3});
*
* store.setValue('employees', increment);
* console.log(store.getValue('employees'));
* // -> 4
* ```
* @example
* This example attempts to set an invalid Value.
*
* ```js
* import {createStore} from 'tinybase';
*
* const store = createStore().setValues({employees: 3});
*
* store.setValue('bug', []);
* console.log(store.getValues());
* // -> {employees: 3}
* ```
* @category Setter
* @since v3.0.0
*/
setValue(valueId: Id, value: Value | MapValue): this;
/**
* The applyChanges method applies a set of Changes to the Store.
*
* This method will take a Changes object (which is available at the end of a
* transaction) and apply it to a Store. The most likely need to do this is to
* take the changes made during the transaction of one Store, and apply it to
* the content of _another_ Store - such as when persisting and synchronizing
* data.
*
* Any part of the provided Changes object are invalid (either because of its
* type, or because it does not match the schemas associated with the Store)
* will be ignored silently.
*
* The method returns a reference to the Store so that subsequent operations
* can be chained in a fluent style.
*
* Prior to v5.0, this method was named `setTransactionChanges`.
* @param changes The Changes to apply to the Store.
* @returns A reference to the Store.
* @example
* This example applies a Changes object that sets a Cell and removes a Value.
*
* ```js
* import {createStore} from 'tinybase';
*
* const store = createStore()
* .setTables({pets: {fido: {species: 'dog', color: 'brown'}}})
* .setValues({open: true});
*
* store.applyChanges([{pets: {fido: {color: 'black'}}}, {open: null}]);
* console.log(store.getTables());
* // -> {pets: {fido: {species: 'dog', color: 'black'}}}
* console.log(store.getValues());
* // -> {}
* ```
* @category Setter
* @since v5.0.0
*/
applyChanges(changes: Changes): this;
/**
* The setTablesJson method takes a string serialization of all of the Tables
* in the Store and attempts to update them to that.
*
* If the JSON cannot be parsed, this will fail silently. If it can be parsed,
* it will then be subject to the same validation rules as the setTables
* method (according to the Tables type, and matching any TablesSchema
* associated with the Store).
* @param tablesJson A string serialization of all of the Tables in the Store.
* @returns A reference to the Store.
* @example
* This example sets the tabular contents of a Store from a serialization.
*
* ```js
* import {createStore} from 'tinybase';
*
* const store = createStore();
* store.setTablesJson('{"pets": {"fido": {"species": "dog"}}}');
* console.log(store.getTables());
* // -> {pets: {fido: {species: 'dog'}}}
* ```
* @example
* This example attempts to set the tabular contents of a Store from an
* invalid serialization.
*
* ```js
* import {createStore} from 'tinybase';
*
* const store = createStore();
* store.setTablesJson('{"pets": {"fido": {');
* console.log(store.getTables());
* // -> {}
* ```
* @category Setter
* @since v3.0.0
*/
setTablesJson(tablesJson: Json): this;
/**
* The setValuesJson method takes a string serialization of all of the Values
* in the Store and attempts to update them to those values.
*
* If the JSON cannot be parsed, this will fail silently. If it can be parsed,
* it will then be subject to the same validation rules as the setValues
* method (according to the Values type, and matching any ValuesSchema
* associated with the Store).
* @param valuesJson A string serialization of all of the Values in the Store.
* @returns A reference to the Store.
* @example
* This example sets the keyed value contents of a Store from a serialization.
*
* ```js
* import {createStore} from 'tinybase';
*
* const store = createStore();
* store.setValuesJson('{"open": true}');
* console.log(store.getValues());
* // -> {open: true}
* ```
* @example
* This example attempts to set the keyed value contents of a Store from an
* invalid serialization.
*
* ```js
* import {createStore} from 'tinybase';
*
* const store = createStore();
* store.setValuesJson('{"open": false');
* console.log(store.getValues());
* // -> {}
* ```
* @category Setter
* @since v3.0.0
*/
setValuesJson(valuesJson: Json): this;
/**
* The setJson method takes a string serialization of all of the Tables and
* Values in the Store and attempts to update them to those values.
*
* From v3.0 onwards, the serialization should be of an array with two
* entries. The first is the Tables object, the second the Values. In previous
* versions (before the existence of the Values data structure), it was a sole
* object of Tables. For backwards compatibility, if a serialization of a
* single object is provided, it will be treated as the Tables type.
*
* If the JSON cannot be parsed, this will fail silently. If it can be parsed,
* it will then be subject to the same validation rules as the setTables
* method (according to the Tables type, and matching any TablesSchema
* associated with the Store), and the setValues method (according to the
* Values type, and matching any ValuesSchema associated with the Store).
* @param tablesAndValuesJson A string serialization of all of the Tables and
* Values in the Store.
* @returns A reference to the Store.
* @example
* This example sets the tabular and keyed value contents of a Store from a
* serialization.
*
* ```js
* import {createStore} from 'tinybase';
*
* const store = createStore();
* store.setJson('[{"pets": {"fido": {"species": "dog"}}}, {"open": true}]');
* console.log(store.getTables());
* // -> {pets: {fido: {species: 'dog'}}}
* console.log(store.getValues());
* // -> {open: true}
* ```
* @example
* This example sets the tabular contents of a Store from a
* legacy single-object serialization (compatible with v2.x and earlier).
*
* ```js
* import {createStore} from 'tinybase';
*
* const store = createStore();
* store.setJson('{"pets": {"fido": {"species": "dog"}}}');
* console.log(store.getTables());
* // -> {pets: {fido: {species: 'dog'}}}
* console.log(store.getValues());
* // -> {}
* ```
* @example
* This example attempts to set both the tabular and keyed value contents of a
* Store from an invalid serialization.
*
* ```js
* import {createStore} from 'tinybase';
*
* const store = createStore();
* store.setValuesJson('[{"pets": {"fido": {"species": "do');
* console.log(store.getTables());
* // -> {}
* console.log(store.getValues());
* // -> {}
* ```
* @category Setter
* @since v1.0.0
*/
setJson(tablesAndValuesJson: Json): this;
/**
* The setTablesSchema method lets you specify the TablesSchema of the tabular
* part of the Store.
*
* Note that this may result in a change to data in the Store, as defaults are
* applied or as invalid Table, Row, or Cell objects are removed. These
* changes will fire any listeners to that data, as expected.
*
* When no longer needed, you can also completely remove an existing
* TablesSchema with the delTablesSchema method.
* @param tablesSchema The TablesSchema to be set for the Store.
* @returns A reference to the Store.
* @example
* This example sets the TablesSchema of a Store after it has been created.
*
* ```js
* import {createStore} from 'tinybase';
*
* const store = createStore().setTablesSchema({
* pets: {
* species: {type: 'string'},
* sold: {type: 'boolean', default: false},
* },
* });
* store.addRow('pets', {species: 'dog', color: 'brown', sold: 'maybe'});
*
* console.log(store.getTables());
* // -> {pets: {0: {species: 'dog', sold: false}}}
* ```
* @category Setter
* @since v3.0.0
*/
setTablesSchema(tablesSchema: TablesSchema): this;
/**
* The setValuesSchema method lets you specify the ValuesSchema of the keyed
* Values part of the Store.
*
* Note that this may result in a change to data in the Store, as defaults are
* applied or as invalid Values are removed. These changes will fire any
* listeners to that data, as expected.
*
* When no longer needed, you can also completely remove an existing
* ValuesSchema with the delValuesSchema method.
* @param valuesSchema The ValuesSchema to be set for the Store.
* @returns A reference to the Store.
* @example
* This example sets the ValuesSchema of a Store after it has been created.
*
* ```js
* import {createStore} from 'tinybase';
*
* const store = createStore().setValuesSchema({
* open: {type: 'boolean', default: false},
* });
* store.setValue('open', 'maybe');
*
* console.log(store.getValues());
* // -> {open: false}
* ```
* @category Setter
* @since v3.0.0
*/
setValuesSchema(valuesSchema: ValuesSchema): this;
/**
* The setSchema method lets you specify the TablesSchema and ValuesSchema of
* the Store.
*
* Note that this may result in a change to data in the Store, as defaults are
* applied or as invalid Table, Row, Cell, or Value objects are removed. These
* changes will fire any listeners to that data, as expected.
*
* From v3.0 onwards, this method takes two arguments. The first is the
* TablesSchema object, the second the ValuesSchema. In previous versions
* (before the existence of the ValuesSchema data structure), only the first
* was present. For backwards compatibility the new second parameter is
* optional.
* @param tablesSchema The TablesSchema to be set for the Store.
* @param valuesSchema The ValuesSchema to be set for the Store.
* @returns A reference to the Store.
* @example
* This example sets the TablesSchema and ValuesSchema of a Store after it has
* been created.
*
* ```js
* import {createStore} from 'tinybase';
*
* const store = createStore().setSchema(
* {
* pets: {
* species: {type: 'string'},
* sold: {type: 'boolean', default: false},
* },
* },
* {open: {type: 'boolean', default: false}},
* );
* store.addRow('pets', {species: 'dog', color: 'brown', sold: 'maybe'});
* store.setValue('open', 'maybe');
*
* console.log(store.getTables());
* // -> {pets: {0: {species: 'dog', sold: false}}}
* console.log(store.getValues());
* // -> {open: false}
* ```
* @example
* This example sets just the TablesSchema of a Store after it has been
* created.
*
* ```js
* import {createStore} from 'tinybase';
*
* const store = createStore().setSchema({
* pets: {
* species: {type: 'string'},
* sold: {type: 'boolean', default: false},
* },
* });
* store.addRow('pets', {species: 'dog', color: 'brown', sold: 'maybe'});
*
* console.log(store.getTables());
* // -> {pets: {0: {species: 'dog', sold: false}}}
* ```
* @category Setter
* @since v1.0.0
*/
setSchema(tablesSchema: TablesSchema, valuesSchema?: ValuesSchema): this;
/**
* The delTables method lets you remove all of the data in a Store.
* @returns A reference to the Store.
* @example
* This example removes the data of a Store.
*
* ```js
* import {createStore} from 'tinybase';
*
* const store = createStore().setTables({pets: {fido: {species: 'dog'}}});
*
* store.delTables();
* console.log(store.getTables());
* // -> {}
* ```
* @category Deleter
* @since v1.0.0
*/
delTables(): this;
/**
* The delTable method lets you remove a single Table from the Store.
* @param tableId The Id of the Table in the Store.
* @returns A reference to the Store.
* @example
* This example removes a Table from a Store.
*
* ```js
* import {createStore} from 'tinybase';
*
* const store = createStore().setTables({
* pets: {fido: {species: 'dog'}},
* species: {dog: {price: 5}},
* });
* store.delTable('pets');
*
* console.log(store.getTables());
* // -> {species: {dog: {price: 5}}}
* ```
* @category Deleter
* @since v1.0.0
*/
delTable(tableId: Id): this;
/**
* The delRow method lets you remove a single Row from a Table.
*
* If this is the last Row in its Table, then that Table will be removed.
* @param tableId The Id of the Table in the Store.
* @param rowId The Id of the Row in the Table.
* @returns A reference to the Store.
* @example
* This example removes a Row from a Table.
*
* ```js
* import {createStore} from 'tinybase';
*
* const store = createStore().setTables({
* pets: {fido: {species: 'dog'}, felix: {species: 'cat'}},
* });
* store.delRow('pets', 'fido');
*
* console.log(store.getTables());
* // -> {pets: {felix: {species: 'cat'}}}
* ```
* @category Deleter
* @since v1.0.0
*/
delRow(tableId: Id, rowId: Id): this;
/**
* The delCell method lets you remove a single Cell from a Row.
*
* When there is no TablesSchema applied to the Store, then if this is the
* last Cell in its Row, then that Row will be removed. If, in turn, that is
* the last Row in its Table, then that Table will be removed.
*
* If there is a TablesSchema applied to the Store and it specifies a default
* value for this Cell, then deletion will result in it being set back to its
* default value. To override this, use the `forceDel` parameter, as described
* below.
*
* The `forceDel` parameter is an optional flag that is only relevant if a
* TablesSchema provides a default value for this Cell. Under such
* circumstances, deleting a Cell value will normally restore it to the
* default value. If this flag is set to `true`, the complete removal of the
* Cell is instead guaranteed. But since doing do so would result in an
* invalid Row (according to the TablesSchema), in fact the whole Row is
* deleted to retain the integrity of the Table. Therefore, this flag should
* be used with caution.
* @param tableId The Id of the Table in the Store.
* @param rowId The Id of the Row in the Table.
* @param cellId The Id of the Cell in the Row.
* @param forceDel An optional flag to indicate that the whole Row should be
* deleted, even if a TablesSchema provides a default value for this Cell.
* Defaults to `false`.
* @returns A reference to the Store.
* @example
* This example removes a Cell from a Row without a TablesSchema.
*
* ```js
* import {createStore} from 'tinybase';
*
* const store = createStore().setTables({
* pets: {fido: {species: 'dog', sold: true}},
* });
* store.delCell('pets', 'fido', 'sold');
*
* console.log(store.getTables());
* // -> {pets: {fido: {species: 'dog'}}}
* ```
* @example
* This example removes a Cell from a Row with a TablesSchema that defaults
* its value.
*
* ```js
* import {createStore} from 'tinybase';
*
* const store = createStore()
* .setTables({
* pets: {fido: {species: 'dog', sold: true}},
* })
* .setTablesSchema({
* pets: {
* species: {type: 'string'},
* sold: {type: 'boolean', default: false},
* },
* });
* store.delCell('pets', 'fido', 'sold');
*
* console.log(store.getTables());
* // -> {pets: {fido: {species: 'dog', sold: false}}}
* ```
* @example
* This example removes a Cell from a Row with a TablesSchema that defaults
* its value, but uses the `forceDel` parameter to override it.
*
* ```js
* import {createStore} from 'tinybase';
*
* const store = createStore()
* .setTables({
* pets: {fido: {species: 'dog', sold: true}, felix: {species: 'cat'}},
* })
* .setTablesSchema({
* pets: {
* species: {type: 'string'},
* sold: {type: 'boolean', default: false},
* },
* });
* store.delCell('pets', 'fido', 'sold', true);
*
* console.log(store.getTables());
* // -> {pets: {felix: {species: 'cat', sold: false}}}
* ```
* @category Deleter
* @since v1.0.0
*/
delCell(tableId: Id, rowId: Id, cellId: Id, forceDel?: boolean): this;
/**
* The delValues method lets you remove all the Values from a Store.
*
* If there is a ValuesSchema applied to the Store and it specifies a default
* value for any Value Id, then deletion will result in it being set back to
* its default value.
* @returns A reference to the Store.
* @example
* This example removes all Values from a Store without a ValuesSchema.
*
* ```js
* import {createStore} from 'tinybase';
*
* const store = createStore().setValues({open: true, employees: 3});
* store.delValues();
*
* console.log(store.getValues());
* // -> {}
* ```
* @example
* This example removes all Values from a Store with a ValuesSchema that
* defaults one of its values.
*
* ```js
* import {createStore} from 'tinybase';
*
* const store = createStore()
* .setValues({open: true, employees: 3})
* .setValuesSchema({
* open: {type: 'boolean', default: false},
* employees: {type: 'number'},
* });
* store.delValues();
*
* console.log(store.getValues());
* // -> {open: false}
* ```
* @category Deleter
* @since v3.0.0
*/
delValues(): this;
/**
* The delValue method lets you remove a single Value from a Store.
*
* If there is a ValuesSchema applied to the Store and it specifies a default
* value for this Value Id, then deletion will result in it being set back to
* its default value.
* @param valueId The Id of the Value in the Row.
* @returns A reference to the Store.
* @example
* This example removes a Value from a Store without a ValuesSchema.
*
* ```js
* import {createStore} from 'tinybase';
*
* const store = createStore().setValues({open: true, employees: 3});
* store.delValue('employees');
*
* console.log(store.getValues());
* // -> {open: true}
* ```
* @example
* This example removes a Value from a Store with a ValuesSchema that defaults
* its value.
*
* ```js
* import {createStore} from 'tinybase';
*
* const store = createStore()
* .setValues({open: true, employees: 3})
* .setValuesSchema({
* open: {type: 'boolean', default: false},
* employees: {type: 'number'},
* });
* store.delValue('open');
*
* console.log(store.getValues());
* // -> {open: false, employees: 3}
* ```
* @category Deleter
* @since v3.0.0
*/
delValue(valueId: Id): this;
/**
* The delTablesSchema method lets you remove the TablesSchema of the Store.
* @returns A reference to the Store.
* @example
* This example removes the TablesSchema of a Store.
*
* ```js
* import {createStore} from 'tinybase';
*
* const store = createStore().setTablesSchema({
* pets: {species: {type: 'string'}},
* });
* store.delTablesSchema();
* console.log(store.getTablesSchemaJson());
* // -> '{}'
* ```
* @category Deleter
* @since v1.0.0
*/
delTablesSchema(): this;
/**
* The delValuesSchema method lets you remove the ValuesSchema of the Store.
* @returns A reference to the Store.
* @example
* This example removes the ValuesSchema of a Store.
*
* ```js
* import {createStore} from 'tinybase';
*
* const store = createStore().setValuesSchema({
* sold: {type: 'boolean', default: false},
* });
* store.delValuesSchema();
* console.log(store.getValuesSchemaJson());
* // -> '{}'
* ```
* @category Deleter
* @since v3.0.0
*/
delValuesSchema(): this;
/**
* The delSchema method lets you remove both the TablesSchema and ValuesSchema
* of the Store.
*
* Prior to v3.0, this method removed the TablesSchema only.
* @returns A reference to the Store.
* @example
* This example removes the TablesSchema and ValuesSchema of a Store.
*
* ```js
* import {createStore} from 'tinybase';
*
* const store = createStore()
* .setTablesSchema({
* pets: {species: {type: 'string'}},
* })
* .setValuesSchema({
* sold: {type: 'boolean', default: false},
* });
* store.delSchema();
* console.log(store.getSchemaJson());
* // -> '[{},{}]'
* ```
* @category Deleter
* @since v3.0.0
*/
delSchema(): this;
/**
* The transaction method takes a function that makes multiple mutations to
* the Store, buffering all calls to the relevant listeners until it
* completes.
*
* This method is useful for making bulk changes to the data in a Store, and
* when you don't want listeners to be called as you make each change. Changes
* are made silently during the transaction, and listeners relevant to the
* changes you have made will instead only be called when the whole
* transaction is complete.
*
* If multiple changes are made to a piece of Store data throughout the
* transaction, a relevant listener will only be called with the final value
* (assuming it is different to the value at the start of the transaction),
* regardless of the changes that happened in between. For example, if a Cell
* had a value `'a'` and then, within a transaction, it was changed to `'b'`
* and then `'c'`, any CellListener registered for that cell would be called
* once as if there had been a single change from `'a'` to `'c'`.
*
* Transactions can be nested. Relevant listeners will be called only when the
* outermost one completes.
*
* The second, optional parameter, `doRollback` is a DoRollback callback that
* you can use to rollback the transaction if it did not complete to your
* satisfaction. See the DoRollback documentation for more details.
* @param actions The function to be executed as a transaction.
* @param doRollback An optional callback that should return `true` if you
* want to rollback the transaction at the end. Since v1.2.
* @returns Whatever value the provided transaction function returns.
* @example
* This example makes changes to two Cells, first outside, and secondly
* within, a transaction. In the second case, the Row listener is only called
* once.
*
* ```js
* import {createStore} from 'tinybase';
*
* const store = createStore().setTables({pets: {fido: {species: 'dog'}}});
* store.addRowListener('pets', 'fido', () => console.log('Fido changed'));
*
* store
* .setCell('pets', 'fido', 'color', 'brown')
* .setCell('pets', 'fido', 'sold', false);
* // -> 'Fido changed'
* // -> 'Fido changed'
*
* store.transaction(() =>
* store
* .setCell('pets', 'fido', 'color', 'walnut')
* .setCell('pets', 'fido', 'sold', true),
* );
* // -> 'Fido changed'
* ```
* @example
* This example makes multiple changes to one Cell. The Cell listener is
* called once - and with the final value - only if there is a net overall
* change.
*
* ```js
* import {createStore} from 'tinybase';
*
* const store = createStore().setTables({pets: {fido: {species: 'dog'}}});
* store.addCellListener(
* 'pets',
* 'fido',
* 'color',
* (store, tableId, rowId, cellId, newCell) => console.log(newCell),
* );
*
* store.transaction(() =>
* store
* .setCell('pets', 'fido', 'color', 'black')
* .setCell('pets', 'fido', 'color', 'brown')
* .setCell('pets', 'fido', 'color', 'walnut'),
* );
* // -> 'walnut'
*
* store.transaction(() =>
* store
* .setCell('pets', 'fido', 'color', 'black')
* .setCell('pets', 'fido', 'color', 'walnut'),
* );
* // -> undefined
* // No net change during the transaction, so the listener is not called.
* ```
* @example
* This example makes multiple changes to the Store, including some attempts
* to update a Cell and Value with invalid values. The `doRollback` callback
* receives information about the changes and invalid attempts, and then
* judges that the transaction should be rolled back to its original state.
*
* ```js
* import {createStore} from 'tinybase';
*
* const store = createStore()
* .setTables({pets: {fido: {species: 'dog', color: 'brown'}}})
* .setValues({open: true});
*
* store.transaction(
* () =>
* store
* .setCell('pets', 'fido', 'color', 'black')
* .setCell('pets', 'fido', 'eyes', ['left', 'right'])
* .setCell('pets', 'fido', 'info', {sold: null})
* .setValue('open', false)
* .setValue('employees', ['alice', 'bob']),
* () => {
* const [, , changedCells, invalidCells, changedValues, invalidValues] =
* store.getTransactionLog();
* console.log(store.getTables());
* console.log(changedCells);
* console.log(invalidCells);
* console.log(changedValues);
* console.log(invalidValues);
* return invalidCells['pets'] != null;
* },
* );
* // -> {pets: {fido: {species: 'dog', color: 'black'}}}
* // -> {pets: {fido: {color: ['brown', 'black']}}}
* // -> {pets: {fido: {eyes: [['left', 'right']], info: [{sold: null}]}}}
* // -> {open: [true, false]}
* // -> {employees: [['alice', 'bob']]}
*
* console.log(store.getTables());
* // -> {pets: {fido: {species: 'dog', color: 'brown'}}}
* console.log(store.getValues());
* // -> {open: true}
* ```
* @category Transaction
* @since v1.0.0
*/
transaction<Return>(actions: () => Return, doRollback?: DoRollback): Return;
/**
* The startTransaction method allows you to explicitly start a transaction
* that will make multiple mutations to the Store, buffering all calls to the
* relevant listeners until it completes when you call the finishTransaction
* method.
*
* Transactions are useful for making bulk changes to the data in a Store, and
* when you don't want listeners to be called as you make each change. Changes
* are made silently during the transaction, and listeners relevant to the
* changes you have made will instead only be called when the whole
* transaction is complete.
*
* Generally it is preferable to use the transaction method to wrap a block of
* code as a transaction. It simply calls both the startTransaction and
* finishTransaction methods for you. See that method for several transaction
* examples.
*
* Use this startTransaction method when you have a more 'open-ended'
* transaction, such as one containing mutations triggered from other events
* that are asynchronous or not occurring inline to your code. You must
* remember to also call the finishTransaction method explicitly when it is
* done, of course.
* @returns A reference to the Store.
* @example
* This example makes changes to two Cells, first outside, and secondly
* within, a transaction that is explicitly started and finished. In the
* second case, the Row listener is only called once.
*
* ```js
* import {createStore} from 'tinybase';
*
* const store = createStore().setTables({pets: {fido: {species: 'dog'}}});
* store.addRowListener('pets', 'fido', () => console.log('Fido changed'));
*
* store
* .setCell('pets', 'fido', 'color', 'brown')
* .setCell('pets', 'fido', 'sold', false);
* // -> 'Fido changed'
* // -> 'Fido changed'
*
* store
* .startTransaction()
* .setCell('pets', 'fido', 'color', 'walnut')
* .setCell('pets', 'fido', 'sold', true)
* .finishTransaction();
* // -> 'Fido changed'
* ```
* @category Transaction
* @since v1.3.0
*/
startTransaction(): this;
/**
* The getTransactionChanges method returns the net meaningful changes that
* have been made to a Store during a transaction.
*
* This is useful for deciding whether to rollback a transaction, for example.
* The returned object is only meaningful if the method is called when the
* Store is in a transaction - such as in a TransactionListener.
* @returns A Changes object representing the changes.
* @example
* This example makes changes to the Store. At the end of the transaction,
* detail about what changed is enumerated.
*
* ```js
* import {createStore} from 'tinybase';
*
* const store = createStore()
* .setTables({pets: {fido: {species: 'dog', color: 'brown'}}})
* .setValues({open: true});
*
* store
* .startTransaction()
* .setCell('pets', 'fido', 'color', 'black')
* .setValue('open', false)
* .finishTransaction(() => {
* const [changedCells, changedValues] = store.getTransactionChanges();
* console.log(changedCells);
* console.log(changedValues);
* });
* // -> {pets: {fido: {color: 'black'}}}
* // -> {open: false}
* ```
* @category Transaction
* @since v5.0.0
*/
getTransactionChanges(): Changes;
/**
* The getTransactionLog method returns the changes that were made to a Store
* during a transaction in more detail, including invalid changes, and what
* previous values were.
*
* This is useful for deciding whether to rollback a transaction, for example.
* The returned object is only meaningful if the method is called when the
* Store is in a transaction - such as in a TransactionListener.
* @returns A TransactionLog object representing the changes.
* @example
* This example makes changes to the Store. At the end of the transaction,
* detail about what changed is enumerated.
*
* ```js
* import {createStore} from 'tinybase';
*
* const store = createStore()
* .setTables({pets: {fido: {species: 'dog', color: 'brown'}}})
* .setValues({open: true});
*
* store
* .startTransaction()
* .setCell('pets', 'fido', 'color', 'black')
* .setCell('pets', 'fido', 'eyes', ['left', 'right'])
* .setCell('pets', 'fido', 'info', {sold: null})
* .setValue('open', false)
* .setValue('employees', ['alice', 'bob'])
* .finishTransaction(() => {
* const [, , changedCells, invalidCells, changedValues, invalidValues] =
* store.getTransactionLog();
* console.log(changedCells);
* console.log(invalidCells);
* console.log(changedValues);
* console.log(invalidValues);
* });
* // -> {pets: {fido: {color: ['brown', 'black']}}}
* // -> {pets: {fido: {eyes: [['left', 'right']], info: [{sold: null}]}}}
* // -> {open: [true, false]}
* // -> {employees: [['alice', 'bob']]}
* ```
* @category Transaction
* @since v5.0.0
*/
getTransactionLog(): TransactionLog;
/**
* The finishTransaction method allows you to explicitly finish a transaction
* that has made multiple mutations to the Store, triggering all calls to the
* relevant listeners.
*
* Transactions are useful for making bulk changes to the data in a Store, and
* when you don't want listeners to be called as you make each change. Changes
* are made silently during the transaction, and listeners relevant to the
* changes you have made will instead only be called when the whole
* transaction is complete.
*
* Generally it is preferable to use the transaction method to wrap a block of
* code as a transaction. It simply calls both the startTransaction and
* finishTransaction methods for you. See that method for several transaction
* examples.
*
* Use this finishTransaction method when you have a more 'open-ended'
* transaction, such as one containing mutations triggered from other events
* that are asynchronous or not occurring inline to your code. There must have
* been a corresponding startTransaction method that this completes, of
* course, otherwise this function has no effect.
*
* The optional parameter, `doRollback` is a DoRollback callback that you can
* use to rollback the transaction if it did not complete to your
* satisfaction. It is called with `getTransactionChanges` and
* `getTransactionLog` parameters, which inform you of the net changes that
* have been made during the transaction, at different levels of detail. See
* the DoRollback documentation for more details.
* @param doRollback An optional callback that should return `true` if you
* want to rollback the transaction at the end.
* @returns A reference to the Store.
* @example
* This example makes changes to two Cells, first outside, and secondly
* within, a transaction that is explicitly started and finished. In the
* second case, the Row listener is only called once.
*
* ```js
* import {createStore} from 'tinybase';
*
* const store = createStore().setTables({pets: {fido: {species: 'dog'}}});
* store.addRowListener('pets', 'fido', () => console.log('Fido changed'));
*
* store
* .setCell('pets', 'fido', 'color', 'brown')
* .setCell('pets', 'fido', 'sold', false);
* // -> 'Fido changed'
* // -> 'Fido changed'
*
* store
* .startTransaction()
* .setCell('pets', 'fido', 'color', 'walnut')
* .setCell('pets', 'fido', 'sold', true)
* .finishTransaction();
* // -> 'Fido changed'
* ```
* @example
* This example makes multiple changes to the Store, including some attempts
* to update a Cell with invalid values. The `doRollback` callback receives
* information about the changes and invalid attempts, and then judges that
* the transaction should be rolled back to its original state.
*
* ```js
* import {createStore} from 'tinybase';
*
* const store = createStore()
* .setTables({pets: {fido: {species: 'dog', color: 'brown'}}})
* .setValues({open: true});
*
* store
* .startTransaction()
* .setCell('pets', 'fido', 'color', 'black')
* .setCell('pets', 'fido', 'eyes', ['left', 'right'])
* .setCell('pets', 'fido', 'info', {sold: null})
* .setValue('open', false)
* .setValue('employees', ['alice', 'bob'])
* .finishTransaction(() => {
* const [, , changedCells, invalidCells, changedValues, invalidValues] =
* store.getTransactionLog();
* console.log(store.getTables());
* console.log(changedCells);
* console.log(invalidCells);
* console.log(changedValues);
* console.log(invalidValues);
* return invalidCells['pets'] != null;
* });
* // -> {pets: {fido: {species: 'dog', color: 'black'}}}
* // -> {pets: {fido: {color: ['brown', 'black']}}}
* // -> {pets: {fido: {eyes: [['left', 'right']], info: [{sold: null}]}}}
* // -> {open: [true, false]}
* // -> {employees: [['alice', 'bob']]}
*
* console.log(store.getTables());
* // -> {pets: {fido: {species: 'dog', color: 'brown'}}}
* console.log(store.getValues());
* // -> {open: true}
* ```
* @category Transaction
* @since v1.3.0
*/
finishTransaction(doRollback?: DoRollback): this;
/**
* The forEachTable method takes a function that it will then call for each
* Table in the Store.
*
* This method is useful for iterating over the Table structure of the Store
* in a functional style. The `tableCallback` parameter is a TableCallback
* function that will be called with the Id of each Table, and with a function
* that can then be used to iterate over each Row of the Table, should you
* wish.
* @param tableCallback The function that should be called for every Table.
* @example
* This example iterates over each Table in a Store, and lists each Row Id
* within them.
*
* ```js
* import {createStore} from 'tinybase';
*
* const store = createStore().setTables({
* pets: {fido: {species: 'dog'}},
* species: {dog: {price: 5}},
* });
* store.forEachTable((tableId, forEachRow) => {
* console.log(tableId);
* forEachRow((rowId) => console.log(`- ${rowId}`));
* });
* // -> 'pets'
* // -> '- fido'
* // -> 'species'
* // -> '- dog'
* ```
* @category Iterator
* @since v1.0.0
*/
forEachTable(tableCallback: TableCallback): void;
/**
* The forEachTableCell method takes a function that it will then call for
* each Cell used across the whole Table.
*
* This method is useful for iterating over the Cell structure of the Table in
* a functional style. The `tableCellCallback` parameter is a
* TableCellCallback function that will be called with the Id of each Cell and
* the count of Rows in the Table in which it appears.
* @param tableId The Id of the Table containing the Cells to iterate over.
* @param tableCellCallback The function that should be called for every Cell
* Id used across the whole Table.
* @example
* This example iterates over each Cell Id used across the whole Table.
*
* ```js
* import {createStore} from 'tinybase';
*
* const store = createStore().setTables({
* pets: {fido: {species: 'dog'}, felix: {species: 'cat', legs: 4}},
* });
* store.forEachTableCell('pets', (cellId, count) => {
* console.log(`${cellId}: ${count}`);
* });
* // -> 'species: 2'
* // -> 'legs: 1'
* ```
* @category Iterator
* @since v3.3.0
*/
forEachTableCell(tableId: Id, tableCellCallback: TableCellCallback): void;
/**
* The forEachRow method takes a function that it will then call for each Row
* in a specified Table.
*
* This method is useful for iterating over the Row structure of the Table in
* a functional style. The `rowCallback` parameter is a RowCallback function
* that will be called with the Id of each Row, and with a function that can
* then be used to iterate over each Cell of the Row, should you wish.
* @param tableId The Id of the Table to iterate over.
* @param rowCallback The function that should be called for every Row.
* @example
* This example iterates over each Row in a Table, and lists each Cell Id
* within them.
*
* ```js
* import {createStore} from 'tinybase';
*
* const store = createStore().setTables({
* pets: {
* fido: {species: 'dog'},
* felix: {color: 'black'},
* },
* });
* store.forEachRow('pets', (rowId, forEachCell) => {
* console.log(rowId);
* forEachCell((cellId) => console.log(`- ${cellId}`));
* });
* // -> 'fido'
* // -> '- species'
* // -> 'felix'
* // -> '- color'
* ```
* @category Iterator
* @since v1.0.0
*/
forEachRow(tableId: Id, rowCallback: RowCallback): void;
/**
* The forEachCell method takes a function that it will then call for each
* Cell in a specified Row.
*
* This method is useful for iterating over the Cell structure of the Row in a
* functional style. The `cellCallback` parameter is a CellCallback function
* that will be called with the Id and value of each Cell.
* @param tableId The Id of the Table containing the Row to iterate over.
* @param rowId The Id of the Row to iterate over.
* @param cellCallback The function that should be called for every Cell.
* @example
* This example iterates over each Cell in a Row, and lists its value.
*
* ```js
* import {createStore} from 'tinybase';
*
* const store = createStore().setTables({
* pets: {fido: {species: 'dog', color: 'brown'}},
* });
* store.forEachCell('pets', 'fido', (cellId, cell) => {
* console.log(`${cellId}: ${cell}`);
* });
* // -> 'species: dog'
* // -> 'color: brown'
* ```
* @category Iterator
* @since v1.0.0
*/
forEachCell(tableId: Id, rowId: Id, cellCallback: CellCallback): void;
/**
* The forEachValue method takes a function that it will then call for each
* Value in a Store.
*
* This method is useful for iterating over the Value structure of the Store
* in a functional style. The `valueCallback` parameter is a ValueCallback
* function that will be called with the Id and value of each Value.
* @param valueCallback The function that should be called for every Value.
* @example
* This example iterates over each Value in a Store, and lists its value.
*
* ```js
* import {createStore} from 'tinybase';
*
* const store = createStore().setValues({open: true, employees: 3});
* store.forEachValue((valueId, value) => {
* console.log(`${valueId}: ${value}`);
* });
* // -> 'open: true'
* // -> 'employees: 3'
* ```
* @category Iterator
* @since v3.0.0
*/
forEachValue(valueCallback: ValueCallback): void;
/**
* The addHasTablesListener method registers a listener function with the
* Store that will be called when Tables as a whole are added to or removed
* from the Store.
*
* The provided listener is a HasTablesListener function, and will be called
* with a reference to the Store. It is also given a flag to indicate whether
* Tables now exist (having not done previously), or do not (having done so
* previously).
*
* Use the optional mutator parameter to indicate that there is code in the
* listener that will mutate Store data. If set to `false` (or omitted), such
* mutations will be silently ignored. All relevant mutator listeners (with
* this flag set to `true`) are called _before_ any non-mutator listeners
* (since the latter may become relevant due to changes made in the former).
* The changes made by mutator listeners do not fire other mutating listeners,
* though they will fire non-mutator listeners.
* @param listener The function that will be called whenever Tables as a whole
* are added or removed.
* @param mutator An optional boolean that indicates that the listener mutates
* Store data.
* @returns A unique Id for the listener that can later be used to call it
* explicitly, or to remove it.
* @example
* This example registers a listener that responds to Tables being added or
* removed.
*
* ```js
* import {createStore} from 'tinybase';
*
* const store = createStore().setTables({
* pets: {fido: {species: 'dog', color: 'brown'}},
* });
* const listenerId = store.addHasTablesListener((store, hasTables) => {
* console.log('Tables ' + (hasTables ? 'added' : 'removed'));
* });
*
* store.delTables();
* // -> 'Tables removed'
*
* store.setTables({species: {dog: {price: 5}}});
* // -> 'Tables added'
*
* store.delListener(listenerId);
* ```
* @example
* This example registers a listener that responds to Tables being added or
* removed, and which also mutates the Store itself.
*
* ```js
* import {createStore} from 'tinybase';
*
* const store = createStore();
* const listenerId = store.addHasTablesListener(
* (store, hasTables) => store.setValue('hasTables', hasTables),
* true,
* );
*
* store.setTables({species: {dog: {price: 5}}});
* console.log(store.getValues());
* // -> {hasTables: true}
*
* store.delListener(listenerId);
* ```
* @category Listener
* @since v4.4.0
*/
addHasTablesListener(
listener: HasTablesListener<this>,
mutator?: boolean,
): Id;
/**
* The addTablesListener method registers a listener function with the Store
* that will be called whenever data in the Store changes.
*
* The provided listener is a TablesListener function, and will be called with
* a reference to the Store and a GetCellChange function in case you need to
* inspect any changes that occurred.
*
* Use the optional mutator parameter to indicate that there is code in the
* listener that will mutate Store data. If set to `false` (or omitted), such
* mutations will be silently ignored. All relevant mutator listeners (with
* this flag set to `true`) are called _before_ any non-mutator listeners
* (since the latter may become relevant due to changes made in the former).
* The changes made by mutator listeners do not fire other mutating listeners,
* though they will fire non-mutator listeners.
* @param listener The function that will be called whenever data in the Store
* changes.
* @param mutator An optional boolean that indicates that the listener mutates
* Store data.
* @returns A unique Id for the listener that can later be used to call it
* explicitly, or to remove it.
* @example
* This example registers a listener that responds to any changes to the whole
* Store.
*
* ```js
* import {createStore} from 'tinybase';
*
* const store = createStore().setTables({
* pets: {fido: {species: 'dog', color: 'brown'}},
* });
* const listenerId = store.addTablesListener((store, getCellChange) => {
* console.log('Tables changed');
* console.log(getCellChange('pets', 'fido', 'color'));
* });
*
* store.setCell('pets', 'fido', 'color', 'walnut');
* // -> 'Tables changed'
* // -> [true, 'brown', 'walnut']
*
* store.delListener(listenerId);
* ```
* @example
* This example registers a listener that responds to any changes to the whole
* Store, and which also mutates the Store itself.
*
* ```js
* import {createStore} from 'tinybase';
*
* const store = createStore().setTables({
* pets: {fido: {species: 'dog', color: 'brown'}},
* });
* const listenerId = store.addTablesListener(
* (store) => store.setCell('meta', 'update', 'store', true),
* true,
* );
*
* store.delCell('pets', 'fido', 'color');
* console.log(store.getTable('meta'));
* // -> {update: {store: true}}
*
* store.delListener(listenerId);
* ```
* @category Listener
* @since v1.0.0
*/
addTablesListener(listener: TablesListener<this>, mutator?: boolean): Id;
/**
* The addTableIdsListener method registers a listener function with the Store
* that will be called whenever the Table Ids in the Store change.
*
* The provided listener is a TableIdsListener function, and will be called
* with a reference to the Store.
*
* By default, such a listener is only called when a Table is added or
* removed. To listen to all changes in the Store, use the addTablesListener
* method.
*
* Use the optional mutator parameter to indicate that there is code in the
* listener that will mutate Store data. If set to `false` (or omitted), such
* mutations will be silently ignored. All relevant mutator listeners (with
* this flag set to `true`) are called _before_ any non-mutator listeners
* (since the latter may become relevant due to changes made in the former).
* The changes made by mutator listeners do not fire other mutating listeners,
* though they will fire non-mutator listeners.
* @param listener The function that will be called whenever the Table Ids in
* the Store change.
* @param mutator An optional boolean that indicates that the listener mutates
* Store data.
* @returns A unique Id for the listener that can later be used to call it
* explicitly, or to remove it.
* @example
* This example registers a listener that responds to any change to the Table
* Ids.
*
* ```js
* import {createStore} from 'tinybase';
*
* const store = createStore().setTables({pets: {fido: {species: 'dog'}}});
* const listenerId = store.addTableIdsListener((store) => {
* console.log('Table Ids changed');
* console.log(store.getTableIds());
* });
*
* store.setTable('species', {dog: {price: 5}});
* // -> 'Table Ids changed'
* // -> ['pets', 'species']
*
* store.delListener(listenerId);
* ```
* @example
* This example registers a listener that responds to any change to the Table
* Ids, and which also mutates the Store itself.
*
* ```js
* import {createStore} from 'tinybase';
*
* const store = createStore().setTables({pets: {fido: {species: 'dog'}}});
* const listenerId = store.addTableIdsListener(
* (store) => store.setCell('meta', 'update', 'store', true),
* true, // mutator
* );
*
* store.setTable('species', {dog: {price: 5}});
* console.log(store.getTable('meta'));
* // -> {update: {store: true}}
*
* store.delListener(listenerId);
* ```
* @category Listener
* @since v1.0.0
*/
addTableIdsListener(listener: TableIdsListener<this>, mutator?: boolean): Id;
/**
* The addHasTableListener method registers a listener function with the Store
* that will be called when a Table is added to or removed from the Store.
*
* The provided listener is a HasTableListener function, and will be called
* with a reference to the Store and the Id of the Table that changed. It is
* also given a flag to indicate whether the Table now exists (having not done
* previously), or does not (having done so previously).
*
* You can either listen to a single Table being added or removed (by
* specifying the Table Id as the method's first parameter) or changes to any
* Table (by providing a `null` wildcard).
*
* Use the optional mutator parameter to indicate that there is code in the
* listener that will mutate Store data. If set to `false` (or omitted), such
* mutations will be silently ignored. All relevant mutator listeners (with
* this flag set to `true`) are called _before_ any non-mutator listeners
* (since the latter may become relevant due to changes made in the former).
* The changes made by mutator listeners do not fire other mutating listeners,
* though they will fire non-mutator listeners.
* @param tableId The Id of the Table to listen to, or `null` as a wildcard.
* @param listener The function that will be called whenever the matching
* Table is added or removed.
* @param mutator An optional boolean that indicates that the listener mutates
* Store data.
* @returns A unique Id for the listener that can later be used to call it
* explicitly, or to remove it.
* @example
* This example registers a listener that responds to a specific Table being
* added or removed.
*
* ```js
* import {createStore} from 'tinybase';
*
* const store = createStore().setTables({
* pets: {fido: {species: 'dog', color: 'brown'}},
* });
* const listenerId = store.addHasTableListener(
* 'pets',
* (store, tableId, hasTable) => {
* console.log('pets table ' + (hasTable ? 'added' : 'removed'));
* },
* );
*
* store.delTable('pets');
* // -> 'pets table removed'
*
* store.setTable('pets', {fido: {species: 'dog', color: 'brown'}});
* // -> 'pets table added'
*
* store.delListener(listenerId);
* ```
* @example
* This example registers a listener that responds to any Table being added or
* removed.
*
* ```js
* import {createStore} from 'tinybase';
*
* const store = createStore().setTables({
* pets: {fido: {species: 'dog', color: 'brown'}},
* });
* const listenerId = store.addHasTableListener(
* null,
* (store, tableId, hasTable) => {
* console.log(`${tableId} table ` + (hasTable ? 'added' : 'removed'));
* },
* );
*
* store.delTable('pets');
* // -> 'pets table removed'
* store.setTable('species', {dog: {price: 5}});
* // -> 'species table added'
*
* store.delListener(listenerId);
* ```
* @example
* This example registers a listener that responds to a specific Table being
* added or removed, and which also mutates the Store itself.
*
* ```js
* import {createStore} from 'tinybase';
*
* const store = createStore().setTables({
* pets: {fido: {species: 'dog', color: 'brown'}},
* });
* const listenerId = store.addHasTableListener(
* 'pets',
* (store, tableId) => store.setCell('meta', 'update', tableId, true),
* true,
* );
*
* store.delTable('pets', 'fido');
* console.log(store.getTable('meta'));
* // -> {update: {pets: true}}
*
* store.delListener(listenerId);
* ```
* @category Listener
* @since v4.4.0
*/
addHasTableListener(
tableId: IdOrNull,
listener: HasTableListener<this>,
mutator?: boolean,
): Id;
/**
* The addTableListener method registers a listener function with the Store
* that will be called whenever data in a Table changes.
*
* The provided listener is a TableListener function, and will be called with
* a reference to the Store, the Id of the Table that changed, and a
* GetCellChange function in case you need to inspect any changes that
* occurred.
*
* You can either listen to a single Table (by specifying its Id as the
* method's first parameter) or changes to any Table (by providing a `null`
* wildcard).
*
* Use the optional mutator parameter to indicate that there is code in the
* listener that will mutate Store data. If set to `false` (or omitted), such
* mutations will be silently ignored. All relevant mutator listeners (with
* this flag set to `true`) are called _before_ any non-mutator listeners
* (since the latter may become relevant due to changes made in the former).
* The changes made by mutator listeners do not fire other mutating listeners,
* though they will fire non-mutator listeners.
* @param tableId The Id of the Table to listen to, or `null` as a wildcard.
* @param listener The function that will be called whenever data in the
* matching Table changes.
* @param mutator An optional boolean that indicates that the listener mutates
* Store data.
* @returns A unique Id for the listener that can later be used to call it
* explicitly, or to remove it.
* @example
* This example registers a listener that responds to any changes to a
* specific Table.
*
* ```js
* import {createStore} from 'tinybase';
*
* const store = createStore().setTables({
* pets: {fido: {species: 'dog', color: 'brown'}},
* });
* const listenerId = store.addTableListener(
* 'pets',
* (store, tableId, getCellChange) => {
* console.log('pets table changed');
* console.log(getCellChange('pets', 'fido', 'color'));
* },
* );
*
* store.setCell('pets', 'fido', 'color', 'walnut');
* // -> 'pets table changed'
* // -> [true, 'brown', 'walnut']
*
* store.delListener(listenerId);
* ```
* @example
* This example registers a listener that responds to any changes to any
* Table.
*
* ```js
* import {createStore} from 'tinybase';
*
* const store = createStore().setTables({
* pets: {fido: {species: 'dog', color: 'brown'}},
* });
* const listenerId = store.addTableListener(null, (store, tableId) => {
* console.log(`${tableId} table changed`);
* });
*
* store.setCell('pets', 'fido', 'color', 'walnut');
* // -> 'pets table changed'
* store.setTable('species', {dog: {price: 5}});
* // -> 'species table changed'
*
* store.delListener(listenerId);
* ```
* @example
* This example registers a listener that responds to any changes to a
* specific Table, and which also mutates the Store itself.
*
* ```js
* import {createStore} from 'tinybase';
*
* const store = createStore().setTables({
* pets: {fido: {species: 'dog', color: 'brown'}},
* });
* const listenerId = store.addTableListener(
* 'pets',
* (store, tableId) => store.setCell('meta', 'update', tableId, true),
* true,
* );
*
* store.delCell('pets', 'fido', 'color');
* console.log(store.getTable('meta'));
* // -> {update: {pets: true}}
*
* store.delListener(listenerId);
* ```
* @category Listener
* @since v1.0.0
*/
addTableListener(
tableId: IdOrNull,
listener: TableListener<this>,
mutator?: boolean,
): Id;
/**
* The addTableCellIdsListener method registers a listener function with the
* Store that will be called whenever the Cell Ids that appear anywhere in a
* Table change.
*
* The provided listener is a TableCellIdsListener function, and will be
* called with a reference to the Store and the Id of the Table that changed.
*
* By default, such a listener is only called when a Cell Id is added or
* removed from the whole of the Table. To listen to all changes in the Table,
* use the addTableListener method.
*
* You can either listen to a single Table (by specifying its Id as the
* method's first parameter) or changes to any Table (by providing a `null`
* wildcard).
*
* Use the optional mutator parameter to indicate that there is code in the
* listener that will mutate Store data. If set to `false` (or omitted), such
* mutations will be silently ignored. All relevant mutator listeners (with
* this flag set to `true`) are called _before_ any non-mutator listeners
* (since the latter may become relevant due to changes made in the former).
* The changes made by mutator listeners do not fire other mutating listeners,
* though they will fire non-mutator listeners.
* @param tableId The Id of the Table to listen to, or `null` as a wildcard.
* @param listener The function that will be called whenever the Cell Ids that
* appear anywhere in a Table change.
* @param mutator An optional boolean that indicates that the listener mutates
* Store data.
* @returns A unique Id for the listener that can later be used to call it
* explicitly, or to remove it.
* @example
* This example registers a listener that responds to any change to the Cell
* Ids that appear anywhere in a Table.
*
* ```js
* import {createStore} from 'tinybase';
*
* const store = createStore().setTables({
* pets: {fido: {species: 'dog', color: 'brown'}},
* });
* const listenerId = store.addTableCellIdsListener('pets', (store) => {
* console.log('Cell Ids in pets table changed');
* console.log(store.getTableCellIds('pets'));
* });
*
* store.setRow('pets', 'felix', {species: 'cat', legs: 4});
* // -> 'Cell Ids in pets table changed'
* // -> ['species', 'color', 'legs']
*
* store.delListener(listenerId);
* ```
* @example
* This example registers a listener that responds to any change to the Cell
* Ids that appear anywhere in any Table.
*
* ```js
* import {createStore} from 'tinybase';
*
* const store = createStore().setTables({
* pets: {fido: {species: 'dog', color: 'brown'}},
* species: {dog: {price: 5}},
* });
* const listenerId = store.addTableCellIdsListener(
* null,
* (store, tableId) => {
* console.log(`Cell Ids in ${tableId} table changed`);
* console.log(store.getTableCellIds(tableId));
* },
* );
*
* store.setRow('pets', 'felix', {species: 'cat', legs: 4});
* // -> 'Cell Ids in pets table changed'
* // -> ['species', 'color', 'legs']
*
* store.setRow('species', 'cat', {price: 4, friendly: true});
* // -> 'Cell Ids in species table changed'
* // -> ['price', 'friendly']
*
* store.delListener(listenerId);
* ```
* @example
* This example registers a listener that responds to the Cell Ids that appear
* anywhere in a Table, and which also mutates the Store itself.
*
* ```js
* import {createStore} from 'tinybase';
*
* const store = createStore().setTables({
* pets: {fido: {species: 'dog', color: 'brown'}},
* });
* const listenerId = store.addTableCellIdsListener(
* 'pets',
* (store, tableId) => store.setCell('meta', 'update', tableId, true),
* true, // mutator
* );
*
* store.setRow('pets', 'felix', {species: 'cat', legs: 4});
* console.log(store.getTable('meta'));
* // -> {update: {pets: true}}
*
* store.delListener(listenerId);
* ```
* @category Listener
* @since v1.0.0
*/
addTableCellIdsListener(
tableId: IdOrNull,
listener: TableCellIdsListener<this>,
mutator?: boolean,
): Id;
/**
* The addHasTableCellListener method registers a listener function with the
* Store that will be called when a Cell is added to or removed from anywhere
* in a Table as a whole.
*
* The provided listener is a HasTableCellListener function, and will be
* called with a reference to the Store, the Id of the Table that changed, and
* the Id of the Table Cell that changed. It is also given a flag to indicate
* whether the Cell now exists anywhere in the Table (having not done
* previously), or does not (having done so previously).
*
* You can either listen to a single Table Cell being added or removed (by
* specifying the Table Id and Cell Id, as the method's first two parameters)
* or changes to any Table Cell (by providing `null` wildcards).
*
* Both, either, or neither of the `tableId` and `cellId` parameters can be
* wildcarded with `null`. You can listen to a specific Row in a specific
* Table, any Row in a specific Table, a specific Row in any Table, or any Row
* in any Table.
*
* Use the optional mutator parameter to indicate that there is code in the
* listener that will mutate Store data. If set to `false` (or omitted), such
* mutations will be silently ignored. All relevant mutator listeners (with
* this flag set to `true`) are called _before_ any non-mutator listeners
* (since the latter may become relevant due to changes made in the former).
* The changes made by mutator listeners do not fire other mutating listeners,
* though they will fire non-mutator listeners.
* @param tableId The Id of the Table to listen to, or `null` as a wildcard.
* @param cellId The Id of the Cell to listen to, or `null` as a wildcard.
* @param listener The function that will be called whenever the matching Cell
* is added to or removed from anywhere in the Table.
* @param mutator An optional boolean that indicates that the listener mutates
* Store data.
* @returns A unique Id for the listener that can later be used to call it
* explicitly, or to remove it.
* @example
* This example registers a listener that responds to a specific Cell being
* added to or removed from the Table as a whole.
*
* ```js
* import {createStore} from 'tinybase';
*
* const store = createStore().setTables({
* pets: {fido: {species: 'dog', color: 'brown'}},
* });
* const listenerId = store.addHasTableCellListener(
* 'pets',
* 'color',
* (store, tableId, cellId, hasTableCell) => {
* console.log(
* 'color cell in pets table ' + (hasTableCell ? 'added' : 'removed'),
* );
* },
* );
*
* store.delCell('pets', 'fido', 'color');
* // -> 'color cell in pets table removed'
*
* store.setRow('pets', 'felix', {species: 'cat', color: 'brown'});
* // -> 'color cell in pets table added'
*
* store.delListener(listenerId);
* ```
* @example
* This example registers a listener that responds to any Cell being
* added to or removed from the Table as a whole.
*
* ```js
* import {createStore} from 'tinybase';
*
* const store = createStore().setTables({
* pets: {fido: {species: 'dog', color: 'brown'}},
* });
* const listenerId = store.addHasTableCellListener(
* null,
* null,
* (store, tableId, cellId, hasTableCell) => {
* console.log(
* `${cellId} cell in ${tableId} table ` +
* (hasTableCell ? 'added' : 'removed'),
* );
* },
* );
*
* store.delCell('pets', 'fido', 'color');
* // -> 'color cell in pets table removed'
* store.setTable('species', {dog: {price: 5}});
* // -> 'price cell in species table added'
*
* store.delListener(listenerId);
* ```
* @example
* This example registers a listener that responds to a specific Cell being
* added or removed, and which also mutates the Store itself.
*
* ```js
* import {createStore} from 'tinybase';
*
* const store = createStore().setTables({
* pets: {fido: {species: 'dog', color: 'brown'}},
* });
* const listenerId = store.addHasTableCellListener(
* 'pets',
* 'color',
* (store, tableId, cellId) =>
* store.setCell('meta', 'update', `${tableId}_${cellId}`, true),
* true,
* );
*
* store.delRow('pets', 'fido');
* console.log(store.getTable('meta'));
* // -> {update: {pets_color: true}}
*
* store.delListener(listenerId);
* ```
* @category Listener
* @since v4.4.0
*/
addHasTableCellListener(
tableId: IdOrNull,
cellId: IdOrNull,
listener: HasTableCellListener<this>,
mutator?: boolean,
): Id;
/**
* The addRowCountListener method registers a listener function with the Store
* that will be called whenever the count of Row objects in a Table change.
*
* The provided listener is a RowCountListener function, and will be called
* with a reference to the Store, the Id of the Table that changed, and the
* number of Row objects in the Table.
*
* You can either listen to a single Table (by specifying its Id as the
* method's first parameter) or changes to any Table (by providing a `null`
* wildcard).
*
* Use the optional mutator parameter to indicate that there is code in the
* listener that will mutate Store data. If set to `false` (or omitted), such
* mutations will be silently ignored. All relevant mutator listeners (with
* this flag set to `true`) are called _before_ any non-mutator listeners
* (since the latter may become relevant due to changes made in the former).
* The changes made by mutator listeners do not fire other mutating listeners,
* though they will fire non-mutator listeners.
* @param tableId The Id of the Table to listen to, or `null` as a wildcard.
* @param listener The function that will be called whenever the number of Row
* objects in the Table changes.
* @param mutator An optional boolean that indicates that the listener mutates
* Store data.
* @returns A unique Id for the listener that can later be used to call it
* explicitly, or to remove it.
* @example
* This example registers a listener that responds to a change in the number
* of Row objects in a specific Table.
*
* ```js
* import {createStore} from 'tinybase';
*
* const store = createStore().setTables({pets: {fido: {species: 'dog'}}});
* const listenerId = store.addRowCountListener(
* 'pets',
* (store, _tableId, count) => {
* console.log('Row count for pets table changed to ' + count);
* },
* );
*
* store.setRow('pets', 'felix', {species: 'cat'});
* // -> 'Row count for pets table changed to 2'
*
* store.delListener(listenerId);
* ```
* @example
* This example registers a listener that responds to any change to a change
* in the number of Row objects of any Table.
*
* ```js
* import {createStore} from 'tinybase';
*
* const store = createStore().setTables({pets: {fido: {species: 'dog'}}});
* const listenerId = store.addRowCountListener(
* null,
* (store, tableId, count) => {
* console.log(`Row count for ${tableId} table changed to ${count}`);
* },
* );
*
* store.setRow('pets', 'felix', {species: 'cat'});
* // -> 'Row count for pets table changed to 2'
* store.setRow('species', 'dog', {price: 5});
* // -> 'Row count for species table changed to 1'
*
* store.delListener(listenerId);
* ```
* @example
* This example registers a listener that responds to any change to a change
* in the number of Row objects of a specific Table, and which also mutates
* the Store itself.
*
* ```js
* import {createStore} from 'tinybase';
*
* const store = createStore().setTables({pets: {fido: {species: 'dog'}}});
* const listenerId = store.addRowCountListener(
* 'pets',
* (store, tableId, count) =>
* store.setCell('meta', 'update', tableId, count),
* true, // mutator
* );
*
* store.setRow('pets', 'felix', {species: 'cat'});
* console.log(store.getTable('meta'));
* // -> {update: {pets: 2}}
*
* store.delListener(listenerId);
* ```
* @category Listener
* @since v4.1.0
*/
addRowCountListener(
tableId: IdOrNull,
listener: RowCountListener<this>,
mutator?: boolean,
): Id;
/**
* The addRowIdsListener method registers a listener function with the Store
* that will be called whenever the Row Ids in a Table change.
*
* The provided listener is a RowIdsListener function, and will be called with
* a reference to the Store and the Id of the Table that changed.
*
* By default, such a listener is only called when a Row is added or removed.
* To listen to all changes in the Table, use the addTableListener method.
*
* You can either listen to a single Table (by specifying its Id as the
* method's first parameter) or changes to any Table (by providing a `null`
* wildcard).
*
* Use the optional mutator parameter to indicate that there is code in the
* listener that will mutate Store data. If set to `false` (or omitted), such
* mutations will be silently ignored. All relevant mutator listeners (with
* this flag set to `true`) are called _before_ any non-mutator listeners
* (since the latter may become relevant due to changes made in the former).
* The changes made by mutator listeners do not fire other mutating listeners,
* though they will fire non-mutator listeners.
* @param tableId The Id of the Table to listen to, or `null` as a wildcard.
* @param listener The function that will be called whenever the Row Ids in
* the Table change.
* @param mutator An optional boolean that indicates that the listener mutates
* Store data.
* @returns A unique Id for the listener that can later be used to call it
* explicitly, or to remove it.
* @example
* This example registers a listener that responds to any change to the Row
* Ids of a specific Table.
*
* ```js
* import {createStore} from 'tinybase';
*
* const store = createStore().setTables({pets: {fido: {species: 'dog'}}});
* const listenerId = store.addRowIdsListener('pets', (store) => {
* console.log('Row Ids for pets table changed');
* console.log(store.getRowIds('pets'));
* });
*
* store.setRow('pets', 'felix', {species: 'cat'});
* // -> 'Row Ids for pets table changed'
* // -> ['fido', 'felix']
*
* store.delListener(listenerId);
* ```
* @example
* This example registers a listener that responds to any change to the Row
* Ids of any Table.
*
* ```js
* import {createStore} from 'tinybase';
*
* const store = createStore().setTables({pets: {fido: {species: 'dog'}}});
* const listenerId = store.addRowIdsListener(null, (store, tableId) => {
* console.log(`Row Ids for ${tableId} table changed`);
* console.log(store.getRowIds(tableId));
* });
*
* store.setRow('pets', 'felix', {species: 'cat'});
* // -> 'Row Ids for pets table changed'
* // -> ['fido', 'felix']
* store.setRow('species', 'dog', {price: 5});
* // -> 'Row Ids for species table changed'
* // -> ['dog']
*
* store.delListener(listenerId);
* ```
* @example
* This example registers a listener that responds to any change to the Row
* Ids of a specific Table, and which also mutates the Store itself.
*
* ```js
* import {createStore} from 'tinybase';
*
* const store = createStore().setTables({pets: {fido: {species: 'dog'}}});
* const listenerId = store.addRowIdsListener(
* 'pets',
* (store, tableId) => store.setCell('meta', 'update', tableId, true),
* true, // mutator
* );
*
* store.setRow('pets', 'felix', {species: 'cat'});
* console.log(store.getTable('meta'));
* // -> {update: {pets: true}}
*
* store.delListener(listenerId);
* ```
* @category Listener
* @since v1.0.0
*/
addRowIdsListener(
tableId: IdOrNull,
listener: RowIdsListener<this>,
mutator?: boolean,
): Id;
/**
* The addSortedRowIdsListener method registers a listener function with the
* Store that will be called whenever sorted (and optionally, paginated) Row
* Ids in a Table change.
*
* The provided listener is a SortedRowIdsListener function, and will be
* called with a reference to the Store, the Id of the Table whose Row Ids
* sorting changed, the Cell Id being used to sort them, whether descending or
* not, and the offset and limit of the number of Ids returned, for pagination
* purposes. It also receives the sorted array of Ids itself, so that you can
* use them in the listener without the additional cost of an explicit call to
* getSortedRowIds.
*
* Such a listener is called when a Row is added or removed, but also when a
* value in the specified Cell (somewhere in the Table) has changed enough to
* change the sorting of the Row Ids.
*
* Unlike most other listeners, you cannot provide wildcards (due to the cost
* of detecting changes to the sorting). You can only listen to a single
* specified Table, sorted by a single specified Cell.
*
* The sorting of the rows is alphanumeric, and you can indicate whether it
* should be in descending order. The `offset` and `limit` parameters are used
* to paginate results, but default to `0` and `undefined` to return all
* available Row Ids if not specified.
*
* Use the optional mutator parameter to indicate that there is code in the
* listener that will mutate Store data. If set to `false` (or omitted), such
* mutations will be silently ignored. All relevant mutator listeners (with
* this flag set to `true`) are called _before_ any non-mutator listeners
* (since the latter may become relevant due to changes made in the former).
* The changes made by mutator listeners do not fire other mutating listeners,
* though they will fire non-mutator listeners.
* @param tableId The Id of the Table to listen to.
* @param cellId The Id of the Cell whose values are used for the sorting, or
* `undefined` to sort by the Row Id itself.
* @param descending Whether the sorting should be in descending order.
* @param offset The number of Row Ids to skip for pagination purposes, if
* any.
* @param limit The maximum number of Row Ids to return, or `undefined` for
* all.
* @param listener The function that will be called whenever the sorted Row
* Ids in the Table change.
* @param mutator An optional boolean that indicates that the listener mutates
* Store data.
* @returns A unique Id for the listener that can later be used to call it
* explicitly, or to remove it.
* @example
* This example registers a listener that responds to any change to the sorted
* Row Ids of a specific Table.
*
* ```js
* import {createStore} from 'tinybase';
*
* const store = createStore().setTables({
* pets: {
* cujo: {species: 'wolf'},
* felix: {species: 'cat'},
* },
* });
* console.log(store.getSortedRowIds('pets', 'species', false));
* // -> ['felix', 'cujo']
*
* const listenerId = store.addSortedRowIdsListener(
* 'pets',
* 'species',
* false,
* 0,
* undefined,
* (store, tableId, cellId, descending, offset, limit, sortedRowIds) => {
* console.log(`Sorted Row Ids for ${tableId} table changed`);
* console.log(sortedRowIds);
* // ^ cheaper than calling getSortedRowIds again
* },
* );
*
* store.setRow('pets', 'fido', {species: 'dog'});
* // -> 'Sorted Row Ids for pets table changed'
* // -> ['felix', 'fido', 'cujo']
*
* store.delListener(listenerId);
* ```
* @example
* This example registers a listener that responds to any change to a
* paginated section of the sorted Row Ids of a specific Table.
*
* ```js
* import {createStore} from 'tinybase';
*
* const store = createStore().setTables({
* pets: {
* fido: {price: 6},
* felix: {price: 5},
* mickey: {price: 2},
* tom: {price: 4},
* carnaby: {price: 3},
* lowly: {price: 1},
* },
* });
*
* const listenerId = store.addSortedRowIdsListener(
* 'pets',
* 'price',
* false,
* 0,
* 3,
* (store, tableId, cellId, descending, offset, limit, sortedRowIds) => {
* console.log(`First three sorted Row Ids for ${tableId} table changed`);
* console.log(sortedRowIds);
* // ^ cheaper than calling getSortedRowIds again
* },
* );
* console.log(store.getSortedRowIds('pets', 'price', false, 0, 3));
* // -> ['lowly', 'mickey', 'carnaby']
*
* store.setCell('pets', 'carnaby', 'price', 4.5);
* // -> 'First three sorted Row Ids for pets table changed'
* // -> ['lowly', 'mickey', 'tom']
*
* store.delListener(listenerId);
* ```
* @example
* This example registers a listener that responds to any change to the sorted
* Row Ids of a specific Table. The Row Ids are sorted by their own value,
* since the `cellId` parameter is explicitly undefined.
*
* ```js
* import {createStore} from 'tinybase';
*
* const store = createStore().setTables({
* pets: {
* fido: {species: 'dog'},
* felix: {species: 'cat'},
* },
* });
* console.log(store.getSortedRowIds('pets', undefined, false));
* // -> ['felix', 'fido']
*
* const listenerId = store.addSortedRowIdsListener(
* 'pets',
* undefined,
* false,
* 0,
* undefined,
* (store, tableId, cellId, descending, offset, limit, sortedRowIds) => {
* console.log(`Sorted Row Ids for ${tableId} table changed`);
* console.log(sortedRowIds);
* // ^ cheaper than calling getSortedRowIds again
* },
* );
*
* store.setRow('pets', 'cujo', {species: 'wolf'});
* // -> 'Sorted Row Ids for pets table changed'
* // -> ['cujo', 'felix', 'fido']
*
* store.delListener(listenerId);
* ```
* @example
* This example registers a listener that responds to a change in the sorting
* of the rows of a specific Table, even though the set of Ids themselves has
* not changed.
*
* ```js
* import {createStore} from 'tinybase';
*
* const store = createStore().setTables({
* pets: {
* fido: {species: 'dog'},
* felix: {species: 'cat'},
* },
* });
* console.log(store.getSortedRowIds('pets', 'species', false));
* // -> ['felix', 'fido']
*
* const listenerId = store.addSortedRowIdsListener(
* 'pets',
* 'species',
* false,
* 0,
* undefined,
* (store, tableId, cellId, descending, offset, limit, sortedRowIds) => {
* console.log(`Sorted Row Ids for ${tableId} table changed`);
* console.log(sortedRowIds);
* // ^ cheaper than calling getSortedRowIds again
* },
* );
*
* store.setCell('pets', 'felix', 'species', 'tiger');
* // -> 'Sorted Row Ids for pets table changed'
* // -> ['fido', 'felix']
*
* store.delListener(listenerId);
* ```
* @example
* This example registers a listener that responds to any change to the sorted
* Row Ids of a specific Table, and which also mutates the Store itself.
*
* ```js
* import {createStore} from 'tinybase';
*
* const store = createStore().setTables({
* pets: {
* cujo: {species: 'wolf'},
* felix: {species: 'cat'},
* },
* });
* const listenerId = store.addSortedRowIdsListener(
* 'pets',
* 'species',
* false,
* 0,
* undefined,
* (store, tableId) => store.setCell('meta', 'sorted', tableId, true),
* true, // mutator
* );
*
* store.setRow('pets', 'fido', {species: 'dog'});
* console.log(store.getTable('meta'));
* // -> {sorted: {pets: true}}
*
* store.delListener(listenerId);
* ```
* @category Listener
* @since v2.0.0
*/
addSortedRowIdsListener(
tableId: Id,
cellId: Id | undefined,
descending: boolean,
offset: number,
limit: number | undefined,
listener: SortedRowIdsListener<this>,
mutator?: boolean,
): Id;
/**
* The addHasRowListener method registers a listener function with the Store
* that will be called when a Row is added to or removed from the Store.
*
* The provided listener is a HasRowListener function, and will be called with
* a reference to the Store, the Id of the Table that changed, and the Id of
* the Row that changed. It is also given a flag to indicate whether the Row
* now exists (having not done previously), or does not (having done so
* previously).
*
* You can either listen to a single Row being added or removed (by specifying
* the Table Id and Row Id, as the method's first two parameters) or changes
* to any Row (by providing `null` wildcards).
*
* Both, either, or neither of the `tableId` and `rowId` parameters can be
* wildcarded with `null`. You can listen to a specific Row in a specific
* Table, any Row in a specific Table, a specific Row in any Table, or any Row
* in any Table.
*
* Use the optional mutator parameter to indicate that there is code in the
* listener that will mutate Store data. If set to `false` (or omitted), such
* mutations will be silently ignored. All relevant mutator listeners (with
* this flag set to `true`) are called _before_ any non-mutator listeners
* (since the latter may become relevant due to changes made in the former).
* The changes made by mutator listeners do not fire other mutating listeners,
* though they will fire non-mutator listeners.
* @param tableId The Id of the Table to listen to, or `null` as a wildcard.
* @param rowId The Id of the Row to listen to, or `null` as a wildcard.
* @param listener The function that will be called whenever the matching Row
* is added or removed.
* @param mutator An optional boolean that indicates that the listener mutates
* Store data.
* @returns A unique Id for the listener that can later be used to call it
* explicitly, or to remove it.
* @example
* This example registers a listener that responds to a specific Row being
* added or removed.
*
* ```js
* import {createStore} from 'tinybase';
*
* const store = createStore().setTables({
* pets: {fido: {species: 'dog', color: 'brown'}},
* });
* const listenerId = store.addHasRowListener(
* 'pets',
* 'fido',
* (store, tableId, rowId, hasRow) => {
* console.log(
* 'fido row in pets table ' + (hasRow ? 'added' : 'removed'),
* );
* },
* );
*
* store.delRow('pets', 'fido');
* // -> 'fido row in pets table removed'
*
* store.setRow('pets', 'fido', {species: 'dog', color: 'brown'});
* // -> 'fido row in pets table added'
*
* store.delListener(listenerId);
* ```
* @example
* This example registers a listener that responds to any Row being added or
* removed.
*
* ```js
* import {createStore} from 'tinybase';
*
* const store = createStore().setTables({
* pets: {fido: {species: 'dog', color: 'brown'}},
* });
* const listenerId = store.addHasRowListener(
* null,
* null,
* (store, tableId, rowId, hasRow) => {
* console.log(
* `${rowId} row in ${tableId} table ` + (hasRow ? 'added' : 'removed'),
* );
* },
* );
*
* store.delRow('pets', 'fido');
* // -> 'fido row in pets table removed'
* store.setTable('species', {dog: {price: 5}});
* // -> 'dog row in species table added'
*
* store.delListener(listenerId);
* ```
* @example
* This example registers a listener that responds to a specific Row being
* added or removed, and which also mutates the Store itself.
*
* ```js
* import {createStore} from 'tinybase';
*
* const store = createStore().setTables({
* pets: {fido: {species: 'dog', color: 'brown'}},
* });
* const listenerId = store.addHasRowListener(
* 'pets',
* 'fido',
* (store, tableId, rowId) =>
* store.setCell('meta', 'update', `${tableId}_${rowId}`, true),
* true,
* );
*
* store.delRow('pets', 'fido');
* console.log(store.getTable('meta'));
* // -> {update: {pets_fido: true}}
*
* store.delListener(listenerId);
* ```
* @category Listener
* @since v4.4.0
*/
addHasRowListener(
tableId: IdOrNull,
rowId: IdOrNull,
listener: HasRowListener<this>,
mutator?: boolean,
): Id;
/**
* The addRowListener method registers a listener function with the Store that
* will be called whenever data in a Row changes.
*
* The provided listener is a RowListener function, and will be called with a
* reference to the Store, the Id of the Table that changed, the Id of the Row
* that changed, and a GetCellChange function in case you need to inspect any
* changes that occurred.
*
* You can either listen to a single Row (by specifying the Table Id and Row
* Id as the method's first two parameters) or changes to any Row (by
* providing `null` wildcards).
*
* Both, either, or neither of the `tableId` and `rowId` parameters can be
* wildcarded with `null`. You can listen to a specific Row in a specific
* Table, any Row in a specific Table, a specific Row in any Table, or any Row
* in any Table.
*
* Use the optional mutator parameter to indicate that there is code in the
* listener that will mutate Store data. If set to `false` (or omitted), such
* mutations will be silently ignored. All relevant mutator listeners (with
* this flag set to `true`) are called _before_ any non-mutator listeners
* (since the latter may become relevant due to changes made in the former).
* The changes made by mutator listeners do not fire other mutating listeners,
* though they will fire non-mutator listeners.
* @param tableId The Id of the Table to listen to, or `null` as a wildcard.
* @param rowId The Id of the Row to listen to, or `null` as a wildcard.
* @param listener The function that will be called whenever data in the
* matching Row changes.
* @param mutator An optional boolean that indicates that the listener mutates
* Store data.
* @returns A unique Id for the listener that can later be used to call it
* explicitly, or to remove it.
* @example
* This example registers a listener that responds to any changes to a
* specific Row.
*
* ```js
* import {createStore} from 'tinybase';
*
* const store = createStore().setTables({
* pets: {fido: {species: 'dog', color: 'brown'}},
* });
* const listenerId = store.addRowListener(
* 'pets',
* 'fido',
* (store, tableId, rowId, getCellChange) => {
* console.log('fido row in pets table changed');
* console.log(getCellChange('pets', 'fido', 'color'));
* },
* );
*
* store.setCell('pets', 'fido', 'color', 'walnut');
* // -> 'fido row in pets table changed'
* // -> [true, 'brown', 'walnut']
*
* store.delListener(listenerId);
* ```
* @example
* This example registers a listener that responds to any changes to any Row.
*
* ```js
* import {createStore} from 'tinybase';
*
* const store = createStore().setTables({
* pets: {fido: {species: 'dog', color: 'brown'}},
* });
* const listenerId = store.addRowListener(
* null,
* null,
* (store, tableId, rowId) => {
* console.log(`${rowId} row in ${tableId} table changed`);
* },
* );
*
* store.setCell('pets', 'fido', 'color', 'walnut');
* // -> 'fido row in pets table changed'
* store.setTable('species', {dog: {price: 5}});
* // -> 'dog row in species table changed'
*
* store.delListener(listenerId);
* ```
* @example
* This example registers a listener that responds to any changes to a
* specific Row, and which also mutates the Store itself.
*
* ```js
* import {createStore} from 'tinybase';
*
* const store = createStore().setTables({
* pets: {fido: {species: 'dog', color: 'brown'}},
* });
* const listenerId = store.addRowListener(
* 'pets',
* 'fido',
* (store, tableId, rowId) =>
* store.setCell('meta', 'update', `${tableId}_${rowId}`, true),
* true,
* );
*
* store.delCell('pets', 'fido', 'color');
* console.log(store.getTable('meta'));
* // -> {update: {pets_fido: true}}
*
* store.delListener(listenerId);
* ```
* @category Listener
* @since v1.0.0
*/
addRowListener(
tableId: IdOrNull,
rowId: IdOrNull,
listener: RowListener<this>,
mutator?: boolean,
): Id;
/**
* The addCellIdsListener method registers a listener function with the Store
* that will be called whenever the Cell Ids in a Row change.
*
* The provided listener is a CellIdsListener function, and will be called
* with a reference to the Store, the Id of the Table, and the Id of the Row
* that changed.
*
* By default, such a listener is only called when a Cell is added or removed.
* To listen to all changes in the Row, use the addRowListener method.
*
* You can either listen to a single Row (by specifying the Table Id and Row
* Id as the method's first two parameters) or changes to any Row (by
* providing a `null` wildcard).
*
* Both, either, or neither of the `tableId` and `rowId` parameters can be
* wildcarded with `null`. You can listen to a specific Row in a specific
* Table, any Row in a specific Table, a specific Row in any Table, or any Row
* in any Table.
*
* Use the optional mutator parameter to indicate that there is code in the
* listener that will mutate Store data. If set to `false` (or omitted), such
* mutations will be silently ignored. All relevant mutator listeners (with
* this flag set to `true`) are called _before_ any non-mutator listeners
* (since the latter may become relevant due to changes made in the former).
* The changes made by mutator listeners do not fire other mutating listeners,
* though they will fire non-mutator listeners.
* @param tableId The Id of the Table to listen to, or `null` as a wildcard.
* @param rowId The Id of the Row to listen to, or `null` as a wildcard.
* @param listener The function that will be called whenever the Cell Ids in
* the Row change.
* @param mutator An optional boolean that indicates that the listener mutates
* Store data.
* @returns A unique Id for the listener that can later be used to call it
* explicitly, or to remove it.
* @example
* This example registers a listener that responds to any change to the Cell
* Ids of a specific Row.
*
* ```js
* import {createStore} from 'tinybase';
*
* const store = createStore().setTables({pets: {fido: {species: 'dog'}}});
* const listenerId = store.addCellIdsListener('pets', 'fido', (store) => {
* console.log('Cell Ids for fido row in pets table changed');
* console.log(store.getCellIds('pets', 'fido'));
* });
*
* store.setCell('pets', 'fido', 'color', 'brown');
* // -> 'Cell Ids for fido row in pets table changed'
* // -> ['species', 'color']
*
* store.delListener(listenerId);
* ```
* @example
* This example registers a listener that responds to any change to the Cell
* Ids of any Row.
*
* ```js
* import {createStore} from 'tinybase';
*
* const store = createStore().setTables({pets: {fido: {species: 'dog'}}});
* const listenerId = store.addCellIdsListener(
* null,
* null,
* (store, tableId, rowId) => {
* console.log(`Cell Ids for ${rowId} row in ${tableId} table changed`);
* console.log(store.getCellIds(tableId, rowId));
* },
* );
*
* store.setCell('pets', 'fido', 'color', 'brown');
* // -> 'Cell Ids for fido row in pets table changed'
* // -> ['species', 'color']
* store.setCell('species', 'dog', 'price', 5);
* // -> 'Cell Ids for dog row in species table changed'
* // -> ['price']
*
* store.delListener(listenerId);
* ```
* @example
* This example registers a listener that responds to any change to the Cell
* Ids of a specific Row, and which also mutates the Store itself.
*
* ```js
* import {createStore} from 'tinybase';
*
* const store = createStore().setTables({pets: {fido: {species: 'dog'}}});
* const listenerId = store.addCellIdsListener(
* 'pets',
* 'fido',
* (store, tableId, rowId) =>
* store.setCell('meta', 'update', `${tableId}_${rowId}`, true),
* true, // mutator
* );
*
* store.setCell('pets', 'fido', 'color', 'brown');
* console.log(store.getTable('meta'));
* // -> {update: {pets_fido: true}}
*
* store.delListener(listenerId);
* ```
* @category Listener
* @since v1.0.0
*/
addCellIdsListener(
tableId: IdOrNull,
rowId: IdOrNull,
listener: CellIdsListener<this>,
mutator?: boolean,
): Id;
/**
* The addHasCellListener method registers a listener function with the Store
* that will be called when a Cell is added to or removed from the Store.
*
* The provided listener is a HasCellListener function, and will be called
* with a reference to the Store, the Id of the Table that changed, the Id of
* the Row that changed, and the Id of the Cell that changed. It is also given
* a flag to indicate whether the Cell now exists (having not done
* previously), or does not (having done so previously).
*
* You can either listen to a single Cell being added or removed (by
* specifying the Table Id, Row Id, and Cell Id as the method's first three
* parameters) or changes to any Cell (by providing `null` wildcards).
*
* All, some, or none of the `tableId`, `rowId`, and `cellId` parameters can
* be wildcarded with `null`. You can listen to a specific Cell in a specific
* Row in a specific Table, any Cell in any Row in any Table, for example - or
* every other combination of wildcards.
*
* Use the optional mutator parameter to indicate that there is code in the
* listener that will mutate Store data. If set to `false` (or omitted), such
* mutations will be silently ignored. All relevant mutator listeners (with
* this flag set to `true`) are called _before_ any non-mutator listeners
* (since the latter may become relevant due to changes made in the former).
* The changes made by mutator listeners do not fire other mutating listeners,
* though they will fire non-mutator listeners.
* @param tableId The Id of the Table to listen to, or `null` as a wildcard.
* @param rowId The Id of the Row to listen to, or `null` as a wildcard.
* @param cellId The Id of the Cell to listen to, or `null` as a wildcard.
* @param listener The function that will be called whenever the matching Cell
* is added or removed.
* @param mutator An optional boolean that indicates that the listener mutates
* Store data.
* @returns A unique Id for the listener that can later be used to call it
* explicitly, or to remove it.
* @example
* This example registers a listener that responds to a specific Cell being
* added or removed.
*
* ```js
* import {createStore} from 'tinybase';
*
* const store = createStore().setTables({
* pets: {fido: {species: 'dog', color: 'brown'}},
* });
* const listenerId = store.addHasCellListener(
* 'pets',
* 'fido',
* 'color',
* (store, tableId, rowId, cellId, hasCell) => {
* console.log(
* 'color cell in fido row in pets table ' +
* (hasCell ? 'added' : 'removed'),
* );
* },
* );
*
* store.delCell('pets', 'fido', 'color');
* // -> 'color cell in fido row in pets table removed'
*
* store.setCell('pets', 'fido', 'color', 'walnut');
* // -> 'color cell in fido row in pets table added'
*
* store.delListener(listenerId);
* ```
* @example
* This example registers a listener that responds to any Cell being added or
* removed.
*
* ```js
* import {createStore} from 'tinybase';
*
* const store = createStore().setTables({
* pets: {fido: {species: 'dog', color: 'brown'}},
* });
* const listenerId = store.addHasCellListener(
* null,
* null,
* null,
* (store, tableId, rowId, cellId, hasCell) => {
* console.log(
* `${cellId} cell in ${rowId} row in ${tableId} table ` +
* (hasCell ? 'added' : 'removed'),
* );
* },
* );
*
* store.delCell('pets', 'fido', 'color');
* // -> 'color cell in fido row in pets table removed'
* store.setTable('species', {dog: {price: 5}});
* // -> 'price cell in dog row in species table added'
*
* store.delListener(listenerId);
* ```
* @example
* This example registers a listener that responds to a specific Cell being
* added or removed, and which also mutates the Store itself.
*
* ```js
* import {createStore} from 'tinybase';
*
* const store = createStore().setTables({
* pets: {fido: {species: 'dog', color: 'brown'}},
* });
* const listenerId = store.addHasCellListener(
* 'pets',
* 'fido',
* 'color',
* (store, tableId, rowId, cellId) =>
* store.setCell('meta', 'update', `${tableId}_${rowId}_${cellId}`, true),
* true,
* );
*
* store.delCell('pets', 'fido', 'color');
* console.log(store.getTable('meta'));
* // -> {update: {pets_fido_color: true}}
*
* store.delListener(listenerId);
* ```
* @category Listener
* @since v4.4.0
*/
addHasCellListener(
tableId: IdOrNull,
rowId: IdOrNull,
cellId: IdOrNull,
listener: HasCellListener<this>,
mutator?: boolean,
): Id;
/**
* The addCellListener method registers a listener function with the Store
* that will be called whenever data in a Cell changes.
*
* The provided listener is a CellListener function, and will be called with a
* reference to the Store, the Id of the Table that changed, the Id of the Row
* that changed, the Id of the Cell that changed, the new Cell value, the old
* Cell value, and a GetCellChange function in case you need to inspect any
* changes that occurred.
*
* You can either listen to a single Cell (by specifying the Table Id, Row Id,
* and Cell Id as the method's first three parameters) or changes to any Cell
* (by providing `null` wildcards).
*
* All, some, or none of the `tableId`, `rowId`, and `cellId` parameters can
* be wildcarded with `null`. You can listen to a specific Cell in a specific
* Row in a specific Table, any Cell in any Row in any Table, for example - or
* every other combination of wildcards.
*
* Use the optional mutator parameter to indicate that there is code in the
* listener that will mutate Store data. If set to `false` (or omitted), such
* mutations will be silently ignored. All relevant mutator listeners (with
* this flag set to `true`) are called _before_ any non-mutator listeners
* (since the latter may become relevant due to changes made in the former).
* The changes made by mutator listeners do not fire other mutating listeners,
* though they will fire non-mutator listeners.
* @param tableId The Id of the Table to listen to, or `null` as a wildcard.
* @param rowId The Id of the Row to listen to, or `null` as a wildcard.
* @param cellId The Id of the Cell to listen to, or `null` as a wildcard.
* @param listener The function that will be called whenever data in the
* matching Cell changes.
* @param mutator An optional boolean that indicates that the listener mutates
* Store data.
* @returns A unique Id for the listener that can later be used to call it
* explicitly, or to remove it.
* @example
* This example registers a listener that responds to any changes to a
* specific Cell.
*
* ```js
* import {createStore} from 'tinybase';
*
* const store = createStore().setTables({
* pets: {fido: {species: 'dog', color: 'brown'}},
* });
* const listenerId = store.addCellListener(
* 'pets',
* 'fido',
* 'color',
* (store, tableId, rowId, cellId, newCell, oldCell, getCellChange) => {
* console.log('color cell in fido row in pets table changed');
* console.log([oldCell, newCell]);
* console.log(getCellChange('pets', 'fido', 'color'));
* },
* );
*
* store.setCell('pets', 'fido', 'color', 'walnut');
* // -> 'color cell in fido row in pets table changed'
* // -> ['brown', 'walnut']
* // -> [true, 'brown', 'walnut']
*
* store.delListener(listenerId);
* ```
* @example
* This example registers a listener that responds to any changes to any Cell.
*
* ```js
* import {createStore} from 'tinybase';
*
* const store = createStore().setTables({
* pets: {fido: {species: 'dog', color: 'brown'}},
* });
* const listenerId = store.addCellListener(
* null,
* null,
* null,
* (store, tableId, rowId, cellId) => {
* console.log(
* `${cellId} cell in ${rowId} row in ${tableId} table changed`,
* );
* },
* );
*
* store.setCell('pets', 'fido', 'color', 'walnut');
* // -> 'color cell in fido row in pets table changed'
* store.setTable('species', {dog: {price: 5}});
* // -> 'price cell in dog row in species table changed'
*
* store.delListener(listenerId);
* ```
* @example
* This example registers a listener that responds to any changes to a
* specific Cell, and which also mutates the Store itself.
*
* ```js
* import {createStore} from 'tinybase';
*
* const store = createStore().setTables({
* pets: {fido: {species: 'dog', color: 'brown'}},
* });
* const listenerId = store.addCellListener(
* 'pets',
* 'fido',
* 'color',
* (store, tableId, rowId, cellId) =>
* store.setCell('meta', 'update', `${tableId}_${rowId}_${cellId}`, true),
* true,
* );
*
* store.delCell('pets', 'fido', 'color');
* console.log(store.getTable('meta'));
* // -> {update: {pets_fido_color: true}}
*
* store.delListener(listenerId);
* ```
* @category Listener
* @since v1.0.0
*/
addCellListener(
tableId: IdOrNull,
rowId: IdOrNull,
cellId: IdOrNull,
listener: CellListener<this>,
mutator?: boolean,
): Id;
/**
* The addHasValuesListener method registers a listener function with the
* Store that will be called when Values as a whole are added to or removed
* from the Store.
*
* The provided listener is a HasValuesListener function, and will be called
* with a reference to the Store. It is also given a flag to indicate whether
* Values now exist (having not done previously), or do not (having done so
* previously).
*
* Use the optional mutator parameter to indicate that there is code in the
* listener that will mutate Store data. If set to `false` (or omitted), such
* mutations will be silently ignored. All relevant mutator listeners (with
* this flag set to `true`) are called _before_ any non-mutator listeners
* (since the latter may become relevant due to changes made in the former).
* The changes made by mutator listeners do not fire other mutating listeners,
* though they will fire non-mutator listeners.
* @param listener The function that will be called whenever Values as a whole
* are added or removed.
* @param mutator An optional boolean that indicates that the listener mutates
* Store data.
* @returns A unique Id for the listener that can later be used to call it
* explicitly, or to remove it.
* @example
* This example registers a listener that responds to Values being added or
* removed.
*
* ```js
* import {createStore} from 'tinybase';
*
* const store = createStore().setValues({open: true, employees: 3});
* const listenerId = store.addHasValuesListener((store, hasValues) => {
* console.log('Values ' + (hasValues ? 'added' : 'removed'));
* });
*
* store.delValues();
* // -> 'Values removed'
*
* store.setValue('employees', 4);
* // -> 'Values added'
*
* store.delListener(listenerId);
* ```
* @example
* This example registers a listener that responds to Values being added or
* removed, and which also mutates the Store itself.
*
* ```js
* import {createStore} from 'tinybase';
*
* const store = createStore();
* const listenerId = store.addHasValuesListener(
* (store, hasValues) => store.setValue('hasValues', hasValues),
* true,
* );
*
* store.setValue('employees', 4);
* console.log(store.getValues());
* // -> {employees: 4, hasValues: true}
*
* store.delListener(listenerId);
* ```
* @category Listener
* @since v4.4.0
*/
addHasValuesListener(
listener: HasValuesListener<this>,
mutator?: boolean,
): Id;
/**
* The addValuesListener method registers a listener function with the Store
* that will be called whenever the Values change.
*
* The provided listener is a ValuesListener function, and will be called with
* a reference to the Store and a GetValueChange function in case you need to
* inspect any changes that occurred.
*
* Use the optional mutator parameter to indicate that there is code in the
* listener that will mutate Store data. If set to `false` (or omitted), such
* mutations will be silently ignored. All relevant mutator listeners (with
* this flag set to `true`) are called _before_ any non-mutator listeners
* (since the latter may become relevant due to changes made in the former).
* The changes made by mutator listeners do not fire other mutating listeners,
* though they will fire non-mutator listeners.
* @param listener The function that will be called whenever data in the
* Values changes.
* @param mutator An optional boolean that indicates that the listener mutates
* Store data.
* @returns A unique Id for the listener that can later be used to call it
* explicitly, or to remove it.
* @example
* This example registers a listener that responds to any changes to the
* Store's Values.
*
* ```js
* import {createStore} from 'tinybase';
*
* const store = createStore().setValues({open: true, employees: 3});
* const listenerId = store.addValuesListener((store, getValueChange) => {
* console.log('values changed');
* console.log(getValueChange('employees'));
* });
*
* store.setValue('employees', 4);
* // -> 'values changed'
* // -> [true, 3, 4]
*
* store.delListener(listenerId);
* ```
* @example
* This example registers a listener that responds to any changes to the
* Store's Values, and which also mutates the Store itself.
*
* ```js
* import {createStore} from 'tinybase';
*
* const store = createStore().setValues({open: true, employees: 3});
* const listenerId = store.addValuesListener(
* (store) => store.setValue('updated', true),
* true,
* );
*
* store.setValue('employees', 4);
* console.log(store.getValues());
* // -> {open: true, employees: 4, updated: true}
*
* store.delListener(listenerId);
* ```
* @category Listener
* @since v3.0.0
*/
addValuesListener(listener: ValuesListener<this>, mutator?: boolean): Id;
/**
* The addValueIdsListener method registers a listener function with the Store
* that will be called whenever the Value Ids in a Store change.
*
* The provided listener is a ValueIdsListener function, and will be called
* with a reference to the Store.
*
* By default, such a listener is only called when a Value is added or
* removed. To listen to all changes in the Values, use the addValuesListener
* method.
*
* Use the optional mutator parameter to indicate that there is code in the
* listener that will mutate Store data. If set to `false` (or omitted), such
* mutations will be silently ignored. All relevant mutator listeners (with
* this flag set to `true`) are called _before_ any non-mutator listeners
* (since the latter may become relevant due to changes made in the former).
* The changes made by mutator listeners do not fire other mutating listeners,
* though they will fire non-mutator listeners.
* @param listener The function that will be called whenever the Value Ids in
* the Store change.
* @param mutator An optional boolean that indicates that the listener mutates
* Store data.
* @returns A unique Id for the listener that can later be used to call it
* explicitly, or to remove it.
* @example
* This example registers a listener that responds to any change to the Value
* Ids.
*
* ```js
* import {createStore} from 'tinybase';
*
* const store = createStore().setValues({open: true});
* const listenerId = store.addValueIdsListener((store) => {
* console.log('Value Ids changed');
* console.log(store.getValueIds());
* });
*
* store.setValue('employees', 3);
* // -> 'Value Ids changed'
* // -> ['open', 'employees']
*
* store.delListener(listenerId);
* ```
* @example
* This example registers a listener that responds to any change to the Value
* Ids, and which also mutates the Store itself.
*
* ```js
* import {createStore} from 'tinybase';
*
* const store = createStore().setValues({open: true});
* const listenerId = store.addValueIdsListener(
* (store) => store.setValue('updated', true),
* true, // mutator
* );
*
* store.setValue('employees', 3);
* console.log(store.getValues());
* // -> {open: true, employees: 3, updated: true}
*
* store.delListener(listenerId);
* ```
* @category Listener
* @since v3.0.0
*/
addValueIdsListener(listener: ValueIdsListener<this>, mutator?: boolean): Id;
/**
* The addHasValueListener method registers a listener function with the Store
* that will be called when a Value is added to or removed from the Store.
*
* The provided listener is a HasValueListener function, and will be called
* with a reference to the Store and the Id of Value that changed. It is also
* given a flag to indicate whether the Value now exists (having not done
* previously), or does not (having done so previously).
*
* You can either listen to a single Value being added or removed (by
* specifying the Value Id) or any Value being added or removed (by providing
* a `null` wildcard).
*
* Use the optional mutator parameter to indicate that there is code in the
* listener that will mutate Store data. If set to `false` (or omitted), such
* mutations will be silently ignored. All relevant mutator listeners (with
* this flag set to `true`) are called _before_ any non-mutator listeners
* (since the latter may become relevant due to changes made in the former).
* The changes made by mutator listeners do not fire other mutating listeners,
* though they will fire non-mutator listeners.
* @param valueId The Id of the Value to listen to, or `null` as a wildcard.
* @param listener The function that will be called whenever the matching
* Value is added or removed.
* @param mutator An optional boolean that indicates that the listener mutates
* Store data.
* @returns A unique Id for the listener that can later be used to call it
* explicitly, or to remove it.
* @example
* This example registers a listener that responds to a specific Value being
* added or removed.
*
* ```js
* import {createStore} from 'tinybase';
*
* const store = createStore().setValues({open: true, employees: 3});
* const listenerId = store.addHasValueListener(
* 'employees',
* (store, valueId, hasValue) => {
* console.log('employee value ' + (hasValue ? 'added' : 'removed'));
* },
* );
*
* store.delValue('employees');
* // -> 'employee value removed'
*
* store.setValue('employees', 4);
* // -> 'employee value added'
*
* store.delListener(listenerId);
* ```
* @example
* This example registers a listener that responds to any Value being added or
* removed.
*
* ```js
* import {createStore} from 'tinybase';
*
* const store = createStore().setValues({open: true, employees: 3});
* const listenerId = store.addHasValueListener(
* null,
* (store, valueId, hasValue) => {
* console.log(valueId + ' value ' + (hasValue ? 'added' : 'removed'));
* },
* );
*
* store.delValue('employees');
* // -> 'employees value removed'
* store.setValue('website', 'https://pets.com');
* // -> 'website value added'
*
* store.delListener(listenerId);
* ```
* @example
* This example registers a listener that responds to a specific Value being
* added or removed, and which also mutates the Store itself.
*
* ```js
* import {createStore} from 'tinybase';
*
* const store = createStore().setValues({open: true, employees: 3});
* const listenerId = store.addHasValueListener(
* 'employees',
* (store) => store.setValue('updated', true),
* true,
* );
*
* store.delValue('employees');
* console.log(store.getValues());
* // -> {open: true, updated: true}
*
* store.delListener(listenerId);
* ```
* @category Listener
* @since v4.4.0
*/
addHasValueListener(
valueId: IdOrNull,
listener: HasValueListener<this>,
mutator?: boolean,
): Id;
/**
* The addValueListener method registers a listener function with the Store
* that will be called whenever data in a Value changes.
*
* The provided listener is a ValueListener function, and will be called with
* a reference to the Store, the Id of the Value that changed, the new Value
* value, the old Value, and a GetValueChange function in case you need to
* inspect any changes that occurred.
*
* You can either listen to a single Value (by specifying the Value Id) or
* changes to any Value (by providing a `null` wildcard).
*
* Use the optional mutator parameter to indicate that there is code in the
* listener that will mutate Store data. If set to `false` (or omitted), such
* mutations will be silently ignored. All relevant mutator listeners (with
* this flag set to `true`) are called _before_ any non-mutator listeners
* (since the latter may become relevant due to changes made in the former).
* The changes made by mutator listeners do not fire other mutating listeners,
* though they will fire non-mutator listeners.
* @param valueId The Id of the Value to listen to, or `null` as a wildcard.
* @param listener The function that will be called whenever data in the
* matching Value changes.
* @param mutator An optional boolean that indicates that the listener mutates
* Store data.
* @returns A unique Id for the listener that can later be used to call it
* explicitly, or to remove it.
* @example
* This example registers a listener that responds to any changes to a
* specific Value.
*
* ```js
* import {createStore} from 'tinybase';
*
* const store = createStore().setValues({open: true, employees: 3});
* const listenerId = store.addValueListener(
* 'employees',
* (store, valueId, newValue, oldValue, getValueChange) => {
* console.log('employee value changed');
* console.log([oldValue, newValue]);
* console.log(getValueChange('employees'));
* },
* );
*
* store.setValue('employees', 4);
* // -> 'employee value changed'
* // -> [3, 4]
* // -> [true, 3, 4]
*
* store.delListener(listenerId);
* ```
* @example
* This example registers a listener that responds to any changes to any
* Value.
*
* ```js
* import {createStore} from 'tinybase';
*
* const store = createStore().setValues({open: true, employees: 3});
* const listenerId = store.addValueListener(null, (store, valueId) => {
* console.log(`${valueId} value changed`);
* });
*
* store.setValue('employees', 4);
* // -> 'employees value changed'
* store.setValue('open', false);
* // -> 'open value changed'
*
* store.delListener(listenerId);
* ```
* @example
* This example registers a listener that responds to any changes to a
* specific Value, and which also mutates the Store itself.
*
* ```js
* import {createStore} from 'tinybase';
*
* const store = createStore().setValues({open: true, employees: 3});
* const listenerId = store.addValueListener(
* 'employees',
* (store) => store.setValue('updated', true),
* true,
* );
*
* store.delValue('employees');
* console.log(store.getValues());
* // -> {open: true, updated: true}
*
* store.delListener(listenerId);
* ```
* @category Listener
* @since v3.0.0
*/
addValueListener(
valueId: IdOrNull,
listener: ValueListener<this>,
mutator?: boolean,
): Id;
/**
* The addInvalidCellListener method registers a listener function with the
* Store that will be called whenever invalid data was attempted to be written
* to a Cell.
*
* The provided listener is an InvalidCellListener function, and will be
* called with a reference to the Store, the Id of the Table, the Id of the
* Row, and the Id of Cell that was being attempted to be changed. It is also
* given the invalid value of the Cell, which could have been of absolutely
* any type. Since there could have been multiple failed attempts to set the
* Cell within a single transaction, this is an array containing each attempt,
* chronologically.
*
* You can either listen to a single Cell (by specifying the Table Id, Row Id,
* and Cell Id as the method's first three parameters) or invalid attempts to
* change any Cell (by providing `null` wildcards).
*
* All, some, or none of the `tableId`, `rowId`, and `cellId` parameters can
* be wildcarded with `null`. You can listen to a specific Cell in a specific
* Row in a specific Table, any Cell in any Row in any Table, for example - or
* every other combination of wildcards.
*
* Use the optional mutator parameter to indicate that there is code in the
* listener that will mutate Store data. If set to `false` (or omitted), such
* mutations will be silently ignored. All relevant mutator listeners (with
* this flag set to `true`) are called _before_ any non-mutator listeners
* (since the latter may become relevant due to changes made in the former).
* The changes made by mutator listeners do not fire other mutating listeners,
* though they will fire non-mutator listeners.
*
* Special note should be made for how the listener will be called when a
* TablesSchema is present. The listener will be called:
*
* - if a Table is being updated that is not specified in the TablesSchema,
* - if a Cell is of the wrong type specified in the TablesSchema,
* - if a Cell is omitted and is not defaulted in the TablesSchema,
* - or if an empty Row is provided and there are no Cell defaults in the
* TablesSchema.
*
* The listener will not be called if a Cell that is defaulted in the
* TablesSchema is not provided, as long as all of the Cells that are _not_
* defaulted _are_ provided.
*
* To help understand all of these schema-based conditions, please see the
* TablesSchema example below.
* @param tableId The Id of the Table to listen to, or `null` as a wildcard.
* @param rowId The Id of the Row to listen to, or `null` as a wildcard.
* @param cellId The Id of the Cell to listen to, or `null` as a wildcard.
* @param listener The function that will be called whenever an attempt to
* write invalid data to the matching Cell was made.
* @param mutator An optional boolean that indicates that the listener mutates
* Store data.
* @returns A unique Id for the listener that can later be used to call it
* explicitly, or to remove it.
* @example
* This example registers a listener that responds to any invalid changes to a
* specific Cell.
*
* ```js
* import {createStore} from 'tinybase';
*
* const store = createStore().setTables({
* pets: {fido: {species: 'dog', color: 'brown'}},
* });
* const listenerId = store.addInvalidCellListener(
* 'pets',
* 'fido',
* 'color',
* (store, tableId, rowId, cellId, invalidCells) => {
* console.log('Invalid color cell in fido row in pets table');
* console.log(invalidCells);
* },
* );
*
* store.setCell('pets', 'fido', 'color', {r: '96', g: '4B', b: '00'});
* // -> 'Invalid color cell in fido row in pets table'
* // -> [{r: '96', g: '4B', b: '00'}]
*
* store.delListener(listenerId);
* ```
* @example
* This example registers a listener that responds to any invalid changes to
* any Cell - in a Store _without_ a TablesSchema. Note also how it then
* responds to cases where empty or invalid Row objects, or Table objects,
* or Tables objects are provided.
*
* ```js
* import {createStore} from 'tinybase';
*
* const store = createStore().setTables({
* pets: {fido: {species: 'dog', color: 'brown'}},
* });
* const listenerId = store.addInvalidCellListener(
* null,
* null,
* null,
* (store, tableId, rowId, cellId) => {
* console.log(
* `Invalid ${cellId} cell in ${rowId} row in ${tableId} table`,
* );
* },
* );
*
* store.setCell('pets', 'fido', 'color', {r: '96', g: '4B', b: '00'});
* // -> 'Invalid color cell in fido row in pets table'
* store.setTable('sales', {fido: {date: new Date()}});
* // -> 'Invalid date cell in fido row in sales table'
*
* store.setRow('pets', 'felix', {});
* // -> 'Invalid undefined cell in felix row in pets table'
*
* store.setRow('filter', 'name', /[a-z]?/);
* // -> 'Invalid undefined cell in name row in filter table'
*
* store.setRow('sales', '2021', {forecast: undefined});
* // -> 'Invalid forecast cell in 2021 row in sales table'
*
* store.addRow('filter', /[0-9]?/);
* // -> 'Invalid undefined cell in undefined row in filter table'
*
* store.setTable('raw', {});
* // -> 'Invalid undefined cell in undefined row in raw table'
*
* store.setTable('raw', ['row1', 'row2']);
* // -> 'Invalid undefined cell in undefined row in raw table'
*
* store.setTables(['table1', 'table2']);
* // -> 'Invalid undefined cell in undefined row in undefined table'
*
* store.delListener(listenerId);
* ```
* @example
* This example registers a listener that responds to any invalid changes to
* any Cell - in a Store _with_ a TablesSchema. Note how it responds to cases
* where missing parameters are provided for optional, and defaulted Cell
* values in a Row.
*
* ```js
* import {createStore} from 'tinybase';
*
* const store = createStore().setTablesSchema({
* pets: {
* species: {type: 'string'},
* color: {type: 'string', default: 'unknown'},
* },
* });
*
* const listenerId = store.addInvalidCellListener(
* null,
* null,
* null,
* (store, tableId, rowId, cellId) => {
* console.log(
* `Invalid ${cellId} cell in ${rowId} row in ${tableId} table`,
* );
* },
* );
*
* store.setRow('sales', 'fido', {price: 5});
* // -> 'Invalid price cell in fido row in sales table'
* // The listener is called, because the sales Table is not in the schema
*
* store.setRow('pets', 'felix', {species: true});
* // -> 'Invalid species cell in felix row in pets table'
* // The listener is called, because species is invalid...
* console.log(store.getRow('pets', 'felix'));
* // -> {color: 'unknown'}
* // ...even though a Row was set with the default value
*
* store.setRow('pets', 'fido', {color: 'brown'});
* // -> 'Invalid species cell in fido row in pets table'
* // The listener is called, because species is missing and not defaulted...
* console.log(store.getRow('pets', 'fido'));
* // -> {color: 'brown'}
* // ...even though a Row was set
*
* store.setRow('pets', 'rex', {species: 'dog'});
* console.log(store.getRow('pets', 'rex'));
* // -> {species: 'dog', color: 'unknown'}
* // The listener is not called, because color is defaulted
*
* store.delTables().setTablesSchema({
* pets: {
* species: {type: 'string'},
* color: {type: 'string'},
* },
* });
*
* store.setRow('pets', 'cujo', {});
* // -> 'Invalid species cell in cujo row in pets table'
* // -> 'Invalid color cell in cujo row in pets table'
* // -> 'Invalid undefined cell in cujo row in pets table'
* // The listener is called multiple times, because neither Cell is defaulted
* // and the Row as a whole is empty
*
* store.delListener(listenerId);
* ```
* @example
* This example registers a listener that responds to any changes to a
* specific Cell, and which also mutates the Store itself.
*
* ```js
* import {createStore} from 'tinybase';
*
* const store = createStore().setTables({
* pets: {fido: {species: 'dog', color: 'brown'}},
* });
* const listenerId = store.addInvalidCellListener(
* 'pets',
* 'fido',
* 'color',
* (store, tableId, rowId, cellId, invalidCells) =>
* store.setCell(
* 'meta',
* 'invalid_updates',
* `${tableId}_${rowId}_${cellId}`,
* JSON.stringify(invalidCells[0]),
* ),
* true,
* );
*
* store.setCell('pets', 'fido', 'color', {r: '96', g: '4B', b: '00'});
* console.log(store.getRow('meta', 'invalid_updates'));
* // -> {'pets_fido_color': '{"r":"96","g":"4B","b":"00"}'}
*
* store.delListener(listenerId);
* ```
* @category Listener
* @since v1.1.0
*/
addInvalidCellListener(
tableId: IdOrNull,
rowId: IdOrNull,
cellId: IdOrNull,
listener: InvalidCellListener<this>,
mutator?: boolean,
): Id;
/**
* The addInvalidValueListener method registers a listener function with the
* Store that will be called whenever invalid data was attempted to be written
* to a Value.
*
* The provided listener is an InvalidValueListener function, and will be
* called with a reference to the Store and the Id of Value that was being
* attempted to be changed. It is also given the invalid value of the Value,
* which could have been of absolutely any type. Since there could have been
* multiple failed attempts to set the Value within a single transaction, this
* is an array containing each attempt, chronologically.
*
* You can either listen to a single Value (by specifying the Value Id as the
* method's first parameter) or invalid attempts to change any Value (by
* providing a `null` wildcard).
*
* Use the optional mutator parameter to indicate that there is code in the
* listener that will mutate Store data. If set to `false` (or omitted), such
* mutations will be silently ignored. All relevant mutator listeners (with
* this flag set to `true`) are called _before_ any non-mutator listeners
* (since the latter may become relevant due to changes made in the former).
* The changes made by mutator listeners do not fire other mutating listeners,
* though they will fire non-mutator listeners.
*
* Special note should be made for how the listener will be called when a
* ValuesSchema is present. The listener will be called:
*
* - if a Value is being updated that is not specified in the ValuesSchema,
* - if a Value is of the wrong type specified in the ValuesSchema,
* - or if a Value is omitted when using setValues that is not defaulted in
* the ValuesSchema.
*
* The listener will not be called if a Value that is defaulted in the
* ValuesSchema is not provided, as long as all of the Values that are _not_
* defaulted _are_ provided.
*
* To help understand all of these schema-based conditions, please see the
* ValuesSchema example below.
* @param valueId The Id of the Value to listen to, or `null` as a wildcard.
* @param listener The function that will be called whenever an attempt to
* write invalid data to the matching Value was made.
* @param mutator An optional boolean that indicates that the listener mutates
* Store data.
* @returns A unique Id for the listener that can later be used to call it
* explicitly, or to remove it.
* @example
* This example registers a listener that responds to any invalid changes to a
* specific Value.
*
* ```js
* import {createStore} from 'tinybase';
*
* const store = createStore().setValues({open: true});
* const listenerId = store.addInvalidValueListener(
* 'open',
* (store, valueId, invalidValues) => {
* console.log('Invalid open value');
* console.log(invalidValues);
* },
* );
*
* store.setValue('open', {yes: true});
* // -> 'Invalid open value'
* // -> [{yes: true}]
*
* store.delListener(listenerId);
* ```
* @example
* This example registers a listener that responds to any invalid changes to
* any Value - in a Store _without_ a ValuesSchema. Note also how it then
* responds to cases where an empty Values object is provided.
*
* ```js
* import {createStore} from 'tinybase';
*
* const store = createStore().setValues({open: true});
* const listenerId = store.addInvalidValueListener(
* null,
* (store, valueId) => {
* console.log(`Invalid ${valueId} value`);
* },
* );
*
* store.setValue('open', {yes: true});
* // -> 'Invalid open value'
* store.setValue('employees', ['alice', 'bob']);
* // -> 'Invalid employees value'
*
* store.setValues('pets', 'felix', {});
* // -> 'Invalid undefined value'
*
* store.delListener(listenerId);
* ```
* @example
* This example registers a listener that responds to any invalid changes to
* any Value - in a Store _with_ a ValuesSchema. Note how it responds to cases
* where missing parameters are provided for optional, and defaulted Values.
*
* ```js
* import {createStore} from 'tinybase';
*
* const store = createStore().setValuesSchema({
* open: {type: 'boolean', default: false},
* employees: {type: 'number'},
* });
*
* console.log(store.getValues());
* // -> {open: false}
*
* const listenerId = store.addInvalidValueListener(
* null,
* (store, valueId) => {
* console.log(`Invalid ${valueId} value`);
* },
* );
*
* store.setValue('website', true);
* // -> 'Invalid website value'
* // The listener is called, because the website Value is not in the schema
*
* store.setValue('open', 'yes');
* // -> 'Invalid open value'
* // The listener is called, because 'open' is invalid...
* console.log(store.getValues());
* // -> {open: false}
* // ...even though it is still present with the default value
*
* store.setValues({open: true});
* // -> 'Invalid employees value'
* // The listener is called because employees is missing and not defaulted...
* console.log(store.getValues());
* // -> {open: true}
* // ...even though the Values were set
*
* store.setValues({employees: 3});
* console.log(store.getValues());
* // -> {open: false, employees: 3}
* // The listener is not called, because 'open' is defaulted
*
* store.setValuesSchema({
* open: {type: 'boolean'},
* employees: {type: 'number'},
* });
*
* store.setValues({});
* // -> 'Invalid open value'
* // -> 'Invalid employees value'
* // -> 'Invalid undefined value'
* // The listener is called multiple times, because neither Value is
* // defaulted and the Values as a whole were empty
*
* store.delListener(listenerId);
* ```
* @example
* This example registers a listener that responds to any changes to a
* specific Value, and which also mutates the Store itself.
*
* ```js
* import {createStore} from 'tinybase';
*
* const store = createStore().setValues({open: true});
* const listenerId = store.addInvalidValueListener(
* 'open',
* (store, valueId, invalidValues) =>
* store.setValue('invalid_updates', JSON.stringify(invalidValues[0])),
* true,
* );
*
* store.setValue('open', {yes: true});
* console.log(store.getValue('invalid_updates'));
* // -> '{"yes":true}'
*
* store.delListener(listenerId);
* ```
* @category Listener
* @since v3.0.0
*/
addInvalidValueListener(
valueId: IdOrNull,
listener: InvalidValueListener<this>,
mutator?: boolean,
): Id;
/**
* The addStartTransactionListener method registers a listener function with
* the Store that will be called at the start of a transaction.
*
* The provided TransactionListener will receive a reference to the Store and
* two booleans to indicate whether Cell or Value data has been touched during
* the transaction. Since this is called at the start, they will both be
* `false`!
*
* Note that a TransactionListener added to the Store with this method can
* mutate the Store, and its changes will be treated as part of the
* transaction that is starting.
* @param listener The function that will be called at the start of a
* transaction.
* @returns A unique Id for the listener that can later be used to remove it.
* @example
* This example registers a listener that is called at start end of the
* transaction, just before its listeners will be called.
*
* ```js
* import {createStore} from 'tinybase';
*
* const store = createStore()
* .setTables({
* pets: {fido: {species: 'dog', color: 'brown'}},
* })
* .setValues({open: true, employees: 3});
* const listenerId = store.addStartTransactionListener(() => {
* console.log('Transaction started');
* });
*
* store.transaction(() =>
* store.setCell('pets', 'fido', 'color', 'brown').setValue('employees', 3),
* );
* // -> 'Transaction started'
*
* store.callListener(listenerId);
* // -> 'Transaction started'
*
* store.delListener(listenerId);
* ```
* @category Listener
* @since v3.2.0
*/
addStartTransactionListener(listener: TransactionListener<this>): Id;
/**
* The addWillFinishTransactionListener method registers a listener function
* with the Store that will be called just before other non-mutating listeners
* are called at the end of the transaction.
*
* This is useful if you need to know that a set of listeners are about to be
* called at the end of a transaction, perhaps to batch _their_ consequences
* together.
*
* The provided TransactionListener will receive a reference to the Store and
* two booleans to indicate whether Cell or Value data has been touched during
* the transaction. The two flags are intended as a hint about whether
* non-mutating listeners might be being called at the end of the transaction.
*
* Here, 'touched' means that Cell or Value data has either been changed, or
* changed and then changed back to its original value during the transaction.
* The exception is a transaction that has been rolled back, for which the
* value of `cellsTouched` and `valuesTouched` in the listener will be `false`
* because all changes have been reverted.
*
* Note that a TransactionListener added to the Store with this method can
* mutate the Store itself, and its changes will be treated as part of the
* transaction that is starting (and may fire non-mutating listeners after
* this).
* @param listener The function that will be called before the end of a
* transaction.
* @returns A unique Id for the listener that can later be used to remove it.
* @example
* This example registers a listener that is called at the end of the
* transaction, just before its listeners will be called. The transactions
* shown here variously change, touch, and rollback cells, demonstrating how
* the `cellsTouched` and `valuesTouched` parameters in the listener work.
*
* ```js
* import {createStore} from 'tinybase';
*
* const store = createStore()
* .setTables({
* pets: {fido: {species: 'dog', color: 'brown'}},
* })
* .setValues({open: true, employees: 3});
* const listenerId = store.addWillFinishTransactionListener((store) => {
* const [cellsTouched, valuesTouched] = store.getTransactionLog() ?? {};
* console.log(`Cells/Values touched: ${cellsTouched}/${valuesTouched}`);
* });
* const listenerId2 = store.addTablesListener(() =>
* console.log('Tables changed'),
* );
* const listenerId3 = store.addValuesListener(() =>
* console.log('Values changed'),
* );
*
* store.transaction(() =>
* store.setCell('pets', 'fido', 'color', 'brown').setValue('employees', 3),
* );
* // -> 'Cells/Values touched: false/false'
*
* store.transaction(() => store.setCell('pets', 'fido', 'color', 'walnut'));
* // -> 'Cells/Values touched: true/false'
* // -> 'Tables changed'
*
* store.transaction(() => store.setValue('employees', 4));
* // -> 'Cells/Values touched: false/true'
* // -> 'Values changed'
*
* store.transaction(() => {
* store
* .setRow('pets', 'felix', {species: 'cat'})
* .delRow('pets', 'felix')
* .setValue('city', 'London')
* .delValue('city');
* });
* // -> 'Cells/Values touched: true/true'
* // But no Tables or Values listeners fired since there are no net changes.
*
* store.transaction(
* () =>
* store
* .setRow('pets', 'felix', {species: 'cat'})
* .setValue('city', 'London'),
* () => true,
* );
* // -> 'Cells/Values touched: false/false'
* // Transaction was rolled back.
*
* store.callListener(listenerId);
* // -> 'Cells/Values touched: false/false'
* // It is meaningless to call this listener directly.
*
* store
* .delListener(listenerId)
* .delListener(listenerId2)
* .delListener(listenerId3);
* ```
* @category Listener
* @since v1.3.0
*/
addWillFinishTransactionListener(listener: TransactionListener<this>): Id;
/**
* The addDidFinishTransactionListener method registers a listener function
* with the Store that will be called just after other non-mutating listeners
* are called at the end of the transaction.
*
* This is useful if you need to know that a set of listeners have just been
* called at the end of a transaction, perhaps to batch _their_ consequences
* together.
*
* The provided TransactionListener will receive a reference to the Store and
* two booleans to indicate whether Cell or Value data has been touched during
* the transaction. The two flags is intended as a hint about whether
* non-mutating listeners might have been called at the end of the
* transaction.
*
* Here, 'touched' means that Cell or Value data has either been changed, or
* changed and then changed back to its original value during the transaction.
* The exception is a transaction that has been rolled back, for which the
* value of `cellsTouched` and `valuesTouched` in the listener will be `false`
* because all changes have been reverted.
*
* Note that a TransactionListener added to the Store with this method
* _cannot_ mutate the Store itself, and attempts to do so will fail silently.
* @param listener The function that will be called after the end of a
* transaction.
* @returns A unique Id for the listener that can later be used to remove it.
* @example
* This example registers a listener that is called at the end of the
* transaction, just after its listeners have been called. The transactions
* shown here variously change, touch, and rollback cells, demonstrating how
* the `cellsTouched` and `valuesTouched` parameters in the listener work.
*
* ```js
* import {createStore} from 'tinybase';
*
* const store = createStore()
* .setTables({
* pets: {fido: {species: 'dog', color: 'brown'}},
* })
* .setValues({open: true, employees: 3});
* const listenerId = store.addDidFinishTransactionListener((store) => {
* const [cellsTouched, valuesTouched] = store.getTransactionLog() ?? {};
* console.log(`Cells/Values touched: ${cellsTouched}/${valuesTouched}`);
* });
* const listenerId2 = store.addTablesListener(() =>
* console.log('Tables changed'),
* );
* const listenerId3 = store.addValuesListener(() =>
* console.log('Values changed'),
* );
*
* store.transaction(() =>
* store.setCell('pets', 'fido', 'color', 'brown').setValue('employees', 3),
* );
* // -> 'Cells/Values touched: false/false'
*
* store.transaction(() => store.setCell('pets', 'fido', 'color', 'walnut'));
* // -> 'Tables changed'
* // -> 'Cells/Values touched: true/false'
*
* store.transaction(() => store.setValue('employees', 4));
* // -> 'Values changed'
* // -> 'Cells/Values touched: false/true'
*
* store.transaction(() => {
* store
* .setRow('pets', 'felix', {species: 'cat'})
* .delRow('pets', 'felix')
* .setValue('city', 'London')
* .delValue('city');
* });
* // -> 'Cells/Values touched: true/true'
* // But no Tables or Values listeners fired since there are no net changes.
*
* store.transaction(
* () =>
* store
* .setRow('pets', 'felix', {species: 'cat'})
* .setValue('city', 'London'),
* () => true,
* );
* // -> 'Cells/Values touched: false/false'
* // Transaction was rolled back.
*
* store.callListener(listenerId);
* // -> 'Cells/Values touched: false/false'
* // It is meaningless to call this listener directly.
*
* store
* .delListener(listenerId)
* .delListener(listenerId2)
* .delListener(listenerId3);
* ```
* @category Listener
* @since v1.3.0
*/
addDidFinishTransactionListener(listener: TransactionListener<this>): Id;
/**
* The callListener method provides a way for you to manually provoke a
* listener to be called, even if the underlying data hasn't changed.
*
* This is useful when you are using mutator listeners to guarantee that data
* conforms to programmatic conditions, and those conditions change such that
* you need to update the Store in bulk.
* @param listenerId The Id of the listener to call.
* @returns A reference to the Store.
* @example
* This example registers a listener that ensures a Cell has one of list of a
* valid values. After that list changes, the listener is called to apply the
* condition to the existing data.
*
* ```js
* import {createStore} from 'tinybase';
*
* const validColors = ['walnut', 'brown', 'black'];
* const store = createStore();
* const listenerId = store.addCellListener(
* 'pets',
* null,
* 'color',
* (store, tableId, rowId, cellId, color) => {
* if (!validColors.includes(color)) {
* store.setCell(tableId, rowId, cellId, validColors[0]);
* }
* },
* true,
* );
*
* store.setRow('pets', 'fido', {species: 'dog', color: 'honey'});
* console.log(store.getRow('pets', 'fido'));
* // -> {species: 'dog', color: 'walnut'}
*
* validColors.shift();
* console.log(validColors);
* // -> ['brown', 'black']
*
* store.callListener(listenerId);
* console.log(store.getRow('pets', 'fido'));
* // -> {species: 'dog', color: 'brown'}
*
* store.delListener(listenerId);
* ```
* @example
* This example registers a listener to Row Id changes. It is explicitly
* called and fires for two Tables in the Store.
*
* ```js
* import {createStore} from 'tinybase';
*
* const store = createStore().setTables({
* pets: {fido: {species: 'dog'}},
* species: {dog: {price: 5}},
* });
*
* const listenerId = store.addRowIdsListener(null, (store, tableId) => {
* console.log(`Row Ids listener called for ${tableId} table`);
* });
*
* store.callListener(listenerId);
* // -> 'Row Ids listener called for pets table'
* // -> 'Row Ids listener called for species table'
*
* store.delListener(listenerId);
* ```
* @example
* This example registers a listener Value changes. It is explicitly called
* and fires for two Values in the Store.
*
* ```js
* import {createStore} from 'tinybase';
*
* const store = createStore().setValues({open: true, employees: 3});
*
* const listenerId = store.addValueListener(
* null,
* (store, valueId, value) => {
* console.log(`Value listener called for ${valueId} value, ${value}`);
* },
* );
*
* store.callListener(listenerId);
* // -> 'Value listener called for open value, true'
* // -> 'Value listener called for employees value, 3'
*
* store.delListener(listenerId);
* ```
* @example
* This example registers listeners for the end of transactions, and for
* invalid Cells. They are explicitly called, meaninglessly. The former
* receives empty arguments. The latter is not called at all.
*
* ```js
* import {createStore} from 'tinybase';
*
* const store = createStore();
*
* const listenerId = store.addWillFinishTransactionListener(
* (store, cellsTouched, valuesTouched) => {
* console.log(`Transaction finish: ${cellsTouched}/${valuesTouched}`);
* },
* );
* store.callListener(listenerId);
* // -> 'Transaction finish: undefined/undefined'
* store.delListener(listenerId);
*
* const listenerId2 = store.addInvalidCellListener(
* null,
* null,
* null,
* (store, tableId, rowId, cellId) => {
* console.log('Invalid cell', tableId, rowId, cellId);
* },
* );
* store.callListener(listenerId2);
* // -> undefined
* store.delListener(listenerId2);
* ```
* @category Listener
* @since v1.0.0
*/
callListener(listenerId: Id): this;
/**
* The delListener method removes a listener that was previously added to the
* Store.
*
* Use the Id returned by whichever method was used to add the listener. Note
* that the Store may re-use this Id for future listeners added to it.
* @param listenerId The Id of the listener to remove.
* @returns A reference to the Store.
* @example
* This example registers a listener and then removes it.
*
* ```js
* import {createStore} from 'tinybase';
*
* const store = createStore().setTables({
* pets: {fido: {species: 'dog', color: 'brown'}},
* });
* const listenerId = store.addTablesListener(() => {
* console.log('Tables changed');
* });
*
* store.setCell('pets', 'fido', 'color', 'walnut');
* // -> 'Tables changed'
*
* store.delListener(listenerId);
*
* store.setCell('pets', 'fido', 'color', 'honey');
* // -> undefined
* // The listener is not called.
* ```
* @category Listener
* @since v1.0.0
*/
delListener(listenerId: Id): this;
/**
* The getListenerStats method provides a set of statistics about the
* listeners registered with the Store, and is used for debugging purposes.
*
* The StoreListenerStats object contains a breakdown of the different types
* of listener. Totals include both mutator and non-mutator listeners.
*
* The method is intended to be used during development to ensure your
* application is not leaking listener registrations, for example.
* @returns A StoreListenerStats object containing Store listener statistics.
* @example
* This example gets the listener statistics of a small and simple Store.
*
* ```js
* import {createStore} from 'tinybase';
*
* const store = createStore();
* store.addTablesListener(() => console.log('Tables changed'));
* store.addRowIdsListener(() => console.log('Row Ids changed'));
*
* const listenerStats = store.getListenerStats();
* console.log(listenerStats.rowIds);
* // -> 1
* console.log(listenerStats.tables);
* // -> 1
* ```
* @category Development
* @since v1.0.0
*/
getListenerStats(): StoreListenerStats;
/**
* The isMergeable method lets you know if the Store is mergeable.
*
* This will always return false for a Store, and true for a MergeableStore.
* @returns Whether the Store is mergeable.
* @category Getter
* @since v5.0.0
*/
isMergeable(): boolean;
//
}
/**
* The createStore function creates a Store, and is the main entry point into
* the store module.
*
* Since (or perhaps _because_) it is the most important function in the whole
* module, it is trivially simple.
* @returns A reference to the new Store.
* @example
* This example creates a Store.
*
* ```js
* import {createStore} from 'tinybase';
*
* const store = createStore();
* console.log(store.getTables());
* // -> {}
* ```
* @example
* This example creates a Store with some initial data:
*
* ```js
* import {createStore} from 'tinybase';
*
* const store = createStore().setTables({pets: {fido: {species: 'dog'}}});
* console.log(store.getTables());
* // -> {pets: {fido: {species: 'dog'}}}
* ```
* @example
* This example creates a Store with some initial data and a TablesSchema:
*
* ```js
* import {createStore} from 'tinybase';
*
* const store = createStore()
* .setTables({pets: {fido: {species: 'dog'}}})
* .setTablesSchema({
* pets: {
* species: {type: 'string'},
* sold: {type: 'boolean', default: false},
* },
* });
* console.log(store.getTables());
* // -> {pets: {fido: {species: 'dog', sold: false}}}
* ```
* @see The Basics guides
* @category Creation
* @since v1.0.0
*/
export function createStore(): Store;