/** * @since 1.0.0 */ import type * as Cause from "effect/Cause" import type * as Chunk from "effect/Chunk" import type * as Context from "effect/Context" import type * as Effect from "effect/Effect" import type { FiberRef } from "effect/FiberRef" import type { Inspectable } from "effect/Inspectable" import type * as Layer from "effect/Layer" import type * as Option from "effect/Option" import type * as ParseResult from "effect/ParseResult" import type * as Schema from "effect/Schema" import type { ParseOptions } from "effect/SchemaAST" import type * as Scope from "effect/Scope" import type { RouterConfig } from "find-my-way-ts" import type * as Etag from "./Etag.js" import type { FileSystem } from "./FileSystem.js" import type * as App from "./HttpApp.js" import type * as Method from "./HttpMethod.js" import type * as Middleware from "./HttpMiddleware.js" import type * as Platform from "./HttpPlatform.js" import type * as HttpServer from "./HttpServer.js" import type * as Error from "./HttpServerError.js" import type * as ServerRequest from "./HttpServerRequest.js" import type * as Respondable from "./HttpServerRespondable.js" import type * as ServerResponse from "./HttpServerResponse.js" import * as internal from "./internal/httpRouter.js" import type { Path } from "./Path.js" /** * @since 1.0.0 * @category type ids */ export const TypeId: unique symbol = internal.TypeId /** * @since 1.0.0 * @category type ids */ export type TypeId = typeof TypeId /** * @since 1.0.0 * @category models */ export interface HttpRouter extends App.Default>, Inspectable { readonly [TypeId]: TypeId readonly routes: Chunk.Chunk> readonly mounts: Chunk.Chunk< readonly [ prefix: string, httpApp: App.Default, options?: { readonly includePrefix?: boolean | undefined } | undefined ] > } /** * @since 1.0.0 */ export declare namespace HttpRouter { /** * @since 1.0.0 */ export type Provided = RouteContext | ServerRequest.HttpServerRequest | ServerRequest.ParsedSearchParams | Scope.Scope /** * @since 1.0.0 */ export type ExcludeProvided = Exclude /** * @since 1.0.0 */ export interface Service { readonly router: Effect.Effect> readonly addRoute: (route: Route) => Effect.Effect readonly all: ( path: PathInput, handler: Route.Handler, options?: { readonly uninterruptible?: boolean | undefined } | undefined ) => Effect.Effect readonly get: ( path: PathInput, handler: Route.Handler, options?: { readonly uninterruptible?: boolean | undefined } | undefined ) => Effect.Effect readonly post: ( path: PathInput, handler: Route.Handler, options?: { readonly uninterruptible?: boolean | undefined } | undefined ) => Effect.Effect readonly put: ( path: PathInput, handler: Route.Handler, options?: { readonly uninterruptible?: boolean | undefined } | undefined ) => Effect.Effect readonly patch: ( path: PathInput, handler: Route.Handler, options?: { readonly uninterruptible?: boolean | undefined } | undefined ) => Effect.Effect readonly del: ( path: PathInput, handler: Route.Handler, options?: { readonly uninterruptible?: boolean | undefined } | undefined ) => Effect.Effect readonly head: ( path: PathInput, handler: Route.Handler, options?: { readonly uninterruptible?: boolean | undefined } | undefined ) => Effect.Effect readonly options: ( path: PathInput, handler: Route.Handler, options?: { readonly uninterruptible?: boolean | undefined } | undefined ) => Effect.Effect readonly mount: ( path: `/${string}`, router: HttpRouter ) => Effect.Effect readonly mountApp: ( path: `/${string}`, router: App.Default, options?: { readonly includePrefix?: boolean | undefined } | undefined ) => Effect.Effect readonly concat: (router: HttpRouter) => Effect.Effect } /** * @since 1.0.0 */ export type DefaultServices = Platform.HttpPlatform | Etag.Generator | FileSystem | Path /** * @since 1.0.0 */ export interface TagClass extends Context.Tag> { new(_: never): Context.TagClassShape> readonly Live: Layer.Layer readonly router: Effect.Effect, never, Self> readonly use: ( f: (router: Service) => Effect.Effect ) => Layer.Layer> readonly unwrap: (f: (router: HttpRouter) => Layer.Layer) => Layer.Layer readonly serve: ( middleware?: Middleware.HttpMiddleware.Applied ) => Layer.Layer< never, never, HttpServer.HttpServer | Exclude > } } /** * @since 1.0.0 * @category type ids */ export const RouteTypeId: unique symbol = internal.RouteTypeId /** * @since 1.0.0 * @category type ids */ export type RouteTypeId = typeof RouteTypeId /** * @since 1.0.0 * @category models */ export type PathInput = `/${string}` | "*" /** * @since 1.0.0 * @category models */ export interface Route extends Inspectable { readonly [RouteTypeId]: RouteTypeId readonly method: Method.HttpMethod | "*" readonly path: PathInput readonly handler: Route.Handler readonly prefix: Option.Option readonly uninterruptible: boolean } /** * @since 1.0.0 */ export declare namespace Route { /** * @since 1.0.0 */ export type Handler = App.HttpApp< Respondable.Respondable, E, R | RouteContext | ServerRequest.ParsedSearchParams > /** * @since 1.0.0 */ export type Middleware = App.HttpApp< ServerResponse.HttpServerResponse, E, R | RouteContext | ServerRequest.ParsedSearchParams > } /** * @since 1.0.0 * @category type ids */ export const RouteContextTypeId: unique symbol = internal.RouteContextTypeId /** * @since 1.0.0 * @category type ids */ export type RouteContextTypeId = typeof RouteContextTypeId /** * @since 1.0.0 * @category models */ export interface RouteContext { readonly [RouteContextTypeId]: RouteContextTypeId readonly params: Readonly> readonly route: Route } /** * @since 1.0.0 * @category route context */ export const RouteContext: Context.Tag = internal.RouteContext /** * @since 1.0.0 * @category route context */ export const params: Effect.Effect< Readonly>, never, RouteContext > = internal.params /** * @since 1.0.0 * @category route context */ export const schemaJson: < R, I extends Partial<{ readonly method: Method.HttpMethod readonly url: string readonly cookies: Readonly> readonly headers: Readonly> readonly pathParams: Readonly> readonly searchParams: Readonly | undefined>> readonly body: any }>, A >( schema: Schema.Schema, options?: ParseOptions | undefined ) => Effect.Effect< A, Error.RequestError | ParseResult.ParseError, RouteContext | R | ServerRequest.HttpServerRequest | ServerRequest.ParsedSearchParams > = internal.schemaJson /** * @since 1.0.0 * @category route context */ export const schemaNoBody: < R, I extends Partial< { readonly method: Method.HttpMethod readonly url: string readonly cookies: Readonly> readonly headers: Readonly> readonly pathParams: Readonly> readonly searchParams: Readonly | undefined>> } >, A >( schema: Schema.Schema, options?: ParseOptions | undefined ) => Effect.Effect< A, ParseResult.ParseError, R | RouteContext | ServerRequest.HttpServerRequest | ServerRequest.ParsedSearchParams > = internal.schemaNoBody /** * @since 1.0.0 * @category route context */ export const schemaParams: | undefined>>, R>( schema: Schema.Schema, options?: ParseOptions | undefined ) => Effect.Effect = internal.schemaParams /** * @since 1.0.0 * @category route context */ export const schemaPathParams: >, R>( schema: Schema.Schema, options?: ParseOptions | undefined ) => Effect.Effect = internal.schemaPathParams /** * @since 1.0.0 * @category router config */ export const currentRouterConfig: FiberRef> = internal.currentRouterConfig /** * @since 1.0.0 * @category router config */ export const withRouterConfig: { /** * @since 1.0.0 * @category router config */ (config: Partial): (effect: Effect.Effect) => Effect.Effect /** * @since 1.0.0 * @category router config */ (effect: Effect.Effect, config: Partial): Effect.Effect } = internal.withRouterConfig /** * @since 1.0.0 * @category router config */ export const setRouterConfig: (config: Partial) => Layer.Layer = internal.setRouterConfig /** * @since 1.0.0 * @category constructors */ export const empty: HttpRouter = internal.empty /** * @since 1.0.0 * @category constructors */ export const fromIterable: >( routes: Iterable ) => HttpRouter ? E : never, R extends Route ? Env : never> = internal.fromIterable /** * @since 1.0.0 * @category constructors */ export const makeRoute: ( method: Method.HttpMethod | "*", path: PathInput, handler: Route.Handler, options?: { readonly prefix?: string | undefined; readonly uninterruptible?: boolean | undefined } | undefined ) => Route> = internal.makeRoute /** * @since 1.0.0 * @category utils */ export const prefixPath: { /** * @since 1.0.0 * @category utils */ (prefix: string): (self: string) => string /** * @since 1.0.0 * @category utils */ (self: string, prefix: string): string } = internal.prefixPath /** * @since 1.0.0 * @category combinators */ export const prefixAll: { /** * @since 1.0.0 * @category combinators */ (prefix: PathInput): (self: HttpRouter) => HttpRouter /** * @since 1.0.0 * @category combinators */ (self: HttpRouter, prefix: PathInput): HttpRouter } = internal.prefixAll /** * @since 1.0.0 * @category combinators */ export const append: { /** * @since 1.0.0 * @category combinators */ (route: Route): ( self: HttpRouter ) => HttpRouter< E1 | E, R | HttpRouter.ExcludeProvided > /** * @since 1.0.0 * @category combinators */ (self: HttpRouter, route: Route): HttpRouter< E | E1, R | HttpRouter.ExcludeProvided > } = internal.append /** * @since 1.0.0 * @category combinators */ export const concat: { /** * @since 1.0.0 * @category combinators */ (that: HttpRouter): ( self: HttpRouter ) => HttpRouter /** * @since 1.0.0 * @category combinators */ (self: HttpRouter, that: HttpRouter): HttpRouter< E | E1, R | R1 > } = internal.concat /** * @since 1.0.0 * @category combinators */ export const concatAll: >>( ...routers: Routers ) => [Routers[number]] extends [HttpRouter] ? HttpRouter : never = internal.concatAll /** * @since 1.0.0 * @category routing */ export const mount: { /** * @since 1.0.0 * @category routing */ (path: `/${string}`, that: HttpRouter): (self: HttpRouter) => HttpRouter /** * @since 1.0.0 * @category routing */ (self: HttpRouter, path: `/${string}`, that: HttpRouter): HttpRouter } = internal.mount /** * @since 1.0.0 * @category routing */ export const mountApp: { /** * @since 1.0.0 * @category routing */ ( path: `/${string}`, that: App.Default, options?: { readonly includePrefix?: boolean | undefined } | undefined ): ( self: HttpRouter ) => HttpRouter< E1 | E, | HttpRouter.ExcludeProvided | HttpRouter.ExcludeProvided > /** * @since 1.0.0 * @category routing */ ( self: HttpRouter, path: `/${string}`, that: App.Default, options?: { readonly includePrefix?: boolean | undefined } | undefined ): HttpRouter< E | E1, | HttpRouter.ExcludeProvided | HttpRouter.ExcludeProvided > } = internal.mountApp /** * @since 1.0.0 * @category routing */ export const route: ( method: Method.HttpMethod | "*" ) => { ( path: PathInput, handler: Route.Handler, options?: { readonly uninterruptible?: boolean | undefined } | undefined ): ( self: HttpRouter ) => HttpRouter> ( self: HttpRouter, path: PathInput, handler: Route.Handler, options?: { readonly uninterruptible?: boolean | undefined } | undefined ): HttpRouter> } = internal.route /** * @since 1.0.0 * @category routing */ export const all: { /** * @since 1.0.0 * @category routing */ ( path: PathInput, handler: Route.Handler, options?: { readonly uninterruptible?: boolean | undefined } | undefined ): ( self: HttpRouter ) => HttpRouter< E1 | E, R | HttpRouter.ExcludeProvided > /** * @since 1.0.0 * @category routing */ ( self: HttpRouter, path: PathInput, handler: Route.Handler, options?: { readonly uninterruptible?: boolean | undefined } | undefined ): HttpRouter< E | E1, R | HttpRouter.ExcludeProvided > } = internal.all /** * @since 1.0.0 * @category routing */ export const get: { /** * @since 1.0.0 * @category routing */ ( path: PathInput, handler: Route.Handler, options?: { readonly uninterruptible?: boolean | undefined } | undefined ): ( self: HttpRouter ) => HttpRouter> /** * @since 1.0.0 * @category routing */ ( self: HttpRouter, path: PathInput, handler: Route.Handler, options?: { readonly uninterruptible?: boolean | undefined } | undefined ): HttpRouter> } = internal.get /** * @since 1.0.0 * @category routing */ export const post: { /** * @since 1.0.0 * @category routing */ ( path: PathInput, handler: Route.Handler, options?: { readonly uninterruptible?: boolean | undefined } | undefined ): ( self: HttpRouter ) => HttpRouter> /** * @since 1.0.0 * @category routing */ ( self: HttpRouter, path: PathInput, handler: Route.Handler, options?: { readonly uninterruptible?: boolean | undefined } | undefined ): HttpRouter> } = internal.post /** * @since 1.0.0 * @category routing */ export const patch: { /** * @since 1.0.0 * @category routing */ ( path: PathInput, handler: Route.Handler, options?: { readonly uninterruptible?: boolean | undefined } | undefined ): ( self: HttpRouter ) => HttpRouter> /** * @since 1.0.0 * @category routing */ ( self: HttpRouter, path: PathInput, handler: Route.Handler, options?: { readonly uninterruptible?: boolean | undefined } | undefined ): HttpRouter> } = internal.patch /** * @since 1.0.0 * @category routing */ export const put: { /** * @since 1.0.0 * @category routing */ ( path: PathInput, handler: Route.Handler, options?: { readonly uninterruptible?: boolean | undefined } | undefined ): ( self: HttpRouter ) => HttpRouter> /** * @since 1.0.0 * @category routing */ ( self: HttpRouter, path: PathInput, handler: Route.Handler, options?: { readonly uninterruptible?: boolean | undefined } | undefined ): HttpRouter> } = internal.put /** * @since 1.0.0 * @category routing */ export const del: { /** * @since 1.0.0 * @category routing */ ( path: PathInput, handler: Route.Handler, options?: { readonly uninterruptible?: boolean | undefined } | undefined ): ( self: HttpRouter ) => HttpRouter> /** * @since 1.0.0 * @category routing */ ( self: HttpRouter, path: PathInput, handler: Route.Handler, options?: { readonly uninterruptible?: boolean | undefined } | undefined ): HttpRouter> } = internal.del /** * @since 1.0.0 * @category routing */ export const head: { /** * @since 1.0.0 * @category routing */ ( path: PathInput, handler: Route.Handler, options?: { readonly uninterruptible?: boolean | undefined } | undefined ): ( self: HttpRouter ) => HttpRouter> /** * @since 1.0.0 * @category routing */ ( self: HttpRouter, path: PathInput, handler: Route.Handler, options?: { readonly uninterruptible?: boolean | undefined } | undefined ): HttpRouter> } = internal.head /** * @since 1.0.0 * @category routing */ export const options: { /** * @since 1.0.0 * @category routing */ ( path: PathInput, handler: Route.Handler, options?: { readonly uninterruptible?: boolean | undefined } | undefined ): ( self: HttpRouter ) => HttpRouter> /** * @since 1.0.0 * @category routing */ ( self: HttpRouter, path: PathInput, handler: Route.Handler, options?: { readonly uninterruptible?: boolean | undefined } | undefined ): HttpRouter> } = internal.options /** * @since 1.0.0 * @category combinators */ export const use: { /** * @since 1.0.0 * @category combinators */ (f: (self: Route.Middleware) => App.Default): (self: HttpRouter) => HttpRouter> /** * @since 1.0.0 * @category combinators */ ( self: HttpRouter, f: (self: Route.Middleware) => App.Default ): HttpRouter> } = internal.use /** * @since 1.0.0 * @category combinators */ export const transform: { /** * @since 1.0.0 * @category combinators */ ( f: (self: Route.Handler) => App.HttpApp ): (self: HttpRouter) => HttpRouter> /** * @since 1.0.0 * @category combinators */ ( self: HttpRouter, f: (self: Route.Handler) => App.HttpApp ): HttpRouter> } = internal.transform /** * @since 1.0.0 * @category combinators */ export const catchAll: { /** * @since 1.0.0 * @category combinators */ (f: (e: E) => Route.Handler): (self: HttpRouter) => HttpRouter> /** * @since 1.0.0 * @category combinators */ (self: HttpRouter, f: (e: E) => Route.Handler): HttpRouter> } = internal.catchAll /** * @since 1.0.0 * @category combinators */ export const catchAllCause: { /** * @since 1.0.0 * @category combinators */ (f: (e: Cause.Cause) => Route.Handler): (self: HttpRouter) => HttpRouter> /** * @since 1.0.0 * @category combinators */ (self: HttpRouter, f: (e: Cause.Cause) => Route.Handler): HttpRouter> } = internal.catchAllCause /** * @since 1.0.0 * @category combinators */ export const catchTag: { /** * @since 1.0.0 * @category combinators */ (k: K, f: (e: Extract) => Route.Handler): ( self: HttpRouter ) => HttpRouter, R | HttpRouter.ExcludeProvided> /** * @since 1.0.0 * @category combinators */ ( self: HttpRouter, k: K, f: (e: Extract) => Route.Handler ): HttpRouter, R | HttpRouter.ExcludeProvided> } = internal.catchTag /** * @since 1.0.0 * @category combinators */ export const catchTags: { /** * @since 1.0.0 * @category combinators */ < E, Cases extends E extends { _tag: string } ? { [K in E["_tag"]]+?: ((error: Extract) => Route.Handler) | undefined } : {} >(cases: Cases): ( self: HttpRouter ) => HttpRouter< | Exclude | { [K in keyof Cases]: Cases[K] extends (...args: Array) => Effect.Effect ? E : never }[keyof Cases], | R | HttpRouter.ExcludeProvided< { [K in keyof Cases]: Cases[K] extends (...args: Array) => Effect.Effect ? R : never }[keyof Cases] > > /** * @since 1.0.0 * @category combinators */ < R, E, Cases extends E extends { _tag: string } ? { [K in E["_tag"]]+?: ((error: Extract) => Route.Handler) | undefined } : {} >(self: HttpRouter, cases: Cases): HttpRouter< | Exclude | { [K in keyof Cases]: Cases[K] extends (...args: Array) => Effect.Effect ? E : never }[keyof Cases], | R | HttpRouter.ExcludeProvided< { [K in keyof Cases]: Cases[K] extends (...args: Array) => Effect.Effect ? R : never }[keyof Cases] > > } = internal.catchTags /** * @since 1.0.0 * @category combinators */ export const provideService: { /** * @since 1.0.0 * @category combinators */ >(tag: T, service: Context.Tag.Service): (self: HttpRouter) => HttpRouter>> /** * @since 1.0.0 * @category combinators */ >(self: HttpRouter, tag: T, service: Context.Tag.Service): HttpRouter>> } = internal.provideService /** * @since 1.0.0 * @category combinators */ export const provideServiceEffect: { /** * @since 1.0.0 * @category combinators */ , R1, E1>(tag: T, effect: Effect.Effect, E1, R1>): ( self: HttpRouter ) => HttpRouter< E1 | E, | Exclude> | Exclude, Context.Tag.Identifier> > /** * @since 1.0.0 * @category combinators */ , R1, E1>( self: HttpRouter, tag: T, effect: Effect.Effect, E1, R1> ): HttpRouter< E | E1, | Exclude> | Exclude, Context.Tag.Identifier> > } = internal.provideServiceEffect /** * @since 1.0.0 * @category tags */ export const Tag: ( id: Name ) => () => HttpRouter.TagClass = internal.Tag /** * @since 1.0.0 * @category tags */ export class Default extends Tag("@effect/platform/HttpRouter/Default")() {} /** * @since 1.0.0 * @category utils */ export const toHttpApp: (self: HttpRouter) => Effect.Effect> = internal.toHttpApp