synapse-storage
Version:
Набор инструментов для управления состоянием и апи-запросами
66 lines (65 loc) • 4.6 kB
TypeScript
import type { Observable } from 'rxjs';
import type { IStorage } from '../../core';
/**
* Handle C-формы: как {@link SynapseModule}, но с СИНХРОННЫМ доступом к main-ядру. Конструкция
* расцеплена со стартом эффектов, поэтому `storage`/`selectors`/`dispatcher`/`state$` доступны
* синхронно (main строится лениво при первом обращении). Это и даёт cross-store DI:
* `otherModule.selectors` можно передать в конструктор чужих селекторов синхронно.
*/
export interface SyncSynapseModule<TState extends Record<string, any>, TDispatcher, TSelectors> extends SynapseModule<TState, TDispatcher, TSelectors> {
readonly storage: IStorage<TState>;
readonly state$: Observable<TState>;
readonly dispatcher: TDispatcher;
/** Алиас `dispatcher`. */
readonly actions: TDispatcher;
/** Селекторы main-ядра — их и берут cross-store DI. */
readonly selectors: TSelectors;
}
/**
* Опции C-формы — ВТОРОЙ аргумент {@link createSynapse}. `postConstruct` живёт здесь (а не в
* объект-конфиге), чтобы его колбэк контекстно типизировался уже выведенными `TDispatcher`/`TSelectors`
* (в одном литерале с `dispatcher: (s) => …` он получил бы implicit any).
*/
export interface SyncSynapseOptions<TState extends Record<string, any>, TDispatcher, TSelectors> {
postConstruct?: (synapse: Synapse<TState, TDispatcher, TSelectors>) => void;
}
/** Готовый synapse — результат `SynapseModule.ready()` (или синхронной конструкции C-формы). */
export interface Synapse<TState extends Record<string, any>, TDispatcher, TSelectors> {
storage: IStorage<TState>;
/** Поток состояния — присутствует ВСЕГДА, даже без эффектов. */
state$: Observable<TState>;
/** Инстанс class-диспетчера (`undefined`, если нет). */
dispatcher: TDispatcher;
/** Алиас `dispatcher`: его поля и есть dispatch-функции. */
actions: TDispatcher;
/** Инстанс class-селекторов (`undefined`, если нет). */
selectors: TSelectors;
destroy(): Promise<void>;
}
/**
* Ленивый пересоздаваемый handle. Конструкция/эффекты запускаются при первом `await`/`ready()`, а не
* на импорте; повторные `await` делят один промис; `destroy()` сбрасывает мемоизацию.
*/
export interface SynapseModule<TState extends Record<string, any>, TDispatcher, TSelectors> extends PromiseLike<Synapse<TState, TDispatcher, TSelectors>> {
/**
* Первый вызов строит ядро и (при `withEffects: true`, по умолчанию) стартует эффекты; повторные —
* тот же промис. `withEffects: false` — серверный прогрев дегидрации: собирает стор без старта
* эффектов (см. {@link import('../dehydrateModule').dehydrateModule}).
*/
ready(options?: {
withEffects?: boolean;
}): Promise<Synapse<TState, TDispatcher, TSelectors>>;
/** Построено ли main-ядро. */
isReady(): boolean;
/** Синхронный доступ к собранному main (или `undefined`). Нужен SSR-биндингу на первом кадре. */
getSnapshot(): Synapse<TState, TDispatcher, TSelectors> | undefined;
/**
* Синхронно строит СВЕЖЕЕ throwaway-ядро из `initialState` (не main): без эффектов и зависимостей.
* Новый инстанс на каждый вызов (per-request изоляция на сервере, throwaway на первый кадр гидрации).
*/
buildSyncShell?(): Synapse<TState, TDispatcher, TSelectors> | undefined;
/** Независимый handle из той же фабрики — свой стор и жизненный цикл (per-request изоляция на сервере). */
fork(): SynapseModule<TState, TDispatcher, TSelectors>;
/** Останавливает модуль (LIFO-teardown) и сбрасывает мемоизацию. */
destroy(): Promise<void>;
}