Socket
Socket
Sign inDemoInstall

@agile-ts/core

Package Overview
Dependencies
2
Maintainers
1
Versions
37
Alerts
File Explorer

Advanced tools

Install Socket

Detect and block malicious and high-risk dependencies

Install

Comparing version 0.2.0-alpha.3 to 0.2.0-alpha.4

dist/collection/collection.d.ts

780

dist/collection/index.d.ts

@@ -1,758 +0,22 @@

import { Agile, Item, Group, GroupKey, Selector, SelectorKey, StorageKey, GroupConfigInterface, CollectionPersistent, GroupAddConfigInterface, SideEffectConfigInterface, SelectorConfigInterface, PatchOptionConfigInterface } from '../internal';
export declare class Collection<DataType extends Object = DefaultItem, GroupValueType = Array<ItemKey>> {
agileInstance: () => Agile;
config: CollectionConfigInterface;
private initialConfig;
_key?: CollectionKey;
size: number;
data: {
[key: string]: Item<DataType>;
};
isPersisted: boolean;
persistent: CollectionPersistent<DataType> | undefined;
groups: {
[key: string]: Group<DataType>;
};
selectors: {
[key: string]: Selector<DataType>;
};
isInstantiated: boolean;
isCollection: boolean;
/**
* A Collection manages a reactive set of Information
* that we need to remember globally at a later point in time.
* While providing a toolkit to use and mutate this set of Information.
*
* It is designed for arrays of data objects following the same pattern.
*
* Each of these data object must have a unique `primaryKey` to be correctly identified later.
*
* You can create as many global Collections as you need.
*
* [Learn more..](https://agile-ts.org/docs/core/collection/)
*
* @public
* @param agileInstance - Instance of Agile the Collection belongs to.
* @param config - Configuration object
*/
constructor(agileInstance: Agile, config?: CollectionConfig<DataType>);
/**
* Updates the key/name identifier of the Collection.
*
* [Learn more..](https://agile-ts.org/docs/core/collection/properties#key)
*
* @public
* @param value - New key/name identifier.
*/
set key(value: CollectionKey | undefined);
/**
* Returns the key/name identifier of the Collection.
*
* [Learn more..](https://agile-ts.org/docs/core/collection/properties#key)
*
* @public
*/
get key(): CollectionKey | undefined;
/**
* Updates the key/name identifier of the Collection.
*
* [Learn more..](https://agile-ts.org/docs/core/collection/methods/#setkey)
*
* @public
* @param value - New key/name identifier.
*/
setKey(value: CollectionKey | undefined): this;
/**
* Creates a new Group without associating it to the Collection.
*
* This way of creating a Group is intended for use in the Collection configuration object,
* where the `constructor()` takes care of the binding.
*
* After a successful initiation of the Collection we recommend using `createGroup()`,
* because it automatically connects the Group to the Collection.
*
* [Learn more..](https://agile-ts.org/docs/core/collection/methods/#group)
*
* @public
* @param initialItems - Key/Name identifiers of the Items to be clustered by the Group.
* @param config - Configuration object
*/
Group(initialItems?: Array<ItemKey>, config?: GroupConfigInterface): Group<DataType>;
/**
* Creates a new Selector without associating it to the Collection.
*
* This way of creating a Selector is intended for use in the Collection configuration object,
* where the `constructor()` takes care of the binding.
*
* After a successful initiation of the Collection we recommend using `createSelector()`,
* because it automatically connects the Group to the Collection.
*
* [Learn more..](https://agile-ts.org/docs/core/collection/methods/#selector)
*
* @public
* @param initialKey - Key/Name identifier of the Item to be represented by the Selector.
* @param config - Configuration object
*/
Selector(initialKey: ItemKey | null, config?: SelectorConfigInterface): Selector<DataType>;
/**
* Sets up the specified Groups or Group keys
* and assigns them to the Collection if they are valid.
*
* It also instantiates and assigns the default Group to the Collection.
* The default Group reflects the default pattern of the Collection.
*
* @internal
* @param groups - Entire Groups or Group keys to be set up.
*/
initGroups(groups: {
[key: string]: Group<any>;
} | string[]): void;
/**
* Sets up the specified Selectors or Selector keys
* and assigns them to the Collection if they are valid.
*
* @internal
* @param selectors - Entire Selectors or Selector keys to be set up.
*/
initSelectors(selectors: {
[key: string]: Selector<any>;
} | string[]): void;
/**
* Appends new data objects following the same pattern to the end of the Collection.
*
* Each collected `data object` requires a unique identifier at the primaryKey property (by default 'id')
* to be correctly identified later.
*
* For example, if we collect some kind of user object,
* it must contain such unique identifier at 'id'
* to be added to the Collection.
* ```
* MY_COLLECTION.collect({id: '1', name: 'jeff'}); // valid
* MY_COLLECTION.collect({name: 'frank'}); // invalid
* ```
*
* [Learn more..](https://agile-ts.org/docs/core/collection/methods/#collect)
*
* @public
* @param data - Data objects or entire Items to be added.
* @param groupKeys - Group/s to which the specified data objects or Items are to be added.
* @param config - Configuration object
*/
collect(data: DataType | Item<DataType> | Array<DataType | Item<DataType>>, groupKeys?: GroupKey | Array<GroupKey>, config?: CollectConfigInterface<DataType>): this;
/**
* Updates the Item `data object` with the specified `object with changes`, if the Item exists.
* By default the `object with changes` is merged into the Item `data object` at top level.
*
* [Learn more..](https://agile-ts.org/docs/core/collection/methods/#update)
*
* @public
* @param itemKey - Key/Name identifier of the Item to be updated.
* @param changes - Object with changes to be merged into the Item data object.
* @param config - Configuration object
*/
update(itemKey: ItemKey, changes: DefaultItem | DataType, config?: UpdateConfigInterface): Item<DataType> | undefined;
/**
* Creates a new Group and associates it to the Collection.
*
* [Learn more..](https://agile-ts.org/docs/core/collection/methods/#createGroup)
*
* @public
* @param groupKey - Unique identifier of the Group to be created.
* @param initialItems - Key/Name identifiers of the Items to be clustered by the Group.
*/
createGroup(groupKey: GroupKey, initialItems?: Array<ItemKey>): Group<DataType>;
/**
* Returns a boolean indicating whether a Group with the specified `groupKey`
* exists in the Collection or not.
*
* [Learn more..](https://agile-ts.org/docs/core/collection/methods/#hasgroup)
*
* @public
* @param groupKey - Key/Name identifier of the Group to be checked for existence.
* @param config - Configuration object
*/
hasGroup(groupKey: GroupKey | undefined, config?: HasConfigInterface): boolean;
/**
* Retrieves a single Group with the specified key/name identifier from the Collection.
*
* If the to retrieve Group doesn't exist, `undefined` is returned.
*
* [Learn more..](https://agile-ts.org/docs/core/collection/methods/#getgroup)
*
* @public
* @param groupKey - Key/Name identifier of the Group.
* @param config - Configuration object
*/
getGroup(groupKey: GroupKey | undefined | null, config?: HasConfigInterface): Group<DataType> | undefined;
/**
* Retrieves the default Group from the Collection.
*
* Every Collection should have a default Group,
* which represents the default pattern of the Collection.
*
* If the default Group, for what ever reason, doesn't exist, `undefined` is returned.
*
* [Learn more..](https://agile-ts.org/docs/core/collection/methods/#getdefaultgroup)
*
* @public
*/
getDefaultGroup(): Group<DataType> | undefined;
/**
* Retrieves a single Group with the specified key/name identifier from the Collection.
*
* If the to retrieve Group doesn't exist, a reference Group is returned.
* This has the advantage that Components that have the reference Group bound to themselves
* are rerenderd when the original Group is created.
*
* [Learn more..](https://agile-ts.org/docs/core/collection/methods/#getgroupwithreference)
*
* @public
* @param groupKey - Key/Name identifier of the Group.
*/
getGroupWithReference(groupKey: GroupKey): Group<DataType>;
/**
* Removes a Group with the specified key/name identifier from the Collection,
* if it exists in the Collection.
*
* [Learn more..](https://agile-ts.org/docs/core/collection/methods/#removegroup)
*
* @public
* @param groupKey - Key/Name identifier of the Group to be removed.
*/
removeGroup(groupKey: GroupKey): this;
/**
* Returns the count of registered Groups in the Collection.
*
* [Learn more..](https://agile-ts.org/docs/core/collection/methods/#getgroupcount)
*
* @public
*/
getGroupCount(): number;
/**
* Creates a new Selector and associates it to the Collection.
*
* [Learn more..](https://agile-ts.org/docs/core/collection/methods/#createSelector)
*
* @public
* @param selectorKey - Unique identifier of the Selector to be created.
* @param itemKey - Key/Name identifier of the Item to be represented by the Selector.
*/
createSelector(selectorKey: SelectorKey, itemKey: ItemKey | null): Selector<DataType>;
/**
* Creates a new Selector and associates it to the Collection.
*
* The specified `itemKey` is used as the unique identifier key of the new Selector.
* ```
* MY_COLLECTION.select('1');
* // is equivalent to
* MY_COLLECTION.createSelector('1', '1');
* ```
*
* [Learn more..](https://agile-ts.org/docs/core/collection/methods/#select)
*
* @public
* @param itemKey - Key/Name identifier of the Item to be represented by the Selector
* and used as unique identifier of the Selector.
*/
select(itemKey: ItemKey): Selector<DataType>;
/**
* Returns a boolean indicating whether a Selector with the specified `selectorKey`
* exists in the Collection or not.
*
* [Learn more..](https://agile-ts.org/docs/core/collection/methods/#hasselector)
*
* @public
* @param selectorKey - Key/Name identifier of the Selector to be checked for existence.
* @param config - Configuration object
*/
hasSelector(selectorKey: SelectorKey | undefined, config?: HasConfigInterface): boolean;
/**
* Retrieves a single Selector with the specified key/name identifier from the Collection.
*
* If the to retrieve Selector doesn't exist, `undefined` is returned.
*
* [Learn more..](https://agile-ts.org/docs/core/collection/methods/#getselector)
*
* @public
* @param selectorKey - Key/Name identifier of the Selector.
* @param config - Configuration object
*/
getSelector(selectorKey: SelectorKey | undefined | null, config?: HasConfigInterface): Selector<DataType> | undefined;
/**
* Retrieves a single Selector with the specified key/name identifier from the Collection.
*
* If the to retrieve Selector doesn't exist, a reference Selector is returned.
* This has the advantage that Components that have the reference Selector bound to themselves
* are rerenderd when the original Selector is created.
*
* [Learn more..](https://agile-ts.org/docs/core/collection/methods/#getselectorwithreference)
*
* @public
* @param selectorKey - Key/Name identifier of the Selector.
*/
getSelectorWithReference(selectorKey: SelectorKey): Selector<DataType>;
/**
* Removes a Selector with the specified key/name identifier from the Collection,
* if it exists in the Collection.
*
* [Learn more..](https://agile-ts.org/docs/core/collection/methods/#removeselector)
*
* @public
* @param selectorKey - Key/Name identifier of the Selector to be removed.
*/
removeSelector(selectorKey: SelectorKey): this;
/**
* Returns the count of registered Selectors in the Collection.
*
* [Learn more..](https://agile-ts.org/docs/core/collection/methods/#getselectorcount)
*
* @public
*/
getSelectorCount(): number;
/**
* Returns a boolean indicating whether a Item with the specified `itemKey`
* exists in the Collection or not.
*
* [Learn more..](https://agile-ts.org/docs/core/collection/methods/#hasitem)
*
* @public
* @param itemKey - Key/Name identifier of the Item.
* @param config - Configuration object
*/
hasItem(itemKey: ItemKey | undefined, config?: HasConfigInterface): boolean;
/**
* Retrieves a single Item with the specified key/name identifier from the Collection.
*
* If the to retrieve Item doesn't exist, `undefined` is returned.
*
* [Learn more..](https://agile-ts.org/docs/core/collection/methods/#getitem)
*
* @public
* @param itemKey - Key/Name identifier of the Item.
* @param config - Configuration object
*/
getItem(itemKey: ItemKey | undefined | null, config?: HasConfigInterface): Item<DataType> | undefined;
/**
* Retrieves a single Item with the specified key/name identifier from the Collection.
*
* If the to retrieve Item doesn't exist, a reference Item is returned.
* This has the advantage that Components that have the reference Item bound to themselves
* are rerenderd when the original Item is created.
*
* [Learn more..](https://agile-ts.org/docs/core/collection/methods/#getitemwithreference)
*
* @public
* @param itemKey - Key/Name identifier of the Item.
*/
getItemWithReference(itemKey: ItemKey): Item<DataType>;
/**
* Creates a placeholder Item
* that can be used to hold a reference to a not existing Item.
*
* @internal
* @param itemKey - Unique identifier of the to create placeholder Item.
* @param addToCollection - Whether to add the Item to be created to the Collection.
*/
createPlaceholderItem(itemKey: ItemKey, addToCollection?: boolean): Item<DataType>;
/**
* Retrieves the value (data object) of a single Item
* with the specified key/name identifier from the Collection.
*
* If the to retrieve Item containing the value doesn't exist, `undefined` is returned.
*
* [Learn more..](https://agile-ts.org/docs/core/collection/methods/#getitemvalue)
*
* @public
* @param itemKey - Key/Name identifier of the Item.
* @param config - Configuration object
*/
getItemValue(itemKey: ItemKey | undefined, config?: HasConfigInterface): DataType | undefined;
/**
* Retrieves all Items from the Collection.
* ```
* MY_COLLECTION.getAllItems();
* // is equivalent to
* MY_COLLECTION.getDefaultGroup().items;
* ```
*
* [Learn more..](https://agile-ts.org/docs/core/collection/methods/#getallitems)
*
* @public
* @param config - Configuration object
*/
getAllItems(config?: HasConfigInterface): Array<Item<DataType>>;
/**
* Retrieves the values (data objects) of all Items from the Collection.
* ```
* MY_COLLECTION.getAllItemValues();
* // is equivalent to
* MY_COLLECTION.getDefaultGroup().output;
* ```
*
* [Learn more..](https://agile-ts.org/docs/core/collection/methods/#getallitemvalues)
*
* @public
* @param config - Configuration object
*/
getAllItemValues(config?: HasConfigInterface): Array<DataType>;
/**
* Preserves the Collection `value` in the corresponding external Storage.
*
* The Collection key/name is used as the unique identifier for the Persistent.
* If that is not desired or the Collection has no unique identifier,
* please specify a separate unique identifier for the Persistent.
*
* [Learn more..](https://agile-ts.org/docs/core/collection/methods/#persist)
*
* @public
* @param config - Configuration object
*/
persist(config?: CollectionPersistentConfigInterface): this;
/**
* Preserves the Collection `value` in the corresponding external Storage.
*
* The specified key is used as the unique identifier for the Persistent.
*
* [Learn more..](https://agile-ts.org/docs/core/collection/methods/#persist)
*
* @public
* @param key - Key/Name identifier of Persistent.
* @param config - Configuration object
*/
persist(key?: StorageKey, config?: CollectionPersistentConfigInterface): this;
/**
* Fires immediately after the persisted `value`
* is loaded into the Collection from a corresponding external Storage.
*
* Registering such callback function makes only sense
* when the Collection is [persisted](https://agile-ts.org/docs/core/collection/methods/#persist) in an external Storage.
*
* [Learn more..](https://agile-ts.org/docs/core/collection/methods/#onload)
*
* @public
* @param callback - A function to be executed after the externally persisted `value` was loaded into the Collection.
*/
onLoad(callback: (success: boolean) => void): this;
/**
* Removes all Items from the Collection
* and resets all Groups and Selectors of the Collection.
*
* [Learn more..](https://agile-ts.org/docs/core/collection/methods/#reset)
*
* @public
*/
reset(): this;
/**
* Puts `itemKeys/s` into Group/s.
*
* [Learn more..](https://agile-ts.org/docs/core/collection/methods/#put)
*
* @public
* @param itemKeys - `itemKey/s` to be put into the specified Group/s.
* @param groupKeys - Key/Name Identifier/s of the Group/s the specified `itemKey/s` are to put in.
* @param config - Configuration object
*/
put(itemKeys: ItemKey | Array<ItemKey>, groupKeys: GroupKey | Array<GroupKey>, config?: GroupAddConfigInterface): this;
/**
* Moves specified `itemKey/s` from one Group to another Group.
*
* [Learn more..](https://agile-ts.org/docs/core/collection/methods/#move)
*
* @public
* @param itemKeys - `itemKey/s` to be moved.
* @param oldGroupKey - Key/Name Identifier of the Group the `itemKey/s` are moved from.
* @param newGroupKey - Key/Name Identifier of the Group the `itemKey/s` are moved in.
* @param config - Configuration object
*/
move(itemKeys: ItemKey | Array<ItemKey>, oldGroupKey: GroupKey, newGroupKey: GroupKey, config?: GroupAddConfigInterface): this;
/**
* Updates the key/name identifier of the Item
* and returns a boolean indicating
* whether the Item identifier was updated successfully.
*
* @internal
* @param oldItemKey - Old key/name Item identifier.
* @param newItemKey - New key/name Item identifier.
* @param config - Configuration object
*/
updateItemKey(oldItemKey: ItemKey, newItemKey: ItemKey, config?: UpdateItemKeyConfigInterface): boolean;
/**
* Returns all key/name identifiers of the Group/s containing the specified `itemKey`.
*
* [Learn more..](https://agile-ts.org/docs/core/collection/methods/#getgroupkeysthathaveitemkey)
*
* @public
* @param itemKey - `itemKey` to be contained in Group/s.
*/
getGroupKeysThatHaveItemKey(itemKey: ItemKey): Array<GroupKey>;
/**
* Removes Item/s from:
*
* - `.everywhere()`:
* Removes Item/s from the entire Collection and all its Groups and Selectors (i.e. from everywhere)
* ```
* MY_COLLECTION.remove('1').everywhere();
* // is equivalent to
* MY_COLLECTION.removeItems('1');
* ```
* - `.fromGroups()`:
* Removes Item/s only from specified Groups.
* ```
* MY_COLLECTION.remove('1').fromGroups(['1', '2']);
* // is equivalent to
* MY_COLLECTION.removeFromGroups('1', ['1', '2']);
* ```
*
* [Learn more..](https://agile-ts.org/docs/core/collection/methods/#remove)
*
* @public
* @param itemKeys - Item/s with identifier/s to be removed.
*/
remove(itemKeys: ItemKey | Array<ItemKey>): {
fromGroups: (groups: Array<ItemKey> | ItemKey) => Collection<DataType>;
everywhere: (config?: RemoveItemsConfigInterface) => Collection<DataType>;
};
/**
* Remove Item/s from specified Group/s.
*
* [Learn more..](https://agile-ts.org/docs/core/collection/methods/#removefromgroups)
*
* @public
* @param itemKeys - Key/Name Identifier/s of the Item/s to be removed from the Group/s.
* @param groupKeys - Key/Name Identifier/s of the Group/s the Item/s are to remove from.
*/
removeFromGroups(itemKeys: ItemKey | Array<ItemKey>, groupKeys: GroupKey | Array<GroupKey>): this;
/**
* Removes Item/s from the entire Collection and all the Collection's Groups and Selectors.
*
* [Learn more..](https://agile-ts.org/docs/core/collection/methods/#removeitems)
*
* @public
* @param itemKeys - Key/Name identifier/s of the Item/s to be removed from the entire Collection.
* @param config - Configuration object
*/
removeItems(itemKeys: ItemKey | Array<ItemKey>, config?: RemoveItemsConfigInterface): this;
/**
* Assigns the provided `data` object to an already existing Item
* with specified key/name identifier found in the `data` object.
* If the Item doesn't exist yet, a new Item with the `data` object as value
* is created and assigned to the Collection.
*
* Returns a boolean indicating
* whether the `data` object was assigned/updated successfully.
*
* @internal
* @param data - Data object
* @param config - Configuration object
*/
assignData(data: DataType, config?: AssignDataConfigInterface): boolean;
/**
* Assigns the specified Item to the Collection
* at the key/name identifier of the Item.
*
* And returns a boolean indicating
* whether the Item was assigned successfully.
*
* @internal
* @param item - Item to be added.
* @param config - Configuration object
*/
assignItem(item: Item<DataType>, config?: AssignItemConfigInterface): boolean;
/**
* Rebuilds all Groups that contain the specified `itemKey`.
*
* @internal
* @itemKey - `itemKey` Groups must contain to be rebuilt.
* @config - Configuration object
*/
rebuildGroupsThatIncludeItemKey(itemKey: ItemKey, config?: RebuildGroupsThatIncludeItemKeyConfigInterface): void;
}
export declare type DefaultItem = Record<string, any>;
export declare type CollectionKey = string | number;
export declare type ItemKey = string | number;
export interface CreateCollectionConfigInterface<DataType = DefaultItem> {
/**
* Initial Groups of the Collection.
* @default []
*/
groups?: {
[key: string]: Group<any>;
} | string[];
/**
* Initial Selectors of the Collection
* @default []
*/
selectors?: {
[key: string]: Selector<any>;
} | string[];
/**
* Key/Name identifier of the Collection.
* @default undefined
*/
key?: CollectionKey;
/**
* Key/Name of the property
* which represents the unique Item identifier
* in collected data objects.
* @default 'id'
*/
primaryKey?: string;
/**
* Key/Name identifier of the default Group that is created shortly after instantiation.
* The default Group represents the default pattern of the Collection.
* @default 'default'
*/
defaultGroupKey?: GroupKey;
/**
* Initial data objects of the Collection.
* @default []
*/
initialData?: Array<DataType>;
}
export declare type CollectionConfig<DataType extends Object = DefaultItem> = CreateCollectionConfigInterface<DataType> | ((collection: Collection<DataType>) => CreateCollectionConfigInterface<DataType>);
export interface CollectionConfigInterface {
/**
* Key/Name of the property
* which represents the unique Item identifier
* in collected data objects.
* @default 'id'
*/
primaryKey: string;
/**
* Key/Name identifier of the default Group that is created shortly after instantiation.
* The default Group represents the default pattern of the Collection.
* @default 'default'
*/
defaultGroupKey: ItemKey;
}
export interface CollectConfigInterface<DataType = any> extends AssignDataConfigInterface {
/**
* In which way the collected data should be added to the Collection.
* - 'push' = at the end
* - 'unshift' = at the beginning
* https://www.tutorialspoint.com/what-are-the-differences-between-unshift-and-push-methods-in-javascript
* @default 'push'
*/
method?: 'push' | 'unshift';
/**
* Performs the specified action for each collected data object.
* @default undefined
*/
forEachItem?: (data: DataType | Item<DataType>, key: ItemKey, success: boolean, index: number) => void;
/**
* Whether to create a Selector for each collected data object.
* @default false
*/
select?: boolean;
}
export interface UpdateConfigInterface {
/**
* Whether to merge the data object with changes into the existing Item data object
* or overwrite the existing Item data object entirely.
* @default true
*/
patch?: boolean | PatchOptionConfigInterface;
/**
* Whether to update the data object in background.
* So that the UI isn't notified of these changes and thus doesn't rerender.
* @default false
*/
background?: boolean;
}
export interface UpdateItemKeyConfigInterface {
/**
* Whether to update the Item key/name identifier in background
* So that the UI isn't notified of these changes and thus doesn't rerender.
* @default false
*/
background?: boolean;
}
export interface RebuildGroupsThatIncludeItemKeyConfigInterface {
/**
* Whether to rebuilt the Group in background.
* So that the UI isn't notified of these changes and thus doesn't rerender.
* @default false
*/
background?: boolean;
/**
* Whether to execute the defined side effects.
* @default true
*/
sideEffects?: SideEffectConfigInterface;
}
export interface HasConfigInterface {
/**
* Whether Items that do not officially exist,
* such as placeholder Items, can be found
* @default true
*/
notExisting?: boolean;
}
export interface CollectionPersistentConfigInterface {
/**
* Whether the Persistent should automatically load
* the persisted value into the Collection after its instantiation.
* @default true
*/
loadValue?: boolean;
/**
* Key/Name identifier of Storages
* in which the Collection value should be or is persisted.
* @default [`defaultStorageKey`]
*/
storageKeys?: StorageKey[];
/**
* Key/Name identifier of the default Storage of the specified Storage keys.
*
* The Collection value is loaded from the default Storage by default
* and is only loaded from the remaining Storages (`storageKeys`)
* if the loading from the default Storage failed.
*
* @default first index of the specified Storage keys or the AgileTs default Storage key
*/
defaultStorageKey?: StorageKey;
}
export interface RemoveItemsConfigInterface {
/**
* Whether to remove not officially existing Items (such as placeholder Items).
* Keep in mind that sometimes it won't remove an Item entirely
* as another Instance (like a Selector) might need to keep reference to it.
* https://github.com/agile-ts/agile/pull/152
* @default false
*/
notExisting?: boolean;
/**
* Whether to remove Selectors that have selected an Item to be removed.
* @default false
*/
removeSelector?: boolean;
}
export interface AssignDataConfigInterface {
/**
* When the Item identifier of the to assign data object already exists in the Collection,
* whether to merge the newly assigned data into the existing one
* or overwrite the existing one entirely.
* @default true
*/
patch?: boolean;
/**
* Whether to assign the data object to the Collection in background.
* So that the UI isn't notified of these changes and thus doesn't rerender.
* @default false
*/
background?: boolean;
}
export interface AssignItemConfigInterface {
/**
* If an Item with the Item identifier already exists,
* whether to overwrite it entirely with the new one.
* @default false
*/
overwrite?: boolean;
/**
* Whether to assign the Item to the Collection in background.
* So that the UI isn't notified of these changes and thus doesn't rerender.
* @default false
*/
background?: boolean;
}
import { Collection, CollectionConfig, DefaultItem, Agile } from '../internal';
export * from './collection';
/**
* Returns a newly created Collection.
*
* A Collection manages a reactive set of Information
* that we need to remember globally at a later point in time.
* While providing a toolkit to use and mutate this set of Information.
*
* It is designed for arrays of data objects following the same pattern.
*
* Each of these data object must have a unique `primaryKey` to be correctly identified later.
*
* You can create as many global Collections as you need.
*
* [Learn more..](https://agile-ts.org/docs/core/agile-instance/methods#createcollection)
*
* @public
* @param config - Configuration object
* @param agileInstance - Instance of Agile the Collection belongs to.
*/
export declare function createCollection<DataType extends Object = DefaultItem>(config?: CollectionConfig<DataType>, agileInstance?: Agile): Collection<DataType>;
"use strict";
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
Object.defineProperty(o, k2, { enumerable: true, get: function() { return m[k]; } });
}) : (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
o[k2] = m[k];
}));
var __exportStar = (this && this.__exportStar) || function(m, exports) {
for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.Collection = void 0;
exports.createCollection = void 0;
const internal_1 = require("../internal");
class Collection {
constructor(agileInstance, config = {}) {
this.size = 0;
this.data = {};
this.isPersisted = false;
this.groups = {};
this.selectors = {};
this.isInstantiated = false;
this.isCollection = true;
this.agileInstance = () => agileInstance;
let _config = typeof config === 'function' ? config(this) : config;
_config = internal_1.defineConfig(_config, {
primaryKey: 'id',
groups: {},
selectors: {},
defaultGroupKey: 'default',
});
this._key = _config.key;
this.config = {
defaultGroupKey: _config.defaultGroupKey,
primaryKey: _config.primaryKey,
};
this.initialConfig = _config;
this.initGroups(_config.groups);
this.initSelectors(_config.selectors);
this.isInstantiated = true;
if (_config.initialData)
this.collect(_config.initialData);
for (const key in this.selectors)
this.selectors[key].reselect();
}
set key(value) {
this.setKey(value);
}
get key() {
return this._key;
}
setKey(value) {
var _a, _b;
const oldKey = this._key;
this._key = value;
if (value != null && ((_a = this.persistent) === null || _a === void 0 ? void 0 : _a._key) === oldKey)
(_b = this.persistent) === null || _b === void 0 ? void 0 : _b.setKey(value);
return this;
}
Group(initialItems, config = {}) {
var _a;
if (this.isInstantiated) {
const key = (_a = config.key) !== null && _a !== void 0 ? _a : internal_1.generateId();
internal_1.LogCodeManager.log('1B:02:00');
return this.createGroup(key, initialItems);
}
return new internal_1.Group(this, initialItems, config);
}
Selector(initialKey, config = {}) {
var _a;
if (this.isInstantiated) {
const key = (_a = config.key) !== null && _a !== void 0 ? _a : internal_1.generateId();
internal_1.LogCodeManager.log('1B:02:01');
return this.createSelector(key, initialKey);
}
return new internal_1.Selector(this, initialKey, config);
}
initGroups(groups) {
if (!groups)
return;
let groupsObject = {};
if (Array.isArray(groups)) {
groups.forEach((groupKey) => {
groupsObject[groupKey] = new internal_1.Group(this, [], {
key: groupKey,
});
});
}
else
groupsObject = groups;
groupsObject[this.config.defaultGroupKey] = new internal_1.Group(this, [], {
key: this.config.defaultGroupKey,
});
for (const key in groupsObject)
if (groupsObject[key]._key == null)
groupsObject[key].setKey(key);
this.groups = groupsObject;
}
initSelectors(selectors) {
if (!selectors)
return;
let selectorsObject = {};
if (Array.isArray(selectors)) {
selectors.forEach((selectorKey) => {
selectorsObject[selectorKey] = new internal_1.Selector(this, selectorKey, {
key: selectorKey,
});
});
}
else
selectorsObject = selectors;
for (const key in selectorsObject)
if (selectorsObject[key]._key == null)
selectorsObject[key].setKey(key);
this.selectors = selectorsObject;
}
collect(data, groupKeys, config = {}) {
const _data = internal_1.normalizeArray(data);
const _groupKeys = internal_1.normalizeArray(groupKeys);
const defaultGroupKey = this.config.defaultGroupKey;
const primaryKey = this.config.primaryKey;
config = internal_1.defineConfig(config, {
method: 'push',
background: false,
patch: false,
select: false,
});
if (!_groupKeys.includes(defaultGroupKey))
_groupKeys.push(defaultGroupKey);
_groupKeys.forEach((key) => this.groups[key] == null && this.createGroup(key));
_data.forEach((data, index) => {
let itemKey;
let success = false;
if (data instanceof internal_1.Item) {
success = this.assignItem(data, {
background: config.background,
});
itemKey = data._key;
}
else {
success = this.assignData(data, {
patch: config.patch,
background: config.background,
});
itemKey = data[primaryKey];
}
if (success) {
_groupKeys.forEach((groupKey) => {
var _a;
(_a = this.getGroup(groupKey)) === null || _a === void 0 ? void 0 : _a.add(itemKey, {
method: config.method,
background: config.background,
});
});
if (config.select)
this.createSelector(itemKey, itemKey);
}
if (config.forEachItem)
config.forEachItem(data, itemKey, success, index);
});
return this;
}
update(itemKey, changes, config = {}) {
const item = this.getItem(itemKey, { notExisting: true });
const primaryKey = this.config.primaryKey;
config = internal_1.defineConfig(config, {
patch: true,
background: false,
});
if (item == null) {
internal_1.LogCodeManager.log('1B:03:00', [itemKey, this._key]);
return undefined;
}
if (!internal_1.isValidObject(changes)) {
internal_1.LogCodeManager.log('1B:03:01', [itemKey, this._key]);
return undefined;
}
const oldItemKey = item._value[primaryKey];
const newItemKey = changes[primaryKey] || oldItemKey;
if (oldItemKey !== newItemKey)
this.updateItemKey(oldItemKey, newItemKey, {
background: config.background,
});
if (config.patch) {
if (changes[primaryKey])
delete changes[primaryKey];
let patchConfig = typeof config.patch === 'object' ? config.patch : {};
patchConfig = Object.assign({ addNewProperties: true }, patchConfig);
item.patch(changes, {
background: config.background,
addNewProperties: patchConfig.addNewProperties,
});
}
else {
if (changes[this.config.primaryKey] !== itemKey) {
changes[this.config.primaryKey] = itemKey;
internal_1.LogCodeManager.log('1B:02:02', [], changes);
}
item.set(changes, {
background: config.background,
});
}
return item;
}
createGroup(groupKey, initialItems = []) {
let group = this.getGroup(groupKey, { notExisting: true });
if (!this.isInstantiated)
internal_1.LogCodeManager.log('1B:02:03');
if (group != null) {
if (!group.isPlaceholder) {
internal_1.LogCodeManager.log('1B:03:02', [groupKey]);
return group;
}
group.set(initialItems, { overwrite: true });
return group;
}
group = new internal_1.Group(this, initialItems, { key: groupKey });
this.groups[groupKey] = group;
return group;
}
hasGroup(groupKey, config = {}) {
return !!this.getGroup(groupKey, config);
}
getGroup(groupKey, config = {}) {
config = internal_1.defineConfig(config, {
notExisting: false,
});
const group = groupKey ? this.groups[groupKey] : undefined;
if (group == null || (!config.notExisting && !group.exists))
return undefined;
internal_1.ComputedTracker.tracked(group.observers['value']);
return group;
}
getDefaultGroup() {
return this.getGroup(this.config.defaultGroupKey);
}
getGroupWithReference(groupKey) {
let group = this.getGroup(groupKey, { notExisting: true });
if (group == null) {
group = new internal_1.Group(this, [], {
key: groupKey,
isPlaceholder: true,
});
this.groups[groupKey] = group;
}
internal_1.ComputedTracker.tracked(group.observers['value']);
return group;
}
removeGroup(groupKey) {
if (this.groups[groupKey] != null)
delete this.groups[groupKey];
return this;
}
getGroupCount() {
let size = 0;
Object.keys(this.groups).map(() => size++);
return size;
}
createSelector(selectorKey, itemKey) {
let selector = this.getSelector(selectorKey, { notExisting: true });
if (!this.isInstantiated)
internal_1.LogCodeManager.log('1B:02:04');
if (selector != null) {
if (!selector.isPlaceholder) {
internal_1.LogCodeManager.log('1B:03:03', [selectorKey]);
return selector;
}
selector.select(itemKey, { overwrite: true });
return selector;
}
selector = new internal_1.Selector(this, itemKey, {
key: selectorKey,
});
this.selectors[selectorKey] = selector;
return selector;
}
select(itemKey) {
return this.createSelector(itemKey, itemKey);
}
hasSelector(selectorKey, config = {}) {
return !!this.getSelector(selectorKey, config);
}
getSelector(selectorKey, config = {}) {
config = internal_1.defineConfig(config, {
notExisting: false,
});
const selector = selectorKey ? this.selectors[selectorKey] : undefined;
if (selector == null || (!config.notExisting && !selector.exists))
return undefined;
internal_1.ComputedTracker.tracked(selector.observers['value']);
return selector;
}
getSelectorWithReference(selectorKey) {
let selector = this.getSelector(selectorKey, { notExisting: true });
if (selector == null) {
selector = new internal_1.Selector(this, null, {
key: selectorKey,
isPlaceholder: true,
});
this.selectors[selectorKey] = selector;
}
internal_1.ComputedTracker.tracked(selector.observers['value']);
return selector;
}
removeSelector(selectorKey) {
if (this.selectors[selectorKey] != null) {
this.selectors[selectorKey].unselect();
delete this.selectors[selectorKey];
}
return this;
}
getSelectorCount() {
let size = 0;
Object.keys(this.selectors).map(() => size++);
return size;
}
hasItem(itemKey, config = {}) {
return !!this.getItem(itemKey, config);
}
getItem(itemKey, config = {}) {
config = internal_1.defineConfig(config, {
notExisting: false,
});
const item = itemKey != null ? this.data[itemKey] : undefined;
if (item == null || (!config.notExisting && !item.exists))
return undefined;
internal_1.ComputedTracker.tracked(item.observers['value']);
return item;
}
getItemWithReference(itemKey) {
let item = this.getItem(itemKey, { notExisting: true });
if (item == null)
item = this.createPlaceholderItem(itemKey, true);
internal_1.ComputedTracker.tracked(item.observers['value']);
return item;
}
createPlaceholderItem(itemKey, addToCollection = false) {
const item = new internal_1.Item(this, {
[this.config.primaryKey]: itemKey,
dummy: 'item',
}, { isPlaceholder: true });
if (addToCollection &&
!Object.prototype.hasOwnProperty.call(this.data, itemKey))
this.data[itemKey] = item;
internal_1.ComputedTracker.tracked(item.observers['value']);
return item;
}
getItemValue(itemKey, config = {}) {
const item = this.getItem(itemKey, config);
if (item == null)
return undefined;
return item.value;
}
getAllItems(config = {}) {
config = internal_1.defineConfig(config, {
notExisting: false,
});
const defaultGroup = this.getDefaultGroup();
let items = [];
if (config.notExisting) {
for (const key in this.data)
items.push(this.data[key]);
}
else {
items = (defaultGroup === null || defaultGroup === void 0 ? void 0 : defaultGroup.getItems()) || [];
}
return items;
}
getAllItemValues(config = {}) {
const items = this.getAllItems(config);
return items.map((item) => item.value);
}
persist(keyOrConfig = {}, config = {}) {
let _config;
let key;
if (internal_1.isValidObject(keyOrConfig)) {
_config = keyOrConfig;
key = this._key;
}
else {
_config = config || {};
key = keyOrConfig;
}
_config = internal_1.defineConfig(_config, {
loadValue: true,
storageKeys: [],
defaultStorageKey: null,
});
if (this.persistent != null && this.isPersisted)
return this;
this.persistent = new internal_1.CollectionPersistent(this, {
instantiate: _config.loadValue,
storageKeys: _config.storageKeys,
key: key,
defaultStorageKey: _config.defaultStorageKey,
});
return this;
}
onLoad(callback) {
if (!this.persistent)
return this;
if (!internal_1.isFunction(callback)) {
internal_1.LogCodeManager.log('00:03:01', ['OnLoad Callback', 'function']);
return this;
}
this.persistent.onLoad = callback;
if (this.isPersisted)
callback(true);
return this;
}
reset() {
var _a, _b;
this.data = {};
this.size = 0;
for (const key in this.groups)
(_a = this.getGroup(key)) === null || _a === void 0 ? void 0 : _a.reset();
for (const key in this.selectors)
(_b = this.getSelector(key)) === null || _b === void 0 ? void 0 : _b.reset();
return this;
}
put(itemKeys, groupKeys, config = {}) {
const _itemKeys = internal_1.normalizeArray(itemKeys);
const _groupKeys = internal_1.normalizeArray(groupKeys);
_groupKeys.forEach((groupKey) => {
var _a;
(_a = this.getGroup(groupKey)) === null || _a === void 0 ? void 0 : _a.add(_itemKeys, config);
});
return this;
}
move(itemKeys, oldGroupKey, newGroupKey, config = {}) {
var _a, _b;
const _itemKeys = internal_1.normalizeArray(itemKeys);
(_a = this.getGroup(oldGroupKey)) === null || _a === void 0 ? void 0 : _a.remove(_itemKeys, internal_1.removeProperties(config, ['method', 'overwrite']));
(_b = this.getGroup(newGroupKey)) === null || _b === void 0 ? void 0 : _b.add(_itemKeys, config);
return this;
}
updateItemKey(oldItemKey, newItemKey, config = {}) {
var _a;
const item = this.getItem(oldItemKey, { notExisting: true });
config = internal_1.defineConfig(config, {
background: false,
});
if (item == null || oldItemKey === newItemKey)
return false;
if (this.hasItem(newItemKey)) {
internal_1.LogCodeManager.log('1B:03:04', [oldItemKey, newItemKey, this._key]);
return false;
}
delete this.data[oldItemKey];
this.data[newItemKey] = item;
item.setKey(newItemKey, {
background: config.background,
});
if (item.persistent != null &&
item.persistent._key ===
internal_1.CollectionPersistent.getItemStorageKey(oldItemKey, this._key))
(_a = item.persistent) === null || _a === void 0 ? void 0 : _a.setKey(internal_1.CollectionPersistent.getItemStorageKey(newItemKey, this._key));
for (const groupKey in this.groups) {
const group = this.getGroup(groupKey, { notExisting: true });
if (group == null || !group.has(oldItemKey))
continue;
group.replace(oldItemKey, newItemKey, { background: config.background });
}
for (const selectorKey in this.selectors) {
const selector = this.getSelector(selectorKey, { notExisting: true });
if (selector == null)
continue;
if (selector.hasSelected(newItemKey, false)) {
selector.reselect({
force: true,
background: config.background,
});
}
if (selector.hasSelected(oldItemKey, false))
selector.select(newItemKey, {
background: config.background,
});
}
return true;
}
getGroupKeysThatHaveItemKey(itemKey) {
const groupKeys = [];
for (const groupKey in this.groups) {
const group = this.groups[groupKey];
if (group === null || group === void 0 ? void 0 : group.has(itemKey))
groupKeys.push(groupKey);
}
return groupKeys;
}
remove(itemKeys) {
return {
fromGroups: (groups) => this.removeFromGroups(itemKeys, groups),
everywhere: (config) => this.removeItems(itemKeys, config || {}),
};
}
removeFromGroups(itemKeys, groupKeys) {
const _itemKeys = internal_1.normalizeArray(itemKeys);
const _groupKeys = internal_1.normalizeArray(groupKeys);
_itemKeys.forEach((itemKey) => {
let removedFromGroupsCount = 0;
_groupKeys.forEach((groupKey) => {
const group = this.getGroup(groupKey, { notExisting: true });
if (!(group === null || group === void 0 ? void 0 : group.has(itemKey)))
return;
group.remove(itemKey);
removedFromGroupsCount++;
});
if (removedFromGroupsCount >=
this.getGroupKeysThatHaveItemKey(itemKey).length)
this.removeItems(itemKey);
});
return this;
}
removeItems(itemKeys, config = {}) {
config = internal_1.defineConfig(config, {
notExisting: false,
removeSelector: false,
});
const _itemKeys = internal_1.normalizeArray(itemKeys);
_itemKeys.forEach((itemKey) => {
var _a, _b;
const item = this.getItem(itemKey, { notExisting: config.notExisting });
if (item == null)
return;
const wasPlaceholder = item.isPlaceholder;
for (const groupKey in this.groups) {
const group = this.getGroup(groupKey, { notExisting: true });
if (group === null || group === void 0 ? void 0 : group.has(itemKey))
group === null || group === void 0 ? void 0 : group.remove(itemKey);
}
(_a = item.persistent) === null || _a === void 0 ? void 0 : _a.removePersistedValue();
delete this.data[itemKey];
for (const selectorKey in this.selectors) {
const selector = this.getSelector(selectorKey, { notExisting: true });
if (selector != null && selector.hasSelected(itemKey, false)) {
if (config.removeSelector) {
this.removeSelector((_b = selector._key) !== null && _b !== void 0 ? _b : 'unknown');
}
else {
selector.reselect({ force: true });
}
}
}
if (!wasPlaceholder)
this.size--;
});
return this;
}
assignData(data, config = {}) {
config = internal_1.defineConfig(config, {
patch: false,
background: false,
});
const _data = internal_1.copy(data);
const primaryKey = this.config.primaryKey;
if (!internal_1.isValidObject(_data)) {
internal_1.LogCodeManager.log('1B:03:05', [this._key]);
return false;
}
if (!Object.prototype.hasOwnProperty.call(_data, primaryKey)) {
internal_1.LogCodeManager.log('1B:02:05', [this._key, primaryKey]);
_data[primaryKey] = internal_1.generateId();
}
const itemKey = _data[primaryKey];
const item = this.getItem(itemKey, { notExisting: true });
const wasPlaceholder = (item === null || item === void 0 ? void 0 : item.isPlaceholder) || false;
if (item != null) {
if (config.patch) {
item.patch(_data, { background: config.background });
}
else {
item.set(_data, { background: config.background });
}
}
else {
this.assignItem(new internal_1.Item(this, _data), {
background: config.background,
});
}
if (wasPlaceholder)
this.size++;
return true;
}
assignItem(item, config = {}) {
config = internal_1.defineConfig(config, {
overwrite: false,
background: false,
});
const primaryKey = this.config.primaryKey;
let itemKey = item._value[primaryKey];
let increaseCollectionSize = true;
if (!Object.prototype.hasOwnProperty.call(item._value, primaryKey)) {
internal_1.LogCodeManager.log('1B:02:05', [this._key, primaryKey]);
itemKey = internal_1.generateId();
item.patch({ [this.config.primaryKey]: itemKey }, { background: config.background });
item._key = itemKey;
}
if (item.collection() !== this) {
internal_1.LogCodeManager.log('1B:03:06', [this._key, item.collection()._key]);
return false;
}
if (this.getItem(itemKey, { notExisting: true }) != null) {
if (!config.overwrite) {
this.assignData(item._value);
return true;
}
else
increaseCollectionSize = false;
}
this.data[itemKey] = item;
this.rebuildGroupsThatIncludeItemKey(itemKey, {
background: config.background,
});
if (increaseCollectionSize)
this.size++;
return true;
}
rebuildGroupsThatIncludeItemKey(itemKey, config = {}) {
config = internal_1.defineConfig(config, {
background: false,
sideEffects: {
enabled: true,
exclude: [],
},
});
for (const groupKey in this.groups) {
const group = this.getGroup(groupKey);
if (group === null || group === void 0 ? void 0 : group.has(itemKey)) {
group === null || group === void 0 ? void 0 : group.rebuild({
background: config === null || config === void 0 ? void 0 : config.background,
sideEffects: config === null || config === void 0 ? void 0 : config.sideEffects,
storage: false,
});
}
}
}
__exportStar(require("./collection"), exports);
function createCollection(config, agileInstance = internal_1.shared) {
return new internal_1.Collection(agileInstance, config);
}
exports.Collection = Collection;
exports.createCollection = createCollection;

@@ -1,109 +0,42 @@

import { State, Agile, Observer, StateConfigInterface, Collection, StateIngestConfigInterface } from '../internal';
export declare class Computed<ComputedValueType = any> extends State<ComputedValueType> {
config: ComputedConfigInterface;
computeFunction: ComputeFunctionType<ComputedValueType>;
deps: Set<Observer>;
hardCodedDeps: Array<Observer>;
isComputed: boolean;
/**
* A Computed is an extension of the State Class
* that computes its value based on a specified compute function.
*
* The computed value will be cached to avoid unnecessary recomputes
* and is only recomputed when one of its direct dependencies changes.
*
* Direct dependencies can be States and Collections.
* So when, for example, a dependent State value changes, the computed value is recomputed.
*
* [Learn more..](https://agile-ts.org/docs/core/computed/)
*
* @public
* @param agileInstance - Instance of Agile the Computed belongs to.
* @param computeFunction - Function to compute the computed value.
* @param config - Configuration object
*/
constructor(agileInstance: Agile, computeFunction: ComputeFunctionType<ComputedValueType>, config?: CreateComputedConfigInterface);
/**
* Forces a recomputation of the cached value with the compute function.
*
* [Learn more..](https://agile-ts.org/docs/core/computed/methods/#recompute)
*
* @public
* @param config - Configuration object
*/
recompute(config?: RecomputeConfigInterface): this;
/**
* Assigns a new function to the Computed Class for computing its value.
*
* The dependencies of the new compute function are automatically detected
* and accordingly updated.
*
* An initial computation is performed with the new function
* to change the obsolete cached value.
*
* [Learn more..](https://agile-ts.org/docs/core/computed/methods/#updatecomputefunction)
*
* @public
* @param computeFunction - New function to compute the value of the Computed Class.
* @param deps - Hard coded dependencies on which the Computed Class depends.
* @param config - Configuration object
*/
updateComputeFunction(computeFunction: () => ComputedValueType, deps?: Array<DependableAgileInstancesType>, config?: RecomputeConfigInterface): this;
/**
* Computes and returns the new value of the Computed Class
* and autodetects used dependencies in the compute function.
*
* @internal
* @param config - Configuration object
*/
compute(config?: ComputeConfigInterface): Promise<ComputedValueType>;
/**
* Not usable in Computed Class.
*/
persist(): this;
import { Computed, ComputeFunctionType, CreateComputedConfigInterface, DependableAgileInstancesType, CreateAgileSubInstanceInterface } from '../internal';
export * from './computed';
export interface CreateComputedConfigInterfaceWithAgile extends CreateAgileSubInstanceInterface, CreateComputedConfigInterface {
}
export declare type ComputeFunctionType<ComputedValueType = any> = () => ComputedValueType | Promise<ComputedValueType>;
export interface CreateComputedConfigInterface extends StateConfigInterface {
/**
* Hard-coded dependencies the Computed Class should depend on.
* @default []
*/
computedDeps?: Array<DependableAgileInstancesType>;
/**
* Whether the Computed should automatically detect
* used dependencies in the specified compute method.
*
* Note that the automatic dependency detection does not work
* in an asynchronous compute method!
*
* @default true if the compute method isn't asynchronous, otherwise false
*/
autodetect?: boolean;
}
export interface ComputedConfigInterface {
/**
* Whether the Computed can automatically detect
* used dependencies in the compute method.
*
* Note that the automatic dependency detection does not work
* in an asynchronous compute method!
*
* @default true if the compute method isn't asynchronous, otherwise false
*/
autodetect: boolean;
}
export interface ComputeConfigInterface {
/**
* Whether the Computed can automatically detect
* used dependencies in the compute method.
*
* Note that the automatic dependency detection does not work
* in an asynchronous compute method!
*
* @default true
*/
autodetect?: boolean;
}
export interface RecomputeConfigInterface extends StateIngestConfigInterface, ComputeConfigInterface {
}
export declare type DependableAgileInstancesType = State | Collection<any> | Observer;
/**
* Returns a newly created Computed.
*
* A Computed is an extension of the State Class
* that computes its value based on a specified compute function.
*
* The computed value will be cached to avoid unnecessary recomputes
* and is only recomputed when one of its direct dependencies changes.
*
* Direct dependencies can be States and Collections.
* So when, for example, a dependent State value changes, the computed value is recomputed.
*
* [Learn more..](https://agile-ts.org/docs/core/agile-instance/methods#createstate)
*
* @public
* @param computeFunction - Function to compute the computed value.
* @param config - Configuration object
*/
export declare function createComputed<ComputedValueType = any>(computeFunction: ComputeFunctionType<ComputedValueType>, config?: CreateComputedConfigInterfaceWithAgile): Computed<ComputedValueType>;
/**
* Returns a newly created Computed.
*
* A Computed is an extension of the State Class
* that computes its value based on a specified compute function.
*
* The computed value will be cached to avoid unnecessary recomputes
* and is only recomputed when one of its direct dependencies changes.
*
* Direct dependencies can be States and Collections.
* So when, for example, a dependent State value changes, the computed value is recomputed.
*
* [Learn more..](https://agile-ts.org/docs/core/agile-instance/methods#createcomputed)
*
* @public
* @param computeFunction - Function to compute the computed value.
* @param deps - Hard-coded dependencies on which the Computed Class should depend.
*/
export declare function createComputed<ComputedValueType = any>(computeFunction: ComputeFunctionType<ComputedValueType>, deps?: Array<DependableAgileInstancesType>): Computed<ComputedValueType>;
"use strict";
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
return new (P || (P = Promise))(function (resolve, reject) {
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
step((generator = generator.apply(thisArg, _arguments || [])).next());
});
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
Object.defineProperty(o, k2, { enumerable: true, get: function() { return m[k]; } });
}) : (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
o[k2] = m[k];
}));
var __exportStar = (this && this.__exportStar) || function(m, exports) {
for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.Computed = void 0;
exports.createComputed = void 0;
const internal_1 = require("../internal");
class Computed extends internal_1.State {
constructor(agileInstance, computeFunction, config = {}) {
super(agileInstance, null, {
key: config.key,
dependents: config.dependents,
__exportStar(require("./computed"), exports);
function createComputed(computeFunction, configOrDeps) {
let _config = {};
if (Array.isArray(configOrDeps)) {
_config = internal_1.defineConfig(_config, {
computedDeps: configOrDeps,
});
this.deps = new Set();
this.hardCodedDeps = [];
this.isComputed = true;
config = internal_1.defineConfig(config, {
computedDeps: [],
autodetect: !internal_1.isAsyncFunction(computeFunction),
});
this.agileInstance = () => agileInstance;
this.computeFunction = computeFunction;
this.config = {
autodetect: config.autodetect,
};
this.hardCodedDeps = internal_1.extractRelevantObservers(config.computedDeps).filter((dep) => dep !== undefined);
this.deps = new Set(this.hardCodedDeps);
this.deps.forEach((observer) => {
observer.addDependent(this.observers['value']);
});
this.recompute({ autodetect: config.autodetect, overwrite: true });
}
recompute(config = {}) {
config = internal_1.defineConfig(config, {
autodetect: false,
});
this.compute({ autodetect: config.autodetect }).then((result) => {
this.observers['value'].ingestValue(result, internal_1.removeProperties(config, ['autodetect']));
});
return this;
else {
if (configOrDeps)
_config = configOrDeps;
}
updateComputeFunction(computeFunction, deps = [], config = {}) {
config = internal_1.defineConfig(config, {
autodetect: this.config.autodetect,
});
this.deps.forEach((observer) => {
observer.removeDependent(this.observers['value']);
});
this.hardCodedDeps = internal_1.extractRelevantObservers(deps).filter((dep) => dep !== undefined);
this.deps = new Set(this.hardCodedDeps);
this.deps.forEach((observer) => {
observer.addDependent(this.observers['value']);
});
this.computeFunction = computeFunction;
this.recompute(internal_1.removeProperties(config, ['overwriteDeps']));
return this;
}
compute(config = {}) {
return __awaiter(this, void 0, void 0, function* () {
config = internal_1.defineConfig(config, {
autodetect: this.config.autodetect,
});
if (config.autodetect)
internal_1.ComputedTracker.track();
const computedValue = this.computeFunction();
if (config.autodetect) {
const foundDeps = internal_1.ComputedTracker.getTrackedObservers();
this.deps.forEach((observer) => {
if (!foundDeps.includes(observer) &&
!this.hardCodedDeps.includes(observer)) {
this.deps.delete(observer);
observer.removeDependent(this.observers['value']);
}
});
foundDeps.forEach((observer) => {
if (!this.deps.has(observer)) {
this.deps.add(observer);
observer.addDependent(this.observers['value']);
}
});
}
return computedValue;
});
}
persist() {
internal_1.LogCodeManager.log('19:03:00');
return this;
}
_config = internal_1.defineConfig(_config, { agileInstance: internal_1.shared });
return new internal_1.Computed(_config.agileInstance, computeFunction, internal_1.removeProperties(_config, ['agileInstance']));
}
exports.Computed = Computed;
exports.createComputed = createComputed;

@@ -1,624 +0,5 @@

import { Item, Group, Selector, isValidObject, normalizeArray, copy, CollectionPersistent, ComputedTracker, generateId, removeProperties, isFunction, LogCodeManager, defineConfig, } from '../internal';
export class Collection {
constructor(agileInstance, config = {}) {
this.size = 0;
this.data = {};
this.isPersisted = false;
this.groups = {};
this.selectors = {};
this.isInstantiated = false;
this.isCollection = true;
this.agileInstance = () => agileInstance;
let _config = typeof config === 'function' ? config(this) : config;
_config = defineConfig(_config, {
primaryKey: 'id',
groups: {},
selectors: {},
defaultGroupKey: 'default',
});
this._key = _config.key;
this.config = {
defaultGroupKey: _config.defaultGroupKey,
primaryKey: _config.primaryKey,
};
this.initialConfig = _config;
this.initGroups(_config.groups);
this.initSelectors(_config.selectors);
this.isInstantiated = true;
if (_config.initialData)
this.collect(_config.initialData);
for (const key in this.selectors)
this.selectors[key].reselect();
}
set key(value) {
this.setKey(value);
}
get key() {
return this._key;
}
setKey(value) {
var _a, _b;
const oldKey = this._key;
this._key = value;
if (value != null && ((_a = this.persistent) === null || _a === void 0 ? void 0 : _a._key) === oldKey)
(_b = this.persistent) === null || _b === void 0 ? void 0 : _b.setKey(value);
return this;
}
Group(initialItems, config = {}) {
var _a;
if (this.isInstantiated) {
const key = (_a = config.key) !== null && _a !== void 0 ? _a : generateId();
LogCodeManager.log('1B:02:00');
return this.createGroup(key, initialItems);
}
return new Group(this, initialItems, config);
}
Selector(initialKey, config = {}) {
var _a;
if (this.isInstantiated) {
const key = (_a = config.key) !== null && _a !== void 0 ? _a : generateId();
LogCodeManager.log('1B:02:01');
return this.createSelector(key, initialKey);
}
return new Selector(this, initialKey, config);
}
initGroups(groups) {
if (!groups)
return;
let groupsObject = {};
if (Array.isArray(groups)) {
groups.forEach((groupKey) => {
groupsObject[groupKey] = new Group(this, [], {
key: groupKey,
});
});
}
else
groupsObject = groups;
groupsObject[this.config.defaultGroupKey] = new Group(this, [], {
key: this.config.defaultGroupKey,
});
for (const key in groupsObject)
if (groupsObject[key]._key == null)
groupsObject[key].setKey(key);
this.groups = groupsObject;
}
initSelectors(selectors) {
if (!selectors)
return;
let selectorsObject = {};
if (Array.isArray(selectors)) {
selectors.forEach((selectorKey) => {
selectorsObject[selectorKey] = new Selector(this, selectorKey, {
key: selectorKey,
});
});
}
else
selectorsObject = selectors;
for (const key in selectorsObject)
if (selectorsObject[key]._key == null)
selectorsObject[key].setKey(key);
this.selectors = selectorsObject;
}
collect(data, groupKeys, config = {}) {
const _data = normalizeArray(data);
const _groupKeys = normalizeArray(groupKeys);
const defaultGroupKey = this.config.defaultGroupKey;
const primaryKey = this.config.primaryKey;
config = defineConfig(config, {
method: 'push',
background: false,
patch: false,
select: false,
});
if (!_groupKeys.includes(defaultGroupKey))
_groupKeys.push(defaultGroupKey);
_groupKeys.forEach((key) => this.groups[key] == null && this.createGroup(key));
_data.forEach((data, index) => {
let itemKey;
let success = false;
if (data instanceof Item) {
success = this.assignItem(data, {
background: config.background,
});
itemKey = data._key;
}
else {
success = this.assignData(data, {
patch: config.patch,
background: config.background,
});
itemKey = data[primaryKey];
}
if (success) {
_groupKeys.forEach((groupKey) => {
var _a;
(_a = this.getGroup(groupKey)) === null || _a === void 0 ? void 0 : _a.add(itemKey, {
method: config.method,
background: config.background,
});
});
if (config.select)
this.createSelector(itemKey, itemKey);
}
if (config.forEachItem)
config.forEachItem(data, itemKey, success, index);
});
return this;
}
update(itemKey, changes, config = {}) {
const item = this.getItem(itemKey, { notExisting: true });
const primaryKey = this.config.primaryKey;
config = defineConfig(config, {
patch: true,
background: false,
});
if (item == null) {
LogCodeManager.log('1B:03:00', [itemKey, this._key]);
return undefined;
}
if (!isValidObject(changes)) {
LogCodeManager.log('1B:03:01', [itemKey, this._key]);
return undefined;
}
const oldItemKey = item._value[primaryKey];
const newItemKey = changes[primaryKey] || oldItemKey;
if (oldItemKey !== newItemKey)
this.updateItemKey(oldItemKey, newItemKey, {
background: config.background,
});
if (config.patch) {
if (changes[primaryKey])
delete changes[primaryKey];
let patchConfig = typeof config.patch === 'object' ? config.patch : {};
patchConfig = Object.assign({ addNewProperties: true }, patchConfig);
item.patch(changes, {
background: config.background,
addNewProperties: patchConfig.addNewProperties,
});
}
else {
if (changes[this.config.primaryKey] !== itemKey) {
changes[this.config.primaryKey] = itemKey;
LogCodeManager.log('1B:02:02', [], changes);
}
item.set(changes, {
background: config.background,
});
}
return item;
}
createGroup(groupKey, initialItems = []) {
let group = this.getGroup(groupKey, { notExisting: true });
if (!this.isInstantiated)
LogCodeManager.log('1B:02:03');
if (group != null) {
if (!group.isPlaceholder) {
LogCodeManager.log('1B:03:02', [groupKey]);
return group;
}
group.set(initialItems, { overwrite: true });
return group;
}
group = new Group(this, initialItems, { key: groupKey });
this.groups[groupKey] = group;
return group;
}
hasGroup(groupKey, config = {}) {
return !!this.getGroup(groupKey, config);
}
getGroup(groupKey, config = {}) {
config = defineConfig(config, {
notExisting: false,
});
const group = groupKey ? this.groups[groupKey] : undefined;
if (group == null || (!config.notExisting && !group.exists))
return undefined;
ComputedTracker.tracked(group.observers['value']);
return group;
}
getDefaultGroup() {
return this.getGroup(this.config.defaultGroupKey);
}
getGroupWithReference(groupKey) {
let group = this.getGroup(groupKey, { notExisting: true });
if (group == null) {
group = new Group(this, [], {
key: groupKey,
isPlaceholder: true,
});
this.groups[groupKey] = group;
}
ComputedTracker.tracked(group.observers['value']);
return group;
}
removeGroup(groupKey) {
if (this.groups[groupKey] != null)
delete this.groups[groupKey];
return this;
}
getGroupCount() {
let size = 0;
Object.keys(this.groups).map(() => size++);
return size;
}
createSelector(selectorKey, itemKey) {
let selector = this.getSelector(selectorKey, { notExisting: true });
if (!this.isInstantiated)
LogCodeManager.log('1B:02:04');
if (selector != null) {
if (!selector.isPlaceholder) {
LogCodeManager.log('1B:03:03', [selectorKey]);
return selector;
}
selector.select(itemKey, { overwrite: true });
return selector;
}
selector = new Selector(this, itemKey, {
key: selectorKey,
});
this.selectors[selectorKey] = selector;
return selector;
}
select(itemKey) {
return this.createSelector(itemKey, itemKey);
}
hasSelector(selectorKey, config = {}) {
return !!this.getSelector(selectorKey, config);
}
getSelector(selectorKey, config = {}) {
config = defineConfig(config, {
notExisting: false,
});
const selector = selectorKey ? this.selectors[selectorKey] : undefined;
if (selector == null || (!config.notExisting && !selector.exists))
return undefined;
ComputedTracker.tracked(selector.observers['value']);
return selector;
}
getSelectorWithReference(selectorKey) {
let selector = this.getSelector(selectorKey, { notExisting: true });
if (selector == null) {
selector = new Selector(this, null, {
key: selectorKey,
isPlaceholder: true,
});
this.selectors[selectorKey] = selector;
}
ComputedTracker.tracked(selector.observers['value']);
return selector;
}
removeSelector(selectorKey) {
if (this.selectors[selectorKey] != null) {
this.selectors[selectorKey].unselect();
delete this.selectors[selectorKey];
}
return this;
}
getSelectorCount() {
let size = 0;
Object.keys(this.selectors).map(() => size++);
return size;
}
hasItem(itemKey, config = {}) {
return !!this.getItem(itemKey, config);
}
getItem(itemKey, config = {}) {
config = defineConfig(config, {
notExisting: false,
});
const item = itemKey != null ? this.data[itemKey] : undefined;
if (item == null || (!config.notExisting && !item.exists))
return undefined;
ComputedTracker.tracked(item.observers['value']);
return item;
}
getItemWithReference(itemKey) {
let item = this.getItem(itemKey, { notExisting: true });
if (item == null)
item = this.createPlaceholderItem(itemKey, true);
ComputedTracker.tracked(item.observers['value']);
return item;
}
createPlaceholderItem(itemKey, addToCollection = false) {
const item = new Item(this, {
[this.config.primaryKey]: itemKey,
dummy: 'item',
}, { isPlaceholder: true });
if (addToCollection &&
!Object.prototype.hasOwnProperty.call(this.data, itemKey))
this.data[itemKey] = item;
ComputedTracker.tracked(item.observers['value']);
return item;
}
getItemValue(itemKey, config = {}) {
const item = this.getItem(itemKey, config);
if (item == null)
return undefined;
return item.value;
}
getAllItems(config = {}) {
config = defineConfig(config, {
notExisting: false,
});
const defaultGroup = this.getDefaultGroup();
let items = [];
if (config.notExisting) {
for (const key in this.data)
items.push(this.data[key]);
}
else {
items = (defaultGroup === null || defaultGroup === void 0 ? void 0 : defaultGroup.getItems()) || [];
}
return items;
}
getAllItemValues(config = {}) {
const items = this.getAllItems(config);
return items.map((item) => item.value);
}
persist(keyOrConfig = {}, config = {}) {
let _config;
let key;
if (isValidObject(keyOrConfig)) {
_config = keyOrConfig;
key = this._key;
}
else {
_config = config || {};
key = keyOrConfig;
}
_config = defineConfig(_config, {
loadValue: true,
storageKeys: [],
defaultStorageKey: null,
});
if (this.persistent != null && this.isPersisted)
return this;
this.persistent = new CollectionPersistent(this, {
instantiate: _config.loadValue,
storageKeys: _config.storageKeys,
key: key,
defaultStorageKey: _config.defaultStorageKey,
});
return this;
}
onLoad(callback) {
if (!this.persistent)
return this;
if (!isFunction(callback)) {
LogCodeManager.log('00:03:01', ['OnLoad Callback', 'function']);
return this;
}
this.persistent.onLoad = callback;
if (this.isPersisted)
callback(true);
return this;
}
reset() {
var _a, _b;
this.data = {};
this.size = 0;
for (const key in this.groups)
(_a = this.getGroup(key)) === null || _a === void 0 ? void 0 : _a.reset();
for (const key in this.selectors)
(_b = this.getSelector(key)) === null || _b === void 0 ? void 0 : _b.reset();
return this;
}
put(itemKeys, groupKeys, config = {}) {
const _itemKeys = normalizeArray(itemKeys);
const _groupKeys = normalizeArray(groupKeys);
_groupKeys.forEach((groupKey) => {
var _a;
(_a = this.getGroup(groupKey)) === null || _a === void 0 ? void 0 : _a.add(_itemKeys, config);
});
return this;
}
move(itemKeys, oldGroupKey, newGroupKey, config = {}) {
var _a, _b;
const _itemKeys = normalizeArray(itemKeys);
(_a = this.getGroup(oldGroupKey)) === null || _a === void 0 ? void 0 : _a.remove(_itemKeys, removeProperties(config, ['method', 'overwrite']));
(_b = this.getGroup(newGroupKey)) === null || _b === void 0 ? void 0 : _b.add(_itemKeys, config);
return this;
}
updateItemKey(oldItemKey, newItemKey, config = {}) {
var _a;
const item = this.getItem(oldItemKey, { notExisting: true });
config = defineConfig(config, {
background: false,
});
if (item == null || oldItemKey === newItemKey)
return false;
if (this.hasItem(newItemKey)) {
LogCodeManager.log('1B:03:04', [oldItemKey, newItemKey, this._key]);
return false;
}
delete this.data[oldItemKey];
this.data[newItemKey] = item;
item.setKey(newItemKey, {
background: config.background,
});
if (item.persistent != null &&
item.persistent._key ===
CollectionPersistent.getItemStorageKey(oldItemKey, this._key))
(_a = item.persistent) === null || _a === void 0 ? void 0 : _a.setKey(CollectionPersistent.getItemStorageKey(newItemKey, this._key));
for (const groupKey in this.groups) {
const group = this.getGroup(groupKey, { notExisting: true });
if (group == null || !group.has(oldItemKey))
continue;
group.replace(oldItemKey, newItemKey, { background: config.background });
}
for (const selectorKey in this.selectors) {
const selector = this.getSelector(selectorKey, { notExisting: true });
if (selector == null)
continue;
if (selector.hasSelected(newItemKey, false)) {
selector.reselect({
force: true,
background: config.background,
});
}
if (selector.hasSelected(oldItemKey, false))
selector.select(newItemKey, {
background: config.background,
});
}
return true;
}
getGroupKeysThatHaveItemKey(itemKey) {
const groupKeys = [];
for (const groupKey in this.groups) {
const group = this.groups[groupKey];
if (group === null || group === void 0 ? void 0 : group.has(itemKey))
groupKeys.push(groupKey);
}
return groupKeys;
}
remove(itemKeys) {
return {
fromGroups: (groups) => this.removeFromGroups(itemKeys, groups),
everywhere: (config) => this.removeItems(itemKeys, config || {}),
};
}
removeFromGroups(itemKeys, groupKeys) {
const _itemKeys = normalizeArray(itemKeys);
const _groupKeys = normalizeArray(groupKeys);
_itemKeys.forEach((itemKey) => {
let removedFromGroupsCount = 0;
_groupKeys.forEach((groupKey) => {
const group = this.getGroup(groupKey, { notExisting: true });
if (!(group === null || group === void 0 ? void 0 : group.has(itemKey)))
return;
group.remove(itemKey);
removedFromGroupsCount++;
});
if (removedFromGroupsCount >=
this.getGroupKeysThatHaveItemKey(itemKey).length)
this.removeItems(itemKey);
});
return this;
}
removeItems(itemKeys, config = {}) {
config = defineConfig(config, {
notExisting: false,
removeSelector: false,
});
const _itemKeys = normalizeArray(itemKeys);
_itemKeys.forEach((itemKey) => {
var _a, _b;
const item = this.getItem(itemKey, { notExisting: config.notExisting });
if (item == null)
return;
const wasPlaceholder = item.isPlaceholder;
for (const groupKey in this.groups) {
const group = this.getGroup(groupKey, { notExisting: true });
if (group === null || group === void 0 ? void 0 : group.has(itemKey))
group === null || group === void 0 ? void 0 : group.remove(itemKey);
}
(_a = item.persistent) === null || _a === void 0 ? void 0 : _a.removePersistedValue();
delete this.data[itemKey];
for (const selectorKey in this.selectors) {
const selector = this.getSelector(selectorKey, { notExisting: true });
if (selector != null && selector.hasSelected(itemKey, false)) {
if (config.removeSelector) {
this.removeSelector((_b = selector._key) !== null && _b !== void 0 ? _b : 'unknown');
}
else {
selector.reselect({ force: true });
}
}
}
if (!wasPlaceholder)
this.size--;
});
return this;
}
assignData(data, config = {}) {
config = defineConfig(config, {
patch: false,
background: false,
});
const _data = copy(data);
const primaryKey = this.config.primaryKey;
if (!isValidObject(_data)) {
LogCodeManager.log('1B:03:05', [this._key]);
return false;
}
if (!Object.prototype.hasOwnProperty.call(_data, primaryKey)) {
LogCodeManager.log('1B:02:05', [this._key, primaryKey]);
_data[primaryKey] = generateId();
}
const itemKey = _data[primaryKey];
const item = this.getItem(itemKey, { notExisting: true });
const wasPlaceholder = (item === null || item === void 0 ? void 0 : item.isPlaceholder) || false;
if (item != null) {
if (config.patch) {
item.patch(_data, { background: config.background });
}
else {
item.set(_data, { background: config.background });
}
}
else {
this.assignItem(new Item(this, _data), {
background: config.background,
});
}
if (wasPlaceholder)
this.size++;
return true;
}
assignItem(item, config = {}) {
config = defineConfig(config, {
overwrite: false,
background: false,
});
const primaryKey = this.config.primaryKey;
let itemKey = item._value[primaryKey];
let increaseCollectionSize = true;
if (!Object.prototype.hasOwnProperty.call(item._value, primaryKey)) {
LogCodeManager.log('1B:02:05', [this._key, primaryKey]);
itemKey = generateId();
item.patch({ [this.config.primaryKey]: itemKey }, { background: config.background });
item._key = itemKey;
}
if (item.collection() !== this) {
LogCodeManager.log('1B:03:06', [this._key, item.collection()._key]);
return false;
}
if (this.getItem(itemKey, { notExisting: true }) != null) {
if (!config.overwrite) {
this.assignData(item._value);
return true;
}
else
increaseCollectionSize = false;
}
this.data[itemKey] = item;
this.rebuildGroupsThatIncludeItemKey(itemKey, {
background: config.background,
});
if (increaseCollectionSize)
this.size++;
return true;
}
rebuildGroupsThatIncludeItemKey(itemKey, config = {}) {
config = defineConfig(config, {
background: false,
sideEffects: {
enabled: true,
exclude: [],
},
});
for (const groupKey in this.groups) {
const group = this.getGroup(groupKey);
if (group === null || group === void 0 ? void 0 : group.has(itemKey)) {
group === null || group === void 0 ? void 0 : group.rebuild({
background: config === null || config === void 0 ? void 0 : config.background,
sideEffects: config === null || config === void 0 ? void 0 : config.sideEffects,
storage: false,
});
}
}
}
import { Collection, shared, } from '../internal';
export * from './collection';
export function createCollection(config, agileInstance = shared) {
return new Collection(agileInstance, config);
}

@@ -1,92 +0,16 @@

var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
return new (P || (P = Promise))(function (resolve, reject) {
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
step((generator = generator.apply(thisArg, _arguments || [])).next());
});
};
import { State, ComputedTracker, removeProperties, LogCodeManager, isAsyncFunction, extractRelevantObservers, defineConfig, } from '../internal';
export class Computed extends State {
constructor(agileInstance, computeFunction, config = {}) {
super(agileInstance, null, {
key: config.key,
dependents: config.dependents,
import { Computed, defineConfig, removeProperties, shared, } from '../internal';
export * from './computed';
export function createComputed(computeFunction, configOrDeps) {
let _config = {};
if (Array.isArray(configOrDeps)) {
_config = defineConfig(_config, {
computedDeps: configOrDeps,
});
this.deps = new Set();
this.hardCodedDeps = [];
this.isComputed = true;
config = defineConfig(config, {
computedDeps: [],
autodetect: !isAsyncFunction(computeFunction),
});
this.agileInstance = () => agileInstance;
this.computeFunction = computeFunction;
this.config = {
autodetect: config.autodetect,
};
this.hardCodedDeps = extractRelevantObservers(config.computedDeps).filter((dep) => dep !== undefined);
this.deps = new Set(this.hardCodedDeps);
this.deps.forEach((observer) => {
observer.addDependent(this.observers['value']);
});
this.recompute({ autodetect: config.autodetect, overwrite: true });
}
recompute(config = {}) {
config = defineConfig(config, {
autodetect: false,
});
this.compute({ autodetect: config.autodetect }).then((result) => {
this.observers['value'].ingestValue(result, removeProperties(config, ['autodetect']));
});
return this;
else {
if (configOrDeps)
_config = configOrDeps;
}
updateComputeFunction(computeFunction, deps = [], config = {}) {
config = defineConfig(config, {
autodetect: this.config.autodetect,
});
this.deps.forEach((observer) => {
observer.removeDependent(this.observers['value']);
});
this.hardCodedDeps = extractRelevantObservers(deps).filter((dep) => dep !== undefined);
this.deps = new Set(this.hardCodedDeps);
this.deps.forEach((observer) => {
observer.addDependent(this.observers['value']);
});
this.computeFunction = computeFunction;
this.recompute(removeProperties(config, ['overwriteDeps']));
return this;
}
compute(config = {}) {
return __awaiter(this, void 0, void 0, function* () {
config = defineConfig(config, {
autodetect: this.config.autodetect,
});
if (config.autodetect)
ComputedTracker.track();
const computedValue = this.computeFunction();
if (config.autodetect) {
const foundDeps = ComputedTracker.getTrackedObservers();
this.deps.forEach((observer) => {
if (!foundDeps.includes(observer) &&
!this.hardCodedDeps.includes(observer)) {
this.deps.delete(observer);
observer.removeDependent(this.observers['value']);
}
});
foundDeps.forEach((observer) => {
if (!this.deps.has(observer)) {
this.deps.add(observer);
observer.addDependent(this.observers['value']);
}
});
}
return computedValue;
});
}
persist() {
LogCodeManager.log('19:03:00');
return this;
}
_config = defineConfig(_config, { agileInstance: shared });
return new Computed(_config.agileInstance, computeFunction, removeProperties(_config, ['agileInstance']));
}

@@ -1,67 +0,1 @@

var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
return new (P || (P = Promise))(function (resolve, reject) {
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
step((generator = generator.apply(thisArg, _arguments || [])).next());
});
};
import { Integration, LogCodeManager, defineConfig } from '../internal';
const onRegisterInitialIntegrationCallbacks = [];
export class Integrations {
constructor(agileInstance, config = {}) {
this.integrations = new Set();
config = defineConfig(config, {
autoIntegrate: true,
});
this.agileInstance = () => agileInstance;
if (config.autoIntegrate) {
Integrations.onRegisterInitialIntegration((integration) => {
this.integrate(integration);
});
}
}
static addInitialIntegration(integration) {
if (integration instanceof Integration) {
onRegisterInitialIntegrationCallbacks.forEach((callback) => callback(integration));
Integrations.initialIntegrations.push(integration);
}
}
static onRegisterInitialIntegration(callback) {
onRegisterInitialIntegrationCallbacks.push(callback);
Integrations.initialIntegrations.forEach((integration) => {
callback(integration);
});
}
integrate(integration) {
return __awaiter(this, void 0, void 0, function* () {
if (integration._key == null) {
LogCodeManager.log('18:03:00', [integration._key, this.agileInstance().key], integration);
return false;
}
if (integration.methods.bind)
integration.ready = yield integration.methods.bind(this.agileInstance());
else
integration.ready = true;
this.integrations.add(integration);
integration.integrated = true;
LogCodeManager.log('18:00:00', [integration._key, this.agileInstance().key], integration);
return true;
});
}
update(componentInstance, updatedData) {
this.integrations.forEach((integration) => {
if (!integration.ready) {
LogCodeManager.log('18:02:00', [integration._key]);
return;
}
if (integration.methods.updateMethod)
integration.methods.updateMethod(componentInstance, updatedData);
});
}
hasIntegration() {
return this.integrations.size > 0;
}
}
Integrations.initialIntegrations = [];
export * from './integrations';

@@ -1,7 +0,1 @@

export let loggerPackage = null;
try {
loggerPackage = require('@agile-ts/logger');
}
catch (e) {
}
const logCodeTypes = {

@@ -13,3 +7,3 @@ '00': 'success',

};
const logCodeMessages = {
const niceLogCodeMessages = {
'10:00:00': 'Created new AgileInstance.',

@@ -94,5 +88,9 @@ '10:02:00': 'Be careful when binding multiple Agile Instances globally in one application!',

};
const logCodeMessages = typeof process === 'object' && process.env.NODE_ENV !== 'production'
? niceLogCodeMessages
: {};
function getLog(logCode, replacers = []) {
var _a;
let result = (_a = logCodeMessages[logCode]) !== null && _a !== void 0 ? _a : `'${logCode}' is a unknown logCode!`;
let result = logCodeMessages[logCode];
if (result == null)
return logCode;
for (let i = 0; i < replacers.length; i++) {

@@ -129,12 +127,35 @@ result = result.replace('${' + i + '}', replacers[i]);

}
export const LogCodeManager = {
getLog,
log,
logCodeLogTypes: logCodeTypes,
logCodeMessages: logCodeMessages,
getLogger: () => {
var _a;
return (_a = loggerPackage === null || loggerPackage === void 0 ? void 0 : loggerPackage.sharedAgileLogger) !== null && _a !== void 0 ? _a : null;
},
logIfTags,
};
let tempLogCodeManager;
if (typeof process === 'object' && process.env.NODE_ENV !== 'production') {
tempLogCodeManager = {
getLog,
log,
logCodeLogTypes: logCodeTypes,
logCodeMessages: logCodeMessages,
getLogger: () => {
var _a;
let loggerPackage = null;
try {
loggerPackage = require('@agile-ts/logger');
}
catch (e) {
}
return (_a = loggerPackage === null || loggerPackage === void 0 ? void 0 : loggerPackage.sharedAgileLogger) !== null && _a !== void 0 ? _a : null;
},
logIfTags,
};
}
else {
tempLogCodeManager = {
getLog: (logCode, replacers) => logCode,
log,
logCodeLogTypes: logCodeTypes,
logCodeMessages: logCodeMessages,
getLogger: () => {
return null;
},
logIfTags: (tags, logCode, replacers) => {
},
};
}
export const LogCodeManager = tempLogCodeManager;

@@ -1,131 +0,1 @@

import { CallbackSubscriptionContainer, ComponentSubscriptionContainer, notEqual, LogCodeManager, defineConfig, } from '../internal';
export class Runtime {
constructor(agileInstance) {
this.currentJob = null;
this.jobQueue = [];
this.jobsToRerender = [];
this.notReadyJobsToRerender = new Set();
this.isPerformingJobs = false;
this.bucketTimeout = null;
this.agileInstance = () => agileInstance;
}
ingest(job, config = {}) {
config = defineConfig(config, {
perform: !this.isPerformingJobs,
});
this.jobQueue.push(job);
LogCodeManager.logIfTags(['runtime'], '16:01:00', [job._key], job);
if (config.perform) {
const performJob = this.jobQueue.shift();
if (performJob)
this.perform(performJob);
}
}
perform(job) {
this.isPerformingJobs = true;
this.currentJob = job;
job.observer.perform(job);
job.performed = true;
job.observer.dependents.forEach((observer) => observer.ingest());
if (job.rerender)
this.jobsToRerender.push(job);
this.currentJob = null;
LogCodeManager.logIfTags(['runtime'], '16:01:01', [job._key], job);
if (this.jobQueue.length > 0) {
const performJob = this.jobQueue.shift();
if (performJob)
this.perform(performJob);
}
else {
this.isPerformingJobs = false;
if (this.jobsToRerender.length > 0) {
if (this.agileInstance().config.bucket) {
if (this.bucketTimeout == null) {
this.bucketTimeout = setTimeout(() => {
this.bucketTimeout = null;
this.updateSubscribers();
});
}
}
else
this.updateSubscribers();
}
}
}
updateSubscribers() {
const jobsToRerender = this.jobsToRerender.concat(Array.from(this.notReadyJobsToRerender));
this.notReadyJobsToRerender = new Set();
this.jobsToRerender = [];
if (!this.agileInstance().hasIntegration() || jobsToRerender.length <= 0)
return false;
const subscriptionContainerToUpdate = this.extractToUpdateSubscriptionContainer(jobsToRerender);
if (subscriptionContainerToUpdate.length <= 0)
return false;
this.updateSubscriptionContainer(subscriptionContainerToUpdate);
return true;
}
extractToUpdateSubscriptionContainer(jobs) {
const subscriptionsToUpdate = new Set();
for (let i = 0; i < jobs.length; i++) {
const job = jobs[i];
job.subscriptionContainersToUpdate.forEach((subscriptionContainer) => {
let updateSubscriptionContainer = true;
if (!subscriptionContainer.ready) {
if (!job.config.maxTriesToUpdate ||
job.timesTriedToUpdateCount < job.config.maxTriesToUpdate) {
job.timesTriedToUpdateCount++;
this.notReadyJobsToRerender.add(job);
LogCodeManager.log('16:02:00', [subscriptionContainer.key], subscriptionContainer);
}
else {
LogCodeManager.log('16:02:01', [job.config.maxTriesToUpdate], subscriptionContainer);
}
return;
}
updateSubscriptionContainer =
updateSubscriptionContainer &&
this.handleSelectors(subscriptionContainer, job);
if (updateSubscriptionContainer) {
subscriptionContainer.updatedSubscribers.add(job.observer);
subscriptionsToUpdate.add(subscriptionContainer);
}
job.subscriptionContainersToUpdate.delete(subscriptionContainer);
});
}
return Array.from(subscriptionsToUpdate);
}
updateSubscriptionContainer(subscriptionsToUpdate) {
for (let i = 0; i < subscriptionsToUpdate.length; i++) {
const subscriptionContainer = subscriptionsToUpdate[i];
if (subscriptionContainer instanceof CallbackSubscriptionContainer)
subscriptionContainer.callback();
if (subscriptionContainer instanceof ComponentSubscriptionContainer)
this.agileInstance().integrations.update(subscriptionContainer.component, this.getUpdatedObserverValues(subscriptionContainer));
subscriptionContainer.updatedSubscribers.clear();
}
LogCodeManager.logIfTags(['runtime'], '16:01:02', [], subscriptionsToUpdate);
}
getUpdatedObserverValues(subscriptionContainer) {
var _a;
const props = {};
for (const observer of subscriptionContainer.updatedSubscribers) {
const key = (_a = subscriptionContainer.subscriberKeysWeakMap.get(observer)) !== null && _a !== void 0 ? _a : observer.key;
if (key != null)
props[key] = observer.value;
}
return props;
}
handleSelectors(subscriptionContainer, job) {
var _a;
const selectorMethods = (_a = subscriptionContainer.selectorsWeakMap.get(job.observer)) === null || _a === void 0 ? void 0 : _a.methods;
if (selectorMethods == null)
return true;
const previousValue = job.observer.previousValue;
const newValue = job.observer.value;
for (const selectorMethod of selectorMethods) {
if (notEqual(selectorMethod(newValue), selectorMethod(previousValue)))
return true;
}
return false;
}
}
export * from './runtime';

@@ -1,2 +0,2 @@

import { Agile, Collection, Computed, defineConfig, removeProperties, runsOnServer, State, Storage, } from './internal';
import { Agile, runsOnServer } from './internal';
let sharedAgileInstance = new Agile({

@@ -10,27 +10,1 @@ key: 'shared',

}
export function createStorage(config) {
return new Storage(config);
}
export function createState(initialValue, config = {}) {
config = defineConfig(config, {
agileInstance: sharedAgileInstance,
});
return new State(config.agileInstance, initialValue, removeProperties(config, ['agileInstance']));
}
export function createComputed(computeFunction, configOrDeps) {
let _config = {};
if (Array.isArray(configOrDeps)) {
_config = defineConfig(_config, {
computedDeps: configOrDeps,
});
}
else {
if (configOrDeps)
_config = configOrDeps;
}
_config = defineConfig(_config, { agileInstance: sharedAgileInstance });
return new Computed(_config.agileInstance, computeFunction, removeProperties(_config, ['agileInstance']));
}
export function createCollection(config, agileInstance = sharedAgileInstance) {
return new Collection(agileInstance, config);
}

@@ -1,261 +0,8 @@

import { copy, flatMerge, isValidObject, StateObserver, StatePersistent, equal, isFunction, notEqual, generateId, ComputedTracker, removeProperties, LogCodeManager, defineConfig, } from '../internal';
export class State {
constructor(agileInstance, initialValue, config = {}) {
this.isSet = false;
this.isPlaceholder = false;
this.observers = {};
this.sideEffects = {};
this.isPersisted = false;
config = defineConfig(config, {
dependents: [],
isPlaceholder: false,
});
this.agileInstance = () => agileInstance;
this._key = config.key;
this.observers['value'] = new StateObserver(this, {
key: config.key,
dependents: config.dependents,
});
this.initialStateValue = copy(initialValue);
this._value = copy(initialValue);
this.previousStateValue = copy(initialValue);
this.nextStateValue = copy(initialValue);
this.isPlaceholder = true;
this.computeExistsMethod = (v) => {
return v != null;
};
if (!config.isPlaceholder)
this.set(initialValue, { overwrite: true });
}
set value(value) {
this.set(value);
}
get value() {
ComputedTracker.tracked(this.observers['value']);
return copy(this._value);
}
set key(value) {
this.setKey(value);
}
get key() {
return this._key;
}
setKey(value) {
var _a, _b;
const oldKey = this._key;
this._key = value;
for (const observerKey in this.observers)
this.observers[observerKey]._key = value;
if (value != null && ((_a = this.persistent) === null || _a === void 0 ? void 0 : _a._key) === oldKey)
(_b = this.persistent) === null || _b === void 0 ? void 0 : _b.setKey(value);
return this;
}
set(value, config = {}) {
config = defineConfig(config, {
force: false,
});
const _value = isFunction(value)
? value(copy(this._value))
: value;
this.observers['value'].ingestValue(_value, config);
return this;
}
ingest(config = {}) {
this.observers['value'].ingest(config);
return this;
}
undo(config = {}) {
this.set(this.previousStateValue, config);
return this;
}
reset(config = {}) {
this.set(this.initialStateValue, config);
return this;
}
patch(targetWithChanges, config = {}) {
config = defineConfig(config, {
addNewProperties: true,
});
if (!isValidObject(this.nextStateValue, true)) {
LogCodeManager.log('14:03:02');
return this;
}
if (!isValidObject(targetWithChanges, true)) {
LogCodeManager.log('00:03:01', ['TargetWithChanges', 'object']);
return this;
}
if (Array.isArray(targetWithChanges) &&
Array.isArray(this.nextStateValue)) {
this.nextStateValue = [
...this.nextStateValue,
...targetWithChanges,
];
}
else {
this.nextStateValue = flatMerge(this.nextStateValue, targetWithChanges, { addNewProperties: config.addNewProperties });
}
this.ingest(removeProperties(config, ['addNewProperties']));
return this;
}
watch(keyOrCallback, callback) {
const generateKey = isFunction(keyOrCallback);
let _callback;
let key;
if (generateKey) {
key = generateId();
_callback = keyOrCallback;
}
else {
key = keyOrCallback;
_callback = callback;
}
if (!isFunction(_callback)) {
LogCodeManager.log('00:03:01', ['Watcher Callback', 'function']);
return this;
}
this.addSideEffect(key, (instance) => {
_callback(instance.value, key);
}, { weight: 0 });
return generateKey ? key : this;
}
removeWatcher(key) {
this.removeSideEffect(key);
return this;
}
onInaugurated(callback) {
const watcherKey = 'InauguratedWatcherKey';
this.watch(watcherKey, (value, key) => {
callback(value, key);
this.removeSideEffect(watcherKey);
});
return this;
}
persist(keyOrConfig = {}, config = {}) {
let _config;
let key;
if (isValidObject(keyOrConfig)) {
_config = keyOrConfig;
key = this._key;
}
else {
_config = config || {};
key = keyOrConfig;
}
_config = defineConfig(_config, {
loadValue: true,
storageKeys: [],
defaultStorageKey: null,
});
if (this.persistent != null && this.isPersisted)
return this;
this.persistent = new StatePersistent(this, {
instantiate: _config.loadValue,
storageKeys: _config.storageKeys,
key: key,
defaultStorageKey: _config.defaultStorageKey,
});
return this;
}
onLoad(callback) {
if (!this.persistent)
return this;
if (!isFunction(callback)) {
LogCodeManager.log('00:03:01', ['OnLoad Callback', 'function']);
return this;
}
this.persistent.onLoad = callback;
if (this.isPersisted)
callback(true);
return this;
}
interval(handler, delay) {
if (!isFunction(handler)) {
LogCodeManager.log('00:03:01', ['Interval Callback', 'function']);
return this;
}
if (this.currentInterval) {
LogCodeManager.log('14:03:03', [], this.currentInterval);
return this;
}
this.currentInterval = setInterval(() => {
this.set(handler(this._value));
}, delay !== null && delay !== void 0 ? delay : 1000);
return this;
}
clearInterval() {
if (this.currentInterval) {
clearInterval(this.currentInterval);
delete this.currentInterval;
}
}
get exists() {
return !this.isPlaceholder && this.computeExistsMethod(this.value);
}
computeExists(method) {
if (!isFunction(method)) {
LogCodeManager.log('00:03:01', ['Compute Exists Method', 'function']);
return this;
}
this.computeExistsMethod = method;
return this;
}
computeValue(method) {
if (!isFunction(method)) {
LogCodeManager.log('00:03:01', ['Compute Value Method', 'function']);
return this;
}
this.computeValueMethod = method;
this.set(this.nextStateValue);
return this;
}
is(value) {
return equal(value, this.value);
}
isNot(value) {
return notEqual(value, this.value);
}
invert() {
switch (typeof this.nextStateValue) {
case 'boolean':
this.set(!this.nextStateValue);
break;
case 'object':
if (Array.isArray(this.nextStateValue))
this.set(this.nextStateValue.reverse());
break;
case 'string':
this.set(this.nextStateValue.split('').reverse().join(''));
break;
case 'number':
this.set((this.nextStateValue * -1));
break;
default:
LogCodeManager.log('14:03:04', [typeof this.nextStateValue]);
}
return this;
}
addSideEffect(key, callback, config = {}) {
config = defineConfig(config, {
weight: 10,
});
if (!isFunction(callback)) {
LogCodeManager.log('00:03:01', ['Side Effect Callback', 'function']);
return this;
}
this.sideEffects[key] = {
callback: callback,
weight: config.weight,
};
return this;
}
removeSideEffect(key) {
delete this.sideEffects[key];
return this;
}
hasSideEffect(key) {
return !!this.sideEffects[key];
}
getPersistableValue() {
return this._value;
}
import { State, defineConfig, removeProperties, shared, } from '../internal';
export * from './state';
export function createState(initialValue, config = {}) {
config = defineConfig(config, {
agileInstance: shared,
});
return new State(config.agileInstance, initialValue, removeProperties(config, ['agileInstance']));
}

@@ -1,129 +0,5 @@

import { Storage, notEqual, LogCodeManager, defineConfig, } from '../internal';
export class Storages {
constructor(agileInstance, config = {}) {
this.storages = {};
this.persistentInstances = new Set();
this.agileInstance = () => agileInstance;
config = defineConfig(config, {
localStorage: false,
defaultStorageKey: null,
});
this.config = { defaultStorageKey: config.defaultStorageKey };
if (config.localStorage)
this.instantiateLocalStorage();
}
instantiateLocalStorage() {
if (!Storages.localStorageAvailable()) {
LogCodeManager.log('11:02:00');
return false;
}
const _localStorage = new Storage({
key: 'localStorage',
async: false,
methods: {
get: localStorage.getItem.bind(localStorage),
set: localStorage.setItem.bind(localStorage),
remove: localStorage.removeItem.bind(localStorage),
},
});
return this.register(_localStorage, { default: true });
}
register(storage, config = {}) {
const hasRegisteredAnyStorage = notEqual(this.storages, {});
if (Object.prototype.hasOwnProperty.call(this.storages, storage.key)) {
LogCodeManager.log('11:03:00', [storage.key]);
return false;
}
if (!hasRegisteredAnyStorage && config.default === false)
LogCodeManager.log('11:02:01');
if (!hasRegisteredAnyStorage)
config.default = true;
this.storages[storage.key] = storage;
if (config.default)
this.config.defaultStorageKey = storage.key;
this.persistentInstances.forEach((persistent) => {
if (persistent.storageKeys.includes(storage.key)) {
const isValid = persistent.validatePersistent();
if (isValid)
persistent.initialLoading();
return;
}
if (persistent.config.defaultStorageKey == null) {
persistent.assignStorageKeys();
const isValid = persistent.validatePersistent();
if (isValid)
persistent.initialLoading();
}
});
LogCodeManager.log('13:00:00', [storage.key], storage);
return true;
}
getStorage(storageKey) {
if (!storageKey)
return undefined;
const storage = this.storages[storageKey];
if (!storage) {
LogCodeManager.log('11:03:01', [storageKey]);
return undefined;
}
if (!storage.ready) {
LogCodeManager.log('11:03:02', [storageKey]);
return undefined;
}
return storage;
}
get(storageItemKey, storageKey) {
if (!this.hasStorage()) {
LogCodeManager.log('11:03:03');
return Promise.resolve(undefined);
}
if (storageKey) {
const storage = this.getStorage(storageKey);
if (storage)
return storage.get(storageItemKey);
}
const defaultStorage = this.getStorage(this.config.defaultStorageKey);
return ((defaultStorage === null || defaultStorage === void 0 ? void 0 : defaultStorage.get(storageItemKey)) || Promise.resolve(undefined));
}
set(storageItemKey, value, storageKeys) {
var _a;
if (!this.hasStorage()) {
LogCodeManager.log('11:03:04');
return;
}
if (storageKeys != null) {
for (const storageKey of storageKeys)
(_a = this.getStorage(storageKey)) === null || _a === void 0 ? void 0 : _a.set(storageItemKey, value);
return;
}
const defaultStorage = this.getStorage(this.config.defaultStorageKey);
defaultStorage === null || defaultStorage === void 0 ? void 0 : defaultStorage.set(storageItemKey, value);
}
remove(storageItemKey, storageKeys) {
var _a;
if (!this.hasStorage()) {
LogCodeManager.log('11:03:05');
return;
}
if (storageKeys) {
for (const storageKey of storageKeys)
(_a = this.getStorage(storageKey)) === null || _a === void 0 ? void 0 : _a.remove(storageItemKey);
return;
}
const defaultStorage = this.getStorage(this.config.defaultStorageKey);
defaultStorage === null || defaultStorage === void 0 ? void 0 : defaultStorage.remove(storageItemKey);
}
hasStorage() {
return notEqual(this.storages, {});
}
static localStorageAvailable() {
try {
localStorage.setItem('_myDummyKey_', 'myDummyValue');
localStorage.removeItem('_myDummyKey_');
return true;
}
catch (e) {
return false;
}
}
import { Storage } from '../internal';
export * from './storages';
export function createStorage(config) {
return new Storage(config);
}

@@ -1,67 +0,1 @@

import { Agile, Integration } from '../internal';
export declare class Integrations {
agileInstance: () => Agile;
integrations: Set<Integration>;
static initialIntegrations: Integration[];
/**
* Registers the specified Integration in each existing or not-yet created Agile Instance.
*
* @public
* @param integration - Integration to be registered in each Agile Instance.
*/
static addInitialIntegration(integration: Integration): void;
/**
* Fires on each external added Integration.
*
* @public
* @param callback - Callback to be fired when an Integration was externally added.
*/
static onRegisterInitialIntegration(callback: (integration: Integration) => void): void;
/**
* The Integrations Class manages all Integrations for an Agile Instance
* and provides an interface to easily update
* and invoke functions in all registered Integrations.
*
* @internal
* @param agileInstance - Instance of Agile the Integrations belongs to.
* @param config - Configuration object
*/
constructor(agileInstance: Agile, config?: IntegrationsConfigInterface);
/**
* Integrates the specified Integration into AgileTs
* and sets it to ready when the binding was successful.
*
* @public
* @param integration - Integration to be integrated into AgileTs.
*/
integrate(integration: Integration): Promise<boolean>;
/**
* Updates the specified UI-Component Instance
* with the updated data object in all registered Integrations that are ready.
*
* In doing so, it calls the `updateMethod()` method
* in all registered Integrations with the specified parameters.
*
* @public
* @param componentInstance - Component Instance to be updated.
* @param updatedData - Data object with updated data.
*/
update(componentInstance: any, updatedData: Object): void;
/**
* Returns a boolean indicating whether any Integration
* has been registered with the Agile Instance or not.
*
* @public
*/
hasIntegration(): boolean;
}
export interface IntegrationsConfigInterface {
/**
* Whether external added Integrations
* are to integrate automatically into the Integrations Class.
* For example, when the package '@agile-ts/react' was installed,
* whether to automatically integrate the 'reactIntegration'.
* @default true
*/
autoIntegrate?: boolean;
}
export * from './integrations';
"use strict";
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
return new (P || (P = Promise))(function (resolve, reject) {
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
step((generator = generator.apply(thisArg, _arguments || [])).next());
});
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
Object.defineProperty(o, k2, { enumerable: true, get: function() { return m[k]; } });
}) : (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
o[k2] = m[k];
}));
var __exportStar = (this && this.__exportStar) || function(m, exports) {
for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.Integrations = void 0;
const internal_1 = require("../internal");
const onRegisterInitialIntegrationCallbacks = [];
class Integrations {
constructor(agileInstance, config = {}) {
this.integrations = new Set();
config = internal_1.defineConfig(config, {
autoIntegrate: true,
});
this.agileInstance = () => agileInstance;
if (config.autoIntegrate) {
Integrations.onRegisterInitialIntegration((integration) => {
this.integrate(integration);
});
}
}
static addInitialIntegration(integration) {
if (integration instanceof internal_1.Integration) {
onRegisterInitialIntegrationCallbacks.forEach((callback) => callback(integration));
Integrations.initialIntegrations.push(integration);
}
}
static onRegisterInitialIntegration(callback) {
onRegisterInitialIntegrationCallbacks.push(callback);
Integrations.initialIntegrations.forEach((integration) => {
callback(integration);
});
}
integrate(integration) {
return __awaiter(this, void 0, void 0, function* () {
if (integration._key == null) {
internal_1.LogCodeManager.log('18:03:00', [integration._key, this.agileInstance().key], integration);
return false;
}
if (integration.methods.bind)
integration.ready = yield integration.methods.bind(this.agileInstance());
else
integration.ready = true;
this.integrations.add(integration);
integration.integrated = true;
internal_1.LogCodeManager.log('18:00:00', [integration._key, this.agileInstance().key], integration);
return true;
});
}
update(componentInstance, updatedData) {
this.integrations.forEach((integration) => {
if (!integration.ready) {
internal_1.LogCodeManager.log('18:02:00', [integration._key]);
return;
}
if (integration.methods.updateMethod)
integration.methods.updateMethod(componentInstance, updatedData);
});
}
hasIntegration() {
return this.integrations.size > 0;
}
}
exports.Integrations = Integrations;
Integrations.initialIntegrations = [];
__exportStar(require("./integrations"), exports);

@@ -1,3 +0,8 @@

export declare let loggerPackage: any;
declare const logCodeMessages: {
declare const logCodeTypes: {
'00': string;
'01': string;
'02': string;
'03': string;
};
declare const niceLogCodeMessages: {
'10:00:00': string;

@@ -64,2 +69,3 @@ '10:02:00': string;

};
declare const logCodeMessages: typeof niceLogCodeMessages;
/**

@@ -97,79 +103,7 @@ * Returns the log message according to the specified log code.

declare function logIfTags<T extends LogCodesArrayType<typeof logCodeMessages>>(tags: string[], logCode: T, replacers?: any[], ...data: any[]): void;
/**
* The Log Code Manager keeps track
* and manages all important Logs of AgileTs.
*
* @internal
*/
export declare const LogCodeManager: {
getLog: typeof getLog;
log: typeof log;
logCodeLogTypes: {
'00': string;
'01': string;
'02': string;
'03': string;
};
logCodeMessages: {
'10:00:00': string;
'10:02:00': string;
'11:02:00': string;
'11:02:01': string;
'11:03:00': string;
'11:03:01': string;
'11:03:02': string;
'11:03:03': string;
'11:03:04': string;
'11:03:05': string;
'12:03:00': string;
'12:03:01': string;
'12:03:02': string;
'13:00:00': string;
'13:01:00': string;
'13:01:01': string;
'13:01:02': string;
'13:02:00': string;
'13:03:00': string;
'14:03:01': string;
'14:03:02': string;
'14:03:03': string;
'14:03:04': string;
'15:01:00': string;
'15:01:01': string;
'15:01:02': string;
'15:01:03': string;
'16:01:00': string;
'16:01:01': string;
'16:01:02': string;
'16:02:00': string;
'16:02:01': string;
'17:03:00': string;
'18:00:00': string;
'18:02:00': string;
'18:03:00': string;
'19:03:00': string;
'1A:02:00': string;
'1A:02:01': string;
'1B:02:00': string;
'1B:02:01': string;
'1B:02:02': string;
'1B:02:03': string;
'1B:02:04': string;
'1B:02:05': string;
'1B:03:00': string;
'1B:03:01': string;
'1B:03:02': string;
'1B:03:03': string;
'1B:03:04': string;
'1B:03:05': string;
'1B:03:06': string;
'1C:02:00': string;
'1C:03:00': string;
'1C:03:01': string;
'20:03:00': string;
'20:03:01': string;
'20:03:02': string;
'00:03:00': string;
'00:03:01': string;
};
logCodeLogTypes: typeof logCodeTypes;
logCodeMessages: typeof logCodeMessages;
getLogger: () => any;

@@ -176,0 +110,0 @@ logIfTags: typeof logIfTags;

"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.LogCodeManager = exports.loggerPackage = void 0;
exports.loggerPackage = null;
try {
exports.loggerPackage = require('@agile-ts/logger');
}
catch (e) {
}
exports.LogCodeManager = void 0;
const logCodeTypes = {

@@ -16,3 +10,3 @@ '00': 'success',

};
const logCodeMessages = {
const niceLogCodeMessages = {
'10:00:00': 'Created new AgileInstance.',

@@ -97,5 +91,9 @@ '10:02:00': 'Be careful when binding multiple Agile Instances globally in one application!',

};
const logCodeMessages = typeof process === 'object' && process.env.NODE_ENV !== 'production'
? niceLogCodeMessages
: {};
function getLog(logCode, replacers = []) {
var _a;
let result = (_a = logCodeMessages[logCode]) !== null && _a !== void 0 ? _a : `'${logCode}' is a unknown logCode!`;
let result = logCodeMessages[logCode];
if (result == null)
return logCode;
for (let i = 0; i < replacers.length; i++) {

@@ -132,12 +130,35 @@ result = result.replace('${' + i + '}', replacers[i]);

}
exports.LogCodeManager = {
getLog,
log,
logCodeLogTypes: logCodeTypes,
logCodeMessages: logCodeMessages,
getLogger: () => {
var _a;
return (_a = exports.loggerPackage === null || exports.loggerPackage === void 0 ? void 0 : exports.loggerPackage.sharedAgileLogger) !== null && _a !== void 0 ? _a : null;
},
logIfTags,
};
let tempLogCodeManager;
if (typeof process === 'object' && process.env.NODE_ENV !== 'production') {
tempLogCodeManager = {
getLog,
log,
logCodeLogTypes: logCodeTypes,
logCodeMessages: logCodeMessages,
getLogger: () => {
var _a;
let loggerPackage = null;
try {
loggerPackage = require('@agile-ts/logger');
}
catch (e) {
}
return (_a = loggerPackage === null || loggerPackage === void 0 ? void 0 : loggerPackage.sharedAgileLogger) !== null && _a !== void 0 ? _a : null;
},
logIfTags,
};
}
else {
tempLogCodeManager = {
getLog: (logCode, replacers) => logCode,
log,
logCodeLogTypes: logCodeTypes,
logCodeMessages: logCodeMessages,
getLogger: () => {
return null;
},
logIfTags: (tags, logCode, replacers) => {
},
};
}
exports.LogCodeManager = tempLogCodeManager;

@@ -1,120 +0,1 @@

/// <reference types="node" />
import { Agile, SubscriptionContainer, RuntimeJob } from '../internal';
export declare class Runtime {
agileInstance: () => Agile;
currentJob: RuntimeJob | null;
jobQueue: Array<RuntimeJob>;
jobsToRerender: Array<RuntimeJob>;
notReadyJobsToRerender: Set<RuntimeJob>;
isPerformingJobs: boolean;
bucketTimeout: NodeJS.Timeout | null;
/**
* The Runtime queues and executes incoming Observer-based Jobs
* to prevent [race conditions](https://en.wikipedia.org/wiki/Race_condition#:~:text=A%20race%20condition%20or%20race,the%20possible%20behaviors%20is%20undesirable.)
* and optimized the re-rendering of the Observer's subscribed UI-Components.
*
* Each queued Job is executed when it is its turn
* by calling the Job Observer's `perform()` method.
*
* After successful execution, the Job is added to a re-render queue,
* which is first put into the browser's 'Bucket' and started to work off
* when resources are left.
*
* The re-render queue is designed for optimizing the render count
* by batching multiple re-render Jobs of the same UI-Component
* and ignoring re-render requests for unmounted UI-Components.
*
* @internal
* @param agileInstance - Instance of Agile the Runtime belongs to.
*/
constructor(agileInstance: Agile);
/**
* Adds the specified Observer-based Job to the internal Job queue,
* where it is executed when it is its turn.
*
* After successful execution, the Job is assigned to the re-render queue,
* where all the Observer's subscribed Subscription Containers (UI-Components)
* are updated (re-rendered).
*
* @public
* @param job - Job to be added to the Job queue.
* @param config - Configuration object
*/
ingest(job: RuntimeJob, config?: IngestConfigInterface): void;
/**
* Performs the specified Job
* and assigns it to the re-render queue if necessary.
*
* After the execution of the provided Job, it is checked whether
* there are still Jobs left in the Job queue.
* - If so, the next Job in the `jobQueue` is performed.
* - If not, the `jobsToRerender` queue is started to work off.
*
* @internal
* @param job - Job to be performed.
*/
perform(job: RuntimeJob): void;
/**
* Processes the `jobsToRerender` queue by updating (causing a re-render on)
* the subscribed Subscription Containers (UI-Components) of each Job Observer.
*
* It returns a boolean indicating whether
* any Subscription Container (UI-Component) was updated (re-rendered) or not.
*
* @internal
*/
updateSubscribers(): boolean;
/**
* Extracts the Subscription Containers (UI-Components)
* to be updated (re-rendered) from the specified Runtime Jobs.
*
* @internal
* @param jobs - Jobs from which to extract the Subscription Containers to be updated.
*/
extractToUpdateSubscriptionContainer(jobs: Array<RuntimeJob>): Array<SubscriptionContainer>;
/**
* Updates the specified Subscription Containers.
*
* Updating a Subscription Container triggers a re-render
* on the Component it represents, based on the type of the Subscription Containers.
*
* @internal
* @param subscriptionsToUpdate - Subscription Containers to be updated.
*/
updateSubscriptionContainer(subscriptionsToUpdate: Array<SubscriptionContainer>): void;
/**
* Maps the values of the updated Observers (`updatedSubscribers`)
* of the specified Subscription Container into a key map object.
*
* The key containing the Observer value is extracted from the Observer itself
* or from the Subscription Container's `subscriberKeysWeakMap`.
*
* @internal
* @param subscriptionContainer - Subscription Container from which the `updatedSubscribers` are to be mapped into a key map.
*/
getUpdatedObserverValues(subscriptionContainer: SubscriptionContainer): {
[key: string]: any;
};
/**
* Returns a boolean indicating whether the specified Subscription Container can be updated or not,
* based on its selector functions (`selectorsWeakMap`).
*
* This is done by checking the '.value' and the '.previousValue' property of the Observer represented by the Job.
* If a selected property differs, the Subscription Container (UI-Component) is allowed to update (re-render)
* and `true` is returned.
*
* If the Subscription Container has no selector function at all, `true` is returned.
*
* @internal
* @param subscriptionContainer - Subscription Container to be checked if it can be updated.
* @param job - Job containing the Observer that is subscribed to the Subscription Container.
*/
handleSelectors(subscriptionContainer: SubscriptionContainer, job: RuntimeJob): boolean;
}
export interface IngestConfigInterface {
/**
* Whether the ingested Job should be performed immediately
* or added to the queue first and then executed when it is his turn.
*/
perform?: boolean;
}
export * from './runtime';
"use strict";
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
Object.defineProperty(o, k2, { enumerable: true, get: function() { return m[k]; } });
}) : (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
o[k2] = m[k];
}));
var __exportStar = (this && this.__exportStar) || function(m, exports) {
for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.Runtime = void 0;
const internal_1 = require("../internal");
class Runtime {
constructor(agileInstance) {
this.currentJob = null;
this.jobQueue = [];
this.jobsToRerender = [];
this.notReadyJobsToRerender = new Set();
this.isPerformingJobs = false;
this.bucketTimeout = null;
this.agileInstance = () => agileInstance;
}
ingest(job, config = {}) {
config = internal_1.defineConfig(config, {
perform: !this.isPerformingJobs,
});
this.jobQueue.push(job);
internal_1.LogCodeManager.logIfTags(['runtime'], '16:01:00', [job._key], job);
if (config.perform) {
const performJob = this.jobQueue.shift();
if (performJob)
this.perform(performJob);
}
}
perform(job) {
this.isPerformingJobs = true;
this.currentJob = job;
job.observer.perform(job);
job.performed = true;
job.observer.dependents.forEach((observer) => observer.ingest());
if (job.rerender)
this.jobsToRerender.push(job);
this.currentJob = null;
internal_1.LogCodeManager.logIfTags(['runtime'], '16:01:01', [job._key], job);
if (this.jobQueue.length > 0) {
const performJob = this.jobQueue.shift();
if (performJob)
this.perform(performJob);
}
else {
this.isPerformingJobs = false;
if (this.jobsToRerender.length > 0) {
if (this.agileInstance().config.bucket) {
if (this.bucketTimeout == null) {
this.bucketTimeout = setTimeout(() => {
this.bucketTimeout = null;
this.updateSubscribers();
});
}
}
else
this.updateSubscribers();
}
}
}
updateSubscribers() {
const jobsToRerender = this.jobsToRerender.concat(Array.from(this.notReadyJobsToRerender));
this.notReadyJobsToRerender = new Set();
this.jobsToRerender = [];
if (!this.agileInstance().hasIntegration() || jobsToRerender.length <= 0)
return false;
const subscriptionContainerToUpdate = this.extractToUpdateSubscriptionContainer(jobsToRerender);
if (subscriptionContainerToUpdate.length <= 0)
return false;
this.updateSubscriptionContainer(subscriptionContainerToUpdate);
return true;
}
extractToUpdateSubscriptionContainer(jobs) {
const subscriptionsToUpdate = new Set();
for (let i = 0; i < jobs.length; i++) {
const job = jobs[i];
job.subscriptionContainersToUpdate.forEach((subscriptionContainer) => {
let updateSubscriptionContainer = true;
if (!subscriptionContainer.ready) {
if (!job.config.maxTriesToUpdate ||
job.timesTriedToUpdateCount < job.config.maxTriesToUpdate) {
job.timesTriedToUpdateCount++;
this.notReadyJobsToRerender.add(job);
internal_1.LogCodeManager.log('16:02:00', [subscriptionContainer.key], subscriptionContainer);
}
else {
internal_1.LogCodeManager.log('16:02:01', [job.config.maxTriesToUpdate], subscriptionContainer);
}
return;
}
updateSubscriptionContainer =
updateSubscriptionContainer &&
this.handleSelectors(subscriptionContainer, job);
if (updateSubscriptionContainer) {
subscriptionContainer.updatedSubscribers.add(job.observer);
subscriptionsToUpdate.add(subscriptionContainer);
}
job.subscriptionContainersToUpdate.delete(subscriptionContainer);
});
}
return Array.from(subscriptionsToUpdate);
}
updateSubscriptionContainer(subscriptionsToUpdate) {
for (let i = 0; i < subscriptionsToUpdate.length; i++) {
const subscriptionContainer = subscriptionsToUpdate[i];
if (subscriptionContainer instanceof internal_1.CallbackSubscriptionContainer)
subscriptionContainer.callback();
if (subscriptionContainer instanceof internal_1.ComponentSubscriptionContainer)
this.agileInstance().integrations.update(subscriptionContainer.component, this.getUpdatedObserverValues(subscriptionContainer));
subscriptionContainer.updatedSubscribers.clear();
}
internal_1.LogCodeManager.logIfTags(['runtime'], '16:01:02', [], subscriptionsToUpdate);
}
getUpdatedObserverValues(subscriptionContainer) {
var _a;
const props = {};
for (const observer of subscriptionContainer.updatedSubscribers) {
const key = (_a = subscriptionContainer.subscriberKeysWeakMap.get(observer)) !== null && _a !== void 0 ? _a : observer.key;
if (key != null)
props[key] = observer.value;
}
return props;
}
handleSelectors(subscriptionContainer, job) {
var _a;
const selectorMethods = (_a = subscriptionContainer.selectorsWeakMap.get(job.observer)) === null || _a === void 0 ? void 0 : _a.methods;
if (selectorMethods == null)
return true;
const previousValue = job.observer.previousValue;
const newValue = job.observer.value;
for (const selectorMethod of selectorMethods) {
if (internal_1.notEqual(selectorMethod(newValue), selectorMethod(previousValue)))
return true;
}
return false;
}
}
exports.Runtime = Runtime;
__exportStar(require("./runtime"), exports);

@@ -1,2 +0,2 @@

import { Agile, Collection, CollectionConfig, Computed, ComputeFunctionType, CreateComputedConfigInterface, CreateStorageConfigInterface, DefaultItem, DependableAgileInstancesType, State, StateConfigInterface, Storage } from './internal';
import { Agile } from './internal';
/**

@@ -13,96 +13,2 @@ * Shared Agile Instance that is used when no Agile Instance was specified.

export declare function assignSharedAgileInstance(agileInstance: Agile): void;
/**
* Returns a newly created Storage.
*
* A Storage Class serves as an interface to external storages,
* such as the [Async Storage](https://github.com/react-native-async-storage/async-storage) or
* [Local Storage](https://www.w3schools.com/html/html5_webstorage.asp).
*
* It creates the foundation to easily [`persist()`](https://agile-ts.org/docs/core/state/methods#persist) [Agile Sub Instances](https://agile-ts.org/docs/introduction/#agile-sub-instance)
* (like States or Collections) in nearly any external storage.
*
* [Learn more..](https://agile-ts.org/docs/core/agile-instance/methods#createstorage)
*
* @public
* @param config - Configuration object
*/
export declare function createStorage(config: CreateStorageConfigInterface): Storage;
/**
* Returns a newly created State.
*
* A State manages a piece of Information
* that we need to remember globally at a later point in time.
* While providing a toolkit to use and mutate this piece of Information.
*
* You can create as many global States as you need.
*
* [Learn more..](https://agile-ts.org/docs/core/agile-instance/methods#createstate)
*
* @public
* @param initialValue - Initial value of the State.
* @param config - Configuration object
*/
export declare function createState<ValueType = any>(initialValue: ValueType, config?: CreateStateConfigInterfaceWithAgile): State<ValueType>;
/**
* Returns a newly created Computed.
*
* A Computed is an extension of the State Class
* that computes its value based on a specified compute function.
*
* The computed value will be cached to avoid unnecessary recomputes
* and is only recomputed when one of its direct dependencies changes.
*
* Direct dependencies can be States and Collections.
* So when, for example, a dependent State value changes, the computed value is recomputed.
*
* [Learn more..](https://agile-ts.org/docs/core/agile-instance/methods#createstate)
*
* @public
* @param computeFunction - Function to compute the computed value.
* @param config - Configuration object
*/
export declare function createComputed<ComputedValueType = any>(computeFunction: ComputeFunctionType<ComputedValueType>, config?: CreateComputedConfigInterfaceWithAgile): Computed<ComputedValueType>;
/**
* Returns a newly created Computed.
*
* A Computed is an extension of the State Class
* that computes its value based on a specified compute function.
*
* The computed value will be cached to avoid unnecessary recomputes
* and is only recomputed when one of its direct dependencies changes.
*
* Direct dependencies can be States and Collections.
* So when, for example, a dependent State value changes, the computed value is recomputed.
*
* [Learn more..](https://agile-ts.org/docs/core/agile-instance/methods#createcomputed)
*
* @public
* @param computeFunction - Function to compute the computed value.
* @param deps - Hard-coded dependencies on which the Computed Class should depend.
*/
export declare function createComputed<ComputedValueType = any>(computeFunction: ComputeFunctionType<ComputedValueType>, deps?: Array<DependableAgileInstancesType>): Computed<ComputedValueType>;
/**
* Returns a newly created Collection.
*
* A Collection manages a reactive set of Information
* that we need to remember globally at a later point in time.
* While providing a toolkit to use and mutate this set of Information.
*
* It is designed for arrays of data objects following the same pattern.
*
* Each of these data object must have a unique `primaryKey` to be correctly identified later.
*
* You can create as many global Collections as you need.
*
* [Learn more..](https://agile-ts.org/docs/core/agile-instance/methods#createcollection)
*
* @public
* @param config - Configuration object
* @param agileInstance - Instance of Agile the Collection belongs to.
*/
export declare function createCollection<DataType extends Object = DefaultItem>(config?: CollectionConfig<DataType>, agileInstance?: Agile): Collection<DataType>;
export interface CreateComputedConfigInterfaceWithAgile extends CreateAgileSubInstanceInterface, CreateComputedConfigInterface {
}
export interface CreateStateConfigInterfaceWithAgile extends CreateAgileSubInstanceInterface, StateConfigInterface {
}
export interface CreateAgileSubInstanceInterface {

@@ -109,0 +15,0 @@ /**

"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.createCollection = exports.createComputed = exports.createState = exports.createStorage = exports.assignSharedAgileInstance = exports.shared = void 0;
exports.assignSharedAgileInstance = exports.shared = void 0;
const internal_1 = require("./internal");

@@ -14,31 +14,1 @@ let sharedAgileInstance = new internal_1.Agile({

exports.assignSharedAgileInstance = assignSharedAgileInstance;
function createStorage(config) {
return new internal_1.Storage(config);
}
exports.createStorage = createStorage;
function createState(initialValue, config = {}) {
config = internal_1.defineConfig(config, {
agileInstance: sharedAgileInstance,
});
return new internal_1.State(config.agileInstance, initialValue, internal_1.removeProperties(config, ['agileInstance']));
}
exports.createState = createState;
function createComputed(computeFunction, configOrDeps) {
let _config = {};
if (Array.isArray(configOrDeps)) {
_config = internal_1.defineConfig(_config, {
computedDeps: configOrDeps,
});
}
else {
if (configOrDeps)
_config = configOrDeps;
}
_config = internal_1.defineConfig(_config, { agileInstance: sharedAgileInstance });
return new internal_1.Computed(_config.agileInstance, computeFunction, internal_1.removeProperties(_config, ['agileInstance']));
}
exports.createComputed = createComputed;
function createCollection(config, agileInstance = sharedAgileInstance) {
return new internal_1.Collection(agileInstance, config);
}
exports.createCollection = createCollection;

@@ -1,429 +0,20 @@

/// <reference types="node" />
import { Agile, StorageKey, StateObserver, StatePersistent, Observer, PersistentKey, StateIngestConfigInterface } from '../internal';
export declare class State<ValueType = any> {
agileInstance: () => Agile;
_key?: StateKey;
isSet: boolean;
isPlaceholder: boolean;
initialStateValue: ValueType;
_value: ValueType;
previousStateValue: ValueType;
nextStateValue: ValueType;
observers: StateObserversInterface<ValueType>;
sideEffects: {
[key: string]: SideEffectInterface<State<ValueType>>;
};
computeValueMethod?: ComputeValueMethod<ValueType>;
computeExistsMethod: ComputeExistsMethod<ValueType>;
isPersisted: boolean;
persistent: StatePersistent | undefined;
currentInterval?: NodeJS.Timer | number;
/**
* A State manages a piece of Information
* that we need to remember globally at a later point in time.
* While providing a toolkit to use and mutate this piece of Information.
*
* You can create as many global States as you need.
*
* [Learn more..](https://agile-ts.org/docs/core/state/)
*
* @public
* @param agileInstance - Instance of Agile the State belongs to.
* @param initialValue - Initial value of the State.
* @param config - Configuration object
*/
constructor(agileInstance: Agile, initialValue: ValueType, config?: StateConfigInterface);
/**
* Assigns a new value to the State
* and rerenders all subscribed Components.
*
* [Learn more..](https://agile-ts.org/docs/core/state/properties#value)
*
* @public
* @param value - New State value.
*/
set value(value: ValueType);
/**
* Returns a reference-free version of the current State value.
*
* [Learn more..](https://agile-ts.org/docs/core/state/properties#value)
*
* @public
*/
get value(): ValueType;
/**
* Updates the key/name identifier of the State.
*
* [Learn more..](https://agile-ts.org/docs/core/state/properties#key)
*
* @public
* @param value - New key/name identifier.
*/
set key(value: StateKey | undefined);
/**
* Returns the key/name identifier of the State.
*
* [Learn more..](https://agile-ts.org/docs/core/state/properties#key)
*
* @public
*/
get key(): StateKey | undefined;
/**
* Updates the key/name identifier of the State.
*
* [Learn more..](https://agile-ts.org/docs/core/state/methods/#setkey)
*
* @public
* @param value - New key/name identifier.
*/
setKey(value: StateKey | undefined): this;
/**
* Assigns a new value to the State
* and re-renders all subscribed UI-Components.
*
* [Learn more..](https://agile-ts.org/docs/core/state/methods/#set)
*
* @public
* @param value - New State value
* @param config - Configuration object
*/
set(value: ValueType | ((value: ValueType) => ValueType), config?: StateIngestConfigInterface): this;
/**
* Ingests the State without any specified new value into the runtime.
*
* Since no new value was defined either the new State value is computed
* based on a compute method (Computed Class)
* or the `nextStateValue` is taken as the next State value.
*
* [Learn more..](https://agile-ts.org/docs/core/state/methods/#ingest)
*
* @internal
* @param config - Configuration object
*/
ingest(config?: StateIngestConfigInterface): this;
/**
* Undoes the latest State value change.
*
* [Learn more..](https://agile-ts.org/docs/core/state/methods/#undo)
*
* @public
* @param config - Configuration object
*/
undo(config?: StateIngestConfigInterface): this;
/**
* Resets the State value to its initial value.
*
* [Learn more..](https://agile-ts.org/docs/core/state/methods/#reset)
*
* @public
* @param config - Configuration object
*/
reset(config?: StateIngestConfigInterface): this;
/**
* Merges the specified `targetWithChanges` object into the current State value.
* This merge can differ for different value combinations:
* - If the current State value is an `object`, it does a partial update for the object.
* - If the current State value is an `array` and the specified argument is an array too,
* it concatenates the current State value with the value of the argument.
* - If the current State value is neither an `object` nor an `array`, the patch can't be performed.
*
* [Learn more..](https://agile-ts.org/docs/core/state/methods/#patch)
*
* @public
* @param targetWithChanges - Object to be merged into the current State value.
* @param config - Configuration object
*/
patch(targetWithChanges: Object, config?: PatchConfigInterface): this;
/**
* Fires on each State value change.
*
* Returns the key/name identifier of the created watcher callback.
*
* [Learn more..](https://agile-ts.org/docs/core/state/methods/#watch)
*
* @public
* @param callback - A function to be executed on each State value change.
*/
watch(callback: StateWatcherCallback<ValueType>): string;
/**
* Fires on each State value change.
*
* [Learn more..](https://agile-ts.org/docs/core/state/methods/#watch)
*
* @public
* @param key - Key/Name identifier of the watcher callback.
* @param callback - A function to be executed on each State value change.
*/
watch(key: string, callback: StateWatcherCallback<ValueType>): this;
/**
* Removes a watcher callback with the specified key/name identifier from the State.
*
* [Learn more..](https://agile-ts.org/docs/core/state/methods/#removewatcher)
*
* @public
* @param key - Key/Name identifier of the watcher callback to be removed.
*/
removeWatcher(key: string): this;
/**
* Fires on the initial State value assignment and then destroys itself.
*
* [Learn more..](https://agile-ts.org/docs/core/state/methods/#oninaugurated)
*
* @public
* @param callback - A function to be executed after the first State value assignment.
*/
onInaugurated(callback: StateWatcherCallback<ValueType>): this;
/**
* Preserves the State `value` in the corresponding external Storage.
*
* The State key/name is used as the unique identifier for the Persistent.
* If that is not desired or the State has no unique identifier,
* please specify a separate unique identifier for the Persistent.
*
* [Learn more..](https://agile-ts.org/docs/core/state/methods/#persist)
*
* @public
* @param config - Configuration object
*/
persist(config?: StatePersistentConfigInterface): this;
/**
* Preserves the State `value` in the corresponding external Storage.
*
* The specified key is used as the unique identifier for the Persistent.
*
* [Learn more..](https://agile-ts.org/docs/core/state/methods/#persist)
*
* @public
* @param key - Key/Name identifier of Persistent.
* @param config - Configuration object
*/
persist(key?: PersistentKey, config?: StatePersistentConfigInterface): this;
/**
* Fires immediately after the persisted `value`
* is loaded into the State from a corresponding external Storage.
*
* Registering such callback function makes only sense
* when the State is [persisted](https://agile-ts.org/docs/core/state/methods/#persist).
*
* [Learn more..](https://agile-ts.org/docs/core/state/methods/#onload)
*
* @public
* @param callback - A function to be executed after the externally persisted `value` was loaded into the State.
*/
onLoad(callback: (success: boolean) => void): this;
/**
* Repeatedly calls the specified callback function,
* with a fixed time delay between each call.
*
* [Learn more..](https://agile-ts.org/docs/core/state/methods/#interval)
*
* @public
* @param handler - A function to be executed every delay milliseconds.
* @param delay - The time, in milliseconds (thousandths of a second),
* the timer should delay in between executions of the specified function.
*/
interval(handler: (value: ValueType) => ValueType, delay?: number): this;
/**
* Cancels a active timed, repeating action
* which was previously established by a call to `interval()`.
*
* [Learn more..](https://agile-ts.org/docs/core/state/methods/#clearinterval)
*
* @public
*/
clearInterval(): void;
/**
* Returns a boolean indicating whether the State exists.
*
* It calculates the value based on the `computeExistsMethod()`
* and whether the State is a placeholder.
*
* [Learn more..](https://agile-ts.org/docs/core/state/methods/#exists)
*
* @public
*/
get exists(): boolean;
/**
* Defines the method used to compute the existence of the State.
*
* It is retrieved on each `exists()` method call
* to determine whether the State exists or not.
*
* [Learn more..](https://agile-ts.org/docs/core/state/methods/#computeexists)
*
* @public
* @param method - Method to compute the existence of the State.
*/
computeExists(method: ComputeExistsMethod<ValueType>): this;
/**
* Defines the method used to compute the value of the State.
*
* It is retrieved on each State value change,
* in order to compute the new State value
* based on the specified compute method.
*
* [Learn more..](https://agile-ts.org/docs/core/state/methods/#computevalue)
*
* @public
* @param method - Method to compute the value of the State.
*/
computeValue(method: ComputeValueMethod<ValueType>): this;
/**
* Returns a boolean indicating whether the specified value is equal to the current State value.
*
* Equivalent to `===` with the difference that it looks at the value
* and not on the reference in the case of objects.
*
* @public
* @param value - Value to be compared with the current State value.
*/
is(value: ValueType): boolean;
/**
* Returns a boolean indicating whether the specified value is not equal to the current State value.
*
* Equivalent to `!==` with the difference that it looks at the value
* and not on the reference in the case of objects.
*
* @public
* @param value - Value to be compared with the current State value.
*/
isNot(value: ValueType): boolean;
/**
* Inverts the current State value.
*
* Some examples are:
* - `'jeff'` -> `'ffej'`
* - `true` -> `false`
* - `[1, 2, 3]` -> `[3, 2, 1]`
* - `10` -> `-10`
*
* @public
*/
invert(): this;
/**
*
* Registers a `callback` function that is executed in the `runtime`
* as a side effect of State changes.
*
* For example, it is called when the State value changes from 'jeff' to 'hans'.
*
* A typical side effect of a State change
* could be the updating of the external Storage value.
*
* @internal
* @param key - Key/Name identifier of the to register side effect.
* @param callback - Callback function to be fired on each State value change.
* @param config - Configuration object
*/
addSideEffect<Instance extends State<ValueType>>(key: string, callback: SideEffectFunctionType<Instance>, config?: AddSideEffectConfigInterface): this;
/**
* Removes a side effect callback with the specified key/name identifier from the State.
*
* [Learn more..](https://agile-ts.org/docs/core/state/methods/#removesideeffect)
*
* @internal
* @param key - Key/Name identifier of the side effect callback to be removed.
*/
removeSideEffect(key: string): this;
/**
* Returns a boolean indicating whether a side effect callback with the specified `key`
* exists in the State or not.
*
* [Learn more..](https://agile-ts.org/docs/core/state/methods/#hassideeffect)
*
* @internal
* @param key - Key/Name identifier of the side effect callback to be checked for existence.
*/
hasSideEffect(key: string): boolean;
/**
* Returns the persistable value of the State.
*
* @internal
*/
getPersistableValue(): any;
import { State, StateConfigInterface, CreateAgileSubInstanceInterface } from '../internal';
export * from './state';
export interface CreateStateConfigInterfaceWithAgile extends CreateAgileSubInstanceInterface, StateConfigInterface {
}
export declare type StateKey = string | number;
export interface StateObserversInterface<ValueType = any> {
/**
* Observer responsible for the value of the State.
*/
value: StateObserver<ValueType>;
}
export interface StateConfigInterface {
/**
* Key/Name identifier of the State.
* @default undefined
*/
key?: StateKey;
/**
* Observers that depend on the State.
* @default []
*/
dependents?: Array<Observer>;
/**
* Whether the State should be a placeholder
* and therefore should only exist in the background.
* @default false
*/
isPlaceholder?: boolean;
}
export interface PatchConfigInterface extends StateIngestConfigInterface, PatchOptionConfigInterface {
}
export interface PatchOptionConfigInterface {
/**
* Whether to add new properties to the object during the merge.
* @default true
*/
addNewProperties?: boolean;
}
export interface StatePersistentConfigInterface {
/**
* Whether the Persistent should automatically load
* the persisted value into the State after its instantiation.
* @default true
*/
loadValue?: boolean;
/**
* Key/Name identifier of Storages
* in which the State value should be or is persisted.
* @default [`defaultStorageKey`]
*/
storageKeys?: StorageKey[];
/**
* Key/Name identifier of the default Storage of the specified Storage keys.
*
* The State value is loaded from the default Storage by default
* and is only loaded from the remaining Storages (`storageKeys`)
* if the loading from the default Storage failed.
*
* @default first index of the specified Storage keys or the AgileTs default Storage key
*/
defaultStorageKey?: StorageKey;
}
export declare type StateWatcherCallback<T = any> = (value: T, key: string) => void;
export declare type ComputeValueMethod<T = any> = (value: T) => T;
export declare type ComputeExistsMethod<T = any> = (value: T) => boolean;
export declare type SideEffectFunctionType<Instance extends State> = (instance: Instance, properties?: {
[key: string]: any;
}) => void;
export interface SideEffectInterface<Instance extends State> {
/**
* Callback function to be called on every State value change.
* @return () => {}
*/
callback: SideEffectFunctionType<Instance>;
/**
* Weight of the side effect.
* The weight determines the order of execution of the registered side effects.
* The higher the weight, the earlier it is executed.
*/
weight: number;
}
export interface AddSideEffectConfigInterface {
/**
* Weight of the side effect.
* The weight determines the order of execution of the registered side effects.
* The higher the weight, the earlier it is executed.
*/
weight?: number;
}
/**
* Returns a newly created State.
*
* A State manages a piece of Information
* that we need to remember globally at a later point in time.
* While providing a toolkit to use and mutate this piece of Information.
*
* You can create as many global States as you need.
*
* [Learn more..](https://agile-ts.org/docs/core/agile-instance/methods#createstate)
*
* @public
* @param initialValue - Initial value of the State.
* @param config - Configuration object
*/
export declare function createState<ValueType = any>(initialValue: ValueType, config?: CreateStateConfigInterfaceWithAgile): State<ValueType>;
"use strict";
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
Object.defineProperty(o, k2, { enumerable: true, get: function() { return m[k]; } });
}) : (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
o[k2] = m[k];
}));
var __exportStar = (this && this.__exportStar) || function(m, exports) {
for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.State = void 0;
exports.createState = void 0;
const internal_1 = require("../internal");
class State {
constructor(agileInstance, initialValue, config = {}) {
this.isSet = false;
this.isPlaceholder = false;
this.observers = {};
this.sideEffects = {};
this.isPersisted = false;
config = internal_1.defineConfig(config, {
dependents: [],
isPlaceholder: false,
});
this.agileInstance = () => agileInstance;
this._key = config.key;
this.observers['value'] = new internal_1.StateObserver(this, {
key: config.key,
dependents: config.dependents,
});
this.initialStateValue = internal_1.copy(initialValue);
this._value = internal_1.copy(initialValue);
this.previousStateValue = internal_1.copy(initialValue);
this.nextStateValue = internal_1.copy(initialValue);
this.isPlaceholder = true;
this.computeExistsMethod = (v) => {
return v != null;
};
if (!config.isPlaceholder)
this.set(initialValue, { overwrite: true });
}
set value(value) {
this.set(value);
}
get value() {
internal_1.ComputedTracker.tracked(this.observers['value']);
return internal_1.copy(this._value);
}
set key(value) {
this.setKey(value);
}
get key() {
return this._key;
}
setKey(value) {
var _a, _b;
const oldKey = this._key;
this._key = value;
for (const observerKey in this.observers)
this.observers[observerKey]._key = value;
if (value != null && ((_a = this.persistent) === null || _a === void 0 ? void 0 : _a._key) === oldKey)
(_b = this.persistent) === null || _b === void 0 ? void 0 : _b.setKey(value);
return this;
}
set(value, config = {}) {
config = internal_1.defineConfig(config, {
force: false,
});
const _value = internal_1.isFunction(value)
? value(internal_1.copy(this._value))
: value;
this.observers['value'].ingestValue(_value, config);
return this;
}
ingest(config = {}) {
this.observers['value'].ingest(config);
return this;
}
undo(config = {}) {
this.set(this.previousStateValue, config);
return this;
}
reset(config = {}) {
this.set(this.initialStateValue, config);
return this;
}
patch(targetWithChanges, config = {}) {
config = internal_1.defineConfig(config, {
addNewProperties: true,
});
if (!internal_1.isValidObject(this.nextStateValue, true)) {
internal_1.LogCodeManager.log('14:03:02');
return this;
}
if (!internal_1.isValidObject(targetWithChanges, true)) {
internal_1.LogCodeManager.log('00:03:01', ['TargetWithChanges', 'object']);
return this;
}
if (Array.isArray(targetWithChanges) &&
Array.isArray(this.nextStateValue)) {
this.nextStateValue = [
...this.nextStateValue,
...targetWithChanges,
];
}
else {
this.nextStateValue = internal_1.flatMerge(this.nextStateValue, targetWithChanges, { addNewProperties: config.addNewProperties });
}
this.ingest(internal_1.removeProperties(config, ['addNewProperties']));
return this;
}
watch(keyOrCallback, callback) {
const generateKey = internal_1.isFunction(keyOrCallback);
let _callback;
let key;
if (generateKey) {
key = internal_1.generateId();
_callback = keyOrCallback;
}
else {
key = keyOrCallback;
_callback = callback;
}
if (!internal_1.isFunction(_callback)) {
internal_1.LogCodeManager.log('00:03:01', ['Watcher Callback', 'function']);
return this;
}
this.addSideEffect(key, (instance) => {
_callback(instance.value, key);
}, { weight: 0 });
return generateKey ? key : this;
}
removeWatcher(key) {
this.removeSideEffect(key);
return this;
}
onInaugurated(callback) {
const watcherKey = 'InauguratedWatcherKey';
this.watch(watcherKey, (value, key) => {
callback(value, key);
this.removeSideEffect(watcherKey);
});
return this;
}
persist(keyOrConfig = {}, config = {}) {
let _config;
let key;
if (internal_1.isValidObject(keyOrConfig)) {
_config = keyOrConfig;
key = this._key;
}
else {
_config = config || {};
key = keyOrConfig;
}
_config = internal_1.defineConfig(_config, {
loadValue: true,
storageKeys: [],
defaultStorageKey: null,
});
if (this.persistent != null && this.isPersisted)
return this;
this.persistent = new internal_1.StatePersistent(this, {
instantiate: _config.loadValue,
storageKeys: _config.storageKeys,
key: key,
defaultStorageKey: _config.defaultStorageKey,
});
return this;
}
onLoad(callback) {
if (!this.persistent)
return this;
if (!internal_1.isFunction(callback)) {
internal_1.LogCodeManager.log('00:03:01', ['OnLoad Callback', 'function']);
return this;
}
this.persistent.onLoad = callback;
if (this.isPersisted)
callback(true);
return this;
}
interval(handler, delay) {
if (!internal_1.isFunction(handler)) {
internal_1.LogCodeManager.log('00:03:01', ['Interval Callback', 'function']);
return this;
}
if (this.currentInterval) {
internal_1.LogCodeManager.log('14:03:03', [], this.currentInterval);
return this;
}
this.currentInterval = setInterval(() => {
this.set(handler(this._value));
}, delay !== null && delay !== void 0 ? delay : 1000);
return this;
}
clearInterval() {
if (this.currentInterval) {
clearInterval(this.currentInterval);
delete this.currentInterval;
}
}
get exists() {
return !this.isPlaceholder && this.computeExistsMethod(this.value);
}
computeExists(method) {
if (!internal_1.isFunction(method)) {
internal_1.LogCodeManager.log('00:03:01', ['Compute Exists Method', 'function']);
return this;
}
this.computeExistsMethod = method;
return this;
}
computeValue(method) {
if (!internal_1.isFunction(method)) {
internal_1.LogCodeManager.log('00:03:01', ['Compute Value Method', 'function']);
return this;
}
this.computeValueMethod = method;
this.set(this.nextStateValue);
return this;
}
is(value) {
return internal_1.equal(value, this.value);
}
isNot(value) {
return internal_1.notEqual(value, this.value);
}
invert() {
switch (typeof this.nextStateValue) {
case 'boolean':
this.set(!this.nextStateValue);
break;
case 'object':
if (Array.isArray(this.nextStateValue))
this.set(this.nextStateValue.reverse());
break;
case 'string':
this.set(this.nextStateValue.split('').reverse().join(''));
break;
case 'number':
this.set((this.nextStateValue * -1));
break;
default:
internal_1.LogCodeManager.log('14:03:04', [typeof this.nextStateValue]);
}
return this;
}
addSideEffect(key, callback, config = {}) {
config = internal_1.defineConfig(config, {
weight: 10,
});
if (!internal_1.isFunction(callback)) {
internal_1.LogCodeManager.log('00:03:01', ['Side Effect Callback', 'function']);
return this;
}
this.sideEffects[key] = {
callback: callback,
weight: config.weight,
};
return this;
}
removeSideEffect(key) {
delete this.sideEffects[key];
return this;
}
hasSideEffect(key) {
return !!this.sideEffects[key];
}
getPersistableValue() {
return this._value;
}
__exportStar(require("./state"), exports);
function createState(initialValue, config = {}) {
config = internal_1.defineConfig(config, {
agileInstance: internal_1.shared,
});
return new internal_1.State(config.agileInstance, initialValue, internal_1.removeProperties(config, ['agileInstance']));
}
exports.State = State;
exports.createState = createState;

@@ -1,157 +0,18 @@

import { Agile, Storage, Persistent, StorageKey, StorageItemKey } from '../internal';
export declare class Storages {
agileInstance: () => Agile;
config: StoragesConfigInterface;
storages: {
[key: string]: Storage;
};
persistentInstances: Set<Persistent>;
/**
* The Storages Class manages all external Storages for an Agile Instance
* and provides an interface to easily store,
* load and remove values from multiple Storages at once.
*
* @internal
* @param agileInstance - Instance of Agile the Storages belongs to.
* @param config - Configuration object
*/
constructor(agileInstance: Agile, config?: CreateStoragesConfigInterface);
/**
* Instantiates and registers the
* [Local Storage](https://developer.mozilla.org/de/docs/Web/API/Window/localStorage).
*
* Note that the Local Storage is only available in a web environment.
*
* @internal
*/
instantiateLocalStorage(): boolean;
/**
* Registers the specified Storage with AgileTs
* and updates the Persistent Instances that have already attempted
* to use the previously unregistered Storage.
*
* @public
* @param storage - Storage to be registered with AgileTs.
* @param config - Configuration object
*/
register(storage: Storage, config?: RegisterConfigInterface): boolean;
/**
* Retrieves a single Storage with the specified key/name identifier
* from the Storages Class.
*
* If the to retrieve Storage doesn't exist, `undefined` is returned.
*
* @public
* @param storageKey - Key/Name identifier of the Storage.
*/
getStorage(storageKey: StorageKey | undefined | null): Storage | undefined;
/**
* Retrieves the stored value at the specified Storage Item key
* from the defined external Storage (`storageKey`).
*
* When no Storage has been specified,
* the value is retrieved from the default Storage.
*
* @public
* @param storageItemKey - Key/Name identifier of the value to be retrieved.
* @param storageKey - Key/Name identifier of the external Storage
* from which the value is to be retrieved.
*/
get<GetType = any>(storageItemKey: StorageItemKey, storageKey?: StorageKey): Promise<GetType | undefined>;
/**
* Stores or updates the value at the specified Storage Item key
* in the defined external Storages (`storageKeys`).
*
* When no Storage has been specified,
* the value is stored/updated in the default Storage.
*
* @public
* @param storageItemKey - Key/Name identifier of the value to be stored.
* @param value - Value to be stored in an external Storage.
* @param storageKeys - Key/Name identifier of the external Storage
* where the value is to be stored.
*/
set(storageItemKey: StorageItemKey, value: any, storageKeys?: StorageKey[]): void;
/**
* Removes the value at the specified Storage Item key
* from the defined external Storages (`storageKeys`).
*
* When no Storage has been specified,
* the value is removed from the default Storage.
*
* @public
* @param storageItemKey - Key/Name identifier of the value to be removed.
* @param storageKeys - Key/Name identifier of the external Storage
* from which the value is to be removed.
*/
remove(storageItemKey: StorageItemKey, storageKeys?: StorageKey[]): void;
/**
* Returns a boolean indicating whether any Storage
* has been registered with the Agile Instance or not.
*
* @public
*/
hasStorage(): boolean;
/**
* Returns a boolean indication whether the
* [Local Storage](https://developer.mozilla.org/de/docs/Web/API/Window/localStorage)
* is available in the current environment.
*
* @public
*/
static localStorageAvailable(): boolean;
}
export interface CreateStoragesConfigInterface {
/**
* Whether to register the Local Storage by default.
* Note that the Local Storage is only available in a web environment.
* @default false
*/
localStorage?: boolean;
/**
* Key/Name identifier of the default Storage.
*
* The default Storage represents the default Storage of the Storages Class,
* on which executed actions are performed if no specific Storage was specified.
*
* Also, the persisted value is loaded from the default Storage by default,
* since only one persisted value can be applied.
* If the loading of the value from the default Storage failed,
* an attempt is made to load the value from the remaining Storages.
*
* @default undefined
*/
defaultStorageKey?: StorageKey;
}
export interface StoragesConfigInterface {
/**
* Key/Name identifier of the default Storage.
*
* The default Storage represents the default Storage of the Storages Class,
* on which executed actions are performed if no specific Storage was specified.
*
* Also, the persisted value is loaded from the default Storage by default,
* since only one persisted value can be applied.
* If the loading of the value from the default Storage failed,
* an attempt is made to load the value from the remaining Storages.
*
* @default undefined
*/
defaultStorageKey: StorageKey | null;
}
export interface RegisterConfigInterface {
/**
* Whether the to register Storage should become the default Storage.
*
* The default Storage represents the default Storage of the Storages Class,
* on which executed actions are performed if no specific Storage was specified.
*
* Also, the persisted value is loaded from the default Storage by default,
* since only one persisted value can be applied.
* If the loading of the value from the default Storage failed,
* an attempt is made to load the value from the remaining Storages.
*
* @default false
*/
default?: boolean;
}
import { CreateStorageConfigInterface, Storage } from '../internal';
export * from './storages';
/**
* Returns a newly created Storage.
*
* A Storage Class serves as an interface to external storages,
* such as the [Async Storage](https://github.com/react-native-async-storage/async-storage) or
* [Local Storage](https://www.w3schools.com/html/html5_webstorage.asp).
*
* It creates the foundation to easily [`persist()`](https://agile-ts.org/docs/core/state/methods#persist) [Agile Sub Instances](https://agile-ts.org/docs/introduction/#agile-sub-instance)
* (like States or Collections) in nearly any external storage.
*
* [Learn more..](https://agile-ts.org/docs/core/agile-instance/methods#createstorage)
*
* @public
* @param config - Configuration object
*/
export declare function createStorage(config: CreateStorageConfigInterface): Storage;
"use strict";
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
Object.defineProperty(o, k2, { enumerable: true, get: function() { return m[k]; } });
}) : (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
o[k2] = m[k];
}));
var __exportStar = (this && this.__exportStar) || function(m, exports) {
for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.Storages = void 0;
exports.createStorage = void 0;
const internal_1 = require("../internal");
class Storages {
constructor(agileInstance, config = {}) {
this.storages = {};
this.persistentInstances = new Set();
this.agileInstance = () => agileInstance;
config = internal_1.defineConfig(config, {
localStorage: false,
defaultStorageKey: null,
});
this.config = { defaultStorageKey: config.defaultStorageKey };
if (config.localStorage)
this.instantiateLocalStorage();
}
instantiateLocalStorage() {
if (!Storages.localStorageAvailable()) {
internal_1.LogCodeManager.log('11:02:00');
return false;
}
const _localStorage = new internal_1.Storage({
key: 'localStorage',
async: false,
methods: {
get: localStorage.getItem.bind(localStorage),
set: localStorage.setItem.bind(localStorage),
remove: localStorage.removeItem.bind(localStorage),
},
});
return this.register(_localStorage, { default: true });
}
register(storage, config = {}) {
const hasRegisteredAnyStorage = internal_1.notEqual(this.storages, {});
if (Object.prototype.hasOwnProperty.call(this.storages, storage.key)) {
internal_1.LogCodeManager.log('11:03:00', [storage.key]);
return false;
}
if (!hasRegisteredAnyStorage && config.default === false)
internal_1.LogCodeManager.log('11:02:01');
if (!hasRegisteredAnyStorage)
config.default = true;
this.storages[storage.key] = storage;
if (config.default)
this.config.defaultStorageKey = storage.key;
this.persistentInstances.forEach((persistent) => {
if (persistent.storageKeys.includes(storage.key)) {
const isValid = persistent.validatePersistent();
if (isValid)
persistent.initialLoading();
return;
}
if (persistent.config.defaultStorageKey == null) {
persistent.assignStorageKeys();
const isValid = persistent.validatePersistent();
if (isValid)
persistent.initialLoading();
}
});
internal_1.LogCodeManager.log('13:00:00', [storage.key], storage);
return true;
}
getStorage(storageKey) {
if (!storageKey)
return undefined;
const storage = this.storages[storageKey];
if (!storage) {
internal_1.LogCodeManager.log('11:03:01', [storageKey]);
return undefined;
}
if (!storage.ready) {
internal_1.LogCodeManager.log('11:03:02', [storageKey]);
return undefined;
}
return storage;
}
get(storageItemKey, storageKey) {
if (!this.hasStorage()) {
internal_1.LogCodeManager.log('11:03:03');
return Promise.resolve(undefined);
}
if (storageKey) {
const storage = this.getStorage(storageKey);
if (storage)
return storage.get(storageItemKey);
}
const defaultStorage = this.getStorage(this.config.defaultStorageKey);
return ((defaultStorage === null || defaultStorage === void 0 ? void 0 : defaultStorage.get(storageItemKey)) || Promise.resolve(undefined));
}
set(storageItemKey, value, storageKeys) {
var _a;
if (!this.hasStorage()) {
internal_1.LogCodeManager.log('11:03:04');
return;
}
if (storageKeys != null) {
for (const storageKey of storageKeys)
(_a = this.getStorage(storageKey)) === null || _a === void 0 ? void 0 : _a.set(storageItemKey, value);
return;
}
const defaultStorage = this.getStorage(this.config.defaultStorageKey);
defaultStorage === null || defaultStorage === void 0 ? void 0 : defaultStorage.set(storageItemKey, value);
}
remove(storageItemKey, storageKeys) {
var _a;
if (!this.hasStorage()) {
internal_1.LogCodeManager.log('11:03:05');
return;
}
if (storageKeys) {
for (const storageKey of storageKeys)
(_a = this.getStorage(storageKey)) === null || _a === void 0 ? void 0 : _a.remove(storageItemKey);
return;
}
const defaultStorage = this.getStorage(this.config.defaultStorageKey);
defaultStorage === null || defaultStorage === void 0 ? void 0 : defaultStorage.remove(storageItemKey);
}
hasStorage() {
return internal_1.notEqual(this.storages, {});
}
static localStorageAvailable() {
try {
localStorage.setItem('_myDummyKey_', 'myDummyValue');
localStorage.removeItem('_myDummyKey_');
return true;
}
catch (e) {
return false;
}
}
__exportStar(require("./storages"), exports);
function createStorage(config) {
return new internal_1.Storage(config);
}
exports.Storages = Storages;
exports.createStorage = createStorage;
{
"name": "@agile-ts/core",
"version": "0.2.0-alpha.3",
"version": "0.2.0-alpha.4",
"author": "BennoDev",

@@ -39,2 +39,3 @@ "license": "MIT",

"release": "node ./scripts/prepublish.js && yarn run prepare",
"release:manual": "yarn run prepare && yarn run release && npm publish && git checkout README.md",
"pack": "npm pack",

@@ -44,4 +45,3 @@ "test": "jest",

"lint": "eslint src/**/*",
"size": "yarn run build && size-limit",
"release:manual": "yarn run prepare && yarn run release && npm publish && git checkout README.md"
"size": "yarn run build && size-limit"
},

@@ -48,0 +48,0 @@ "devDependencies": {

@@ -209,3 +209,11 @@ <img src="https://raw.githubusercontent.com/agile-ts/agile/master/static/header_background.png" alt="AgileTs">

### ♥️ Contributors
<a href="https://github.com/agile-ts/agile/graphs/contributors">
<img src="https://contrib.rocks/image?repo=agile-ts/agile" />
</a>
[Become a contributor](https://github.com/agile-ts/agile/blob/master/CONTRIBUTING.md)
<br />

@@ -212,0 +220,0 @@

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc