/** * @since 1.0.0 */ import * as HttpServerRequest from "@effect/platform/HttpServerRequest"; 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"; import * as Option from "effect/Option"; import type * as Predicate from "effect/Predicate"; import * as Scope from "effect/Scope"; import type * as Types from "effect/Types"; import * as FindMyWay from "find-my-way-ts"; import type * as Etag from "./Etag.js"; import type { FileSystem } from "./FileSystem.js"; import type * as HttpApi from "./HttpApi.js"; import type * as HttpApiGroup from "./HttpApiGroup.js"; import type * as HttpMethod from "./HttpMethod.js"; import type { HttpPlatform } from "./HttpPlatform.js"; import { RouteContext } from "./HttpRouter.js"; import * as HttpServer from "./HttpServer.js"; import * as HttpServerError from "./HttpServerError.js"; import type { Path } from "./Path.js"; /** * @since 1.0.0 * @category Re-exports */ export * as FindMyWay from "find-my-way-ts"; /** * @since 1.0.0 * @category HttpRouter */ export declare const TypeId: unique symbol; /** * @since 1.0.0 * @category HttpRouter */ export type TypeId = typeof TypeId; /** * @since 1.0.0 * @category HttpRouter */ export interface HttpRouter { readonly [TypeId]: TypeId; readonly prefixed: (prefix: string) => HttpRouter; readonly add: (method: "*" | "GET" | "POST" | "PUT" | "PATCH" | "DELETE" | "OPTIONS", path: PathInput, handler: Effect.Effect | ((request: HttpServerRequest.HttpServerRequest) => Effect.Effect), options?: { readonly uninterruptible?: boolean | undefined; } | undefined) => Effect.Effect> | Request.From<"Error", E>>; readonly addAll: >>(routes: Routes) => Effect.Effect, Provided>> | Request.From<"Error", Route.Error>>; readonly addGlobalMiddleware: (middleware: ((effect: Effect.Effect) => Effect.Effect) & (unhandled extends E ? unknown : "You cannot handle any errors")) => Effect.Effect> | Request.From<"GlobalError", Exclude>>; readonly asHttpEffect: () => Effect.Effect; } /** * @since 1.0.0 * @category HttpRouter */ export declare const HttpRouter: Context.Tag; /** * @since 1.0.0 * @category HttpRouter */ export declare const make: Effect.Effect; declare const RouterConfig_base: Context.ReferenceClass>; /** * @since 1.0.0 * @category Configuration */ export declare class RouterConfig extends RouterConfig_base { } export { /** * @since 1.0.0 * @category Route context */ params, /** * @since 1.0.0 * @category Route context */ RouteContext, /** * @since 1.0.0 * @category Route context */ schemaJson, /** * @since 1.0.0 * @category Route context */ schemaNoBody, /** * @since 1.0.0 * @category Route context */ schemaParams, /** * @since 1.0.0 * @category Route context */ schemaPathParams } from "./HttpRouter.js"; /** * A helper function that is the equivalent of: * * ```ts * import * as HttpLayerRouter from "@effect/platform/HttpLayerRouter" * import * as Effect from "effect/Effect" * import * as Layer from "effect/Layer" * * const MyRoute = Layer.scopedDiscard(Effect.gen(function*() { * const router = yield* HttpLayerRouter.HttpRouter * * // then use `yield* router.add(...)` to add a route * })) * ``` * * @since 1.0.0 * @category HttpRouter */ export declare const use: (f: (router: HttpRouter) => Effect.Effect) => Layer.Layer>; /** * Create a layer that adds a single route to the HTTP router. * * ```ts * import * as HttpLayerRouter from "@effect/platform/HttpLayerRouter" * import * as HttpServerResponse from "@effect/platform/HttpServerResponse" * * const Route = HttpLayerRouter.add("GET", "/hello", HttpServerResponse.text("Hello, World!")) * ``` * * @since 1.0.0 * @category HttpRouter */ export declare const add: (method: "*" | "GET" | "POST" | "PUT" | "PATCH" | "DELETE" | "OPTIONS", path: PathInput, handler: Effect.Effect | ((request: HttpServerRequest.HttpServerRequest) => Effect.Effect), options?: { readonly uninterruptible?: boolean | undefined; }) => Layer.Layer> | Request.From<"Error", E>>; /** * Create a layer that adds multiple routes to the HTTP router. * * ```ts * import * as HttpLayerRouter from "@effect/platform/HttpLayerRouter" * import * as HttpServerResponse from "@effect/platform/HttpServerResponse" * * const Routes = HttpLayerRouter.addAll([ * HttpLayerRouter.route("GET", "/hello", HttpServerResponse.text("Hello, World!")) * ]) * ``` * * @since 1.0.0 * @category HttpRouter */ export declare const addAll: >, EX = never, RX = never>(routes: Routes | Effect.Effect, options?: { readonly prefix?: string | undefined; }) => Layer.Layer | Request.From<"Requires", Exclude, Provided>> | Request.From<"Error", Route.Error>>; /** * @since 1.0.0 * @category HttpRouter */ export declare const layer: Layer.Layer; /** * @since 1.0.0 * @category HttpRouter */ export declare const toHttpEffect: (appLayer: Layer.Layer) => Effect.Effect | Request.Only<"GlobalRequires", R> | HttpServerError.RouteNotFound, Scope.Scope | HttpServerRequest.HttpServerRequest | Request.Only<"Requires", R> | Request.Only<"GlobalRequires", R>>, Request.Without, Exclude, HttpRouter> | Scope.Scope>; /** * @since 1.0.0 * @category Route */ export declare const RouteTypeId: unique symbol; /** * @since 1.0.0 * @category Route */ export type RouteTypeId = typeof RouteTypeId; /** * @since 1.0.0 * @category Route */ export interface Route { readonly [RouteTypeId]: RouteTypeId; readonly method: HttpMethod.HttpMethod | "*"; readonly path: PathInput; readonly handler: Effect.Effect; readonly uninterruptible: boolean; readonly prefix: Option.Option; } /** * @since 1.0.0 * @category Route */ export declare namespace Route { /** * @since 1.0.0 * @category Route */ type Error> = R extends Route ? E : never; /** * @since 1.0.0 * @category Route */ type Context> = T extends Route ? R : never; } /** * @since 1.0.0 * @category Route */ export declare const route: (method: "*" | "GET" | "POST" | "PUT" | "PATCH" | "DELETE" | "OPTIONS", path: PathInput, handler: Effect.Effect | ((request: HttpServerRequest.HttpServerRequest) => Effect.Effect), options?: { readonly uninterruptible?: boolean | undefined; }) => Route>; /** * @since 1.0.0 * @category PathInput */ export type PathInput = `/${string}` | "*"; /** * @since 1.0.0 * @category PathInput */ export declare const prefixPath: { /** * @since 1.0.0 * @category PathInput */ (prefix: string): (self: string) => string; /** * @since 1.0.0 * @category PathInput */ (self: string, prefix: string): string; }; /** * @since 1.0.0 * @category Route */ export declare const prefixRoute: { /** * @since 1.0.0 * @category Route */ (prefix: string): (self: Route) => Route; /** * @since 1.0.0 * @category Route */ (self: Route, prefix: string): Route; }; /** * Represents a request-level dependency, that needs to be provided by * middleware. * * @since 1.0.0 * @category Request types */ export interface Request { readonly _: unique symbol; readonly kind: Kind; readonly type: T; } /** * @since 1.0.0 * @category Request types */ export declare namespace Request { /** * @since 1.0.0 * @category Request types */ type From = R extends infer T ? Request : never; /** * @since 1.0.0 * @category Request types */ type Only = A extends Request ? T : never; /** * @since 1.0.0 * @category Request types */ type Without = A extends Request ? never : A; } /** * Services provided by the HTTP router, which are available in the * request context. * * @since 1.0.0 * @category Request types */ export type Provided = HttpServerRequest.HttpServerRequest | Scope.Scope | HttpServerRequest.ParsedSearchParams | RouteContext; /** * Services provided to global middleware. * * @since 1.0.0 * @category Request types */ export type GlobalProvided = HttpServerRequest.HttpServerRequest | Scope.Scope; /** * @since 1.0.0 * @category Middleware */ export declare const MiddlewareTypeId: unique symbol; /** * @since 1.0.0 * @category Middleware */ export type MiddlewareTypeId = typeof MiddlewareTypeId; /** * A pseudo-error type that represents an error that should be not handled by * the middleware. * * @since 1.0.0 * @category Middleware */ export interface unhandled { readonly _: unique symbol; } /** * @since 1.0.0 * @category Middleware */ export interface Middleware { readonly [MiddlewareTypeId]: Config; readonly layer: [Config["requires"]] extends [never] ? Layer.Layer, Config["layerError"], Config["layerRequires"] | Request.From<"Requires", Config["requires"]> | Request.From<"Error", Config["error"]>> : "Need to .combine(middleware) that satisfy the missing request dependencies"; readonly combine: (other: Middleware) => Middleware<{ provides: Config2["provides"] | Config["provides"]; handles: Config2["handles"] | Config["handles"]; error: Config2["error"] | Exclude; requires: Exclude | Config2["requires"]; layerError: Config["layerError"] | Config2["layerError"]; layerRequires: Config["layerRequires"] | Config2["layerRequires"]; }>; } /** * 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`. * * ```ts * 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")() {} * * // 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]) * ) * ``` * * @since 1.0.0 * @category Middleware */ export declare const middleware: middleware.Make & (() => middleware.Make); /** * @since 1.0.0 * @category Middleware */ export declare namespace middleware { /** * @since 1.0.0 * @category Middleware */ type Make = { (middleware: Effect.Effect<(effect: Effect.Effect, Types.NoInfer>) => Effect.Effect & (unhandled extends E ? unknown : "You must only handle the configured errors"), EX, RX>, options?: { readonly global?: Global | undefined; }): Global extends true ? Layer.Layer | Request.From<"Error", Handles> | Request.From<"GlobalRequires", Provides> | Request.From<"GlobalError", Handles>, EX, HttpRouter | Exclude | Request.From<"GlobalRequires", Exclude> | Request.From<"GlobalError", Exclude>> : Middleware<{ provides: Provides; handles: Handles; error: Exclude; requires: Exclude; layerError: EX; layerRequires: Exclude; }>; (middleware: ((effect: Effect.Effect, Types.NoInfer>) => Effect.Effect) & (unhandled extends E ? unknown : "You must only handle the configured errors"), options?: { readonly global?: Global | undefined; }): Global extends true ? Layer.Layer | Request.From<"Error", Handles> | Request.From<"GlobalRequires", Provides> | Request.From<"GlobalError", Handles>, never, HttpRouter | Request.From<"GlobalRequires", Exclude> | Request.From<"GlobalError", Exclude>> : Middleware<{ provides: Provides; handles: Handles; error: Exclude; requires: Exclude; layerError: never; layerRequires: never; }>; }; /** * @since 1.0.0 * @category Middleware */ type Fn = (effect: Effect.Effect) => Effect.Effect; } /** * A middleware that applies CORS headers to the HTTP response. * * @since 1.0.0 * @category Middleware */ export declare const cors: (options?: { readonly allowedOrigins?: ReadonlyArray | Predicate.Predicate | undefined; readonly allowedMethods?: ReadonlyArray | undefined; readonly allowedHeaders?: ReadonlyArray | undefined; readonly exposedHeaders?: ReadonlyArray | undefined; readonly maxAge?: number | undefined; readonly credentials?: boolean | undefined; } | undefined) => Layer.Layer; /** * A middleware that disables the logger for some routes. * * ```ts * 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) * ) * ``` * * @since 1.0.0 * @category Middleware */ export declare const disableLogger: Layer.Layer; /** * ```ts * import * as NodeHttpServer from "@effect/platform-node/NodeHttpServer" * import * as NodeRuntime from "@effect/platform-node/NodeRuntime" * import * as HttpApi from "@effect/platform/HttpApi" * import * as HttpApiBuilder from "@effect/platform/HttpApiBuilder" * import * as HttpApiEndpoint from "@effect/platform/HttpApiEndpoint" * import * as HttpApiGroup from "@effect/platform/HttpApiGroup" * import * as HttpApiScalar from "@effect/platform/HttpApiScalar" * import * as HttpLayerRouter from "@effect/platform/HttpLayerRouter" * import * as HttpMiddleware from "@effect/platform/HttpMiddleware" * import * as Effect from "effect/Effect" * import * as Layer from "effect/Layer" * import { createServer } from "http" * * // First, we define our HttpApi * class MyApi extends HttpApi.make("api").add( * HttpApiGroup.make("users").add( * HttpApiEndpoint.get("me", "/me") * ).prefix("/users") * ) {} * * // Implement the handlers for the API * const UsersApiLayer = HttpApiBuilder.group(MyApi, "users", (handers) => handers.handle("me", () => Effect.void)) * * // Use `HttpLayerRouter.addHttpApi` to register the API with the router * const HttpApiRoutes = HttpLayerRouter.addHttpApi(MyApi, { * openapiPath: "/docs/openapi.json" * }).pipe( * // Provide the api handlers layer * Layer.provide(UsersApiLayer) * ) * * // Create a /docs route for the API documentation * const DocsRoute = HttpApiScalar.layerHttpLayerRouter({ * api: MyApi, * path: "/docs" * }) * * const CorsMiddleware = HttpLayerRouter.middleware(HttpMiddleware.cors()) * // You can also use HttpLayerRouter.cors() to create a CORS middleware * * // Finally, we merge all routes and serve them using the Node HTTP server * const AllRoutes = Layer.mergeAll( * HttpApiRoutes, * DocsRoute * ).pipe( * Layer.provide(CorsMiddleware.layer) * ) * * HttpLayerRouter.serve(AllRoutes).pipe( * Layer.provide(NodeHttpServer.layer(createServer, { port: 3000 })), * Layer.launch, * NodeRuntime.runMain * ) * ``` * * @since 1.0.0 * @category HttpApi */ export declare const addHttpApi: (api: HttpApi.HttpApi, options?: { readonly openapiPath?: `/${string}` | undefined; }) => Layer.Layer | HttpApiGroup.HttpApiGroup.ErrorContext>; /** * Serves the provided application layer as an HTTP server. * * @since 1.0.0 * @category Server */ export declare const serve: | Request.Only<"GlobalRequires", R>>(appLayer: Layer.Layer, options?: { readonly routerConfig?: Partial | undefined; readonly disableLogger?: boolean | undefined; readonly disableListenLog?: boolean; /** * Middleware to apply to the HTTP server. * * NOTE: This middleware is applied to the entire HTTP server chain, * including the sending of the response. This means that modifications * to the response **WILL NOT** be reflected in the final response sent to the * client. * * Use HttpLayerRouter.middleware to create middleware that can modify the * response. */ readonly middleware?: (effect: Effect.Effect | Request.Only<"GlobalError", R> | HttpServerError.RouteNotFound, Scope.Scope | HttpServerRequest.HttpServerRequest | Request.Only<"Requires", R> | Request.Only<"GlobalRequires", R>>) => Effect.Effect; }) => Layer.Layer, HttpServer.HttpServer | Exclude | Exclude, HttpRouter>>; /** * @since 1.0.0 * @category Server */ export declare const toWebHandler: | Request<"GlobalRequires", any> | Request<"Error", any> | Request<"GlobalError", any>, HE, HR = Exclude | Request.Only<"GlobalRequires", R>, A>>(appLayer: Layer.Layer, options?: { readonly memoMap?: Layer.MemoMap | undefined; readonly routerConfig?: Partial | undefined; readonly disableLogger?: boolean | undefined; /** * Middleware to apply to the HTTP server. * * NOTE: This middleware is applied to the entire HTTP server chain, * including the sending of the response. This means that modifications * to the response **WILL NOT** be reflected in the final response sent to the * client. * * Use HttpLayerRouter.middleware to create middleware that can modify the * response. */ readonly middleware?: (effect: Effect.Effect | Request.Only<"GlobalError", R> | HttpServerError.RouteNotFound, Scope.Scope | HttpServerRequest.HttpServerRequest | Request.Only<"Requires", R> | Request.Only<"GlobalRequires", R>>) => Effect.Effect; }) => { readonly handler: [HR] extends [never] ? ((request: globalThis.Request, context?: Context.Context | undefined) => Promise) : ((request: globalThis.Request, context: Context.Context
) => Promise); readonly dispose: () => Promise; }; //# sourceMappingURL=HttpLayerRouter.d.ts.map