@stainless-code/persist
Version:
Hydration-aware persistence middleware for reactive stores (storage × codec seams, TanStack Store adapters, React hydration hook)
54 lines (53 loc) • 1.85 kB
JavaScript
import { a as jsonCodec, i as identityCodec, n as createPersistRegistry, o as persistSource, r as createStorage, t as createJSONStorage } from "./persist-core-BFflqOey.mjs";
//#region src/hydration.ts
/**
* Derive a `HydrationSignal` from a `HydrationSource` (e.g. a `PersistApi`),
* bridging `onHydrate` / `onFinishHydration` into one external-store
* subscribe target that notifies on either transition. Null-tolerant:
* `null` / `undefined` in → `null` out, so a conditional-persist consumer
* drops its hydration ternary (`persist ? toHydrationSignal(persist) : null`
* → `toHydrationSignal(persist)`).
*/
function toHydrationSignal(source) {
if (!source) return null;
const listeners = /* @__PURE__ */ new Set();
const emit = () => {
for (const listener of listeners) listener();
};
let unsubHydrate = null;
let unsubFinish = null;
return {
subscribeHydrated(listener) {
const entry = () => listener();
listeners.add(entry);
if (listeners.size === 1) {
unsubHydrate = source.onHydrate(emit);
unsubFinish = source.onFinishHydration(emit);
}
return () => {
if (!listeners.delete(entry)) return;
if (listeners.size === 0) {
unsubHydrate?.();
unsubFinish?.();
unsubHydrate = null;
unsubFinish = null;
}
};
},
isHydrated: () => source.hasHydrated()
};
}
/**
* Always-hydrated `HydrationSignal` for the no-persist path — a uniform
* handle instead of a `null` branch at the call site. Solves null-tolerance
* once in the core so framework adapters stay dumb (subscribe + snapshot,
* nothing else).
*/
function alwaysHydratedSignal() {
return {
subscribeHydrated: () => () => {},
isHydrated: () => true
};
}
//#endregion
export { alwaysHydratedSignal, createJSONStorage, createPersistRegistry, createStorage, identityCodec, jsonCodec, persistSource, toHydrationSignal };