import express from 'express' ; import { readFile } from 'fs-extra' ; import http from 'http' ; import { resolve } from 'path' ; import { parse } from 'url' ; import { UrlUtils } from './../internal' ; export const LoadingEndpoint = '/_expo/loading' ; export const DeepLinkEndpoint = '/_expo/link' ; type OnDeepLinkListener = ( projectRoot : string , isDevClient : boolean , platform : string | null ) => Promise < void > ; let onDeepLink = async ( ) => { } ; export function setOnDeepLink ( listener ) { onDeepLink = listener ; } function getPlatform ( query ) { if ( query [ 'platform' ] === 'android' || query [ 'platform' ] === 'ios' ) { return query [ 'platform' ] ; } return null ; } export function noCacheMiddleware ( res ) { res . setHeader ( 'Cache-Control' , 'private, no-cache, no-store, must-revalidate' ) ; res . setHeader ( 'Expires' , '-1' ) ; res . setHeader ( 'Pragma' , 'no-cache' ) ; return res ; } async function loadingEndpointHandler ( req , res ) { res . setHeader ( 'Content-Type' , 'text/html' ) ; res . end ( ( await readFile ( resolve ( __dirname , './../../static/loading-page/index.html' ) ) ) . toString ( 'utf-8' ) ) ; } async function deeplinkEndpointHandler ( projectRoot , req , res ) { const { query } = parse ( req . url ! , true ) ; const isDevClient = query [ 'choice' ] === 'expo-dev-client' ; if ( isDevClient ) { const projectUrl = await UrlUtils . constructDevClientUrlAsync ( projectRoot , { hostType : 'localhost' } ) ; res . setHeader ( 'Location' , projectUrl ) ; } else { const projectUrl = await UrlUtils . constructManifestUrlAsync ( projectRoot , { hostType : 'localhost' } ) ; res . setHeader ( 'Location' , projectUrl ) ; } onDeepLink ( projectRoot , isDevClient , getPlatform ( query ) ) ; res . setHeader ( 'Cache-Control' , 'private, no-cache, no-store, must-revalidate' ) ; res . setHeader ( 'Expires' , '-1' ) ; res . setHeader ( 'Pragma' , 'no-cache' ) ; res . statusCode = 307 ; res . end ( ) ; } export function getLoadingPageHandler ( projectRoot ) { return async ( req , res , next ) => { if ( ! req . url ) { next ( ) ; return ; } try { const url = parse ( req . url ) . pathname || req . url ; switch ( url ) { case LoadingEndpoint : await loadingEndpointHandler ( req , noCacheMiddleware ( res ) ) ; break ; case DeepLinkEndpoint : await deeplinkEndpointHandler ( projectRoot , req , noCacheMiddleware ( res ) ) ; break ; default : next ( ) ; } } catch ( exception ) { res . statusCode = 520 ; if ( typeof exception == 'object' && exception != null ) { res . end ( JSON . stringify ( { error : exception . toString ( ) } ) ) ; } else { res . end ( `Unexpected error: ${ exception }` ) ; } } } ; }