Skip to content

Middleware

Overview

Middleware in neutrix provides a way to intercept and modify store operations. It can:

  • Intercept state changes (onSet) and reads (onGet)
  • Transform values
  • Perform validation
  • Handle errors
  • Log operations
  • Add custom behavior

Basic Usage

Creating Middleware

typescript
interface Middleware {
  onSet?: (path: string, value: any, prevValue: any) => any;
  onGet?: (path: string, value: any) => any;
  onError?: (error: Error) => void;
}

const useStore = createNeutrixStore({
  count: 0,
  user: { name: '', isLoggedIn: false }
});

const loggerMiddleware: Middleware = {
  onSet: (path, value, prevValue) => {
    console.log(`Setting ${path}:`, prevValue, '→', value);
    return value;
  },
  onGet: (path, value) => {
    console.log(`Getting ${path}:`, value);
    return value;
  },
  onError: (error) => {
    console.error('Store error:', error);
  }
};

// Attach the middleware to the store
const cleanup = useStore.store.use(loggerMiddleware);

Common use cases:

1. Value Transformation

typescript
const transformMiddleware: Middleware = {
  onSet: (path, value, prevValue) => {
    // transform values before they're stored
    if (path.startsWith('user.name')) {
      return value.trim();
    }
    if (path.startsWith('user.email')) {
      return value.toLowerCase();
    }
    return value;
  }
};

2. Validation

typescript
const validationMiddleware: Middleware = {
  onSet: (path, value, prevValue) => {
    // Validate values before they're stored
    if (path === 'user.age' && (value < 0 || value > 120)) {
      throw new Error('Invalid age');
    }
    if (path === 'user.email' && !value.includes('@')) {
      throw new Error('Invalid email');
    }
    return value;
  },
  onError: (error) => {
    console.error('Validation failed:', error);
  }
};

3. Logging

typescript
const debugMiddleware: Middleware = {
  onSet: (path, value, prevValue) => {
    console.log(`[${new Date().toISOString()}] Setting ${path}`, {
      from: prevValue,
      to: value
    });
    return value;
  },
  onGet: (path, value) => {
    console.log(`[${new Date().toISOString()}] Getting ${path}:`, value);
    return value;
  }
};

Middleware Cleanup

Middleware can be removed when no longer needed using the cleanup function returned by use

typescript
const cleanup = useStore.store.use(debugMiddleware);

cleanup(); // removing the middleware

Important Notes

  • Return Values: Middleware must return the value in onSet and onGet.
  • Execution Order: Multiple middleware can be used. They run in the order added.
  • Error Handling: Errors thrown in onSet or onGet will trigger onError if provided.
  • Batch Updates: Middleware also applies to batched updates.