Skip to main content

middleware

---
title: Middleware API
sidebar_label: Middleware
---

import CodeBlock from '@theme/CodeBlock';
import { Admonition } from '@site/src/components/Admonition';

# API: Middleware

Middleware in SoulState allows you to intercept and enhance the store's `set` method using a functional composition pattern. Middleware wraps the `set` function to add cross-cutting concerns like logging, persistence, or debugging.

## How Middleware Works

In SoulState, middleware follows a **curried function pattern** that wraps the store's `set` method. Each middleware receives configuration and returns a function that enhances the state creation process.

### Basic Pattern

<CodeBlock language="typescript">
{`import { createStore } from 'soulstate';
import { logger } from 'soulstate/core';

// Middleware is applied by wrapping the store creation
const store = createStore(
logger((set, get) => ({
count: 0,
increment: () => set(state => ({ count: state.count + 1 }))
}))
);
`}
</CodeBlock>

## Built-in Middleware

### `logger` Middleware

Adds console logging for all state updates.

<CodeBlock language="typescript">
{`import { createStore } from 'soulstate';
import { logger } from 'soulstate/core';

const store = createStore(
logger((set, get) => ({
count: 0,
increment: () => set(state => ({ count: state.count + 1 }))
}))
);

store.set({ count: 1 });
// Console output:
// SoulState Update
// Previous State: { count: 0 }
// Next State: { count: 1 }
`}
</CodeBlock>

### `reduxDevtools` Middleware

Connects to Redux DevTools Extension.

<CodeBlock language="typescript">
{`import { createStore } from 'soulstate';
import { reduxDevtools } from 'soulstate/core';

const store = createStore(
reduxDevtools('MyApp')((set, get) => ({
todos: [],
addTodo: (text) => set(state => ({
todos: [...state.todos, { id: Date.now(), text }]
}))
}))
);
`}
</CodeBlock>

### `persistMiddleware`

Persists state to localStorage.

<CodeBlock language="typescript">
{`import { createStore } from 'soulstate';
import { persistMiddleware } from 'soulstate/core';

const store = createStore(
persistMiddleware({
key: 'my-app-state',
storage: localStorage
})((set, get) => ({
user: null,
theme: 'light',
setUser: (user) => set({ user })
}))
);
`}
</CodeBlock>

## Creating Custom Middleware

Custom middleware follows the same curried pattern.

### Middleware Signature

<CodeBlock language="typescript">
{`type Middleware = <T>(
config?: any
) => (
set: (partial: T | ((state: T) => T)) => void,
get: () => T,
api: any
) => (partial: T | ((state: T) => T)) => void;
`}
</CodeBlock>

### Simple Custom Middleware

<CodeBlock language="typescript">
{`const analyticsMiddleware = (eventName: string) => (set, get, api) => (partial) => {
const prevState = get();
const result = set(partial);
const nextState = get();

console.log(`[Analytics] ${eventName}:`, { prevState, nextState });
return result;
};

const store = createStore(
analyticsMiddleware('counter-update')((set, get) => ({
count: 0,
increment: () => set(state => ({ count: state.count + 1 }))
}))
);
`}
</CodeBlock>

### Advanced Custom Middleware

<CodeBlock language="typescript">
{`const createUndoMiddleware = (maxHistory = 50) => (set, get, api) => {
const history = [get()];
let index = 0;

const enhancedSet = (partial) => {
const result = set(partial);
history.push(get());
index = history.length - 1;

if (history.length > maxHistory) history.shift();
return result;
};

api.undo = () => index > 0 && set(history[--index]);
api.redo = () => index < history.length - 1 && set(history[++index]);

return enhancedSet;
};

const store = createStore(
createUndoMiddleware()((set, get, api) => ({
count: 0,
increment: () => set(state => ({ count: state.count + 1 })),
undo: api.undo,
redo: api.redo
}))
);
`}
</CodeBlock>

## Middleware Composition

Chain multiple middleware by nesting them.

<CodeBlock language="typescript">
{`import { logger, reduxDevtools, persistMiddleware } from 'soulstate/core';

const store = createStore(
logger(
reduxDevtools('App')(
persistMiddleware({ key: 'app' })(
(set, get) => ({
user: null,
setUser: (user) => set({ user })
})
)
)
)
);
`}
</CodeBlock>

<Admonition type="warning" title="Important Pattern">
<p>SoulState middleware uses a <strong>curried function pattern</strong>, not a store enhancement pattern. Middleware wraps the store creation process, not existing stores.</p>
</Admonition>

<Admonition type="info" title="Implementation Detail">
<p>All built-in middleware follow the same pattern: <code>(config) => (set, get, api) => (partial) => { ... }</code></p>
</Admonition>