diff --git a/.changeset/silly-turkeys-knock.md b/.changeset/silly-turkeys-knock.md new file mode 100644 index 0000000..8b4dda2 --- /dev/null +++ b/.changeset/silly-turkeys-knock.md @@ -0,0 +1,5 @@ +--- +"dredge-types": patch +--- + +Fix client type issue due to path type diff --git a/packages/types/source/client/dredge-client-option.ts b/packages/types/source/client/dredge-client-option.ts index 4fd5561..c7ea544 100644 --- a/packages/types/source/client/dredge-client-option.ts +++ b/packages/types/source/client/dredge-client-option.ts @@ -53,7 +53,7 @@ export type inferDredgeClientOption< { method: Method; dataType?: keyof RouteOptions["dataTypes"]; - responseDataTypes?: keyof RouteOptions["dataTypes"]; + responseDataType?: keyof RouteOptions["dataTypes"]; dataTypes?: { [key in keyof RouteOptions["dataTypes"]]?: string; }; diff --git a/packages/types/source/route/route-path.ts b/packages/types/source/route/route-path.ts index 8568853..d9fce69 100644 --- a/packages/types/source/route/route-path.ts +++ b/packages/types/source/route/route-path.ts @@ -2,10 +2,36 @@ import { Parser, inferParserType } from "../parser"; import { IsNever } from "../utils"; import { Route } from "./dredge-route.js"; +type _inferPathArray = T extends `${infer P}/${infer Rest}` + ? [P, ..._inferPathArray] + : T extends `/${infer P}` + ? [P] + : [T]; + +type TrimSlashes = T extends `/${infer U}/` + ? U + : T extends `/${infer U}` + ? U + : T extends `${infer U}/` + ? U + : T; + +export type inferPathArray = _inferPathArray>; + +type SupportedTypeInTemplateLiteral = + | string + | number + | bigint + | boolean + | null + | undefined; + type inferParamParserType

= IsNever

extends true ? string : P extends Parser - ? inferParserType

+ ? inferParserType

extends SupportedTypeInTemplateLiteral + ? inferParserType

+ : string : string; type _inferSimplePathString< @@ -26,6 +52,36 @@ export type inferSimplePathString< ? _inferSimplePathString : never; +export type inferRouteGenericPath = R extends Route< + any, + any, + any, + any, + infer PathArray extends string[], + any, + any, + any, + any, + any +> + ? inferGenericPath + : never; + +type _inferGenericPath = Paths extends [ + infer First extends string, + ...infer Tail extends string[], +] + ? `/${First extends `:${infer N}` + ? string | number | bigint + : First}${_inferGenericPath}` + : ""; + +export type inferGenericPath = Paths extends [] + ? never + : Paths extends string[] + ? _inferGenericPath + : never; + type _inferParamPathString = Paths extends [ infer First extends string, ...infer Tail extends string[], @@ -111,6 +167,21 @@ export type inferRouteSimplePath = R extends Route< ? inferSimplePathString : never; +export type inferRouteParamPath = R extends Route< + any, + any, + any, + any, + infer PathArray, + any, + any, + any, + any, + any +> + ? inferParamPathString + : never; + export type inferRouteSignature = R extends Route< any, any, diff --git a/packages/types/source/router.ts b/packages/types/source/router.ts index 7a6251b..ceff4ef 100644 --- a/packages/types/source/router.ts +++ b/packages/types/source/router.ts @@ -1,8 +1,8 @@ import { AnyRoute, - ExcludeRoute, HasRouteParamPath, Route, + inferRouteGenericPath, inferRouteSimplePath, } from "./route"; import { IsNever, Merge } from "./utils"; @@ -35,13 +35,10 @@ export type ModifyRoutes< ? HasRouteParamPath extends false ? ModifyRoutes : IsNever< - Extract< - inferRouteSimplePath>, - inferRouteSimplePath - > - > extends true - ? ModifyRoutes - : ModifyRoutes]> + Extract, inferRouteSimplePath> + > extends false + ? ModifyRoutes]> + : ModifyRoutes : U; type MakeDynamicRoute = T extends Route< diff --git a/packages/types/source/utils.ts b/packages/types/source/utils.ts index 27a2209..f3b1e3b 100644 --- a/packages/types/source/utils.ts +++ b/packages/types/source/utils.ts @@ -148,6 +148,13 @@ export type RequiredKeys = Type extends unknown ? Exclude> : never; +export type DistributiveIndex = T extends Record< + K, + infer V +> + ? V + : never; + // https://stackoverflow.com/questions/49927523/disallow-call-with-any/49928360#49928360 export type IsAny = 0 extends 1 & Type ? true : false; diff --git a/packages/types/test/client-options.test-d.ts b/packages/types/test/client-options.test-d.ts new file mode 100644 index 0000000..7d3904c --- /dev/null +++ b/packages/types/test/client-options.test-d.ts @@ -0,0 +1,217 @@ +import { expectTypeOf, test } from "vitest"; +import { dredgeRoute } from "./helpers/dredge-route"; +import { dredgeRouter } from "./helpers/dredge-router"; +import { inferDredgeClientOption } from "../source/client/dredge-client-option"; +import { DistributiveIndex, inferRouterRoutes } from "../source"; +import { z } from "zod"; + +test("options.method", () => { + const getPostPutRouter = dredgeRouter([ + dredgeRoute().path("/a").get().build(), + dredgeRoute().path("/b").post().build(), + dredgeRoute().path("/c").put().build(), + ]); + + type GetPostPutRouter = inferRouterRoutes; + type GetPostPutOptions = inferDredgeClientOption; + + expectTypeOf().toEqualTypeOf< + "get" | "post" | "put" + >(); + + const deletePatchHeadRouter = dredgeRouter([ + dredgeRoute().path("/d").delete().build(), + dredgeRoute().path("/e").patch().build(), + dredgeRoute().path("/f").head().build(), + ]); + + type DeletePatchHeadRouter = inferRouterRoutes; + type DeletePatchHeadOptions = inferDredgeClientOption< + DeletePatchHeadRouter[number] + >; + + expectTypeOf().toEqualTypeOf< + "delete" | "patch" | "head" + >(); +}); + +test("options.dataTypes", () => { + const r = dredgeRoute().options({ + dataTypes: { + json: "application/json", + form: "application/x-www-form-urlencoded", + text: "text/plain", + }, + }); + + const router = dredgeRouter([ + r.path("/a").get().build(), + r.path("/b").post(z.string()).build(), + ]); + + type Router = inferRouterRoutes; + type DataTypes = inferDredgeClientOption["dataTypes"]; + + expectTypeOf().toEqualTypeOf< + | { + readonly json?: string | undefined; + readonly form?: string | undefined; + readonly text?: string | undefined; + } + | undefined + >(); +}); + +test("options.dataType and options.responseDataType", () => { + const r = dredgeRoute().options({ + dataTypes: { + json: "application/json", + form: "application/x-www-form-urlencoded", + text: "text/plain", + }, + }); + + const router = dredgeRouter([ + r.path("/a").get().build(), + r.path("/b").get().build(), + r.path("/c").get().build(), + ]); + + type Router = inferRouterRoutes; + type Options = inferDredgeClientOption; + + expectTypeOf().toEqualTypeOf< + "json" | "form" | "text" | undefined + >(); + expectTypeOf().toEqualTypeOf< + "json" | "form" | "text" | undefined + >(); +}); + +test.todo( + "options.params should not exist if there are none defined in the route", +); + +test("options.params", () => { + const r = dredgeRoute(); + + const router = dredgeRouter([ + r.path("/a/:b").get().build(), + r + .path("/c/:d/:e") + .params({ + d: z.number(), + e: z.enum(["a", "b"]), + }) + .get() + .build(), + r + .path("/f/g/:h/:i/:j") + .params({ + h: z.string(), + i: z.boolean(), + j: z.date(), + }) + .get() + .build(), + // r.path('/k').get().build(), // TODO: fix this, it causes some unneccary type in params type. + ]); + + type Router = inferRouterRoutes; + type Params = inferDredgeClientOption["params"]; + + expectTypeOf().toEqualTypeOf< + | { + b: string; + } + | { readonly d: number; readonly e: "a" | "b" } + | { readonly h: string; readonly i: boolean; readonly j: Date } + >(); +}); + +test("options.searchParams", () => { + const r = dredgeRoute(); + + const router = dredgeRouter([ + r.path("/a").get().build(), + r + .path("/c") + .searchParams({ + d: z.number(), + e: z.enum(["a", "b"]), + }) + .get() + .build(), + r + .path("/f") + .searchParams({ + h: z.string(), + i: z.boolean(), + j: z.date(), + }) + .get() + .build(), + r + .path("/k") + .get() + .build(), // TODO: fix this + ]); + + type Router = inferRouterRoutes; + type SearchParams = inferDredgeClientOption["searchParams"]; + + expectTypeOf().toEqualTypeOf< + | Record + | { + // TODO: see what to do with this, and where Record and undefined is coming from + readonly d: number | number[]; + readonly e: "a" | "b" | ("a" | "b")[]; + } + | { + readonly h: string | string[]; + readonly i: boolean | boolean[]; + readonly j: Date | Date[]; + } + | undefined + >(); +}); +test.todo("options.data should not exist if method does not suport it"); +test("options.data", () => { + const r = dredgeRoute().options({ + dataTypes: { + json: "application/json", + form: "application/x-www-form-urlencoded", + text: "text/plain", + }, + }); + + const router = dredgeRouter([ + r.path("/a").get().build(), + r.path("/c").put(z.number()).build(), + r.path("/b").post(z.string()).build(), + r + .path("/c") + .patch(z.object({ a: z.string() })) + .build(), + ]); + + type Routes = inferRouterRoutes; + type Options = inferDredgeClientOption; + + type ExpectedData = string | number | { a: string }; + expectTypeOf< + DistributiveIndex + >().toEqualTypeOf(); + + expectTypeOf< + DistributiveIndex + >().toEqualTypeOf(); + + expectTypeOf< + DistributiveIndex + >().toEqualTypeOf(); + + expectTypeOf< + DistributiveIndex + >().toEqualTypeOf(); +}); diff --git a/packages/types/test/client-path.test-d.ts b/packages/types/test/client-path.test-d.ts new file mode 100644 index 0000000..ea98f0c --- /dev/null +++ b/packages/types/test/client-path.test-d.ts @@ -0,0 +1,138 @@ +import { expectTypeOf, test } from "vitest"; +import { + inferRouteFirstPath, + inferRouteParamPath, + inferRouteSecondPath, +} from "../source/route/route-path"; +import { inferRouterRoutes } from "../source/router"; +import { dredgeRoute } from "./helpers/dredge-route"; +import { dredgeRouter } from "./helpers/dredge-router"; +import { + singleParamAutoRouter, + singleParamNonAutoRouter, + doubleParamAutoRouter, + doubleParamNonAutoRouter, +} from "./path-routes"; + +test("ParamPath only reutrn for route containing dynamic path", () => { + const testRouter = dredgeRouter([ + dredgeRoute().path("/a/:b").build(), + dredgeRoute().path("/:x/y/z").build(), + dredgeRoute().path("/m/n/:o").get().build(), + dredgeRoute().path("/a").build(), + dredgeRoute().path("/x/y/z").build(), + dredgeRoute().path("/x/:y/z").build(), + ]); + type TestRouter = typeof testRouter; + + type Routes = inferRouterRoutes; + + type ParamPath = inferRouteParamPath; + + expectTypeOf().toEqualTypeOf< + ":/a/:b" | ":/:x/y/z" | ":/m/n/:o" | ":/x/:y/z" + >(); +}); + +type SingleParamNonAutoRouter = typeof singleParamNonAutoRouter; +type SingleParamAutoRouter = typeof singleParamAutoRouter; +type DoubleParamNonAutoRouter = typeof doubleParamNonAutoRouter; +type DoubleParamAutoRouter = typeof doubleParamAutoRouter; + +type SingleParamNonAutoRouterRoutes = + inferRouterRoutes; +type SingleParamAutoRouterRoutes = inferRouterRoutes; +type DoubleParamNonAutoRouterRoutes = + inferRouterRoutes; +type DoubleParamAutoRouterRoutes = inferRouterRoutes; + +const testRouter = dredgeRouter([ + singleParamNonAutoRouter, + singleParamAutoRouter, + doubleParamNonAutoRouter, + doubleParamAutoRouter, +]); + +type TestRouter = typeof testRouter; +type Routes = inferRouterRoutes; + +test("autocompletable paths", () => { + type SingleParamNonAutoPath = + | `/a/b/c/d` + | `:/:a/b/c/d` + | `:/a/:b/c/d` + | `:/a/b/:c/d` + | `:/a/b/c/:d`; + + type SingleParamAutoPath = + | "/e/f/g/h" + | ":/:e/f/g/h" + | ":/e/:f/g/h" + | ":/e/f/:g/h" + | ":/e/f/g/:h" + | "/a/f/g/h" + | "/b/f/g/h" + | "/e/true/g/h" + | "/e/false/g/h" + | "/e/f/undefined/h" + | "/e/f/g/null"; + + type SingleParamPath = SingleParamNonAutoPath | SingleParamAutoPath; + + type DoubleParamNonAutoPath = + | "/s/t/u/v/w/x" + | ":/:s/t/:u/v/w/x" + | ":/s/:t/u/:v/w/x" + | ":/s/t/u/v/:w/:x"; + + type DoubleParamAutoPath = + | "/p/q/r/s/t/u" + | ":/:p/q/:r/s/t/u" + | ":/p/:q/r/:s/t/u" + | ":/p/q/r/s/:t/:u" + | "/a/q/true/s/t/u" + | "/a/q/false/s/t/u" + | "/b/q/true/s/t/u" + | "/b/q/false/s/t/u" + | "/p/true/r/undefined/t/u" + | "/p/false/r/undefined/t/u" + | "/p/q/r/s/undefined/null"; + + type DoubleParamPath = DoubleParamNonAutoPath | DoubleParamAutoPath; + + type AllPath = SingleParamPath | DoubleParamPath; + + expectTypeOf< + inferRouteFirstPath + >().toEqualTypeOf(); + + expectTypeOf< + inferRouteFirstPath + >().toEqualTypeOf(); + + expectTypeOf< + inferRouteFirstPath + >().toEqualTypeOf(); + + expectTypeOf< + inferRouteFirstPath + >().toEqualTypeOf(); + + expectTypeOf>().toEqualTypeOf(); +}); + +test("non-autocompletable paths", () => { + type Path = inferRouteSecondPath; + + type SingleParam = + | `/${string}/b/c/d` + | `/a/${number}/c/d` + | `/a/b/${bigint}/d` + | `/a/b/c/${string}`; + type DoubleParams = + | `/${string}/t/${number}/v/w/x` + | `/s/${number}/u/${bigint}/w/x` + | `/s/t/u/v/${bigint}/${string}`; + + expectTypeOf().toEqualTypeOf(); +}); diff --git a/packages/types/test/client-response.test-d.ts b/packages/types/test/client-response.test-d.ts new file mode 100644 index 0000000..4bf5910 --- /dev/null +++ b/packages/types/test/client-response.test-d.ts @@ -0,0 +1,64 @@ +import { describe, expectTypeOf, test } from "vitest"; +import { createClient } from "./helpers/dredge-client"; +import { pathRouter } from "./path-routes"; + +type PathRouter = typeof pathRouter; +describe("pathRoutes", () => { + const client = createClient(); + test("/a/b/c/d", async () => { + expectTypeOf( + await client.get("/a/b/c/d").data(), + ).toEqualTypeOf<"GET/a/b/c/d">(); + + expectTypeOf( + await client("/a/b/c/d", { + method: "get", + }).data(), + ).toEqualTypeOf<"GET/a/b/c/d">(); + + expectTypeOf( + await client.delete("/a/b/c/d").data(), + ).toEqualTypeOf<"DELETE/a/b/c/d">(); + }); + + test("/:a/b/c/d", async () => { + type ExpectedPutType = "PUT/:a/b/c/d"; + expectTypeOf( + await client.get("/param/b/c/d").data(), + ).toEqualTypeOf<"GET/:a/b/c/d">(); + + expectTypeOf( + await client.put("/param/b/c/d").data(), + ).toEqualTypeOf<"PUT/:a/b/c/d">(); + + expectTypeOf( + await client + .put(":/:a/b/c/d", { + params: { + a: "param", + }, + }) + .data(), + ).toEqualTypeOf(); + + expectTypeOf( + await client("/param/b/c/d", { + method: "put", + }).data(), + ).toEqualTypeOf(); + }); + + test("/a/:b/c/d", async () => { + expectTypeOf( + await client.get("/a/1/c/d").data(), + ).toEqualTypeOf<"GET/a/:b/c/d">(); + + expectTypeOf( + await client("/a/1/c/d", { method: "get" }).data(), + ).toEqualTypeOf<"GET/a/:b/c/d">(); + + expectTypeOf( + await client(":/a/:b/c/d", { method: "get", params: { b: 2 } }).data(), + ).toEqualTypeOf<"GET/a/:b/c/d">(); + }); +}); diff --git a/packages/types/test/helpers/dredge-client.ts b/packages/types/test/helpers/dredge-client.ts new file mode 100644 index 0000000..f09f86f --- /dev/null +++ b/packages/types/test/helpers/dredge-client.ts @@ -0,0 +1,18 @@ +import { DredgeRouter } from "../../source"; +import { DredgeClient } from "../../source/client"; + +export const createClient = (defaultOptions?: object) => { + function client(path: string, options: object) { + return ["root", path, options, defaultOptions]; + } + + const methods = ["get", "post"]; + + methods.forEach((m) => { + (client as any)[m] = (path: string, options: null) => { + return [m, path, options, defaultOptions]; + }; + }); + + return client as any as DredgeClient; +}; diff --git a/packages/types/test/helpers/dredge-route.ts b/packages/types/test/helpers/dredge-route.ts new file mode 100644 index 0000000..c87841e --- /dev/null +++ b/packages/types/test/helpers/dredge-route.ts @@ -0,0 +1,30 @@ +import { UnresolvedRoute } from "../../source/route/dredge-route"; + +export function dredgeRoute = {}>() { + return createRouteBuilder() as any as UnresolvedRoute< + { + initialContext: Context; + modifiedInitialContext: Context; + withDynamicPath: false; + dataTypes: {}; + }, + Context, + Context, + string, + [], + {}, + {} + >; +} + +function createRouteBuilder() { + const object = {}; + + const proxy = new Proxy(object, { + get(target, prop) { + return () => { + return proxy; + }; + }, + }); +} diff --git a/packages/types/test/helpers/dredge-router.ts b/packages/types/test/helpers/dredge-router.ts new file mode 100644 index 0000000..03e7946 --- /dev/null +++ b/packages/types/test/helpers/dredge-router.ts @@ -0,0 +1,10 @@ +import { AnyRoute } from "../../source/route/dredge-route"; +import { DredgeRouter, OverwriteRoutes } from "../../source/router"; + +export function dredgeRouter( + routes: T, +): DredgeRouter> { + const router = null; + + return router as any; +} diff --git a/packages/types/test/main.test-d.ts b/packages/types/test/main.test-d.ts deleted file mode 100644 index dc868be..0000000 --- a/packages/types/test/main.test-d.ts +++ /dev/null @@ -1,167 +0,0 @@ -import { expectTypeOf, test } from "vitest"; -import { - ExcludeRoute, - ExtractRouteBy, - HasRouteParamPath, - Route, -} from "../source/route"; -import { ModifyRoutes, OverwriteRoutes } from "../source/router"; - -test("ExtractRouteBy", () => { - type GetUserRoute = Route< - { - withDynamicPath: false; - initialContext: {}; - modifiedInitialContext: {}; - dataTypes: {}; - }, - any, - any, - "get", - ["user"], - any, - any, - any, - any, - any - >; - type GetUserByIdRoute = Route< - { - withDynamicPath: false; - initialContext: {}; - modifiedInitialContext: {}; - dataTypes: {}; - }, - any, - any, - "get", - ["user", ":id"], - {}, - any, - any, - any, - any - >; - type PostUserRoute = Route< - { - withDynamicPath: false; - initialContext: {}; - modifiedInitialContext: {}; - dataTypes: {}; - }, - any, - any, - "post", - ["user"], - {}, - any, - any, - any, - any - >; - type WithDynamicPathRoute = Route< - { - withDynamicPath: true; - initialContext: {}; - modifiedInitialContext: {}; - dataTypes: {}; - }, - any, - any, - "delete", - ["user", ":id"], - {}, - any, - null, - any, - {} - >; - - type Routes = [ - GetUserRoute, - PostUserRoute, - GetUserByIdRoute, - WithDynamicPathRoute, - ]; - - expectTypeOf< - ExtractRouteBy - >().toEqualTypeOf(); - - expectTypeOf< - ExtractRouteBy - >().toEqualTypeOf(); - - type UserRoute = ExtractRouteBy; - // expectTypeOf().not.toEqualTypeOf(); - expectTypeOf().toEqualTypeOf(); - expectTypeOf().toEqualTypeOf(); -}); - -test("ExcludeRoute", () => { - type GetUserByIdRoute = Route< - { - withDynamicPath: false; - }, - any, - any, - "get", - ["user", ":id"], - {}, - any, - any, - any, - any - >; - - type GetUsers = Route< - { - withDynamicPath: false; - }, - any, - any, - "get", - ["users"], - {}, - any, - any, - any, - any - >; - - type PostUsers = Route< - { - withDynamicPath: false; - }, - any, - any, - "post", - ["users"], - {}, - any, - any, - any, - any - >; - - type GetAdminRoute = Route< - { - withDynamicPath: false; - }, - any, - any, - "get", - ["user", "admin"], - {}, - any, - any, - any, - any - >; - - type Routes = [GetUserByIdRoute, GetAdminRoute, GetUsers, PostUsers]; - - type ModifiedRoutes = ModifyRoutes; - - type y = ExcludeRoute; -}); diff --git a/packages/types/test/path-routes.ts b/packages/types/test/path-routes.ts new file mode 100644 index 0000000..03f3415 --- /dev/null +++ b/packages/types/test/path-routes.ts @@ -0,0 +1,228 @@ +import { dredgeRoute } from "./helpers/dredge-route"; +import { dredgeRouter } from "./helpers/dredge-router"; +import z from "zod"; + +export const singleParamNonAutoRouter = dredgeRouter([ + dredgeRoute() + .path("/a/b/c/d") + .get() + .use((_req, res) => { + return res.end({ + data: "GET/a/b/c/d" as const, + }); + }) + .build(), + + dredgeRoute() + .path("/a/b/c/d") + .delete() + .use((_req, res) => { + return res.end({ + data: "DELETE/a/b/c/d" as const, + }); + }) + .build(), + + dredgeRoute() + .path("/:a/b/c/d") + .get() + .use((_req, res) => { + return res.end({ + data: "GET/:a/b/c/d" as const, + }); + }) + .build(), + + dredgeRoute() + .path("/:a/b/c/d") + .put(z.any()) + .use((_req, res) => { + return res.end({ + data: "PUT/:a/b/c/d" as const, + }); + }) + .build(), + + dredgeRoute() + .path("/a/:b/c/d") + .get() + .params({ + b: z.number(), + }) + .use((_req, res) => { + return res.end({ + data: "GET/a/:b/c/d" as const, + }); + }) + .build(), + + dredgeRoute() + .path("/a/b/:c/d") + .params({ + c: z.bigint(), + }) + .get() + .use((_req, res) => { + return res.end({ + data: "GET/a/b/:c/d" as const, + }); + }) + .build(), + + dredgeRoute() + .path("/a/b/c/:d") + .params({ + d: z.date(), + }) + .get() + .use((_req, res) => { + return res.end({ + data: "GET/a/b/c/:d" as const, + }); + }) + .build(), +]); + +export const singleParamAutoRouter = dredgeRouter([ + dredgeRoute().path("/e/f/g/h").get().build(), + dredgeRoute() + .path("/:e/f/g/h") + .params({ + e: z.enum(["a", "b"]), + }) + .get() + .use((_req, res) => { + return res.end({ + data: "GET/:e/f/g/h" as const, + }); + }) + .build(), + dredgeRoute() + .path("/e/:f/g/h") + .params({ + f: z.boolean(), + }) + .get() + .use((_req, res) => { + return res.end({ + data: "GET/e/:f/g/h" as const, + }); + }) + .build(), + dredgeRoute() + .path("/e/f/:g/h") + .params({ + g: z.undefined(), + }) + .get() + .use((_req, res) => { + return res.end({ + data: "GET/e/f/:g/h" as const, + }); + }) + .build(), + dredgeRoute() + .path("/e/f/g/:h") + .params({ + h: z.null(), + }) + .get() + .use((_req, res) => { + return res.end({ + data: "GET/e/f/g/:h" as const, + }); + }) + .build(), +]); + +export const doubleParamNonAutoRouter = dredgeRouter([ + dredgeRoute().path("/s/t/u/v/w/x").get().build(), + dredgeRoute() + .path("/:s/t/:u/v/w/x") + .params({ + s: z.string(), + u: z.number(), + }) + .get() + .use((_req, res) => { + return res.end({ + data: "GET/:s/t/:u/v/w/x" as const, + }); + }) + .build(), + dredgeRoute() + .path("/s/:t/u/:v/w/x") + .params({ + t: z.number(), + v: z.bigint(), + }) + .get() + .use((_req, res) => { + return res.end({ + data: "GET/s/:t/u/:v/w/x" as const, + }); + }) + .build(), + dredgeRoute() + .path("/s/t/u/v/:w/:x") + .params({ + w: z.bigint(), + x: z.date(), + }) + .get() + .use((_req, res) => { + return res.end({ + data: "GET/s/t/u/v/:w/:x" as const, + }); + }) + .build(), +]); +export const doubleParamAutoRouter = dredgeRouter([ + dredgeRoute().path("/p/q/r/s/t/u").get().build(), + dredgeRoute() + .path("/:p/q/:r/s/t/u") + .params({ + p: z.enum(["a", "b"]), + r: z.boolean(), + }) + .get() + .use((_req, res) => { + return res.end({ + data: "GET/:p/q/:r/s/t/u" as const, + }); + }) + .build(), + dredgeRoute() + .path("/p/:q/r/:s/t/u") + .params({ + q: z.boolean(), + s: z.undefined(), + }) + .get() + .use((_req, res) => { + return res.end({ + data: "/GET/p/:q/r/:s/t/u" as const, + }); + }) + .build(), + dredgeRoute() + .path("/p/q/r/s/:t/:u") + .params({ + t: z.undefined(), + u: z.null(), + }) + .get() + .use((_req, res) => { + return res.end({ + data: "GET/p/q/r/s/:t/:u" as const, + }); + }) + .build(), +]); + +export const pathRouter = dredgeRouter([ + singleParamNonAutoRouter, + singleParamAutoRouter, + doubleParamNonAutoRouter, + doubleParamAutoRouter, +]);