@stainless-code/persist
Version:
Hydration-aware persistence for any reactive store — zero-dep persistSource core; codecs, backends, cross-tab transport, source + framework hydration adapters ship as opt-in recipes
63 lines (48 loc) • 1.79 kB
Markdown
---
name: alpine-persist
description: Gate Alpine.js UI on Persist hydration (Alpine.plugin + useHydrated / $hydrated). Use when wiring HydrationSignal into Alpine data components.
license: MIT
metadata:
type: framework
library: "@stainless-code/persist"
library_version: "0.4.1"
framework: "alpine"
requires:
- persist
sources:
- stainless-code/persist:src/adapters/frameworks/alpine.ts
---
# Alpine hydration gate
`@stainless-code/persist/frameworks/alpine` is **plugin-first**: `Alpine.plugin(persist)` registers `$hydrated` and enables reactive `useHydrated`. Call `destroy()` from `Alpine.data` teardown.
## Install
```bash
bun add @stainless-code/persist alpinejs
```
Peer: `alpinejs` `>=3.0.0` (types via `@types/alpinejs` — package ships none).
## Minimal wiring
```ts
import Alpine from "alpinejs";
import persist, {
useHydrated,
} from "@stainless-code/persist/frameworks/alpine";
Alpine.plugin(persist);
Alpine.data("prefs", () => {
const hydration = useHydrated(prefsHydration);
return {
get hydrated() {
return hydration.hydrated;
},
destroy() {
hydration.destroy();
},
};
});
```
Template: `x-show="$hydrated(prefsHydration).hydrated"` — `$hydrated(signal)` returns a **bag** (`{ hydrated, destroy }`), not a boolean (a bare bag is always truthy in `x-show`). Magic caches per element.
## Common mistakes
- **Skipping `Alpine.plugin(persist)`.** `useHydrated` falls back to a plain object + one-time non-prod warn.
- **`x-show="$hydrated(...)"` without `.hydrated`.**
- **Not forwarding `destroy()`** from `Alpine.data`.
## API surface
- default/`persist(Alpine)` — plugin; registers `$hydrated(signal) → HydratedBag`
- `useHydrated(signal) → { hydrated; destroy() }` (null signal → `{ hydrated: true }`)