@agile-ts/core
Advanced tools
Comparing version 0.0.14 to 0.0.15
# Change Log | ||
## 0.0.15 | ||
### Patch Changes | ||
- 616681d: - Outsourced Logger and Utils from the `core` package. | ||
- Created Proxy Tree | ||
- Added `useProxy` Hook to `react` package | ||
- Updated `core` to work with Proxy KeyMap | ||
- Updated dependencies [616681d] | ||
- @agile-ts/logger@0.0.2 | ||
- @agile-ts/utils@0.0.2 | ||
## 0.0.14 | ||
@@ -4,0 +16,0 @@ |
@@ -35,3 +35,3 @@ import { Runtime, Integration, State, Storage, Collection, CollectionConfig, DefaultItem, Computed, Integrations, Observer, SubController, Storages, CreateStorageConfigInterface, RegisterConfigInterface, Logger, CreateLoggerConfigInterface, StateConfigInterface, Group } from './internal'; | ||
*/ | ||
createCollection<DataType = DefaultItem>(config?: CollectionConfig<DataType>): Collection<DataType>; | ||
createCollection<DataType extends object = DefaultItem>(config?: CollectionConfig<DataType>): Collection<DataType>; | ||
/** | ||
@@ -38,0 +38,0 @@ * @public |
@@ -33,3 +33,3 @@ "use strict"; | ||
if (!internal_1.globalBind(Agile.globalKey, this)) | ||
Agile.logger.warn('Be careful with binding multiple Agile Instances global in one Application!'); | ||
Agile.logger.warn('Be careful with binding multiple Agile Instances globally in one Application!'); | ||
} | ||
@@ -36,0 +36,0 @@ } |
@@ -1,3 +0,3 @@ | ||
import { Collection, CollectionKey, CreatePersistentConfigInterface, Group, GroupKey, ItemKey, Persistent, PersistentKey, StorageKey } from '../internal'; | ||
export declare class CollectionPersistent<DataType = any> extends Persistent { | ||
import { Collection, CollectionKey, CreatePersistentConfigInterface, DefaultItem, Group, GroupKey, ItemKey, Persistent, PersistentKey, StorageKey } from '../internal'; | ||
export declare class CollectionPersistent<DataType extends object = DefaultItem> extends Persistent { | ||
collection: () => Collection<DataType>; | ||
@@ -28,20 +28,20 @@ static defaultGroupSideEffectKey: string; | ||
* Loads Collection from Storage | ||
* @param key - Prefix Key of Persisted Instances (default PersistentKey) | ||
* @param storageKey - Prefix Key of Persisted Instances (default PersistentKey) | ||
* @return Success? | ||
*/ | ||
loadPersistedValue(key?: PersistentKey): Promise<boolean>; | ||
loadPersistedValue(storageKey?: PersistentKey): Promise<boolean>; | ||
/** | ||
* @internal | ||
* Sets everything up so that the Collection gets saved in the Storage | ||
* @param key - Prefix Key of Persisted Instances (default PersistentKey) | ||
* @param storageKey - Prefix Key of Persisted Instances (default PersistentKey) | ||
* @return Success? | ||
*/ | ||
persistValue(key?: PersistentKey): Promise<boolean>; | ||
persistValue(storageKey?: PersistentKey): Promise<boolean>; | ||
/** | ||
* @internal | ||
* Removes Collection from the Storage | ||
* @param key - Prefix Key of Persisted Instances (default PersistentKey) | ||
* @param storageKey - Prefix Key of Persisted Instances (default PersistentKey) | ||
* @return Success? | ||
*/ | ||
removePersistedValue(key?: PersistentKey): Promise<boolean>; | ||
removePersistedValue(storageKey?: PersistentKey): Promise<boolean>; | ||
/** | ||
@@ -48,0 +48,0 @@ * @internal |
@@ -22,2 +22,3 @@ "use strict"; | ||
storageKeys: [], | ||
defaultStorageKey: null, | ||
}); | ||
@@ -28,2 +29,3 @@ this.collection = () => collection; | ||
storageKeys: config.storageKeys, | ||
defaultStorageKey: config.defaultStorageKey, | ||
}); | ||
@@ -61,8 +63,8 @@ if (this.ready && config.instantiate) | ||
} | ||
loadPersistedValue(key) { | ||
loadPersistedValue(storageKey) { | ||
return __awaiter(this, void 0, void 0, function* () { | ||
if (!this.ready) | ||
return false; | ||
const _key = key || this._key; | ||
const isPersisted = yield this.agileInstance().storages.get(_key, this.defaultStorageKey); | ||
const _storageKey = storageKey || this._key; | ||
const isPersisted = yield this.agileInstance().storages.get(_storageKey, this.config.defaultStorageKey); | ||
if (!isPersisted) | ||
@@ -76,3 +78,3 @@ return false; | ||
defaultGroup.persist({ | ||
instantiate: false, | ||
loadValue: false, | ||
followCollectionPersistKeyPattern: true, | ||
@@ -85,4 +87,4 @@ }); | ||
for (const itemKey of defaultGroup._value) { | ||
const itemStorageKey = CollectionPersistent.getItemStorageKey(itemKey, _key); | ||
const storageValue = yield this.agileInstance().storages.get(itemStorageKey, this.defaultStorageKey); | ||
const itemStorageKey = CollectionPersistent.getItemStorageKey(itemKey, _storageKey); | ||
const storageValue = yield this.agileInstance().storages.get(itemStorageKey, this.config.defaultStorageKey); | ||
if (!storageValue) | ||
@@ -96,21 +98,21 @@ continue; | ||
if (success) | ||
yield this.persistValue(_key); | ||
yield this.persistValue(_storageKey); | ||
return success; | ||
}); | ||
} | ||
persistValue(key) { | ||
persistValue(storageKey) { | ||
return __awaiter(this, void 0, void 0, function* () { | ||
if (!this.ready) | ||
return false; | ||
const _key = key || this._key; | ||
const _storageKey = storageKey || this._key; | ||
const defaultGroup = this.collection().getGroup(this.collection().config.defaultGroupKey); | ||
if (!defaultGroup) | ||
return false; | ||
this.agileInstance().storages.set(_key, true, this.storageKeys); | ||
this.agileInstance().storages.set(_storageKey, true, this.storageKeys); | ||
if (!defaultGroup.isPersisted) | ||
defaultGroup.persist({ followCollectionPersistKeyPattern: true }); | ||
defaultGroup.addSideEffect(CollectionPersistent.defaultGroupSideEffectKey, () => this.rebuildStorageSideEffect(defaultGroup, _key), { weight: 0 }); | ||
defaultGroup.addSideEffect(CollectionPersistent.defaultGroupSideEffectKey, () => this.rebuildStorageSideEffect(defaultGroup, _storageKey), { weight: 0 }); | ||
for (const itemKey of defaultGroup._value) { | ||
const item = this.collection().getItem(itemKey); | ||
const itemStorageKey = CollectionPersistent.getItemStorageKey(itemKey, _key); | ||
const itemStorageKey = CollectionPersistent.getItemStorageKey(itemKey, _storageKey); | ||
item === null || item === void 0 ? void 0 : item.persist(itemStorageKey); | ||
@@ -122,3 +124,3 @@ } | ||
} | ||
removePersistedValue(key) { | ||
removePersistedValue(storageKey) { | ||
var _a, _b; | ||
@@ -128,7 +130,7 @@ return __awaiter(this, void 0, void 0, function* () { | ||
return false; | ||
const _key = key || this._key; | ||
const _storageKey = storageKey || this._key; | ||
const defaultGroup = this.collection().getGroup(this.collection().config.defaultGroupKey); | ||
if (!defaultGroup) | ||
return false; | ||
this.agileInstance().storages.remove(_key, this.storageKeys); | ||
this.agileInstance().storages.remove(_storageKey, this.storageKeys); | ||
(_a = defaultGroup.persistent) === null || _a === void 0 ? void 0 : _a.removePersistedValue(); | ||
@@ -135,0 +137,0 @@ defaultGroup.removeSideEffect(CollectionPersistent.defaultGroupSideEffectKey); |
import { State, Collection, DefaultItem, ItemKey, Item, StatePersistentConfigInterface, PersistentKey, StateRuntimeJobConfigInterface, StateIngestConfigInterface } from '../internal'; | ||
export declare class Group<DataType = DefaultItem> extends State<Array<ItemKey>> { | ||
export declare class Group<DataType extends object = DefaultItem> extends State<Array<ItemKey>> { | ||
static rebuildGroupSideEffectKey: string; | ||
@@ -4,0 +4,0 @@ collection: () => Collection<DataType>; |
@@ -108,5 +108,6 @@ "use strict"; | ||
_config = internal_1.defineConfig(_config, { | ||
instantiate: true, | ||
loadValue: true, | ||
followCollectionPattern: false, | ||
storageKeys: [], | ||
defaultStorageKey: null, | ||
}); | ||
@@ -117,4 +118,5 @@ if (_config.followCollectionPersistKeyPattern) { | ||
super.persist(key, { | ||
instantiate: _config.instantiate, | ||
loadValue: _config.loadValue, | ||
storageKeys: _config.storageKeys, | ||
defaultStorageKey: _config.defaultStorageKey, | ||
}); | ||
@@ -121,0 +123,0 @@ return this; |
import { Agile, Item, Group, GroupKey, Selector, SelectorKey, StorageKey, GroupConfigInterface, CollectionPersistent, GroupAddConfigInterface, SideEffectConfigInterface, SelectorConfigInterface } from '../internal'; | ||
export declare class Collection<DataType = DefaultItem> { | ||
export declare class Collection<DataType extends object = DefaultItem> { | ||
agileInstance: () => Agile; | ||
@@ -12,3 +12,3 @@ config: CollectionConfigInterface; | ||
isPersisted: boolean; | ||
persistent: CollectionPersistent | undefined; | ||
persistent: CollectionPersistent<DataType> | undefined; | ||
groups: { | ||
@@ -371,8 +371,10 @@ [key: string]: Group<DataType>; | ||
/** | ||
* @param instantiate - If Persistent gets instantiated | ||
* @param loadValue - If Persistent loads the persisted value into the Collection | ||
* @param storageKeys - Key/Name of Storages which gets used to persist the Collection Value (NOTE: If not passed the default Storage will be used) | ||
* @param defaultStorageKey - Default Storage Key (if not provided it takes the first index of storageKeys or the AgileTs default Storage) | ||
*/ | ||
export interface CollectionPersistentConfigInterface { | ||
instantiate?: boolean; | ||
loadValue?: boolean; | ||
storageKeys?: StorageKey[]; | ||
defaultStorageKey?: StorageKey; | ||
} | ||
@@ -387,2 +389,2 @@ /** | ||
} | ||
export declare type CollectionConfig<DataType = DefaultItem> = CreateCollectionConfigInterface<DataType> | ((collection: Collection<DataType>) => CreateCollectionConfigInterface<DataType>); | ||
export declare type CollectionConfig<DataType extends object = DefaultItem> = CreateCollectionConfigInterface<DataType> | ((collection: Collection<DataType>) => CreateCollectionConfigInterface<DataType>); |
@@ -360,4 +360,5 @@ "use strict"; | ||
_config = internal_1.defineConfig(_config, { | ||
instantiate: true, | ||
loadValue: true, | ||
storageKeys: [], | ||
defaultStorageKey: null, | ||
}); | ||
@@ -367,5 +368,6 @@ if (this.persistent) | ||
this.persistent = new internal_1.CollectionPersistent(this, { | ||
instantiate: _config.instantiate, | ||
instantiate: _config.loadValue, | ||
storageKeys: _config.storageKeys, | ||
key: key, | ||
defaultStorageKey: _config.defaultStorageKey, | ||
}); | ||
@@ -372,0 +374,0 @@ return this; |
import { State, Collection, DefaultItem, StateKey, StateRuntimeJobConfigInterface } from '../internal'; | ||
export declare class Item<DataType = DefaultItem> extends State<DataType> { | ||
export declare class Item<DataType extends object = DefaultItem> extends State<DataType> { | ||
static updateGroupSideEffectKey: string; | ||
@@ -4,0 +4,0 @@ isSelected: boolean; |
import { Collection, DefaultItem, Item, ItemKey, State, StateRuntimeJobConfigInterface } from '../internal'; | ||
export declare class Selector<DataType = DefaultItem> extends State<DataType | undefined> { | ||
export declare class Selector<DataType extends object = DefaultItem> extends State<DataType | undefined> { | ||
static dummyItemKey: string; | ||
@@ -4,0 +4,0 @@ static rebuildSelectorSideEffectKey: string; |
@@ -1,3 +0,4 @@ | ||
export * from './logger'; | ||
export * from '@agile-ts/logger'; | ||
export * from './utils'; | ||
export * from '@agile-ts/utils'; | ||
export * from './agile'; | ||
@@ -4,0 +5,0 @@ export * from './runtime'; |
@@ -13,4 +13,5 @@ "use strict"; | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
__exportStar(require("./logger"), exports); | ||
__exportStar(require("@agile-ts/logger"), exports); | ||
__exportStar(require("./utils"), exports); | ||
__exportStar(require("@agile-ts/utils"), exports); | ||
__exportStar(require("./agile"), exports); | ||
@@ -17,0 +18,0 @@ __exportStar(require("./runtime"), exports); |
@@ -29,3 +29,4 @@ import { Agile, SubscriptionContainer, RuntimeJob } from '../internal'; | ||
* @internal | ||
* Updates/Rerenders all Subscribed Components of the Job (Observer) | ||
* Updates/Rerenders all Subscribed Components (SubscriptionContainer) of the Job (Observer) | ||
* @return If any subscriptionContainer got updated (-> triggered a rerender on the Component it represents) | ||
*/ | ||
@@ -48,2 +49,14 @@ updateSubscribers(): boolean; | ||
}; | ||
/** | ||
* @internal | ||
* Checks if the subscriptionContainer should be updated. | ||
* Therefore it reviews the '.value' and the '.previousValue' property of the Observer the Job represents. | ||
* If a property at the proxy detected path differs, the subscriptionContainer is allowed to update. | ||
* @param subscriptionContainer - SubscriptionContainer | ||
* @param job - Job | ||
* @return {boolean} If the subscriptionContainer should be updated | ||
* -> If a from the Proxy Tree detected property differs from the same property in the previous value | ||
* or the passed subscriptionContainer isn't properly proxy based | ||
*/ | ||
handleProxyBasedSubscription(subscriptionContainer: SubscriptionContainer, job: RuntimeJob): boolean; | ||
} | ||
@@ -50,0 +63,0 @@ /** |
@@ -63,4 +63,11 @@ "use strict"; | ||
if (!subscriptionContainer.ready) { | ||
this.notReadyJobsToRerender.add(job); | ||
internal_1.Agile.logger.warn("SubscriptionContainer/Component isn't ready to rerender!", subscriptionContainer); | ||
if (!job.config.numberOfTriesToUpdate || | ||
job.triesToUpdate < job.config.numberOfTriesToUpdate) { | ||
job.triesToUpdate++; | ||
this.notReadyJobsToRerender.add(job); | ||
internal_1.Agile.logger.warn("SubscriptionContainer/Component isn't ready to rerender!", subscriptionContainer); | ||
} | ||
else { | ||
internal_1.Agile.logger.warn(`Job with not ready SubscriptionContainer/Component was removed from the runtime after ${job.config.numberOfTriesToUpdate} tries to avoid an overflow.`, subscriptionContainer); | ||
} | ||
return; | ||
@@ -70,6 +77,12 @@ } | ||
this.handleObjectBasedSubscription(subscriptionContainer, job); | ||
subscriptionsToUpdate.add(subscriptionContainer); | ||
const updateSubscriptionContainer = subscriptionContainer.proxyBased | ||
? this.handleProxyBasedSubscription(subscriptionContainer, job) | ||
: true; | ||
if (updateSubscriptionContainer) | ||
subscriptionsToUpdate.add(subscriptionContainer); | ||
job.subscriptionContainersToUpdate.delete(subscriptionContainer); | ||
}); | ||
}); | ||
if (subscriptionsToUpdate.size <= 0) | ||
return false; | ||
subscriptionsToUpdate.forEach((subscriptionContainer) => { | ||
@@ -105,3 +118,35 @@ if (subscriptionContainer instanceof internal_1.CallbackSubscriptionContainer) | ||
} | ||
handleProxyBasedSubscription(subscriptionContainer, job) { | ||
if (!subscriptionContainer.proxyBased || | ||
!job.observer._key || | ||
!subscriptionContainer.proxyKeyMap[job.observer._key]) | ||
return true; | ||
const paths = subscriptionContainer.proxyKeyMap[job.observer._key].paths; | ||
if (paths) { | ||
for (const path of paths) { | ||
let newValue = job.observer.value; | ||
let newValueDeepness = 0; | ||
for (const branch of path) { | ||
if (!internal_1.isValidObject(newValue)) | ||
break; | ||
newValue = newValue[branch]; | ||
newValueDeepness++; | ||
} | ||
let previousValue = job.observer.previousValue; | ||
let previousValueDeepness = 0; | ||
for (const branch of path) { | ||
if (!internal_1.isValidObject(previousValue)) | ||
break; | ||
previousValue = previousValue[branch]; | ||
previousValueDeepness++; | ||
} | ||
if (internal_1.notEqual(newValue, previousValue) || | ||
newValueDeepness !== previousValueDeepness) { | ||
return true; | ||
} | ||
} | ||
} | ||
return false; | ||
} | ||
} | ||
exports.Runtime = Runtime; |
@@ -9,2 +9,3 @@ import { Agile, StateKey, RuntimeJob, SubscriptionContainer, IngestConfigInterface, CreateRuntimeJobConfigInterface } from '../internal'; | ||
value?: ValueType; | ||
previousValue?: ValueType; | ||
/** | ||
@@ -11,0 +12,0 @@ * @internal |
@@ -17,2 +17,3 @@ "use strict"; | ||
this.value = config.value; | ||
this.previousValue = config.value; | ||
(_a = config.dependents) === null || _a === void 0 ? void 0 : _a.forEach((observer) => this.depend(observer)); | ||
@@ -19,0 +20,0 @@ (_b = config.subs) === null || _b === void 0 ? void 0 : _b.forEach((subscriptionContainer) => this.subscribe(subscriptionContainer)); |
import { Observer, SubscriptionContainer } from '../internal'; | ||
export declare class RuntimeJob<ObserverType extends Observer = Observer> { | ||
_key?: RuntimeJobKey; | ||
config: RuntimeJobConfigInterface; | ||
observer: ObserverType; | ||
config: RuntimeJobConfigInterface; | ||
rerender: boolean; | ||
performed: boolean; | ||
subscriptionContainersToUpdate: Set<SubscriptionContainer>; | ||
triesToUpdate: number; | ||
/** | ||
@@ -30,2 +31,5 @@ * @internal | ||
* @param force - Force performing Job | ||
* @param numberOfTriesToUpdate - How often the runtime should try to update not ready SubscriptionContainers of this Job | ||
* If 'null' the runtime tries to update the not ready SubscriptionContainer until they are ready (infinite). | ||
* But be aware that this can lead to an overflow of 'old' Jobs after some time. (affects performance) | ||
*/ | ||
@@ -36,2 +40,3 @@ export interface RuntimeJobConfigInterface { | ||
force?: boolean; | ||
numberOfTriesToUpdate?: number | null; | ||
} | ||
@@ -38,0 +43,0 @@ /** |
@@ -9,2 +9,3 @@ "use strict"; | ||
this.subscriptionContainersToUpdate = new Set(); | ||
this.triesToUpdate = 0; | ||
config = internal_1.defineConfig(config, { | ||
@@ -17,2 +18,3 @@ background: false, | ||
force: false, | ||
numberOfTriesToUpdate: 3, | ||
}); | ||
@@ -23,2 +25,3 @@ this.config = { | ||
sideEffects: config.sideEffects, | ||
numberOfTriesToUpdate: config.numberOfTriesToUpdate, | ||
}; | ||
@@ -25,0 +28,0 @@ this.observer = observer; |
@@ -1,2 +0,2 @@ | ||
import { Observer, SubscriptionContainer, SubscriptionContainerKeyType } from '../../../internal'; | ||
import { Observer, SubscriptionContainer, SubscriptionContainerConfigInterface } from '../../../internal'; | ||
export declare class CallbackSubscriptionContainer extends SubscriptionContainer { | ||
@@ -9,5 +9,5 @@ callback: Function; | ||
* @param subs - Initial Subscriptions | ||
* @param key - Key/Name of Callback Subscription Container | ||
* @param config - Config | ||
*/ | ||
constructor(callback: Function, subs?: Array<Observer>, key?: SubscriptionContainerKeyType); | ||
constructor(callback: Function, subs?: Array<Observer>, config?: SubscriptionContainerConfigInterface); | ||
} |
@@ -6,4 +6,4 @@ "use strict"; | ||
class CallbackSubscriptionContainer extends internal_1.SubscriptionContainer { | ||
constructor(callback, subs = [], key) { | ||
super(subs, key); | ||
constructor(callback, subs = [], config = {}) { | ||
super(subs, config); | ||
this.callback = callback; | ||
@@ -10,0 +10,0 @@ } |
@@ -1,2 +0,2 @@ | ||
import { Observer, SubscriptionContainer, SubscriptionContainerKeyType } from '../../../internal'; | ||
import { Observer, SubscriptionContainer, SubscriptionContainerConfigInterface } from '../../../internal'; | ||
export declare class ComponentSubscriptionContainer extends SubscriptionContainer { | ||
@@ -9,5 +9,5 @@ component: any; | ||
* @param subs - Initial Subscriptions | ||
* @param key - Key/Name of Component Subscription Container | ||
* @param config - Config | ||
*/ | ||
constructor(component: any, subs?: Array<Observer>, key?: SubscriptionContainerKeyType); | ||
constructor(component: any, subs?: Array<Observer>, config?: SubscriptionContainerConfigInterface); | ||
} |
@@ -6,4 +6,4 @@ "use strict"; | ||
class ComponentSubscriptionContainer extends internal_1.SubscriptionContainer { | ||
constructor(component, subs = [], key) { | ||
super(subs, key); | ||
constructor(component, subs = [], config = {}) { | ||
super(subs, config); | ||
this.component = component; | ||
@@ -10,0 +10,0 @@ } |
@@ -6,2 +6,4 @@ import { Observer } from '../../../internal'; | ||
subs: Set<Observer>; | ||
proxyKeyMap: ProxyKeyMapInterface; | ||
proxyBased: boolean; | ||
isObjectBased: boolean; | ||
@@ -17,6 +19,33 @@ observerKeysToUpdate: Array<string>; | ||
* @param subs - Initial Subscriptions | ||
* @param key - Key/Name of Subscription Container | ||
* @param config - Config | ||
*/ | ||
constructor(subs?: Array<Observer>, key?: SubscriptionContainerKeyType); | ||
constructor(subs?: Array<Observer>, config?: SubscriptionContainerConfigInterface); | ||
} | ||
export declare type SubscriptionContainerKeyType = string | number; | ||
/** | ||
* @param proxyKeyMap - A keymap with a 2 dimensional arrays with paths/routes to particular properties in the State at key. | ||
* The subscriptionContainer will then only rerender the Component, when a property at a given path changes. | ||
* Not anymore if anything in the State object mutates, although it might not even be displayed in the Component. | ||
* For example: | ||
* { | ||
* myState1: {paths: [['data', 'name']]}, | ||
* myState2: {paths: [['car', 'speed']]} | ||
* } | ||
* Now the subscriptionContain will only trigger a rerender on the Component | ||
* if 'data.name' in myState1 or 'car.speed' in myState2 changes. | ||
* If, for instance, 'data.age' in myState1 mutates it won't trigger a rerender, | ||
* since 'data.age' isn't represented in the proxyKeyMap. | ||
* | ||
* These particular paths can be tracked with the ProxyTree. | ||
* https://github.com/agile-ts/agile/tree/master/packages/proxytree | ||
* @param key - Key/Name of Subscription Container | ||
*/ | ||
export interface SubscriptionContainerConfigInterface { | ||
proxyKeyMap?: ProxyKeyMapInterface; | ||
key?: SubscriptionContainerKeyType; | ||
} | ||
export interface ProxyKeyMapInterface { | ||
[key: string]: { | ||
paths: string[][]; | ||
}; | ||
} |
@@ -6,10 +6,17 @@ "use strict"; | ||
class SubscriptionContainer { | ||
constructor(subs = [], key) { | ||
constructor(subs = [], config = {}) { | ||
this.ready = false; | ||
this.proxyBased = false; | ||
this.isObjectBased = false; | ||
this.observerKeysToUpdate = []; | ||
config = internal_1.defineConfig(config, { | ||
proxyKeyMap: {}, | ||
key: internal_1.generateId(), | ||
}); | ||
this.subs = new Set(subs); | ||
this.key = key || internal_1.generateId(); | ||
this.key = config.key; | ||
this.proxyKeyMap = config.proxyKeyMap; | ||
this.proxyBased = internal_1.notEqual(this.proxyKeyMap, {}); | ||
} | ||
} | ||
exports.SubscriptionContainer = SubscriptionContainer; |
@@ -1,2 +0,2 @@ | ||
import { Agile, Observer, SubscriptionContainer, ComponentSubscriptionContainer, CallbackSubscriptionContainer, SubscriptionContainerKeyType } from '../../internal'; | ||
import { Agile, Observer, SubscriptionContainer, ComponentSubscriptionContainer, CallbackSubscriptionContainer, SubscriptionContainerConfigInterface } from '../../internal'; | ||
export declare class SubController { | ||
@@ -18,7 +18,7 @@ agileInstance: () => Agile; | ||
* @param subs - Initial Subscription Object | ||
* @param key - Key/Name of SubscriptionContainer | ||
* @param config - Config | ||
*/ | ||
subscribeWithSubsObject(integrationInstance: any, subs?: { | ||
[key: string]: Observer; | ||
}, key?: SubscriptionContainerKeyType): { | ||
}, config?: SubscriptionContainerConfigInterface): { | ||
subscriptionContainer: SubscriptionContainer; | ||
@@ -34,5 +34,5 @@ props: { | ||
* @param subs - Initial Subscription Array | ||
* @param key - Key/Name of SubscriptionContainer | ||
* @param config - Config | ||
*/ | ||
subscribeWithSubsArray(integrationInstance: any, subs?: Array<Observer>, key?: SubscriptionContainerKeyType): SubscriptionContainer; | ||
subscribeWithSubsArray(integrationInstance: any, subs?: Array<Observer>, config?: SubscriptionContainerConfigInterface): SubscriptionContainer; | ||
/** | ||
@@ -49,5 +49,5 @@ * @internal | ||
* @param subs - Initial Subscriptions | ||
* @param key - Key/Name of SubscriptionContainer | ||
* @param config - Config | ||
*/ | ||
registerSubscription(integrationInstance: any, subs?: Array<Observer>, key?: SubscriptionContainerKeyType): SubscriptionContainer; | ||
registerSubscription(integrationInstance: any, subs?: Array<Observer>, config?: SubscriptionContainerConfigInterface): SubscriptionContainer; | ||
/** | ||
@@ -60,5 +60,5 @@ * @internal | ||
* @param subs - Initial Subscriptions | ||
* @param key - Key/Name of SubscriptionContainer | ||
* @param config - Config | ||
*/ | ||
registerComponentSubscription(componentInstance: any, subs?: Array<Observer>, key?: SubscriptionContainerKeyType): ComponentSubscriptionContainer; | ||
registerComponentSubscription(componentInstance: any, subs?: Array<Observer>, config?: SubscriptionContainerConfigInterface): ComponentSubscriptionContainer; | ||
/** | ||
@@ -69,5 +69,5 @@ * @internal | ||
* @param subs - Initial Subscriptions | ||
* @param key - Key/Name of SubscriptionContainer | ||
* @param config - Config | ||
*/ | ||
registerCallbackSubscription(callbackFunction: () => void, subs?: Array<Observer>, key?: SubscriptionContainerKeyType): CallbackSubscriptionContainer; | ||
registerCallbackSubscription(callbackFunction: () => void, subs?: Array<Observer>, config?: SubscriptionContainerConfigInterface): CallbackSubscriptionContainer; | ||
/** | ||
@@ -74,0 +74,0 @@ * @internal |
@@ -12,3 +12,3 @@ "use strict"; | ||
} | ||
subscribeWithSubsObject(integrationInstance, subs = {}, key) { | ||
subscribeWithSubsObject(integrationInstance, subs = {}, config = {}) { | ||
const props = {}; | ||
@@ -18,3 +18,3 @@ const subsArray = []; | ||
subsArray.push(subs[key]); | ||
const subscriptionContainer = this.registerSubscription(integrationInstance, subsArray, key); | ||
const subscriptionContainer = this.registerSubscription(integrationInstance, subsArray, config); | ||
subscriptionContainer.isObjectBased = true; | ||
@@ -33,4 +33,4 @@ subscriptionContainer.subsObject = subs; | ||
} | ||
subscribeWithSubsArray(integrationInstance, subs = [], key) { | ||
const subscriptionContainer = this.registerSubscription(integrationInstance, subs, key); | ||
subscribeWithSubsArray(integrationInstance, subs = [], config = {}) { | ||
const subscriptionContainer = this.registerSubscription(integrationInstance, subs, config); | ||
subs.forEach((observer) => observer.subscribe(subscriptionContainer)); | ||
@@ -86,9 +86,9 @@ return subscriptionContainer; | ||
} | ||
registerSubscription(integrationInstance, subs = [], key) { | ||
registerSubscription(integrationInstance, subs = [], config = {}) { | ||
if (internal_1.isFunction(integrationInstance)) | ||
return this.registerCallbackSubscription(integrationInstance, subs, key); | ||
return this.registerComponentSubscription(integrationInstance, subs, key); | ||
return this.registerCallbackSubscription(integrationInstance, subs, config); | ||
return this.registerComponentSubscription(integrationInstance, subs, config); | ||
} | ||
registerComponentSubscription(componentInstance, subs = [], key) { | ||
const componentSubscriptionContainer = new internal_1.ComponentSubscriptionContainer(componentInstance, subs, key); | ||
registerComponentSubscription(componentInstance, subs = [], config = {}) { | ||
const componentSubscriptionContainer = new internal_1.ComponentSubscriptionContainer(componentInstance, subs, config); | ||
this.componentSubs.add(componentSubscriptionContainer); | ||
@@ -111,4 +111,4 @@ if (this.agileInstance().config.waitForMount) { | ||
} | ||
registerCallbackSubscription(callbackFunction, subs = [], key) { | ||
const callbackSubscriptionContainer = new internal_1.CallbackSubscriptionContainer(callbackFunction, subs, key); | ||
registerCallbackSubscription(callbackFunction, subs = [], config = {}) { | ||
const callbackSubscriptionContainer = new internal_1.CallbackSubscriptionContainer(callbackFunction, subs, config); | ||
this.callbackSubs.add(callbackSubscriptionContainer); | ||
@@ -115,0 +115,0 @@ callbackSubscriptionContainer.ready = true; |
@@ -0,1 +1,2 @@ | ||
/// <reference types="node" /> | ||
import { Agile, StorageKey, StateObserver, StatePersistent, Observer, PersistentKey, StateIngestConfigInterface } from '../internal'; | ||
@@ -23,2 +24,3 @@ export declare class State<ValueType = any> { | ||
}; | ||
currentInterval?: NodeJS.Timer | number; | ||
/** | ||
@@ -64,3 +66,3 @@ * @public | ||
*/ | ||
set(value: ValueType, config?: StateIngestConfigInterface): this; | ||
set(value: ValueType | ((value: ValueType) => ValueType), config?: StateIngestConfigInterface): this; | ||
/** | ||
@@ -153,2 +155,14 @@ * @internal | ||
* @public | ||
* Calls callback at certain intervals in milliseconds and assigns the callback return value to the State | ||
* @param callback- Callback that is called on each interval and should return the new State value | ||
* @param ms - The intervals in milliseconds | ||
*/ | ||
interval(callback: (value: ValueType) => ValueType, ms?: number): this; | ||
/** | ||
* @public | ||
* Clears the current Interval | ||
*/ | ||
clearInterval(): void; | ||
/** | ||
* @public | ||
* Creates fresh copy of State Value (-> No reference to State Value) | ||
@@ -248,8 +262,10 @@ */ | ||
/** | ||
* @param instantiate - If Persistent gets instantiated | ||
* @param loadValue - If Persistent loads the persisted value into the State | ||
* @param storageKeys - Key/Name of Storages which gets used to persist the State Value (NOTE: If not passed the default Storage will be used) | ||
* @param defaultStorageKey - Default Storage Key (if not provided it takes the first index of storageKeys or the AgileTs default Storage) | ||
*/ | ||
export interface StatePersistentConfigInterface { | ||
instantiate?: boolean; | ||
loadValue?: boolean; | ||
storageKeys?: StorageKey[]; | ||
defaultStorageKey?: StorageKey; | ||
} | ||
@@ -256,0 +272,0 @@ export declare type StateWatcherCallback<T = any> = (value: T, key: string) => void; |
@@ -59,4 +59,7 @@ "use strict"; | ||
}); | ||
if (!this.hasCorrectType(value)) { | ||
const message = `Incorrect type (${typeof value}) was provided.`; | ||
const _value = internal_1.isFunction(value) | ||
? value(internal_1.copy(this._value)) | ||
: value; | ||
if (!this.hasCorrectType(_value)) { | ||
const message = `Incorrect type (${typeof _value}) was provided.`; | ||
if (!config.force) { | ||
@@ -68,3 +71,3 @@ internal_1.Agile.logger.error(message); | ||
} | ||
this.observer.ingestValue(value, config); | ||
this.observer.ingestValue(_value, config); | ||
return this; | ||
@@ -159,11 +162,14 @@ } | ||
_config = internal_1.defineConfig(_config, { | ||
instantiate: true, | ||
loadValue: true, | ||
storageKeys: [], | ||
defaultStorageKey: null, | ||
}); | ||
if (this.persistent) | ||
internal_1.Agile.logger.warn(`By persisting the State '${this._key}' twice you overwrite the old Persistent Instance!`); | ||
if (this.persistent) { | ||
internal_1.Agile.logger.warn(`By persisting the State '${this._key}' twice you overwrite the old Persistent Instance!`, this.persistent); | ||
} | ||
this.persistent = new internal_1.StatePersistent(this, { | ||
instantiate: _config.instantiate, | ||
instantiate: _config.loadValue, | ||
storageKeys: _config.storageKeys, | ||
key: key, | ||
defaultStorageKey: _config.defaultStorageKey, | ||
}); | ||
@@ -173,12 +179,27 @@ return this; | ||
onLoad(callback) { | ||
if (this.persistent) { | ||
this.persistent.onLoad = callback; | ||
if (this.isPersisted) | ||
callback(true); | ||
} | ||
else { | ||
if (!this.persistent) { | ||
internal_1.Agile.logger.error(`Please make sure you persist the State '${this._key}' before using the 'onLoad' function!`); | ||
return this; | ||
} | ||
this.persistent.onLoad = callback; | ||
if (this.isPersisted) | ||
callback(true); | ||
return this; | ||
} | ||
interval(callback, ms) { | ||
if (this.currentInterval) { | ||
internal_1.Agile.logger.warn(`You can only have one interval active!`, this.currentInterval); | ||
return this; | ||
} | ||
this.currentInterval = setInterval(() => { | ||
this.set(callback(this._value)); | ||
}, ms !== null && ms !== void 0 ? ms : 1000); | ||
return this; | ||
} | ||
clearInterval() { | ||
if (this.currentInterval) { | ||
clearInterval(this.currentInterval); | ||
delete this.currentInterval; | ||
} | ||
} | ||
copy() { | ||
@@ -185,0 +206,0 @@ return internal_1.copy(this.value); |
@@ -56,2 +56,3 @@ "use strict"; | ||
const state = job.observer.state(); | ||
const previousValue = internal_1.copy(state.getPublicValue()); | ||
state.previousStateValue = internal_1.copy(state._value); | ||
@@ -68,2 +69,3 @@ state._value = internal_1.copy(job.observer.nextStateValue); | ||
job.observer.value = internal_1.copy(state.getPublicValue()); | ||
job.observer.previousValue = previousValue; | ||
} | ||
@@ -70,0 +72,0 @@ sideEffects(job) { |
@@ -26,17 +26,20 @@ import { CreatePersistentConfigInterface, Persistent, PersistentKey, State, StorageKey } from '../internal'; | ||
* Loads State Value from the Storage | ||
* @param storageKey - Prefix Key of Persisted Instances (default PersistentKey) | ||
* @return Success? | ||
*/ | ||
loadPersistedValue(key?: PersistentKey): Promise<boolean>; | ||
loadPersistedValue(storageKey?: PersistentKey): Promise<boolean>; | ||
/** | ||
* @internal | ||
* Sets everything up so that the State gets saved in the Storage on every Value change | ||
* @param storageKey - Prefix Key of Persisted Instances (default PersistentKey) | ||
* @return Success? | ||
*/ | ||
persistValue(key?: PersistentKey): Promise<boolean>; | ||
persistValue(storageKey?: PersistentKey): Promise<boolean>; | ||
/** | ||
* @internal | ||
* Removes State Value form the Storage | ||
* @param storageKey - Prefix Key of Persisted Instances (default PersistentKey) | ||
* @return Success? | ||
*/ | ||
removePersistedValue(key?: PersistentKey): Promise<boolean>; | ||
removePersistedValue(storageKey?: PersistentKey): Promise<boolean>; | ||
/** | ||
@@ -52,8 +55,8 @@ * @internal | ||
* @param state - State that holds the new Value | ||
* @param key - Key/Name of Persistent | ||
* @param storageKey - StorageKey where value should be persisted | ||
* @param config - Config | ||
*/ | ||
rebuildStorageSideEffect(state: State<ValueType>, key: PersistentKey, config?: { | ||
rebuildStorageSideEffect(state: State<ValueType>, storageKey: PersistentKey, config?: { | ||
[key: string]: any; | ||
}): void; | ||
} |
@@ -22,2 +22,3 @@ "use strict"; | ||
storageKeys: [], | ||
defaultStorageKey: null, | ||
}); | ||
@@ -28,2 +29,3 @@ this.state = () => state; | ||
storageKeys: config.storageKeys, | ||
defaultStorageKey: config.defaultStorageKey, | ||
}); | ||
@@ -61,24 +63,24 @@ if (this.ready && config.instantiate) | ||
} | ||
loadPersistedValue(key) { | ||
loadPersistedValue(storageKey) { | ||
return __awaiter(this, void 0, void 0, function* () { | ||
if (!this.ready) | ||
return false; | ||
const _key = key || this._key; | ||
const loadedValue = yield this.agileInstance().storages.get(_key, this.defaultStorageKey); | ||
const _storageKey = storageKey || this._key; | ||
const loadedValue = yield this.agileInstance().storages.get(_storageKey, this.config.defaultStorageKey); | ||
if (!loadedValue) | ||
return false; | ||
this.state().set(loadedValue, { storage: false }); | ||
yield this.persistValue(_key); | ||
yield this.persistValue(_storageKey); | ||
return true; | ||
}); | ||
} | ||
persistValue(key) { | ||
persistValue(storageKey) { | ||
return __awaiter(this, void 0, void 0, function* () { | ||
if (!this.ready) | ||
return false; | ||
const _key = key || this._key; | ||
const _storageKey = storageKey || this._key; | ||
this.state().addSideEffect(StatePersistent.storeValueSideEffectKey, (instance, config) => { | ||
this.rebuildStorageSideEffect(this.state(), _key, config); | ||
this.rebuildStorageSideEffect(this.state(), _storageKey, config); | ||
}, { weight: 0 }); | ||
this.rebuildStorageSideEffect(this.state(), _key); | ||
this.rebuildStorageSideEffect(this.state(), _storageKey); | ||
this.isPersisted = true; | ||
@@ -88,9 +90,9 @@ return true; | ||
} | ||
removePersistedValue(key) { | ||
removePersistedValue(storageKey) { | ||
return __awaiter(this, void 0, void 0, function* () { | ||
if (!this.ready) | ||
return false; | ||
const _key = key || this._key; | ||
const _storageKey = storageKey || this._key; | ||
this.state().removeSideEffect(StatePersistent.storeValueSideEffectKey); | ||
this.agileInstance().storages.remove(_key, this.storageKeys); | ||
this.agileInstance().storages.remove(_storageKey, this.storageKeys); | ||
this.isPersisted = false; | ||
@@ -110,6 +112,6 @@ return true; | ||
} | ||
rebuildStorageSideEffect(state, key, config = {}) { | ||
rebuildStorageSideEffect(state, storageKey, config = {}) { | ||
if (config.storage !== undefined && !config.storage) | ||
return; | ||
this.agileInstance().storages.set(key, this.state().getPersistableValue(), this.storageKeys); | ||
this.agileInstance().storages.set(storageKey, this.state().getPersistableValue(), this.storageKeys); | ||
} | ||
@@ -116,0 +118,0 @@ } |
import { Agile, Storage, Persistent, StorageKey, StorageItemKey } from '../internal'; | ||
export declare class Storages { | ||
agileInstance: () => Agile; | ||
defaultStorage?: Storage; | ||
config: StoragesConfigInterface; | ||
storages: { | ||
@@ -15,3 +15,3 @@ [key: string]: Storage; | ||
*/ | ||
constructor(agileInstance: Agile, config?: StoragesConfigInterface); | ||
constructor(agileInstance: Agile, config?: CreateStoragesConfigInterface); | ||
/** | ||
@@ -32,5 +32,5 @@ * @internal | ||
* Get Storage at Key/Name | ||
* @param key - Key/Name of Storage | ||
* @param storageKey - Key/Name of Storage | ||
*/ | ||
getStorage(key: StorageKey): Storage | undefined; | ||
getStorage(storageKey: StorageKey | undefined | null): Storage | undefined; | ||
/** | ||
@@ -71,7 +71,15 @@ * @internal | ||
* @param localStorage - If Local Storage should be instantiated | ||
* @param defaultStorage - Default Storage Key | ||
*/ | ||
export interface StoragesConfigInterface { | ||
export interface CreateStoragesConfigInterface { | ||
localStorage?: boolean; | ||
defaultStorageKey?: StorageKey; | ||
} | ||
/** | ||
* @param defaultStorage - Default Storage Key | ||
*/ | ||
export interface StoragesConfigInterface { | ||
defaultStorageKey: StorageKey | null; | ||
} | ||
/** | ||
* @param default - If the registered Storage gets the default Storage | ||
@@ -78,0 +86,0 @@ */ |
@@ -12,3 +12,5 @@ "use strict"; | ||
localStorage: false, | ||
defaultStorageKey: null, | ||
}); | ||
this.config = { defaultStorageKey: config.defaultStorageKey }; | ||
if (config.localStorage) | ||
@@ -46,6 +48,5 @@ this.instantiateLocalStorage(); | ||
if (config.default) | ||
this.defaultStorage = storage; | ||
this.config.defaultStorageKey = storage.key; | ||
this.persistentInstances.forEach((persistent) => { | ||
if (!persistent.defaultStorageKey) { | ||
persistent.assignStorageKeys(); | ||
if (persistent.storageKeys.includes(storage.key)) { | ||
const isValid = persistent.validatePersistent(); | ||
@@ -56,15 +57,21 @@ if (isValid) | ||
} | ||
if (persistent.storageKeys.includes(storage.key)) | ||
persistent.persistValue(); | ||
if (!persistent.config.defaultStorageKey) { | ||
persistent.assignStorageKeys(); | ||
const isValid = persistent.validatePersistent(); | ||
if (isValid) | ||
persistent.initialLoading(); | ||
} | ||
}); | ||
return true; | ||
} | ||
getStorage(key) { | ||
const storage = this.storages[key]; | ||
getStorage(storageKey) { | ||
if (!storageKey) | ||
return undefined; | ||
const storage = this.storages[storageKey]; | ||
if (!storage) { | ||
internal_1.Agile.logger.error(`Storage with the key/name '${key}' doesn't exist`); | ||
internal_1.Agile.logger.error(`Storage with the key/name '${storageKey}' doesn't exist!`); | ||
return undefined; | ||
} | ||
if (!storage.ready) { | ||
internal_1.Agile.logger.error(`Storage with the key/name '${key}' isn't ready`); | ||
internal_1.Agile.logger.error(`Storage with the key/name '${storageKey}' isn't ready yet!`); | ||
return undefined; | ||
@@ -75,3 +82,2 @@ } | ||
get(key, storageKey) { | ||
var _a; | ||
if (!this.hasStorage()) { | ||
@@ -86,6 +92,7 @@ internal_1.Agile.logger.error('No Storage found! Please provide at least one Storage.'); | ||
} | ||
return ((_a = this.defaultStorage) === null || _a === void 0 ? void 0 : _a.get(key)) || Promise.resolve(undefined); | ||
const defaultStorage = this.getStorage(this.config.defaultStorageKey); | ||
return (defaultStorage === null || defaultStorage === void 0 ? void 0 : defaultStorage.get(key)) || Promise.resolve(undefined); | ||
} | ||
set(key, value, storageKeys) { | ||
var _a, _b; | ||
var _a; | ||
if (!this.hasStorage()) { | ||
@@ -100,6 +107,7 @@ internal_1.Agile.logger.error('No Storage found! Please provide at least one Storage.'); | ||
} | ||
(_b = this.defaultStorage) === null || _b === void 0 ? void 0 : _b.set(key, value); | ||
const defaultStorage = this.getStorage(this.config.defaultStorageKey); | ||
defaultStorage === null || defaultStorage === void 0 ? void 0 : defaultStorage.set(key, value); | ||
} | ||
remove(key, storageKeys) { | ||
var _a, _b; | ||
var _a; | ||
if (!this.hasStorage()) { | ||
@@ -114,3 +122,4 @@ internal_1.Agile.logger.error('No Storage found! Please provide at least one Storage.'); | ||
} | ||
(_b = this.defaultStorage) === null || _b === void 0 ? void 0 : _b.remove(key); | ||
const defaultStorage = this.getStorage(this.config.defaultStorageKey); | ||
defaultStorage === null || defaultStorage === void 0 ? void 0 : defaultStorage.remove(key); | ||
} | ||
@@ -117,0 +126,0 @@ hasStorage() { |
@@ -5,2 +5,3 @@ import { Agile, StorageKey } from '../internal'; | ||
static placeHolderKey: string; | ||
config: PersistentConfigInterface; | ||
_key: PersistentKey; | ||
@@ -11,3 +12,2 @@ ready: boolean; | ||
storageKeys: StorageKey[]; | ||
defaultStorageKey: StorageKey | undefined; | ||
/** | ||
@@ -44,3 +44,3 @@ * @internal | ||
*/ | ||
instantiatePersistent(config?: PersistentConfigInterface): void; | ||
instantiatePersistent(config?: InstantiatePersistentConfigInterface): void; | ||
/** | ||
@@ -55,4 +55,5 @@ * @internal | ||
* @param storageKeys - New Storage Keys | ||
* @param defaultStorageKey - Key of default Storage | ||
*/ | ||
assignStorageKeys(storageKeys?: StorageKey[]): void; | ||
assignStorageKeys(storageKeys?: StorageKey[], defaultStorageKey?: StorageKey): void; | ||
/** | ||
@@ -92,2 +93,3 @@ * @internal | ||
* @param storageKeys - Keys of Storages in that the persisted Value gets saved | ||
* @param defaultStorage - Default Storage Key | ||
* @param instantiate - If Persistent gets Instantiated immediately | ||
@@ -98,11 +100,20 @@ */ | ||
storageKeys?: StorageKey[]; | ||
defaultStorageKey?: StorageKey; | ||
instantiate?: boolean; | ||
} | ||
/** | ||
* @param defaultStorageKey - Default Storage Key | ||
*/ | ||
export interface PersistentConfigInterface { | ||
defaultStorageKey: StorageKey | null; | ||
} | ||
/** | ||
* @param key - Key/Name of Persistent | ||
* @param storageKeys - Keys of Storages in that the persisted Value gets saved | ||
* @param defaultStorageKey - Default Storage Key (if not provided it takes the first index of storageKeys or the AgileTs default Storage) | ||
*/ | ||
export interface PersistentConfigInterface { | ||
export interface InstantiatePersistentConfigInterface { | ||
key?: PersistentKey; | ||
storageKeys?: StorageKey[]; | ||
defaultStorageKey?: StorageKey; | ||
} |
@@ -24,9 +24,13 @@ "use strict"; | ||
storageKeys: [], | ||
defaultStorageKey: null, | ||
}); | ||
this.agileInstance().storages.persistentInstances.add(this); | ||
if (config.instantiate) | ||
this.config = { defaultStorageKey: config.defaultStorageKey }; | ||
if (config.instantiate) { | ||
this.instantiatePersistent({ | ||
storageKeys: config.storageKeys, | ||
key: config.key, | ||
defaultStorageKey: config.defaultStorageKey, | ||
}); | ||
} | ||
} | ||
@@ -44,3 +48,3 @@ set key(value) { | ||
this._key = this.formatKey(config.key) || Persistent.placeHolderKey; | ||
this.assignStorageKeys(config.storageKeys); | ||
this.assignStorageKeys(config.storageKeys, config.defaultStorageKey); | ||
this.validatePersistent(); | ||
@@ -54,22 +58,30 @@ } | ||
} | ||
if (!this.defaultStorageKey || this.storageKeys.length <= 0) { | ||
if (!this.config.defaultStorageKey || this.storageKeys.length <= 0) { | ||
internal_1.Agile.logger.error('No persist Storage Key found! Please provide at least one Storage Key.'); | ||
isValid = false; | ||
} | ||
this.storageKeys.map((key) => { | ||
if (!this.agileInstance().storages.storages[key]) { | ||
internal_1.Agile.logger.error(`Storage '${key}' doesn't exist yet. Please provide only existing StorageKeys!`); | ||
isValid = false; | ||
} | ||
}); | ||
this.ready = isValid; | ||
return isValid; | ||
} | ||
assignStorageKeys(storageKeys = []) { | ||
assignStorageKeys(storageKeys = [], defaultStorageKey) { | ||
const storages = this.agileInstance().storages; | ||
if (storageKeys.length <= 0) { | ||
this.storageKeys = []; | ||
if (storages.defaultStorage) { | ||
const key = storages.defaultStorage.key; | ||
this.defaultStorageKey = key; | ||
this.storageKeys.push(key); | ||
} | ||
return; | ||
const _storageKeys = internal_1.copy(storageKeys); | ||
if (defaultStorageKey && !_storageKeys.includes(defaultStorageKey)) { | ||
internal_1.Agile.logger.warn(`Default Storage Key '${defaultStorageKey}' isn't contained in storageKeys!`, _storageKeys); | ||
_storageKeys.push(defaultStorageKey); | ||
} | ||
this.storageKeys = storageKeys; | ||
this.defaultStorageKey = storageKeys[0]; | ||
if (_storageKeys.length <= 0) { | ||
this.config.defaultStorageKey = storages.config.defaultStorageKey; | ||
_storageKeys.push(storages.config.defaultStorageKey); | ||
} | ||
else { | ||
this.config.defaultStorageKey = defaultStorageKey || _storageKeys[0]; | ||
} | ||
this.storageKeys = _storageKeys; | ||
} | ||
@@ -76,0 +88,0 @@ initialLoading() { |
import { Agile, Observer } from './internal'; | ||
/** | ||
* @internal | ||
* Creates a fresh copy of an Array/Object | ||
* https://www.samanthaming.com/tidbits/70-3-ways-to-clone-objects/ | ||
* @param value - Array/Object that gets copied | ||
*/ | ||
export declare function copy<T = any>(value: T): T; | ||
/** | ||
* @internal | ||
* Checks if an value is a valid Object | ||
* https://stackoverflow.com/questions/12996871/why-does-typeof-array-with-objects-return-object-and-not-array | ||
* @param value - Value that is tested for its correctness | ||
*/ | ||
export declare function isValidObject(value: any): boolean; | ||
/** | ||
* @internal | ||
* Check if array1 contains all elements of array2 | ||
* @param array1 - Array 1 | ||
* @param array2 - Array 2 | ||
*/ | ||
export declare function includesArray<DataType = any>(array1: Array<DataType>, array2: Array<DataType>): boolean; | ||
/** | ||
* @internal | ||
* Transforms Item/s to an Item Array | ||
* @param items - Item/s that gets transformed to an Array | ||
* @param config - Config | ||
*/ | ||
export declare function normalizeArray<DataType = any>(items?: DataType | Array<DataType>, config?: { | ||
createUndefinedArray?: boolean; | ||
}): Array<DataType>; | ||
/** | ||
* @internal | ||
* Tries to get an Instance of Agile from provided Instance | ||
@@ -47,88 +17,2 @@ * If no agileInstance found it returns the global bound Agile Instance | ||
* @internal | ||
* Checks if value is a function | ||
* @param value - Value that gets tested if its a function | ||
*/ | ||
export declare function isFunction(value: any): boolean; | ||
/** | ||
* @internal | ||
* Checks if value is an async function | ||
* @param value - Value that gets tested if its an async function | ||
*/ | ||
export declare function isAsyncFunction(value: any): boolean; | ||
/** | ||
* @internal | ||
* Checks if value is valid JsonString | ||
* @param value - Value that gets checked | ||
*/ | ||
export declare function isJsonString(value: any): boolean; | ||
/** | ||
* @internal | ||
* Merges default values/properties into config object | ||
* @param config - Config object that receives default values | ||
* @param defaults - Default values object that gets merged into config object | ||
* @param overwriteUndefinedProperties - If undefined Properties in config gets overwritten by the default value | ||
*/ | ||
export declare function defineConfig<ConfigInterface = Object>(config: ConfigInterface, defaults: Object, overwriteUndefinedProperties?: boolean): ConfigInterface; | ||
/** | ||
* @internal | ||
* @param addNewProperties - Adds new properties to source Object | ||
*/ | ||
export interface FlatMergeConfigInterface { | ||
addNewProperties?: boolean; | ||
} | ||
/** | ||
* @internal | ||
* Merges items into object, be aware that the merge will only happen at the top level of the object. | ||
* Initially it adds new properties of the changes object into the source object. | ||
* @param source - Source object | ||
* @param changes - Changes that get merged into the source object | ||
* @param config - Config | ||
*/ | ||
export declare function flatMerge<DataType = Object>(source: DataType, changes: Object, config?: FlatMergeConfigInterface): DataType; | ||
/** | ||
* @internal | ||
* Check if two values are equal | ||
* @param value1 - First Value | ||
* @param value2 - Second Value | ||
*/ | ||
export declare function equal(value1: any, value2: any): boolean; | ||
/** | ||
* @internal | ||
* Checks if two values aren't equal | ||
* @param value1 - First Value | ||
* @param value2 - Second Value | ||
*/ | ||
export declare function notEqual(value1: any, value2: any): boolean; | ||
/** | ||
* @internal | ||
* Generates random Id | ||
* @param length - Length of generated Id | ||
*/ | ||
export declare function generateId(length?: number): string; | ||
/** | ||
* @internal | ||
* Transforms Object to Array | ||
* @param object - Object that gets transformed | ||
*/ | ||
export declare function createArrayFromObject<P = any>(object: { | ||
[key: string]: P; | ||
}): Array<{ | ||
key: string; | ||
instance: P; | ||
}>; | ||
/** | ||
* @internal | ||
* Clones a Class | ||
* @param instance - Instance of Class you want to clone | ||
*/ | ||
export declare function clone<T = any>(instance: T): T; | ||
/** | ||
* @internal | ||
* Removes properties from Object | ||
* @param object - Object from which the properties get removed | ||
* @param properties - Properties that get removed from the object | ||
*/ | ||
export declare function removeProperties<T = Object>(object: T, properties: Array<string>): T; | ||
/** | ||
* @internal | ||
* Binds passed Instance globally at passed Key | ||
@@ -135,0 +19,0 @@ * https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/globalThis |
"use strict"; | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
exports.globalBind = exports.removeProperties = exports.clone = exports.createArrayFromObject = exports.generateId = exports.notEqual = exports.equal = exports.flatMerge = exports.defineConfig = exports.isJsonString = exports.isAsyncFunction = exports.isFunction = exports.extractObservers = exports.getAgileInstance = exports.normalizeArray = exports.includesArray = exports.isValidObject = exports.copy = void 0; | ||
exports.globalBind = exports.extractObservers = exports.getAgileInstance = void 0; | ||
const internal_1 = require("./internal"); | ||
function copy(value) { | ||
if (!value) | ||
return value; | ||
const valConstructorName = Object.getPrototypeOf(value).constructor.name; | ||
if (!['object', 'array'].includes(valConstructorName.toLowerCase())) | ||
return value; | ||
let temp; | ||
const newObject = Array.isArray(value) ? [] : {}; | ||
for (const property in value) { | ||
temp = value[property]; | ||
newObject[property] = typeof temp === 'object' ? copy(temp) : temp; | ||
} | ||
return newObject; | ||
} | ||
exports.copy = copy; | ||
function isValidObject(value) { | ||
function isHTMLElement(obj) { | ||
try { | ||
return obj instanceof HTMLElement; | ||
} | ||
catch (e) { | ||
return (typeof obj === 'object' && | ||
obj.nodeType === 1 && | ||
typeof obj.style === 'object' && | ||
typeof obj.ownerDocument === 'object'); | ||
} | ||
} | ||
return (value !== null && | ||
typeof value === 'object' && | ||
!isHTMLElement(value) && | ||
!Array.isArray(value)); | ||
} | ||
exports.isValidObject = isValidObject; | ||
function includesArray(array1, array2) { | ||
return array2.every((element) => array1.includes(element)); | ||
} | ||
exports.includesArray = includesArray; | ||
function normalizeArray(items, config = {}) { | ||
config = defineConfig(config, { | ||
createUndefinedArray: false, | ||
}); | ||
if (!items && !config.createUndefinedArray) | ||
return []; | ||
return Array.isArray(items) ? items : [items]; | ||
} | ||
exports.normalizeArray = normalizeArray; | ||
function getAgileInstance(instance) { | ||
try { | ||
if (instance) { | ||
const _agileInstance = isFunction(instance['agileInstance']) | ||
const _agileInstance = internal_1.isFunction(instance['agileInstance']) | ||
? instance['agileInstance']() | ||
@@ -70,3 +24,3 @@ : instance['agileInstance']; | ||
const instancesArray = []; | ||
const tempInstancesArray = normalizeArray(instances, { | ||
const tempInstancesArray = internal_1.normalizeArray(instances, { | ||
createUndefinedArray: true, | ||
@@ -96,99 +50,2 @@ }); | ||
exports.extractObservers = extractObservers; | ||
function isFunction(value) { | ||
return typeof value === 'function'; | ||
} | ||
exports.isFunction = isFunction; | ||
function isAsyncFunction(value) { | ||
const valueString = value.toString(); | ||
return (isFunction(value) && | ||
(value.constructor.name === 'AsyncFunction' || | ||
valueString.includes('__awaiter'))); | ||
} | ||
exports.isAsyncFunction = isAsyncFunction; | ||
function isJsonString(value) { | ||
if (typeof value !== 'string') | ||
return false; | ||
try { | ||
JSON.parse(value); | ||
} | ||
catch (e) { | ||
return false; | ||
} | ||
return true; | ||
} | ||
exports.isJsonString = isJsonString; | ||
function defineConfig(config, defaults, overwriteUndefinedProperties) { | ||
if (overwriteUndefinedProperties === undefined) | ||
overwriteUndefinedProperties = true; | ||
if (overwriteUndefinedProperties) { | ||
const finalConfig = Object.assign(Object.assign({}, defaults), config); | ||
for (const key in finalConfig) | ||
if (finalConfig[key] === undefined) | ||
finalConfig[key] = defaults[key]; | ||
return finalConfig; | ||
} | ||
return Object.assign(Object.assign({}, defaults), config); | ||
} | ||
exports.defineConfig = defineConfig; | ||
function flatMerge(source, changes, config = {}) { | ||
config = defineConfig(config, { | ||
addNewProperties: true, | ||
}); | ||
const _source = copy(source); | ||
if (!_source) | ||
return _source; | ||
const keys = Object.keys(changes); | ||
keys.forEach((property) => { | ||
if (!config.addNewProperties && !_source[property]) | ||
return; | ||
_source[property] = changes[property]; | ||
}); | ||
return _source; | ||
} | ||
exports.flatMerge = flatMerge; | ||
function equal(value1, value2) { | ||
return value1 === value2 || JSON.stringify(value1) === JSON.stringify(value2); | ||
} | ||
exports.equal = equal; | ||
function notEqual(value1, value2) { | ||
return !equal(value1, value2); | ||
} | ||
exports.notEqual = notEqual; | ||
function generateId(length) { | ||
const characters = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789'; | ||
const charactersLength = characters.length; | ||
let result = ''; | ||
if (!length) | ||
length = 5; | ||
for (let i = 0; i < length; i++) { | ||
result += characters.charAt(Math.floor(Math.random() * charactersLength)); | ||
} | ||
return result; | ||
} | ||
exports.generateId = generateId; | ||
function createArrayFromObject(object) { | ||
const array = []; | ||
for (const key in object) { | ||
array.push({ | ||
key: key, | ||
instance: object[key], | ||
}); | ||
} | ||
return array; | ||
} | ||
exports.createArrayFromObject = createArrayFromObject; | ||
function clone(instance) { | ||
const objectCopy = Object.create(Object.getPrototypeOf(instance)); | ||
const objectClone = Object.assign(objectCopy, instance); | ||
for (const key in objectClone) | ||
objectClone[key] = copy(objectClone[key]); | ||
return objectClone; | ||
} | ||
exports.clone = clone; | ||
function removeProperties(object, properties) { | ||
const copiedObject = copy(object); | ||
properties.map((property) => delete copiedObject[property]); | ||
return copiedObject; | ||
} | ||
exports.removeProperties = removeProperties; | ||
function globalBind(key, instance, overwrite = false) { | ||
@@ -195,0 +52,0 @@ try { |
{ | ||
"name": "@agile-ts/core", | ||
"version": "0.0.14", | ||
"version": "0.0.15", | ||
"author": "BennoDev", | ||
@@ -33,3 +33,4 @@ "license": "MIT", | ||
"dev:push": "yalc push", | ||
"watch": "tsc-watch --onSuccess \"yarn run dev:push\"", | ||
"watch:push": "tsc-watch --onSuccess \"yarn run dev:push\"", | ||
"watch": "tsc -w", | ||
"release": "node ./scripts/prepublish.js && yarn run prepare", | ||
@@ -41,2 +42,10 @@ "preview": "npm pack", | ||
}, | ||
"devDependencies": { | ||
"@agile-ts/logger": "file:../logger", | ||
"@agile-ts/utils": "file:../utils" | ||
}, | ||
"dependencies": { | ||
"@agile-ts/utils": "^0.0.2", | ||
"@agile-ts/logger": "^0.0.2" | ||
}, | ||
"publishConfig": { | ||
@@ -43,0 +52,0 @@ "access": "public" |
<img src="https://raw.githubusercontent.com/agile-ts/agile/master/static/header_background.png" alt="AgileTs"> | ||
> Global, simple, spacy State and Logic Framework | ||
> Global, simple, spacy State and Logic Framework | ||
<br /> | ||
<p align="left"> | ||
@@ -79,4 +79,4 @@ <a href="https://github.com/agile-ts/agile"> | ||
AgileTs is a global, simple, well-tested State Management Framework implemented in Typescript. | ||
It offers a reimagined API that focus on **developer experience** and allows you to **quickly** and **easily** manage your States. | ||
Besides States, AgileTs offers some other powerful apis that make your life easier. | ||
It offers a reimagined API that focuses on **developer experience** and allows you to **quickly** and **easily** manage your States. | ||
Besides States, AgileTs offers some other powerful APIs that make your life easier. | ||
The philosophy behind AgileTs is simple: | ||
@@ -120,4 +120,4 @@ | ||
AgileTs is designed to take all business logic out of UI-Components and put them in a central place often called `core`. | ||
The benefit of keeping logic separate to UI-Components is to make your code more decoupled, portable and above all easily testable. | ||
AgileTs is designed to take all business logic out of UI-Components and put them in a central place, often called `core`. | ||
The benefit of keeping logic separate to UI-Components is to make your code more decoupled, portable, and above all, easily testable. | ||
@@ -137,3 +137,3 @@ ### 🎯 Easy to Use | ||
To properly use AgileTs, in a UI-Framework we need to install **two** packages. | ||
To properly use AgileTs, in a UI-Framework, we need to install **two** packages. | ||
@@ -145,3 +145,3 @@ - The _Core Package_, which acts as the brain of AgileTs and manages all your States | ||
- and a _fitting Integration_ for your preferd UI-Framework. In my case the [React Integration](https://www.npmjs.com/package/@agile-ts/react). | ||
- and a _fitting Integration_ for your preferred UI-Framework. In my case, the [React Integration](https://www.npmjs.com/package/@agile-ts/react). | ||
Check [here](https://agile-ts.org/docs/frameworks) if your desired Framework is supported, too. | ||
@@ -151,4 +151,4 @@ ``` | ||
``` | ||
<br /> | ||
@@ -162,4 +162,4 @@ | ||
Checkout our **[documentation](https://agile-ts.org/docs/introduction)**, to learn more. | ||
And I promise you, you will be able to use AgileTs in no time. | ||
In case you have any further questions don't hesitate joining our [Community Discord](https://discord.gg/T9GzreAwPH). | ||
And I promise you. You will be able to use AgileTs in no time. | ||
In case you have any further questions, don't hesitate to join our [Community Discord](https://discord.gg/T9GzreAwPH). | ||
@@ -173,4 +173,4 @@ | ||
Get a part of AgileTs and start contributing. We welcome any meaningful contribution 😀 | ||
To find out more checkout the [CONTRIBUTING.md](https://github.com/agile-ts/agile/blob/master/CONTRIBUTING.md). | ||
Get a part of AgileTs and start contributing. We welcome any meaningful contribution. 😀 | ||
To find out more, check out the [CONTRIBUTING.md](https://github.com/agile-ts/agile/blob/master/CONTRIBUTING.md). | ||
@@ -203,3 +203,2 @@ <a href="https://codeclimate.com/github/agile-ts/agile/coverage.svg"> | ||
AgileTs is inspired by [MVVM Frameworks](https://de.wikipedia.org/wiki/Model_View_ViewModel) like [MobX](https://mobx.js.org/README.html) and [PulseJs](https://github.com/pulse-framework/pulse). | ||
AgileTs is inspired by [MVVM Frameworks](https://de.wikipedia.org/wiki/Model_View_ViewModel) like [MobX](https://mobx.js.org/README.html) and [PulseJs](https://github.com/pulse-framework/pulse). |
192154
2
2
58
4690
196
+ Added@agile-ts/logger@^0.0.2
+ Added@agile-ts/utils@^0.0.2
+ Added@agile-ts/logger@0.0.2(transitive)
+ Added@agile-ts/utils@0.0.2(transitive)