Skip to content

HttpLayerRouter

42 exports Added in v1.0.0 Source

Configuration

RouterConfig

Added in v1.0.0 Source

Signature

declare class RouterConfig extends any {
  constructor();
}

HttpApi

addHttpApi

Added in v1.0.0 Source

Signature

declare function addHttpApi<Id extends string, Groups extends Any, E, R>(
  api: HttpApi<Id, Groups, E, R>,
  options?: {
    readonly openapiPath?: `/${string}`;
  },
): Layer<
  never,
  never,
  | Generator
  | FileSystem
  | HttpPlatform
  | Path
  | HttpRouter
  | R
  | ToService<Id, Groups>
  | ErrorContext<Groups>
>;

HttpRouter

add

Added in v1.0.0 Source

Create a layer that adds a single route to the HTTP router.

Signature

declare function add<E, R>(method: "GET" | "POST" | "PUT" | "DELETE" | "PATCH" | "OPTIONS" | "*", path: PathInput, handler: Effect<HttpServerResponse, E, R> | (request: HttpServerRequest) => Effect<HttpServerResponse, E, R>, options?: {
  readonly uninterruptible?: boolean;
}): Layer<never, never, HttpRouter | From<"Requires", Exclude<R, Provided>> | From<"Error", E>>

addAll

Added in v1.0.0 Source

Create a layer that adds multiple routes to the HTTP router.

Signature

declare function addAll<Routes extends readonly Array<Route<any, any>>, EX = never, RX = never>(routes: Routes | Effect<Routes, EX, RX>, options?: {
  readonly prefix?: string;
}): Layer<never, EX, HttpRouter | Exclude<RX, Scope> | From<"Requires", Exclude<Context<Routes[number]>, Provided>> | From<"Error", Error<Routes[number]>>>

HttpRouter

Added in v1.0.0 Source

Signature

declare const HttpRouter: Tag<HttpRouter, HttpRouter>;

HttpRouter interface

Added in v1.0.0 Source

Signature

interface HttpRouter {
  readonly [TypeId]: typeof TypeId;
  readonly add: <E, R>(method: "GET" | "POST" | "PUT" | "DELETE" | "PATCH" | "OPTIONS" | "*", path: PathInput, handler: Effect<HttpServerResponse, E, R> | (request: HttpServerRequest) => Effect<HttpServerResponse, E, R>, options?: {
    readonly uninterruptible?: boolean;
  }) => Effect<void, never, From<"Requires", Exclude<R, Provided>> | From<"Error", E>>;
  readonly addAll: <Routes extends readonly Array<Route<any, any>>>(routes: Routes) => Effect<void, never, From<"Requires", Exclude<Context<Routes[number]>, Provided>> | From<"Error", Error<Routes[number]>>>;
  readonly addGlobalMiddleware: <E, R>(middleware: (effect: Effect<HttpServerResponse, unhandled>) => Effect<HttpServerResponse, E, R> & unhandled extends E ? unknown : "You cannot handle any errors") => Effect<void, never, From<"GlobalRequires", Exclude<R, GlobalProvided>> | From<"GlobalError", Exclude<E, unhandled>>>;
  readonly asHttpEffect: () => Effect<HttpServerResponse, unknown, Scope | HttpServerRequest>;
  readonly prefixed: (prefix: string) => HttpRouter;
}

layer

Added in v1.0.0 Source

Signature

declare const layer: Layer.Layer<HttpRouter>;

make

Added in v1.0.0 Source

Signature

declare const make: Effect<any, unknown, unknown>;

toHttpEffect

Added in v1.0.0 Source

Signature

declare function toHttpEffect<A, E, R>(
  appLayer: Layer<A, E, R>,
): Effect<
  Effect<
    HttpServerResponse,
    RouteNotFound | Only<"Error", R> | Only<"GlobalRequires", R>,
    Scope | HttpServerRequest | Only<"GlobalRequires", R> | Only<"Requires", R>
  >,
  Without<E>,
  Scope | Exclude<Without<R>, HttpRouter>
>;

TypeId

Added in v1.0.0 Source

Signature

declare const TypeId: unique symbol;

TypeId type

Added in v1.0.0 Source

Signature

type TypeId = typeof TypeId;

