Skip to content

Commit

Permalink
released v4.0.9 - hotfix: fixed prettier mangling Router
Browse files Browse the repository at this point in the history
  • Loading branch information
kwhitley committed Jun 1, 2023
1 parent 4c8e93b commit 88a145b
Show file tree
Hide file tree
Showing 3 changed files with 53 additions and 87 deletions.
1 change: 1 addition & 0 deletions .prettierignore
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
src/Router.ts
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "itty-router",
"version": "4.0.8",
"version": "4.0.9",
"description": "A tiny, zero-dependency router, designed to make beautiful APIs in any environment.",
"type": "module",
"main": "./index.js",
Expand Down
137 changes: 51 additions & 86 deletions src/Router.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,21 +3,21 @@ export type GenericTraps = {
}

export type RequestLike = {
method: string
url: string
method: string,
url: string,
} & GenericTraps

export type IRequestStrict = {
method: string
url: string
route: string
method: string,
url: string,
route: string,
params: {
[key: string]: string
}
[key: string]: string,
},
query: {
[key: string]: string | string[] | undefined
}
proxy?: any
[key: string]: string | string[] | undefined,
},
proxy?: any,
} & Request

export type IRequest = IRequestStrict & GenericTraps
Expand All @@ -34,112 +34,77 @@ export type RouteHandler<I = IRequest, A extends any[] = any[]> = {
export type RouteEntry = [string, RegExp, RouteHandler[], string]

// this is the generic "Route", which allows per-route overrides
export type Route = <
RequestType = IRequest,
Args extends any[] = any[],
RT = RouterType
>(
export type Route = <RequestType = IRequest, Args extends any[] = any[], RT = RouterType>(
path: string,
...handlers: RouteHandler<RequestType, Args>[]
) => RT

// this is an alternative UniveralRoute, accepting generics (from upstream), but without
// per-route overrides
export type UniversalRoute<
RequestType = IRequest,
Args extends any[] = any[]
> = (
export type UniversalRoute<RequestType = IRequest, Args extends any[] = any[]> = (
path: string,
...handlers: RouteHandler<RequestType, Args>[]
) => RouterType<UniversalRoute<RequestType, Args>, Args>

// helper function to detect equality in types (used to detect custom Request on router)
type Equal<X, Y> = (<T>() => T extends X ? 1 : 2) extends <T>() => T extends Y
? 1
: 2
? true
: false
type Equal<X, Y> = (<T>() => T extends X ? 1 : 2) extends (<T>() => T extends Y ? 1 : 2) ? true : false;

export type CustomRoutes<R = Route> = {
[key: string]: R
[key: string]: R,
}

export type RouterType<R = Route, Args extends any[] = any[]> = {
__proto__: RouterType<R>
routes: RouteEntry[]
handle: <A extends any[] = Args>(
request: RequestLike,
...extra: Equal<R, Args> extends true ? A : Args
) => Promise<any>
all: R
delete: R
get: R
head: R
options: R
patch: R
post: R
put: R
__proto__: RouterType<R>,
routes: RouteEntry[],
handle: <A extends any[] = Args>(request: RequestLike, ...extra: Equal<R, Args> extends true ? A : Args) => Promise<any>
all: R,
delete: R,
get: R,
head: R,
options: R,
patch: R,
post: R,
put: R,
} & CustomRoutes<R>

export const Router = <
RequestType = IRequest,
Args extends any[] = any[],
RouteType = Equal<RequestType, IRequest> extends true
? Route
: UniversalRoute<RequestType, Args>
>({ base = '', routes = [] }: RouterOptions = {}): RouterType<
RouteType,
Args
> =>
RouteType = Equal<RequestType, IRequest> extends true ? Route : UniversalRoute<RequestType, Args>
>({ base = '', routes = [] }: RouterOptions = {}): RouterType<RouteType, Args> =>
// @ts-expect-error TypeScript doesn't know that Proxy makes this work
({
__proto__: new Proxy(
{},
{
// @ts-expect-error (we're adding an expected prop "path" to the get)
get:
(target: any, prop: string, receiver: object, path: string) =>
(route: string, ...handlers: RouteHandler<I>[]) =>
routes.push([
prop.toUpperCase(),
RegExp(
`^${
(path = (base + '/' + route).replace(/\/+(\/|$)/g, '$1')) // strip double & trailing splash
.replace(/(\/?\.?):(\w+)\+/g, '($1(?<$2>*))') // greedy params
.replace(/(\/?\.?):(\w+)/g, '($1(?<$2>[^$1/]+?))') // named params and image format
.replace(/\./g, '\\.') // dot in path
.replace(/(\/?)\*/g, '($1.*)?') // wildcard
}/*$`
),
handlers, // embed handlers
path, // embed clean route path
]) && receiver,
}
),
__proto__: new Proxy({}, {
// @ts-expect-error (we're adding an expected prop "path" to the get)
get: (target: any, prop: string, receiver: object, path: string) => (route: string, ...handlers: RouteHandler<I>[]) =>
routes.push(
[
prop.toUpperCase(),
RegExp(`^${(path = (base + '/' + route).replace(/\/+(\/|$)/g, '$1')) // strip double & trailing splash
.replace(/(\/?\.?):(\w+)\+/g, '($1(?<$2>*))') // greedy params
.replace(/(\/?\.?):(\w+)/g, '($1(?<$2>[^$1/]+?))') // named params and image format
.replace(/\./g, '\\.') // dot in path
.replace(/(\/?)\*/g, '($1.*)?') // wildcard
}/*$`),
handlers, // embed handlers
path, // embed clean route path
]
) && receiver
}),
routes,
async handle(request: RequestLike, ...args) {
let response,
match,
url = new URL(request.url),
query: any = (request.query = { __proto__: null })
async handle (request: RequestLike, ...args) {
let response, match, url = new URL(request.url), query: any = request.query = { __proto__: null }
for (let [k, v] of url.searchParams) {
query[k] = query[k] === undefined ? v : [query[k], v].flat()
}
for (let [method, regex, handlers, path] of routes) {
if (
(method === request.method || method === 'ALL') &&
(match = url.pathname.match(regex))
) {
request.params = match.groups || {} // embed params in request
request.route = path // embed route path in request
if ((method === request.method || method === 'ALL') && (match = url.pathname.match(regex))) {
request.params = match.groups || {} // embed params in request
request.route = path // embed route path in request
for (let handler of handlers) {
if (
(response = await handler(request.proxy || request, ...args)) !==
undefined
)
return response
if ((response = await handler(request.proxy || request, ...args)) !== undefined) return response
}
}
}
},
}
})

0 comments on commit 88a145b

Please sign in to comment.