Alveron Middleware Persistence

raw JSON →
8.0.3 verified Thu Apr 23 auth: no javascript

Alveron Middleware Persistence is a specialized middleware designed to integrate a state persistence layer into Alveron applications. Alveron is a lightweight, Elm-inspired state management library for React (approx. 1.2kb) that leverages React's `useState` hook and handles asynchronous side effects. This middleware enables Alveron stores to automatically persist their state to browser storage mechanisms like `localStorage` or `sessionStorage`, ensuring that application data endures across page reloads or browser sessions. The current stable version, 8.0.3, is designed to work seamlessly with Alveron versions greater than 8.0.0. While a specific release cadence for this middleware is not publicly documented, its versioning typically aligns with major releases of the core `alveron` library. Its primary differentiator is its direct compatibility and integration within the Alveron ecosystem, providing a structured approach to state hydration and rehydration tailored for Alveron's model, actions, and effects architecture.

error Uncaught TypeError: Cannot read properties of undefined (reading 'getItem')
cause Attempting to use the middleware in a Node.js environment (e.g., SSR) where `localStorage` or `sessionStorage` are not defined.
fix
Wrap your Alveron store initialization with a check for typeof window !== 'undefined' or provide localStorage / sessionStorage polyfills for Node.js environments.
error TypeError: (0 , _alveron_middleware_persistence__WEBPACK_IMPORTED_MODULE_1__.default) is not a function
cause Incorrect CommonJS `require()` usage for an ESM-first package or incorrect named vs default import syntax in an ESM context.
fix
For ESM, use import persistenceMiddleware from 'alveron-middleware-persistence';. For CommonJS (if supported), ensure correct interop or use a bundler that handles ESM imports correctly.
error Error: Alveron: useStoreWithMiddleware expects the 'alveron' library to be installed. Please ensure it's in your dependencies.
cause The peer dependency `alveron` is missing or an incompatible version is installed.
fix
Install or upgrade Alveron: npm install alveron@'>8.0.0' or yarn add alveron@'>8.0.0'.
breaking Major version updates (e.g., from v7 to v8) typically introduce breaking changes, often related to underlying Alveron API changes or persistence configuration format. Consult Alveron's changelog and this middleware's documentation for migration steps.
fix Review the official Alveron and alveron-middleware-persistence documentation for migration guides and updated API usage when upgrading major versions.
gotcha Changes to the shape of your persisted state (e.g., adding/removing properties, changing data types) can lead to hydration errors or unexpected behavior if old, incompatible data exists in `localStorage` or `sessionStorage`. Users' browsers might hold stale data from previous versions of your application.
fix Implement a versioning strategy within your persistence configuration (if supported by the library) and provide migration functions. For development, manually clear browser storage (`localStorage.clear()`) after schema changes. For production, consider user-data migration strategies or default fallbacks for undefined properties.
gotcha This middleware is designed for browser environments using `localStorage` or `sessionStorage`. Attempting to use it directly in a Node.js environment (e.g., for Server-Side Rendering) without appropriate polyfills for these browser APIs will result in runtime errors.
fix Ensure the middleware is only executed in browser contexts, or provide global polyfills for `localStorage` and `sessionStorage` (e.g., using `node-localstorage` or a mock) for SSR or Node.js testing environments.
npm install alveron-middleware-persistence
yarn add alveron-middleware-persistence
pnpm add alveron-middleware-persistence

This example demonstrates how to integrate `alveron-middleware-persistence` with an Alveron store to persist and rehydrate a simple counter's state using `localStorage`. It shows the basic setup of an Alveron store with actions and how to apply the configured persistence middleware.

import * as React from 'react';
import { useStoreWithMiddleware, Middleware } from 'alveron';
import persistenceMiddleware from 'alveron-middleware-persistence';

interface Model {
  count: number;
  lastUpdate: string;
}

interface Actions {
  increment: (amount?: number) => Model;
  decrement: (amount?: number) => Model;
}

const initialModel: Model = {
  count: 0,
  lastUpdate: new Date().toISOString(),
};

const actions = {
  increment: (amount: number = 1) => (prevState: Model) => [
    { ...prevState, count: prevState.count + amount, lastUpdate: new Date().toISOString() },
  ],
  decrement: (amount: number = 1) => (prevState: Model) => [
    { ...prevState, count: prevState.count - amount, lastUpdate: new Date().toISOString() },
  ],
};

// Define persistence configuration
const persistenceConfig = {
  key: 'my-alveron-app-state', // Unique key for localStorage
  storage: localStorage, // or sessionStorage
  // Optional: only persist `count`, not `lastUpdate`
  partialize: (state: Model) => ({ count: state.count }),
};

const persistedCounterMiddleware: Middleware<Model, Actions> = persistenceMiddleware(persistenceConfig);

function Counter() {
  const [state, { increment, decrement }] = useStoreWithMiddleware(
    actions,
    initialModel,
    [persistedCounterMiddleware]
  );

  return (
    <div>
      <h1>Count: {state.count}</h1>
      <p>Last updated: {new Date(state.lastUpdate).toLocaleTimeString()}</p>
      <button onClick={() => increment()}>Increment</button>
      <button onClick={() => decrement()}>Decrement</button>
      <button onClick={() => localStorage.clear()}>Clear Storage</button>
      <p>Refresh the page to see the count persist!</p>
    </div>
  );
}

function App() {
  return (
    <React.StrictMode>
      <Counter />
    </React.StrictMode>
  );
}

export default App;