use

Added in v1.0.0 Source

A helper function that is the equivalent of:

Signature

declare function use<A, E, R>(
  f: (router: HttpRouter) => Effect<A, E, R>,
): Layer<never, E, HttpRouter | Exclude<R, Scope>>;

Middleware

cors

Added in v1.0.0 Source

A middleware that applies CORS headers to the HTTP response.

Signature

declare function cors(options?: {
  readonly allowedHeaders?: readonly Array<string>;
  readonly allowedMethods?: readonly Array<string>;
  readonly allowedOrigins?: readonly Array<string> | Predicate<string>;
  readonly credentials?: boolean;
  readonly exposedHeaders?: readonly Array<string>;
  readonly maxAge?: number;
}): Layer<never, never, HttpRouter>

A middleware that disables the logger for some routes.

Signature

declare const disableLogger: Layer.Layer<never>;

Example

import * as HttpLayerRouter from "@effect/platform/HttpLayerRouter"
import * as HttpServerResponse from "@effect/platform/HttpServerResponse"
import * as Layer from "effect/Layer"

const Route = HttpLayerRouter.add("GET", "/hello", HttpServerResponse.text("Hello, World!")).pipe(
  // disable the logger for this route
  Layer.provide(HttpLayerRouter.disableLogger),
)

middleware

Added in v1.0.0 Source

Create a middleware layer that can be used to modify requests and responses.

By default, the middleware only affects the routes that it is provided to.

If you want to create a middleware that applies globally to all routes, pass the global option as true.

Signature

declare const middleware: middleware.Make<never, never> & <Config extends {
  handles?: any;
  provides?: any;
} = {}>() => middleware.Make<Config extends {
  provides: infer R;
} ? R : never, Config extends {
  handles: infer E;
} ? E : never>

Example

import * as HttpLayerRouter from "@effect/platform/HttpLayerRouter"
import * as HttpMiddleware from "@effect/platform/HttpMiddleware"
import * as HttpServerResponse from "@effect/platform/HttpServerResponse"
import * as Context from "effect/Context"
import * as Effect from "effect/Effect"
import * as Layer from "effect/Layer"

// Here we are defining a CORS middleware
const CorsMiddleware = HttpLayerRouter.middleware(HttpMiddleware.cors()).layer
// You can also use HttpLayerRouter.cors() to create a CORS middleware

class CurrentSession extends Context.Tag("CurrentSession")<
  CurrentSession,
  {
    readonly token: string
  }
>() {}

// You can create middleware that provides a service to the HTTP requests.
const SessionMiddleware = HttpLayerRouter.middleware<{
  provides: CurrentSession
}>()(
  Effect.gen(function* () {
    yield* Effect.log("SessionMiddleware initialized")

    return (httpEffect) =>
      Effect.provideService(httpEffect, CurrentSession, {
        token: "dummy-token",
      })
  }),
).layer

Effect.gen(function* () {
  const router = yield* HttpLayerRouter.HttpRouter
  yield* router.add(
    "GET",
    "/hello",
    Effect.gen(function* () {
      // Requests can now access the current session
      const session = yield* CurrentSession
      return HttpServerResponse.text(`Hello, World! Your token is ${session.token}`)
    }),
  )
}).pipe(
  Layer.effectDiscard,
  // Provide the SessionMiddleware & CorsMiddleware to some routes
  Layer.provide([SessionMiddleware, CorsMiddleware]),
)

middleware

Added in v1.0.0 Source

Middleware interface

Added in v1.0.0 Source

Signature

interface Middleware<
  Config extends {
    error: any;
    handles: any;
    layerError: any;
    layerRequires: any;
    provides: any;
    requires: any;
  },
> {
  readonly [MiddlewareTypeId]: Config;
  readonly combine: <
    Config2 extends {
      error: any;
      handles: any;
      layerError: any;
      layerRequires: any;
      provides: any;
      requires: any;
    },
  >(
    other: Middleware<Config2>,
  ) => Middleware<{
    error: Config2["error"] | Exclude<Config["error"], Config2["handles"]>;
    handles: Config2["handles"] | Config["handles"];
    layerError: Config["layerError"] | Config2["layerError"];
    layerRequires: Config["layerRequires"] | Config2["layerRequires"];
    provides: Config["provides"] | Config2["provides"];
    requires: Exclude<Config["requires"], Config2["provides"]> | Config2["requires"];
  }>;
  readonly layer: [Config["requires"]] extends [never]
    ? Layer<
        From<"Requires", Config["provides"]>,
        Config["layerError"],
        Config["layerRequires"] | From<"Requires", any[any]> | From<"Error", Config["error"]>
      >
    : "Need to .combine(middleware) that satisfy the missing request dependencies";
}

