Skip to content

Commit

Permalink
mostly working except for rejections
Browse files Browse the repository at this point in the history
  • Loading branch information
Akolyte01 committed Jul 25, 2023
1 parent 6af4016 commit 7cc4482
Show file tree
Hide file tree
Showing 4 changed files with 334 additions and 223 deletions.
8 changes: 7 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,11 @@
# Changelog #

notes:

- state store now always included
- all mapping load functions are rebounced by default
- if an async store loses all subscriptions and then gains one the mapping load function will always evaluate even if the inputs have not changed

## 1.0.17 (2023-6-20)

- *BREAKING CHANGE* chore: rearrange dependencies to minimize installed package size
Expand All @@ -8,7 +14,7 @@

## 1.0.16 (2023-6-20)

- fix: moduleResoltion: NoodeNext support
- fix: moduleResoltion: NodeNext support
- feat: allow for custom storage types for persisted stores

## 1.0.15 (2023-2-27)
Expand Down
109 changes: 89 additions & 20 deletions src/async-stores/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ import {
reloadAll,
loadAll,
rebounce,
getAll,
} from '../utils/index.js';
import { flagStoreCreated, getStoreTestingMode, logError } from '../config.js';

Expand Down Expand Up @@ -66,7 +67,9 @@ export const asyncWritable = <S extends Stores, T>(
options: AsyncStoreOptions<T> = {}
): WritableLoadable<T> => {
flagStoreCreated();
const { reloadable, trackState, initial } = options;
const { reloadable, initial, debug } = options;

const debuggy = debug ? console.log : undefined;

const rebouncedMappingLoad = rebounce(mappingLoadFunction);

Expand Down Expand Up @@ -95,16 +98,22 @@ export const asyncWritable = <S extends Stores, T>(
const mappingLoadThenSet = async (setStoreValue) => {
if (get(loadState).isSettled) {
setCurrentLoadPromise();
debuggy?.('setting RELOADING');
setState('RELOADING');
}

try {
const finalValue = await rebouncedMappingLoad(parentValues);
debuggy?.('setting value');
setStoreValue(finalValue);
if (!get(loadState).isWriting) {
debuggy?.('setting LOADED');
setState('LOADED');
}
resolveCurrentLoad(finalValue);
setState('LOADED');
} catch (e) {
if (e.name !== 'AbortError') {
logError(e);
setState('ERROR');
rejectCurrentLoad(e);
}
Expand All @@ -113,28 +122,34 @@ export const asyncWritable = <S extends Stores, T>(

const onFirstSubscription: StartStopNotifier<T> = (setStoreValue) => {
setCurrentLoadPromise();
parentValues = getAll(stores);

const initialLoad = async () => {
debuggy?.('initial load called');
try {
parentValues = await loadAll(stores);
debuggy?.('setting ready');
ready = true;
changeReceived = false;
mappingLoadThenSet(setStoreValue);
} catch (error) {
console.log('wtf is happening', error);
rejectCurrentLoad(error);
}
};
initialLoad();

const parentUnsubscribers = getStoresArray(stores).map((store, i) =>
store.subscribe((value) => {
debuggy?.('received value', value);
changeReceived = true;
if (Array.isArray(stores)) {
parentValues[i] = value;
} else {
parentValues = value as any;
parentValues = value as StoresValues<S>;
}
if (ready) {
debuggy?.('proceeding because ready');
mappingLoadThenSet(setStoreValue);
}
})
Expand All @@ -143,41 +158,93 @@ export const asyncWritable = <S extends Stores, T>(
// called on losing last subscriber
return () => {
parentUnsubscribers.map((unsubscriber) => unsubscriber());
ready = false;
};
};

const thisStore = writable(initial, onFirstSubscription);

const setStoreValueThenWrite = async (
updater: Updater<T>,
persist?: boolean
) => {
setState('WRITING');
let oldValue: T;
try {
oldValue = await currentLoadPromise;
} catch {
oldValue = get(thisStore);
}

setCurrentLoadPromise();
let newValue = updater(oldValue);
thisStore.set(newValue);

if (mappingWriteFunction && persist) {
try {
const writeResponse = (await mappingWriteFunction(
newValue,
parentValues,
oldValue
)) as T;

if (writeResponse !== undefined) {
thisStore.set(writeResponse);
newValue = writeResponse;
}
} catch (error) {
logError(error);
debuggy?.('setting ERROR');
setState('ERROR');
rejectCurrentLoad(error);
throw error;
}
}
setState('LOADED');
resolveCurrentLoad(newValue);
};

// required properties
const subscribe = thisStore.subscribe;
const load = async () => {
const load = () => {
const dummyUnsubscribe = thisStore.subscribe(() => {
/* no-op */
});
try {
const result = await currentLoadPromise;
dummyUnsubscribe();
return result;
} catch (error) {
dummyUnsubscribe();
throw error;
}
currentLoadPromise
.catch(() => {
/* no-op */
})
.finally(dummyUnsubscribe);
return currentLoadPromise;
};
const reload = async (visitedMap?: VisitedMap) => {
ready = false;
changeReceived = false;
setCurrentLoadPromise();
debuggy?.('setting RELOADING from reload');
setState('RELOADING');

const visitMap = visitedMap ?? new WeakMap();
await reloadAll(stores, visitMap);
ready = true;
if (changeReceived || reloadable) {
mappingLoadThenSet(thisStore.set);
} else {
resolveCurrentLoad(get(thisStore));
try {
await reloadAll(stores, visitMap);
ready = true;
if (changeReceived || reloadable) {
mappingLoadThenSet(thisStore.set);
} else {
resolveCurrentLoad(get(thisStore));
setState('LOADED');
}
} catch (error) {
debuggy?.('caught error during reload');
setState('ERROR');
rejectCurrentLoad(error);
}
return currentLoadPromise;
};
const set = (newValue: T, persist = true) =>
setStoreValueThenWrite(() => newValue, persist);
const update = (updater: Updater<T>, persist = true) =>
setStoreValueThenWrite(updater, persist);

return {
get store() {
Expand All @@ -186,10 +253,12 @@ export const asyncWritable = <S extends Stores, T>(
subscribe,
load,
reload,
set: () => Promise.resolve(),
update: () => Promise.resolve(),
set,
update,
state: { subscribe: loadState.subscribe },
};
};

/**
* Generate a Loadable store that is considered 'loaded' after resolving asynchronous behavior.
* This asynchronous behavior may be derived from the value of parent Loadable or non Loadable stores.
Expand Down
1 change: 1 addition & 0 deletions src/async-stores/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@ export type WritableLoadable<T> = Loadable<T> & AsyncWritable<T>;
export interface AsyncStoreOptions<T> {
reloadable?: true;
trackState?: true;
debug?: true;
initial?: T;
}
export declare type StoresArray =
Expand Down
Loading

0 comments on commit 7cc4482

Please sign in to comment.