diff --git a/docs/docs/api-reference/CollectionInstance.mdx b/docs/docs/api-reference/CollectionInstance.mdx
index dd72c6af..d9108675 100644
--- a/docs/docs/api-reference/CollectionInstance.mdx
+++ b/docs/docs/api-reference/CollectionInstance.mdx
@@ -136,7 +136,8 @@ A Collection Instance
Get the Value of the data item with the provided key (the raw data). If there
- is not an existing data item, this will return a provisional one
+ is not an existing data item, this will return a provisional one (an
+ empty untracked data instance)
**Returns**: this
The new Collection Instance
diff --git a/packages/plexus-core/src/collection/collection.ts b/packages/plexus-core/src/collection/collection.ts
index 08ea96d8..78689a7a 100644
--- a/packages/plexus-core/src/collection/collection.ts
+++ b/packages/plexus-core/src/collection/collection.ts
@@ -349,7 +349,7 @@ export class CollectionInstance<
return this
}
/**
- * Get the Value of the data item with the provided key (the raw data). If there is not an existing data item, this will return a _provisional_ one
+ * Get the Value of the data item with the provided key (the raw data). If there is not an existing data item, this will return a _provisional_ one (an empty untracked data instance)
* @param {string|number} dataKey The key of the data item to get
* @returns {this} The new Collection Instance
*/
@@ -469,7 +469,8 @@ export class CollectionInstance<
*/
createGroup(
groupName: Name,
- config?: PlexusCollectionGroupConfig
+ config?: PlexusCollectionGroupConfig,
+ fetcher?: (currentValue?: DataType) => DataType
) {
this.mount()
if (this._internalStore._groups.has(groupName)) return this
diff --git a/packages/plexus-core/src/collection/data.ts b/packages/plexus-core/src/collection/data.ts
index 94f1f20d..e7d625df 100644
--- a/packages/plexus-core/src/collection/data.ts
+++ b/packages/plexus-core/src/collection/data.ts
@@ -123,7 +123,7 @@ export class CollectionData<
// loop through the foreign keys
for (idKey of Object.keys(foreignKeys ?? {})) {
- const isArray = foreignKeys[idKey]?.mode === 'array';
+ const isArray = foreignKeys[idKey]?.mode === 'array'
const newKey = foreignKeys[idKey]?.newKey as string
const foreignCollectionName = foreignKeys[idKey]?.reference as string
const foreignCollection = this.instance().findReference(
@@ -132,9 +132,12 @@ export class CollectionData<
// if we have a shallow value, then we can try to get the fresh value from the foreign collection
if (this.shallowValue) {
- const freshValue = isArray ?
- this.shallowValue?.[idKey]?.map((id: string) => foreignCollection?.getItem(id).shallowValue) || undefined
- : foreignCollection?.getItem(this.shallowValue?.[idKey]).shallowValue || undefined
+ const freshValue = isArray
+ ? this.shallowValue?.[idKey]?.map(
+ (id: string) => foreignCollection?.getItem(id).shallowValue
+ ) || undefined
+ : foreignCollection?.getItem(this.shallowValue?.[idKey])
+ .shallowValue || undefined
if (
freshValue &&
foreignCollection?.config.foreignKeys?.[idKey]?.newKey
diff --git a/packages/plexus-core/src/index.ts b/packages/plexus-core/src/index.ts
index e2f8f289..4b5b596b 100644
--- a/packages/plexus-core/src/index.ts
+++ b/packages/plexus-core/src/index.ts
@@ -30,8 +30,8 @@ import { LiteralType, AlmostAnything } from '@plexusjs/utils'
export function state<
Literal extends PlexusStateType = any,
Value = Literal extends AlmostAnything ? Literal : LiteralType
->(item: Value) {
- return _state(() => instance(), item)
+>(item: Value, fetcher?: (currentValue?: Value) => Value) {
+ return _state(() => instance(), item, fetcher)
}
/**
* Generate a Plexus State
diff --git a/packages/plexus-core/src/initializer.ts b/packages/plexus-core/src/initializer.ts
new file mode 100644
index 00000000..01e3c0a5
--- /dev/null
+++ b/packages/plexus-core/src/initializer.ts
@@ -0,0 +1,8 @@
+import { Watchable } from '.'
+
+export function WatchableInitializer(
+ watchable: Watchable,
+ initFunction: (currentValue?: ValueType) => ValueType
+) {
+ watchable
+}
diff --git a/packages/plexus-core/src/state.ts b/packages/plexus-core/src/state.ts
index 71ce8eda..f95df8e7 100644
--- a/packages/plexus-core/src/state.ts
+++ b/packages/plexus-core/src/state.ts
@@ -42,9 +42,9 @@ export class StateInstance<
constructor(
instance: () => PlexusInstance,
init: StateValue,
- fetcher?: (currentValue: StateValue) => StateValue
+ fetcher?: (currentValue?: StateValue) => StateValue
) {
- super(instance, init)
+ super(instance, init, fetcher)
this.instance = instance
this._internalStore = {
_name: '',
@@ -267,9 +267,10 @@ export class StateInstance<
export function _state(
instance: () => PlexusInstance,
- _init: StateValue
+ _init: StateValue,
+ fetcher?: (currentValue?: StateValue) => StateValue
) {
// Returned Object //
- return new StateInstance(instance, _init)
+ return new StateInstance(instance, _init, fetcher)
}
diff --git a/packages/plexus-core/src/watchable.ts b/packages/plexus-core/src/watchable.ts
index e74ec4b7..f5fa158a 100644
--- a/packages/plexus-core/src/watchable.ts
+++ b/packages/plexus-core/src/watchable.ts
@@ -9,6 +9,7 @@ interface WatchableStore {
_nextValue: Value
_watchers: Set>
_internalId: string
+ _initialized: boolean
}
type HistorySeed = {
@@ -22,15 +23,26 @@ type HistorySeed = {
export class Watchable {
protected _watchableStore: WatchableStore
protected instance: () => PlexusInstance
+ protected initFetcher: ((currentValue?: ValueType) => ValueType) | undefined
+ private loading: boolean = false
+ public get isLoading() {
+ return this.loading
+ }
+
/**
* The internal id of the computed state
*/
get id(): string {
return `${this._watchableStore._internalId}`
}
- constructor(instance: () => PlexusInstance, init: ValueType) {
+ constructor(
+ instance: () => PlexusInstance,
+ init: ValueType,
+ fetcher?: (currentValue?: ValueType) => ValueType
+ ) {
this.instance = instance
this._watchableStore = {
+ _initialized: false,
_internalId: instance().genId(),
_nextValue: init,
_value: init,
@@ -39,6 +51,14 @@ export class Watchable {
_lastValue: null,
_watchers: new Set(),
}
+ this.initFetcher = fetcher
+ ? (currentValue?: ValueType) => {
+ this.loading = true
+ const newValue = fetcher?.(currentValue)
+ this.loading = false
+ return newValue || init
+ }
+ : undefined
}
watch(
@@ -54,6 +74,13 @@ export class Watchable {
}
}
get value(): ValueType {
+ if (this._watchableStore._initialized === false && this.initFetcher) {
+ this._watchableStore._value =
+ this.initFetcher?.(this._watchableStore._value) ||
+ this._watchableStore._value
+ this._watchableStore._publicValue = deepClone(this._watchableStore._value)
+ this._watchableStore._initialized = true
+ }
return this._watchableStore._publicValue
}
}
@@ -62,8 +89,12 @@ export class WatchableMutable<
ValueType extends NonNullable = any
> extends Watchable {
private _history: HistorySeed | undefined
- constructor(instance: () => PlexusInstance, init: ValueType) {
- super(instance, init)
+ constructor(
+ instance: () => PlexusInstance,
+ init: ValueType,
+ fetcher?: (currentValue?: ValueType) => ValueType
+ ) {
+ super(instance, init, fetcher)
}
/**
diff --git a/packages/plexus-react/src/index.ts b/packages/plexus-react/src/index.ts
index 550cf414..492b66a4 100644
--- a/packages/plexus-react/src/index.ts
+++ b/packages/plexus-react/src/index.ts
@@ -4,4 +4,4 @@ export { useEvent } from './useEvent'
export { useDeposit } from './useDeposit'
-export { useInit } from './useInit'
\ No newline at end of file
+export { useInit } from './useInit'
diff --git a/packages/plexus-react/src/useInit.ts b/packages/plexus-react/src/useInit.ts
index 4736fb9a..9321a248 100644
--- a/packages/plexus-react/src/useInit.ts
+++ b/packages/plexus-react/src/useInit.ts
@@ -1,32 +1,38 @@
-import { PlexusAction, Watchable } from '@plexusjs/core';
-import { FunctionType, InnerFunction } from '@plexusjs/core/dist/action';
-import { useEffect, useState } from 'react';
-import { usePlexus, PlexusValue, PlexusValueArray } from './usePlexus';
+import { PlexusAction, Watchable } from '@plexusjs/core'
+import { FunctionType, InnerFunction } from '@plexusjs/core/dist/action'
+import { useEffect, useState } from 'react'
+import { usePlexus, PlexusValue, PlexusValueArray } from './usePlexus'
export type PlexusInitReturn = {
- value: T;
- loading: boolean;
+ value: T
+ loading: boolean
}
// Singleton argument
-export function useInit(deps: V, action: InnerFunction): PlexusInitReturn>
+export function useInit(
+ deps: V,
+ action: InnerFunction
+): PlexusInitReturn>
// array argument
export function useInit(
deps: V | [],
- action: InnerFunction
+ action: InnerFunction
): PlexusInitReturn>
-export function useInit (deps: typeof usePlexus.arguments[0], action: InnerFunction) {
- const value = usePlexus(deps);
- const [loading, setLoading] = useState(true);
+export function useInit(
+ deps: typeof usePlexus.arguments[0],
+ action: InnerFunction
+) {
+ const value = usePlexus(deps)
+ const [loading, setLoading] = useState(true)
- useEffect(() => {
- setLoading(true);
- action().then(() => setLoading(false));
- }, [action])
+ useEffect(() => {
+ setLoading(true)
+ action().then(() => setLoading(false))
+ }, [action])
- return {
- loading,
- value
- }
-}
\ No newline at end of file
+ return {
+ loading,
+ value,
+ }
+}
diff --git a/packages/plexus-utils/src/shared/itemManipulation.ts b/packages/plexus-utils/src/shared/itemManipulation.ts
index 1447b1b5..70921fed 100644
--- a/packages/plexus-utils/src/shared/itemManipulation.ts
+++ b/packages/plexus-utils/src/shared/itemManipulation.ts
@@ -147,3 +147,15 @@ export function isEqual(a: NonNullable, b: NonNullable): boolean {
}
return false
}
+
+/**
+ *
+ */
+// export function asyncNormalizer<
+// InputFunction extends () => Promise | unknown
+// >(
+// inputFunction: InputFunction
+// ): [ReturnType | undefined, Error | undefined] {
+
+// // return [inputFunction()]
+// }