Signature

declare const MiddlewareTypeId: unique symbol;

MiddlewareTypeId type

Added in v1.0.0 Source

Signature

type MiddlewareTypeId = typeof MiddlewareTypeId;

unhandled interface

Added in v1.0.0 Source

A pseudo-error type that represents an error that should be not handled by the middleware.

Signature

interface unhandled {
  readonly _: typeof _;
}

Models

RouteContext interface

Added in v1.0.0 Source

Signature

interface RouteContext {
  readonly [RouteContextTypeId]: typeof RouteContextTypeId;
  readonly params: Readonly<Record<string, string | undefined>>;
  readonly route: Route<unknown, unknown>;
}

PathInput

PathInput type

Added in v1.0.0 Source

Signature

type PathInput = `/${string}` | "*";

prefixPath

Added in v1.0.0 Source

Signature

declare const prefixPath: {
  (prefix: string): (self: string) => string;
  (self: string, prefix: string): string;
};

Re-Exports

FindMyWay

Added in v1.0.0

Signature

declare const FindMyWay: any;

Request Types

GlobalProvided type

Added in v1.0.0 Source

Services provided to global middleware.

Signature

type GlobalProvided = HttpServerRequest.HttpServerRequest | Scope.Scope;

Provided type

Added in v1.0.0 Source

Services provided by the HTTP router, which are available in the request context.

Signature

type Provided =
  | HttpServerRequest.HttpServerRequest
  | Scope.Scope
  | HttpServerRequest.ParsedSearchParams
  | RouteContext;

Request

Added in v1.0.0 Source

Request interface

Added in v1.0.0 Source

Represents a request-level dependency, that needs to be provided by middleware.

Signature

interface Request<Kind extends string, T> {
  readonly _: typeof _;
  readonly kind: Kind;
  readonly type: T;
}

Route

prefixRoute

Added in v1.0.0 Source

Signature

declare const prefixRoute: {
  (prefix: string): <E, R>(self: Route<E, R>) => Route<E, R>;
  <E, R>(self: Route<E, R>, prefix: string): Route<E, R>;
};

route

Added in v1.0.0 Source

Signature

declare function route<E, R>(method: "GET" | "POST" | "PUT" | "DELETE" | "PATCH" | "OPTIONS" | "*", path: PathInput, handler: Effect<HttpServerResponse, E, R> | (request: HttpServerRequest) => Effect<HttpServerResponse, E, R>, options?: {
  readonly uninterruptible?: boolean;
}): Route<E, Exclude<R, Provided>>

Route

Added in v1.0.0 Source

Route interface

Added in v1.0.0 Source

Signature

interface Route<E = never, R = never> {
  readonly [RouteTypeId]: typeof RouteTypeId;
  readonly handler: Effect<HttpServerResponse, E, R>;
  readonly method: HttpMethod | "*";
  readonly path: PathInput;
  readonly prefix: Option<string>;
  readonly uninterruptible: boolean;
}

RouteTypeId

Added in v1.0.0 Source

Signature

declare const RouteTypeId: unique symbol;

RouteTypeId type

Added in v1.0.0 Source

Signature

type RouteTypeId = typeof RouteTypeId;

Route Context

params

Added in v1.0.0 Source

Signature

declare const params: Effect.Effect<
  Readonly<Record<string, string | undefined>>,
  never,
  RouteContext
>;

RouteContext

Added in v1.0.0 Source

Signature

declare const RouteContext: Tag<RouteContext, RouteContext>;

schemaJson

Added in v1.0.0 Source

Signature

