Utilities
createStore
Section titled “createStore”Creates a store: a value you can change, commit, and revert, the same way Inkweaver handles state.
createStore<T>(initial: T): Store<T>
interface Store<T> { clear: () => void; commit: () => void; get: () => T; getCommitted: () => T; getPrevious: () => T; onChange: (listener: (value: T, oldValue: T) => void) => () => void; onClear: (listener: (value: T) => void) => () => void; onCommit: (listener: (committed: T, previous: T) => void) => () => void; onRevert: (listener: (value: T) => void) => () => void; revert: () => void; set: (value: ((current: T) => T) | T) => T; update: (partial: Partial<T>) => T;}| Function | Description |
|---|---|
get | Returns the current value. |
set | Replaces the current value. Takes a value, or a function that receives the current value. |
update | Merges a partial value into the current value. |
commit | Makes the current value the committed value. Does nothing if the current value hasn’t changed. |
getCommitted | Returns the value from the most recent commit. |
getPrevious | Returns the committed value from before the most recent commit. |
revert | Sets the current value back to the committed value. |
clear | Resets the current, committed, and previous values to initial. |
Stored values are deeply frozen. A store lives in memory only, so it isn’t saved in history or bookmarks.
Each on function adds a listener, and returns a function that removes it.
| Listener | Called when |
|---|---|
onChange | The current value changes, including through revert and clear. |
onCommit | commit records a new committed value. |
onRevert | revert is called. |
onClear | clear is called. |
Listeners run synchronously, in the order they were added. If any throw, the rest still run, and the errors are thrown together as an AggregateError.
Example
const store = createStore({ count: 0 });store.onChange((value) => console.log(value.count));
store.update({ count: 1 }); // logs 1store.commit();
store.getCommitted(); // { count: 1 }store.getPrevious(); // { count: 0 }immutable
Section titled “immutable”Runs an async function, and calls onError if it changed state.
immutable<T>( fn: () => Promise<T>, onError: (changes: string) => void): Promise<T>Use it during development to catch unexpected state changes. onError receives a description of what changed.
Example
await immutable( () => doSomeWork(), (changes) => console.warn(`Unexpected state changes: ${changes}`),);withCallStack
Section titled “withCallStack”Gives part of your state a separate value for each level of the screenplay’s call stack. When the story calls into a section, the value gets a new level, and when it returns, the previous value comes back.
withCallStack<T>( key: string, onPush?: () => T, onPop?: (item: undefined | T) => void): void| Parameter | Description |
|---|---|
key | The state key to track. |
onPush | Returns the value for a new level. By default, a new level starts as a shallow copy of the current value. |
onPop | Called with a level’s value when it’s removed. |
Call withCallStack once, from your init command. After that, state[key] always holds the current level’s value, and state[key + "Stack"] holds the full stack.
Example
withCallStack("beat");With this in place, state.beat holds the beat for the current level, and state.beatStack holds the levels beneath it. Calling into a section starts a new beat, and returning restores the one you left.
withCallStack( "inventory", () => ({ items: [] }), (discarded) => console.log(`Left a level holding ${discarded?.items.length} items`),);