1import { 2 installGlobals as installRemixGlobals, 3 Request, 4 RequestInfo, 5 RequestInit, 6 Response, 7 ResponseInit, 8 Headers, 9} from '@remix-run/node'; 10import { URL } from 'node:url'; 11 12import { ExpoRouterServerManifestV1FunctionRoute } from './types'; 13 14// Ensure these are available for the API Routes. 15export function installGlobals() { 16 installRemixGlobals(); 17 18 // @ts-expect-error 19 global.Request = ExpoRequest; 20 // @ts-expect-error 21 global.Response = ExpoResponse; 22 // @ts-expect-error 23 global.ExpoResponse = ExpoResponse; 24 // @ts-expect-error 25 global.ExpoRequest = ExpoRequest; 26} 27 28export class ExpoResponse extends Response { 29 // TODO: Drop when we upgrade to node-fetch v3 30 static json(data: any = undefined, init: ResponseInit = {}): ExpoResponse { 31 const body = JSON.stringify(data); 32 33 if (body === undefined) { 34 throw new TypeError('data is not JSON serializable'); 35 } 36 37 const headers = new Headers(init?.headers); 38 39 if (!headers.has('content-type')) { 40 headers.set('content-type', 'application/json'); 41 } 42 43 return new ExpoResponse(body, { 44 ...init, 45 headers, 46 }); 47 } 48} 49 50export const NON_STANDARD_SYMBOL = Symbol('non-standard'); 51 52export class ExpoURL extends URL { 53 static from(url: string, config: ExpoRouterServerManifestV1FunctionRoute): ExpoURL { 54 const expoUrl = new ExpoURL(url); 55 const match = config.namedRegex.exec(expoUrl.pathname); 56 if (match?.groups) { 57 for (const [key, value] of Object.entries(match.groups)) { 58 const namedKey = config.routeKeys[key]; 59 expoUrl.searchParams.set(namedKey, value); 60 } 61 } 62 63 return expoUrl; 64 } 65} 66 67export class ExpoRequest extends Request { 68 [NON_STANDARD_SYMBOL]: { 69 url: ExpoURL; 70 }; 71 72 constructor(info: RequestInfo, init?: RequestInit) { 73 super(info, init); 74 75 this[NON_STANDARD_SYMBOL] = { 76 url: new ExpoURL(typeof info !== 'string' && 'url' in info ? info.url : String(info)), 77 }; 78 } 79 80 public get expoUrl() { 81 return this[NON_STANDARD_SYMBOL].url; 82 } 83} 84