declare const schemaJson: <
  R,
  I extends Partial<{
    readonly body: any;
    readonly cookies: Readonly<Record<string, string | undefined>>;
    readonly headers: Readonly<Record<string, string | undefined>>;
    readonly method: Method.HttpMethod;
    readonly pathParams: Readonly<Record<string, string | undefined>>;
    readonly searchParams: Readonly<Record<string, string | ReadonlyArray<string> | undefined>>;
    readonly url: string;
  }>,
  A,
>(
  schema: Schema.Schema<A, I, R>,
  options?: ParseOptions,
) => Effect.Effect<
  A,
  Error.RequestError | ParseResult.ParseError,
  RouteContext | R | ServerRequest.HttpServerRequest | ServerRequest.ParsedSearchParams
>;

schemaNoBody

Added in v1.0.0 Source

Signature

declare const schemaNoBody: <
  R,
  I extends Partial<{
    readonly cookies: Readonly<Record<string, string | undefined>>;
    readonly headers: Readonly<Record<string, string | undefined>>;
    readonly method: Method.HttpMethod;
    readonly pathParams: Readonly<Record<string, string | undefined>>;
    readonly searchParams: Readonly<Record<string, string | ReadonlyArray<string> | undefined>>;
    readonly url: string;
  }>,
  A,
>(
  schema: Schema.Schema<A, I, R>,
  options?: ParseOptions,
) => Effect.Effect<
  A,
  ParseResult.ParseError,
  R | RouteContext | ServerRequest.HttpServerRequest | ServerRequest.ParsedSearchParams
>;

schemaParams

Added in v1.0.0 Source

Signature

declare const schemaParams: <
  A,
  I extends Readonly<Record<string, string | ReadonlyArray<string> | undefined>>,
  R,
>(
  schema: Schema.Schema<A, I, R>,
  options?: ParseOptions,
) => Effect.Effect<A, ParseResult.ParseError, R | RouteContext | ServerRequest.ParsedSearchParams>;

Signature

declare const schemaPathParams: <A, I extends Readonly<Record<string, string | undefined>>, R>(
  schema: Schema.Schema<A, I, R>,
  options?: ParseOptions,
) => Effect.Effect<A, ParseResult.ParseError, R | RouteContext>;

Server

serve

Added in v1.0.0 Source

Serves the provided application layer as an HTTP server.

Signature

declare function serve<A, E, R, HE, HR = Only<"Requires", R> | Only<"GlobalRequires", R>>(
  appLayer: Layer<A, E, R>,
  options?: {
    readonly disableListenLog?: boolean;
    readonly disableLogger?: boolean;
    readonly middleware?: (
      effect: Effect<
        HttpServerResponse,
        RouteNotFound | Only<"Error", R> | Only<"GlobalError", R>,
        Scope | HttpServerRequest | Only<"Requires", R> | Only<"GlobalRequires", R>
      >,
    ) => Effect<HttpServerResponse, HE, HR>;
    readonly routerConfig?: any;
  },
): Layer<
  A,
  Without<E>,
  HttpServer | Exclude<Without<R>, HttpRouter> | Exclude<Exclude<HR, GlobalProvided>, HttpRouter>
>;

toWebHandler

Added in v1.0.0 Source

Signature

declare function toWebHandler<
  A,
  E,
  R extends
    | HttpRouter
    | Request<"Requires", any>
    | Request<"GlobalRequires", any>
    | Request<"Error", any>
    | Request<"GlobalError", any>,
  HE,
  HR = Exclude<Only<"Requires", R>, A> | Exclude<Only<"GlobalRequires", R>, A>,
>(
  appLayer: Layer<A, E, R>,
  options?: {
    readonly disableLogger?: boolean;
    readonly memoMap?: MemoMap;
    readonly middleware?: (
      effect: Effect<
        HttpServerResponse,
        RouteNotFound | Only<"Error", R> | Only<"GlobalError", R>,
        Scope | HttpServerRequest | Only<"Requires", R> | Only<"GlobalRequires", R>
      >,
    ) => Effect<HttpServerResponse, HE, HR>;
    readonly routerConfig?: any;
  },
): {
  readonly dispose: () => Promise<void>;
  readonly handler: [HR] extends [never]
    ? (request: Request, context?: Context<never>) => Promise<Response>
    : (request: Request, context: Context<HR>) => Promise<Response>;
};