@zedux/atoms
Version:
A Molecular State Engine for React
275 lines (274 loc) • 11.8 kB
TypeScript
import { AnyAtomInstance, AnyAtomTemplate, AtomGettersBase, AtomInstanceType, AtomParamsType, AtomStateType, EcosystemConfig, GraphEdgeInfo, GraphViewRecursive, ParamlessTemplate, PartialAtomInstance, Selectable } from '../types/index';
import { EvaluationStack } from './EvaluationStack';
import { Graph } from './Graph';
import { IdGenerator } from './IdGenerator';
import { Scheduler } from './Scheduler';
import { Selectors } from './Selectors';
import { Mod, ZeduxPlugin } from './ZeduxPlugin';
export declare class Ecosystem<Context extends Record<string, any> | undefined = any> implements AtomGettersBase {
atomDefaults?: EcosystemConfig['atomDefaults'];
complexParams?: boolean;
context: Context;
destroyOnUnmount?: boolean;
flags?: string[];
hydration?: Record<string, any>;
id: string;
modBus: import("@zedux/core").Store<any>;
onReady: EcosystemConfig<Context>['onReady'];
overrides: Record<string, AnyAtomTemplate>;
selectors: Selectors;
ssr?: boolean;
_graph: Graph;
_evaluationStack: EvaluationStack;
_idGenerator: IdGenerator;
_instances: Record<string, AnyAtomInstance>;
_mods: Record<Mod, number>;
_refCount: number;
_scheduler: Scheduler;
/**
* Only for use by internal addon packages - lets us attach anything we want
* to the ecosystem. For example, the React package uses this to store React
* Context objects
*/
_storage: Record<string, any>;
private cleanup?;
private isInitialized;
private plugins;
constructor(config: EcosystemConfig<Context>);
/**
* Merge the passed atom overrides into the ecosystem's current list of
* overrides. Force-destroys all atom instances currently in the ecosystem
* that should now be overridden.
*
* This can't be used to remove overrides. Use `.setOverrides()` or
* `.removeOverrides()` for that.
*/
addOverrides(overrides: AnyAtomTemplate[]): void;
/**
* Batch all state updates that happen synchronously during the passed
* callback's execution. Flush all updates when the passed callback completes.
*
* Has no effect if the scheduler is already running - updates are always
* batched when the scheduler is running.
*/
batch<T = any>(callback: () => T): T;
/**
* Retrieve an object mapping atom instance ids to their current values.
*
* Calls the `dehydrate` atom config option (on atoms that have one) to
* transform state to a serializable form. Pass `transform: false` to prevent
* this.
*
* Atoms can be excluded from dehydration by passing `exclude` and/or
* `excludeFlags` options:
*
* ```ts
* myEcosystem.dehydrate({
* exclude: [myAtom, 'my-fuzzy-search-string'],
* excludeFlags: ['no-ssr']
* })
* ```
*
* An atom passed to `exclude` will exclude all instances of that atom. A
* string passed to `exclude` will exclude all instances whose id contains the
* string (case-insensitive)
*
* You can dehydrate only a subset of all atoms by passing `include` and/or
* `includeFlags` options:
*
* ```ts
* myEcosystem.dehydrate({
* include: [myAtom, 'my-fuzzy-search-string'],
* includeFlags: ['ssr']
* })
* ```
*
* An atom passed to `include` will include all instances of that atom. A
* string passed to `include` will include all instances whose id contains the
* string (case-insensitive)
*
* Excludes takes precedence over includes.
*
* By default, dehydration will call any configured `dehydrate` atom config
* options to transform atom instance state. Pass `{ transform: false }` to
* prevent this.
*/
dehydrate({ exclude, excludeFlags, include, includeFlags, transform, }?: {
exclude?: (AnyAtomTemplate | string)[];
excludeFlags?: string[];
include?: (AnyAtomTemplate | string)[];
includeFlags?: string[];
transform?: boolean;
}): Record<string, any>;
/**
* Destroy this ecosystem - destroy all this ecosystem's atom instances,
* remove and clean up all plugins, and remove this ecosystem from the
* internal store.
*
* Destruction will bail out by default if this ecosystem is still being
* provided via an <EcosystemProvider>. Pass `true` as the first parameter to
* force destruction anyway.
*/
destroy(force?: boolean): void;
/**
* Get an atom instance. Don't create the atom instance if it doesn't exist.
* Don't register any graph dependencies.
*
* Tries to find an exact match, but falls back to doing a fuzzy search if no
* exact match is found. Pass atom params (or an empty array if no params or
* when passing a search string) for the second argument to disable fuzzy
* search.
*/
find<A extends AnyAtomTemplate>(template: A, params: AtomParamsType<A>): AtomInstanceType<A> | undefined;
find<A extends AnyAtomTemplate<{
Params: [];
}>>(template: A): AtomInstanceType<A> | undefined;
find<A extends AnyAtomTemplate>(template: ParamlessTemplate<A>): AtomInstanceType<A> | undefined;
find<A extends AnyAtomTemplate = any>(searchStr: string, params?: []): AtomInstanceType<A> | undefined;
/**
* Get an object of all atom instances in this ecosystem keyed by their id.
*
* Pass an atom template to only find instances of that atom. Pass an atom key
* string to only return instances whose id weakly matches the passed key.
*/
findAll(template?: AnyAtomTemplate | string): Record<string, AnyAtomInstance<"any">>;
get<A extends AnyAtomTemplate>(template: A, params: AtomParamsType<A>): AtomStateType<A>;
get<A extends AnyAtomTemplate<{
Params: [];
}>>(template: A): AtomStateType<A>;
get<A extends AnyAtomTemplate>(template: ParamlessTemplate<A>): AtomStateType<A>;
get<I extends AnyAtomInstance>(instance: I): AtomStateType<I>;
getInstance<A extends AnyAtomTemplate>(template: A, params: AtomParamsType<A>, edgeInfo?: GraphEdgeInfo): AtomInstanceType<A>;
getInstance<A extends AnyAtomTemplate<{
Params: [];
}>>(template: A): AtomInstanceType<A>;
getInstance<A extends AnyAtomTemplate>(template: ParamlessTemplate<A>): AtomInstanceType<A>;
getInstance<I extends AnyAtomInstance>(instance: I, params?: [], edgeInfo?: GraphEdgeInfo): I;
/**
* Hydrate the state of atoms in this ecosystem with an object mapping atom
* instance ids to their hydrated state. This object will usually be the
* result of a call to `ecosystem.dehydrate()`.
*
* This is the key to SSR. The ecosystem's initial state can be dehydrated on
* the server, sent to the client in serialized form, deserialized, and passed
* to `ecosystem.hydrate()`. Every atom instance that evaluates after this
* hydration can use the `hydrate` injectStore config option to retrieve its
* hydrated state.
*
* Pass `retroactive: false` to prevent this call from updating the state of
* all atom instances that have already been initialized with this new
* hydration. Hydration is retroactive by default.
*
* ```ts
* ecosystem.hydrate(dehydratedState, { retroactive: false })
* ```
*/
hydrate(dehydratedState: Record<string, any>, config?: {
retroactive?: boolean;
}): void;
/**
* Add a ZeduxPlugin to this ecosystem. This ecosystem will subscribe to the
* plugin's modStore, whose state can be changed to reactively update the mods
* of this ecosystem.
*
* This method will also call the passed plugin's `.registerEcosystem` method,
* allowing the plugin to subscribe to this ecosystem's modBus
*
* The plugin will remain part of this ecosystem until it is unregistered or
* this ecosystem is destroyed. `.wipe()` and `.reset()` don't remove plugins.
* However, a plugin _can_ set the `ecosystemWiped` mod and react to those
* events.
*/
registerPlugin(plugin: ZeduxPlugin): void;
/**
* Remove all passed atoms from this ecosystem's list of atom overrides. Does
* nothing for passed atoms that aren't currently in the overrides list.
*
* Force destroys all instances of all removed atoms. This forced destruction
* will cause dependents of those instances to recreate their dependency atom
* instance without using an override.
*/
removeOverrides(overrides: (AnyAtomTemplate | string)[]): void;
/**
* Destroys all atom instances in this ecosystem, runs the cleanup function
* returned from `onReady` (if any), and calls `onReady` again to reinitialize
* the ecosystem.
*
* Note that this doesn't remove overrides or plugins but _does_ remove
* hydrations. This is because you can remove overrides/plugins yourself if
* needed, but there isn't currently a way to remove hydrations.
*/
reset(newContext?: Context): void;
/**
* Runs an AtomSelector statically - without registering any dependencies or
* updating any caches. If we've already cached this exact selector + args
* combo, returns the cached value without running the selector again
*/
select<T, Args extends any[]>(selectable: Selectable<T, Args>, ...args: Args): T;
/**
* Completely replace this ecosystem's current list of atom overrides with a
* new list.
*
* Force destroys all instances of all previously- and newly-overridden atoms.
* This forced destruction will cause dependents of those instances to
* recreate their dependency atom instance.
*/
setOverrides(newOverrides: AnyAtomTemplate[]): void;
/**
* Unregister a plugin registered in this ecosystem via `.registerPlugin()`
*/
unregisterPlugin(plugin: ZeduxPlugin): void;
viewGraph(view: 'bottom-up'): GraphViewRecursive;
viewGraph(view?: 'flat'): Record<string, {
dependencies: {
key: string;
operation: string;
}[];
dependents: {
key: string;
operation: string;
}[];
weight: number;
}>;
viewGraph(view: 'top-down'): GraphViewRecursive;
/**
* Returns the list of reasons detailing why the current atom instance or
* selector is evaluating.
*
* Returns undefined if nothing is currently evaluating. Returns an empty
* array if this is the first evaluation of the instance or selector.
*/
why(): import("../types/index").EvaluationReason<any>[] | undefined;
/**
* Destroy all atom instances in this ecosystem. Also run the cleanup function
* returned from the onReady callback (if any). Don't remove plugins or re-run
* the onReady callback.
*
* Also don't remove overrides. This may usually be wanted, but it's easy
* enough to add a `.setOverrides([])` call when you need it.
*
* Important! This method is mostly for internal use. You won't typically want
* to call this method. Prefer `.reset()` which re-runs the onReady callback
* after wiping the ecosystem, allowing onReady to re-initialize the ecosystem
* - preloading atoms, registering plugins, configuring context, etc
*/
wipe(): void;
/**
* Should only be used internally
*/
_consumeHydration(instance: PartialAtomInstance): any;
/**
* Should only be used internally
*/
_decrementRefCount(): void;
/**
* Should only be used internally
*/
_destroyAtomInstance(id: string): void;
/**
* Should only be used internally
*/
_incrementRefCount(): void;
private recalculateMods;
private resolveAtom;
}