Skip to main content

createHandler

Creates a handler factory function with custom options for building type-safe request handlers.
import { createHandler } from '@apisr/controller';

const handler = createHandler({
  responseHandler: myResponseHandler,
  bindings: (bind) => ({
    user: bind.model(User),
  }),
  cache: {
    store: myStore,
  },
});
handlerOptions
HandlerOptions
required
Configuration options for the handler factory
responseHandler
AnyResponseHandler
Response handler instance for error formatting and response mapping
bindings
(helpers: BindingsHelpers) => BindingsInput
Factory function that returns bindings for dependency injection
cache
CacheOptions
Default cache configuration for all handlers
store
CacheStore
required
Cache store implementation
key
CacheKey | CacheKeyResolver
Cache key or resolver function
wrapHandler
boolean
Whether to cache the entire handler response
name
string
Name identifier for the handler
handler
HandlerFn.Base
Handler factory function for creating individual handlers

Handler Factory Function

The function returned by createHandler is used to define individual request handlers.
const getUser = handler(
  async ({ payload, user, cache, fail }) => {
    // Handler logic
    return { id: user.id, name: user.name };
  },
  {
    payload: { id: s.params("id") },
    user: true,
  }
);
callback
HandlerFn.Callback
required
The handler function that processes requestsContext Properties:
payload
InferUndefined<Schema>
Validated payload data from the schema
cache
CacheFn
Cache function for memoizing expensive operations
const result = await cache(['key', userId], async () => {
  return await expensiveOperation();
});
fail
(name: string, input: any) => never
Function to throw formatted errors via the response handler
redirect
(to: string, returnType?: T) => T | {}
Function to perform redirects with optional return type
...bindings
InferredBindings
All injected bindings are spread into the context
options
HandlerFn.Options
Per-handler configuration options
payload
Schema
Schema definition for request validation
cache
CacheOptions
Override cache options for this handler
...bindingOptions
OptionsBindings
Configuration for each binding (pass true to enable or an options object)
component
HandlerFn.Component
A compiled handler component with two execution modes
component(data, opts?)
Promise<Result>
Execute the handler in direct mode with type-safe data
const { data, error } = await getUser({ id: '123' });
component.raw({ request })
Promise<Response>
Execute the handler in raw mode with a full HTTP request
const response = await getUser.raw({ request });

HandlerFn.Result

The result object returned by handler components.
interface Result<TData, TError> {
  data: TData;
  error: TError;
}
data
TData | null
The successful response data, or null if an error occurred
error
TError | null
The error object if the handler failed, or null on success

Usage Example

import { createHandler, createOptions } from '@apisr/controller';
import { createResponseHandler } from '@apisr/response';
import { s } from '@apisr/schema';
import { User } from './models';

const responseHandler = createResponseHandler({
  errors: {
    notFound: { status: 404, message: 'Not found' },
    internal: { status: 500, message: 'Internal error' },
  },
});

const options = createOptions({
  responseHandler,
  bindings: (bind) => ({
    user: bind.model(User, {
      from: 'params',
      fromKey: 'userId',
      primaryKey: 'id',
      async load({ id, fail }) {
        const user = await User.findById(id);
        if (!user) throw fail('notFound', { id });
        return user;
      },
    }),
  }),
});

const handler = createHandler(options);

// Define a handler
const getUser = handler(
  async ({ payload, user }) => {
    return {
      id: user.id,
      name: user.name,
      email: user.email,
    };
  },
  {
    payload: {
      userId: s.params('id'),
    },
    user: true,
  }
);

// Use the handler
const { data, error } = await getUser({ userId: '123' });

if (error) {
  console.error('Failed to get user:', error);
} else {
  console.log('User:', data);
}

Type Utilities

HandlerFn.Context

Infers the context type for a handler callback.
type MyContext = HandlerFn.Context<typeof options, typeof handlerOptions>;

HandlerFn.Component

The compiled handler component type.
type MyComponent = HandlerFn.Component<
  typeof options,
  typeof handlerOptions,
  ReturnType<typeof callback>
>;

HandlerFn.Result

The result type returned by handler execution.
type MyResult = HandlerFn.Result<UserData, ErrorSchema>;

Build docs developers (and LLMs) love