-
-
Notifications
You must be signed in to change notification settings - Fork 29
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
* Use `URLPattern` for routing * chore(dependencies): updated changesets for modified dependencies * Multiple query params * Ponyfill URLPattern * Go * chore(dependencies): updated changesets for modified dependencies * / * Remove itty-router completely * Prettier * Go * Go * Use Error Handling * Go * YAS * Go2 Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
- Loading branch information
1 parent
b8c6eac
commit 563cfaa
Showing
21 changed files
with
360 additions
and
34 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,5 @@ | ||
--- | ||
'@whatwg-node/fetch': patch | ||
--- | ||
dependencies updates: | ||
- Added dependency [`urlpattern-polyfill@^6.0.2` ↗︎](https://www.npmjs.com/package/urlpattern-polyfill/v/6.0.2) (to `dependencies`) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,5 @@ | ||
--- | ||
'@whatwg-node/router': patch | ||
--- | ||
dependencies updates: | ||
- Removed dependency [`itty-router@3.0.11` ↗︎](https://www.npmjs.com/package/itty-router/v/3.0.11) (from `dependencies`) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,6 @@ | ||
--- | ||
'@whatwg-node/router': minor | ||
'@whatwg-node/fetch': minor | ||
--- | ||
|
||
Drop itty-router in favor of new URLPattern in the fetch ponyfill |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -2,3 +2,4 @@ dist | |
CHANGELOG.md | ||
.next | ||
[...slug].js | ||
.changeset |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,33 +1,120 @@ | ||
import { createServerAdapter, type DefaultServerAdapterContext } from '@whatwg-node/server'; | ||
import { Router as IttyRouter } from 'itty-router'; | ||
import { Request as DefaultRequestCtor } from '@whatwg-node/fetch'; | ||
import type { Router, RouterBaseObject } from './types'; | ||
import { Request as DefaultRequestCtor, URLPattern } from '@whatwg-node/fetch'; | ||
import type { HTTPMethod, RouteMethodKey, Router, RouterBaseObject, RouterHandler, RouterRequest } from './types'; | ||
|
||
interface RouterOptions<TServerContext = DefaultServerAdapterContext> { | ||
base?: string; | ||
RequestCtor?: typeof Request; | ||
plugins?: Array<(router: RouterBaseObject<TServerContext>) => RouterBaseObject<TServerContext>>; | ||
} | ||
|
||
const HTTP_METHODS = ['GET', 'HEAD', 'POST', 'PUT', 'DELETE', 'CONNECT', 'OPTIONS', 'TRACE', 'PATCH'] as HTTPMethod[]; | ||
|
||
export function createRouter<TServerContext = DefaultServerAdapterContext>( | ||
options?: RouterOptions<TServerContext> | ||
): Router<TServerContext> { | ||
let ittyRouter = IttyRouter({ | ||
base: options?.base, | ||
}) as unknown as RouterBaseObject<TServerContext>; | ||
ittyRouter.all!('*', request => { | ||
let parsedUrl: URL; | ||
Object.defineProperty(request, 'parsedUrl', { | ||
get() { | ||
if (!parsedUrl) { | ||
parsedUrl = new URL(request.url); | ||
const routesByMethod = new Map<HTTPMethod, Map<URLPattern, RouterHandler<TServerContext>[]>>(); | ||
function addHandlersToMethod(method: HTTPMethod, path: string, ...handlers: RouterHandler<TServerContext>[]) { | ||
let methodPatternMaps = routesByMethod.get(method); | ||
if (!methodPatternMaps) { | ||
methodPatternMaps = new Map(); | ||
routesByMethod.set(method, methodPatternMaps); | ||
} | ||
const basePath = options?.base || '/'; | ||
let fullPath = ''; | ||
if (basePath === '/') { | ||
fullPath = path; | ||
} else if (path === '/') { | ||
fullPath = basePath; | ||
} else { | ||
fullPath = `${basePath}${path}`; | ||
} | ||
const pattern = new URLPattern({ pathname: fullPath }); | ||
methodPatternMaps.set(pattern, handlers); | ||
} | ||
async function handleRequest(request: Request, context: TServerContext) { | ||
const method = request.method as HTTPMethod; | ||
let _parsedUrl: URL; | ||
function getParsedUrl() { | ||
if (!_parsedUrl) { | ||
_parsedUrl = new URL(request.url); | ||
} | ||
return _parsedUrl; | ||
} | ||
const methodPatternMaps = routesByMethod.get(method); | ||
if (methodPatternMaps) { | ||
const queryProxy = new Proxy( | ||
{}, | ||
{ | ||
get(_, prop) { | ||
const parsedUrl = getParsedUrl(); | ||
const allQueries = parsedUrl.searchParams.getAll(prop.toString()); | ||
return allQueries.length === 1 ? allQueries[0] : allQueries; | ||
}, | ||
has(_, prop) { | ||
const parsedUrl = getParsedUrl(); | ||
return parsedUrl.searchParams.has(prop.toString()); | ||
}, | ||
} | ||
); | ||
for (const [pattern, handlers] of methodPatternMaps) { | ||
const match = pattern.exec(request.url); | ||
if (match) { | ||
const routerRequest = new Proxy(request, { | ||
get(target, prop) { | ||
if (prop === 'parsedUrl') { | ||
return getParsedUrl(); | ||
} | ||
if (prop === 'params') { | ||
return match.pathname.groups; | ||
} | ||
if (prop === 'query') { | ||
return queryProxy; | ||
} | ||
const targetProp = target[prop]; | ||
if (typeof targetProp === 'function') { | ||
return targetProp.bind(target); | ||
} | ||
return targetProp; | ||
}, | ||
has(target, prop) { | ||
return prop in target || prop === 'parsedUrl' || prop === 'params' || prop === 'query'; | ||
}, | ||
}) as RouterRequest; | ||
for (const handler of handlers) { | ||
const result = await handler(routerRequest as RouterRequest, context); | ||
if (result) { | ||
return result; | ||
} | ||
} | ||
} | ||
} | ||
} | ||
} | ||
let routerBaseObject = new Proxy({} as RouterBaseObject<TServerContext>, { | ||
get(_, prop) { | ||
if (prop === 'handle') { | ||
return handleRequest; | ||
} | ||
const method = prop.toString().toLowerCase() as RouteMethodKey; | ||
return function routeMethodKeyFn( | ||
this: RouterBaseObject<TServerContext>, | ||
path: string, | ||
...handlers: RouterHandler<TServerContext>[] | ||
) { | ||
if (method === 'all') { | ||
for (const httpMethod of HTTP_METHODS) { | ||
addHandlersToMethod(httpMethod, path, ...handlers); | ||
} | ||
} else { | ||
addHandlersToMethod(method.toUpperCase() as HTTPMethod, path, ...handlers); | ||
} | ||
return parsedUrl; | ||
}, | ||
}); | ||
return this; | ||
}; | ||
}, | ||
}); | ||
options?.plugins?.forEach(plugin => { | ||
ittyRouter = plugin(ittyRouter); | ||
routerBaseObject = plugin(routerBaseObject); | ||
}); | ||
return createServerAdapter(ittyRouter, options?.RequestCtor || DefaultRequestCtor); | ||
return createServerAdapter(routerBaseObject, options?.RequestCtor || DefaultRequestCtor); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,4 +1,4 @@ | ||
export * from './types'; | ||
export * from './createRouter'; | ||
export { Response } from '@whatwg-node/fetch'; | ||
export { Response, URLPattern } from '@whatwg-node/fetch'; | ||
export { withErrorHandling, withCORS, DefaultServerAdapterContext } from '@whatwg-node/server'; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.