{"version":3,"file":"router.cjs","sources":["../../src/router/router.ts"],"sourcesContent":["import { applyHeaders, applySearchParams, isUrl } from '@/router/http';\n\nimport type { RequestContext } from './request-context';\nimport type { ConfigMetadata, RoutingMatch } from './routes-matcher';\nimport { RoutesMatcher } from './routes-matcher';\nimport type { RoutesGroupedByPhase } from './types';\n\nexport class Router {\n\tconstructor(\n\t\tprivate routes: RoutesGroupedByPhase,\n\t\tprivate configMetadata: ConfigMetadata,\n\t) {}\n\n\tpublic fetch = async (ctx: RequestContext) => {\n\t\tconst matcher = new RoutesMatcher(this.routes, ctx, this.configMetadata);\n\t\tconst match = await this.findMatch(matcher);\n\n\t\treturn this.generateResponse(ctx, match);\n\t};\n\n\t/**\n\t * Finds a match for the request.\n\t *\n\t * @param matcher Instance of the matcher for the request.\n\t * @param phase The phase to run, either `none` or `error`.\n\t * @param skipErrorMatch Whether to skip the error match.\n\t * @returns The matched set of path, status, headers, and search params.\n\t */\n\tprivate findMatch = async (\n\t\tmatcher: RoutesMatcher,\n\t\tphase: 'none' | 'error' = 'none',\n\t\tskipErrorMatch = false,\n\t): Promise<RoutingMatch> => {\n\t\tconst result = await matcher.run(phase);\n\n\t\tif (result === 'error' || (!skipErrorMatch && matcher.status && matcher.status >= 400)) {\n\t\t\treturn this.findMatch(matcher, 'error', true);\n\t\t}\n\n\t\treturn {\n\t\t\tpath: matcher.path,\n\t\t\tstatus: matcher.status,\n\t\t\theaders: matcher.headers,\n\t\t\tsearchParams: matcher.searchParams,\n\t\t\tbody: matcher.body,\n\t\t};\n\t};\n\n\t/**\n\t * Serves a file from the Vercel build output.\n\t *\n\t * @param reqCtx Request Context object.\n\t * @param match The match from the Vercel build output.\n\t * @returns A response object.\n\t */\n\t// eslint-disable-next-line class-methods-use-this\n\tprivate generateResponse = async (\n\t\t{ request, assets }: RequestContext,\n\t\t{ path = '/404', status, headers, searchParams, body }: RoutingMatch,\n\t): Promise<Response> => {\n\t\t// Redirect user to external URL for redirects.\n\t\tconst locationHeader = headers.normal.get('location');\n\t\tif (locationHeader) {\n\t\t\t// Apply the search params to the location header if it was not from middleware.\n\t\t\t// Middleware that returns a redirect will specify the destination, including any search params\n\t\t\t// that they want to include. Therefore, we should not be appending search params to those.\n\t\t\tif (locationHeader !== headers.middlewareLocation) {\n\t\t\t\tconst paramsStr = [...searchParams.keys()].length ? `?${searchParams.toString()}` : '';\n\t\t\t\theaders.normal.set('location', `${locationHeader ?? '/'}${paramsStr}`);\n\t\t\t}\n\n\t\t\treturn new Response(null, { status, headers: headers.normal });\n\t\t}\n\n\t\tlet resp: Response;\n\n\t\tif (body !== undefined) {\n\t\t\t// If we have a response body from matching, use it instead.\n\t\t\tresp = new Response(body, { status });\n\t\t} else if (isUrl(path)) {\n\t\t\t// If the path is an URL from matching, that means it was rewritten to a full URL.\n\t\t\tconst url = new URL(path);\n\t\t\tapplySearchParams(url.searchParams, searchParams);\n\t\t\tresp = await fetch(url, request);\n\t\t} else {\n\t\t\t// Otherwise, we need to serve a file from the Vercel build output.\n\t\t\tresp =\n\t\t\t\t(await assets.get(path)?.fetch({ path, searchParams })) ??\n\t\t\t\tnew Response('Not Found', { status: 404 });\n\t\t}\n\n\t\tconst newHeaders = headers.normal;\n\t\tapplyHeaders(newHeaders, resp.headers);\n\t\tapplyHeaders(newHeaders, headers.important);\n\n\t\tresp = new Response(resp.body, {\n\t\t\t...resp,\n\t\t\tstatus: status || resp.status,\n\t\t\theaders: newHeaders,\n\t\t});\n\n\t\treturn resp;\n\t};\n}\n"],"names":["Router","routes","configMetadata","ctx","matcher","RoutesMatcher","match","phase","skipErrorMatch","request","assets","path","status","headers","searchParams","body","locationHeader","paramsStr","resp","isUrl","url","applySearchParams","_a","newHeaders","applyHeaders"],"mappings":"0QAOO,MAAMA,CAAO,CACnB,YACSC,EACAC,EACP,CAFO,KAAA,OAAAD,EACA,KAAA,eAAAC,EAGF,KAAA,MAAQ,MAAOC,GAAwB,CAC7C,MAAMC,EAAU,IAAIC,EAAAA,cAAc,KAAK,OAAQF,EAAK,KAAK,cAAc,EACjEG,EAAQ,MAAM,KAAK,UAAUF,CAAO,EAEnC,OAAA,KAAK,iBAAiBD,EAAKG,CAAK,CAAA,EAWxC,KAAQ,UAAY,MACnBF,EACAG,EAA0B,OAC1BC,EAAiB,KAEF,MAAMJ,EAAQ,IAAIG,CAAK,IAEvB,SAAY,CAACC,GAAkBJ,EAAQ,QAAUA,EAAQ,QAAU,IAC1E,KAAK,UAAUA,EAAS,QAAS,EAAI,EAGtC,CACN,KAAMA,EAAQ,KACd,OAAQA,EAAQ,OAChB,QAASA,EAAQ,QACjB,aAAcA,EAAQ,aACtB,KAAMA,EAAQ,IAAA,EAYhB,KAAQ,iBAAmB,MAC1B,CAAE,QAAAK,EAAS,OAAAC,CAAO,EAClB,CAAE,KAAAC,EAAO,OAAQ,OAAAC,EAAQ,QAAAC,EAAS,aAAAC,EAAc,KAAAC,KACzB,OAEvB,MAAMC,EAAiBH,EAAQ,OAAO,IAAI,UAAU,EACpD,GAAIG,EAAgB,CAIf,GAAAA,IAAmBH,EAAQ,mBAAoB,CAClD,MAAMI,EAAY,CAAC,GAAGH,EAAa,KAAM,CAAA,EAAE,OAAS,IAAIA,EAAa,UAAU,GAAK,GAC5ED,EAAA,OAAO,IAAI,WAAY,GAAGG,GAAkB,GAAG,GAAGC,CAAS,EAAE,CACtE,CAEO,OAAA,IAAI,SAAS,KAAM,CAAE,OAAAL,EAAQ,QAASC,EAAQ,OAAQ,CAC9D,CAEI,IAAAK,EAEJ,GAAIH,IAAS,OAEZG,EAAO,IAAI,SAASH,EAAM,CAAE,OAAAH,CAAQ,CAAA,UAC1BO,EAAAA,MAAMR,CAAI,EAAG,CAEjB,MAAAS,EAAM,IAAI,IAAIT,CAAI,EACNU,EAAAA,kBAAAD,EAAI,aAAcN,CAAY,EACzCI,EAAA,MAAM,MAAME,EAAKX,CAAO,CAAA,MAG/BS,EACE,OAAMI,EAAAZ,EAAO,IAAIC,CAAI,IAAf,YAAAW,EAAkB,MAAM,CAAE,KAAAX,EAAM,aAAAG,CAAa,KACpD,IAAI,SAAS,YAAa,CAAE,OAAQ,IAAK,EAG3C,MAAMS,EAAaV,EAAQ,OACdW,OAAAA,EAAAA,aAAAD,EAAYL,EAAK,OAAO,EACxBM,EAAAA,aAAAD,EAAYV,EAAQ,SAAS,EAEnCK,EAAA,IAAI,SAASA,EAAK,KAAM,CAC9B,GAAGA,EACH,OAAQN,GAAUM,EAAK,OACvB,QAASK,CAAA,CACT,EAEML,CAAA,CA1FL,CA4FJ"}