Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion packages/route-pattern/src/index.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
export { RoutePattern } from './lib/route-pattern.ts'
export { RoutePattern,urlpat } from './lib/route-pattern.ts'
export { createRouter } from './lib/router.ts'
export type { RoutePatternOptions, RouteMatch } from './lib/route-pattern.ts'
export { MissingParamError, createHrefBuilder } from './lib/href.ts'
export type { HrefBuilder, HrefBuilderOptions } from './lib/href.ts'
Expand Down
29 changes: 29 additions & 0 deletions packages/route-pattern/src/lib/route-pattern.ts
Original file line number Diff line number Diff line change
Expand Up @@ -222,3 +222,32 @@ function matchSearch(search: string, constraints: SearchConstraints): boolean {

return true
}
/**
// Anative URLPattern for pathname-only patterns (variables, wildcards)
//eturns null if not supported or pattern uses enums or optionals or origin/search....
**/


export function urlpat(input:string|RoutePattern):URLPattern|null{
let Ctor =(globalThis as any).URLPattern
if (!Ctor) return null;
let src=typeof input==='string' ? input:input.source
let {protocol,hostname,port,pathname,search}=parse(src)
if(protocol||hostname||port|| search) return null
if(!pathname) return new Ctor({pathname: '/'})
let path=token(pathname)
if (path==null) return null
if(!path.startsWith('/')) path='/'+path
return new Ctor({pathname: path})
}
function token(tokens: TokenList): string|null{
let o=''
for (let i=0;i<tokens.length;i++ ){
let t=tokens[i]
if (t.type==='text') o+=t.value
else if(t.type==='variable') o+=`:${t.name}`
else if (t.type==='wildcard') o+=t.name?`*${t.name}` : '*';
else return null;
}
return o;
}
30 changes: 30 additions & 0 deletions packages/route-pattern/src/lib/router.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
import {RoutePattern,urlpat} from './route-pattern.ts'
import type {Params} from './params.ts'
export type Method='GET'|'POST'|'PUT'|'DELETE'|'PATCH'|'HEAD'|'OPTIONS'|'*'
export type Handler<P extends string>=(req:Request,params:Params<P>)=>Response | Promise<Response>
type Route ={method:Method; pattern:RoutePattern<any>; up?:URLPattern; handler:Handler<any>}

export function createRouter(){
const routes:Route[]=[]
const api={
get<P extends string>(pattern:P,handler:Handler<P>){add('GET',pattern,handler);return api},
all<P extends string>(pattern:P,handler:Handler<P>){add('*',pattern,handler);return api},
async handle(req:Request):Promise<Response|undefined>{
const url=new URL(req.url)
const method=(req.method||'GET').toUpperCase()
for(const r of routes){
if(r.method!=='*'&&r.method!==method) continue
if(r.up&&!r.up.test(url)) continue
const m=r.pattern.match(url)
if(m) return r.handler(req,m.params as any)
}
return undefined
}
}
function add(method:Method, src:string, handler:Handler<any>) {
const rp=new RoutePattern(src)
const up=urlpat(rp)||undefined
routes.push({method,pattern:rp,up,handler})
}
return api
}