Skip to content

Commit

Permalink
feat(http): add more egronomic route api
Browse files Browse the repository at this point in the history
  • Loading branch information
0x706b committed May 19, 2024
1 parent d44e76f commit d3fe19a
Show file tree
Hide file tree
Showing 4 changed files with 86 additions and 5 deletions.
5 changes: 5 additions & 0 deletions .changeset/ninety-flowers-burn.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"@fncts/http": patch
---

feat(http): add more egronomic route api
52 changes: 49 additions & 3 deletions packages/http/src/Route/api.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import type { Method } from "../Method.js";
import type { PathInput, Route } from "./definition.js";
import type { PathInput } from "./definition.js";

import { RouteContext } from "./definition.js";
import { Route, RouteContext } from "./definition.js";
import { RouteImpl } from "./internal.js";

/**
Expand Down Expand Up @@ -44,10 +44,56 @@ export function schemaSearchParams<A>(schema: Schema<A>): IO<RouteContext, Parse
* @tsplus static fncts.http.RouteOps __call
*/
export function make<R, E>(
method: Method,
method: Method | "*",
path: PathInput,
handler: Route.Handler<R, E>,
prefix: Maybe<string> = Nothing(),
): Route<R, E> {
return new RouteImpl(method, path, handler, prefix);
}

export function route(method: Method | "*") {
return <R, E>(path: PathInput, handler: Route.Handler<R, E>): Route<R, E> => {
return Route(method, path, handler);
};
}

/**
* @tsplus static fncts.http.RouteOps get
*/
export const get: <R, E>(path: PathInput, handler: Route.Handler<R, E>) => Route<R, E> = route("GET");

/**
* @tsplus static fncts.http.RouteOps post
*/
export const post: <R, E>(path: PathInput, handler: Route.Handler<R, E>) => Route<R, E> = route("POST");

/**
* @tsplus static fncts.http.RouteOps put
*/
export const put: <R, E>(path: PathInput, handler: Route.Handler<R, E>) => Route<R, E> = route("PUT");

/**
* @tsplus static fncts.http.RouteOps patch
*/
export const patch: <R, E>(path: PathInput, handler: Route.Handler<R, E>) => Route<R, E> = route("PATCH");

/**
* @tsplus static fncts.http.RouteOps del
*/
export const del: <R, E>(path: PathInput, handler: Route.Handler<R, E>) => Route<R, E> = route("DELETE");

/**
* @tsplus static fncts.http.RouteOps head
*/
export const head: <R, E>(path: PathInput, handler: Route.Handler<R, E>) => Route<R, E> = route("HEAD");

/**
* @tsplus static fncts.http.RouteOps options
*/
export const options: <R, E>(path: PathInput, handler: Route.Handler<R, E>) => Route<R, E> = route("OPTIONS");

/**
* @tsplus static fncts.http.RouteOps all
*/
export const all: <R, E>(path: PathInput, handler: Route.Handler<R, E>) => Route<R, E> = route("*");
4 changes: 4 additions & 0 deletions packages/http/src/Route/definition.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,10 @@ export type RouteTypeId = typeof RouteTypeId;

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

/**
* @tsplus type fncts.http.Route
* @tsplus companion fncts.http.RouteOps
*/
export abstract class Route<R, E> {
readonly [RouteTypeId]: RouteTypeId = RouteTypeId;

Expand Down
30 changes: 28 additions & 2 deletions packages/http/src/Router/api.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,11 @@
import type { HttpApp } from "../HttpApp.js";
import type { Method } from "../Method.js";
import type { PathInput, Route } from "../Route.js";
import type { Router } from "./definition.js";

import { RouteImpl } from "../Route/internal.js";
import { ServerRequest } from "../ServerRequest.js";
import { ServerResponse } from "../ServerResponse.js";
import { Router } from "./definition.js";
import { RouterInternal } from "./internal.js";

/**
Expand Down Expand Up @@ -92,10 +94,34 @@ export function use<R, E, R1, E1>(f: (self: Route.Handler<R, E>) => HttpApp.Defa
*/
export function from<R extends Route<any, any>>(
routes: Iterable<R>,
): Router<R extends Route<infer Env, infer _> ? Env : never, R extends Route<infer _, infer E> ? E : never> {
): Router<
R extends Route<infer Env, infer _> ? Router.ExcludeProvided<Env> : never,
R extends Route<infer _, infer E> ? E : never
> {
return new RouterInternal(Conc.from(routes), Conc.empty());
}

/**
* @tsplus static fncts.http.RouterOps routes
*/
export function routes<Rs extends Array<Route<any, any>>>(
...routes: Rs
): Router<
{ [K in keyof Rs]: Rs[K] extends Route<infer Env, infer _> ? Router.ExcludeProvided<Env> : never }[number],
{ [K in keyof Rs]: Rs[K] extends Route<infer _, infer E> ? E : never }[number]
> {
return Router.from(routes);
}

/**
* @tsplus pipeable fncts.http.Router append
*/
export function append<R1, E1>(route: Route<R1, E1>) {
return <R, E>(self: Router<R, E>): Router<R | Router.ExcludeProvided<R1>, E | E1> => {
return new RouterInternal<any, any>(self.routes.append(route), self.mounts);
};
}

/**
* @tsplus pipeable fncts.http.Router concat
*/
Expand Down

0 comments on commit d3fe19a

Please sign in to comment.