1import { ExpoConfig } from '@expo/config'; 2import os from 'os'; 3import { URLSearchParams } from 'url'; 4 5import { CommandError } from '../utils/errors'; 6import { fetchAsync } from './rest/client'; 7 8/** Create the expected session info. */ 9export function createSessionInfo({ 10 exp, 11 runtime, 12 url, 13}: { 14 exp: Pick<ExpoConfig, 'name' | 'description' | 'slug' | 'primaryColor'>; 15 runtime: 'native' | 'web'; 16 url: string; 17}) { 18 return { 19 session: { 20 description: `${exp.name} on ${os.hostname()}`, 21 hostname: os.hostname(), 22 platform: runtime, 23 config: { 24 // TODO: if icons are specified, upload a url for them too so people can distinguish 25 description: exp.description, 26 name: exp.name, 27 slug: exp.slug, 28 primaryColor: exp.primaryColor, 29 }, 30 url, 31 source: 'desktop', 32 }, 33 }; 34} 35 36/** Send a request to Expo API to keep the 'development session' alive for the provided devices. */ 37export async function updateDevelopmentSessionAsync({ 38 deviceIds, 39 exp, 40 runtime, 41 url, 42}: { 43 deviceIds: string[]; 44 exp: Pick<ExpoConfig, 'name' | 'description' | 'slug' | 'primaryColor'>; 45 runtime: 'native' | 'web'; 46 url: string; 47}) { 48 const searchParams = new URLSearchParams(); 49 deviceIds.forEach((id) => { 50 searchParams.append('deviceId', id); 51 }); 52 53 const results = await fetchAsync('development-sessions/notify-alive', { 54 searchParams, 55 method: 'POST', 56 body: JSON.stringify({ 57 data: createSessionInfo({ exp, runtime, url }), 58 }), 59 }); 60 61 if (!results.ok) { 62 throw new CommandError( 63 'API', 64 `Unexpected response when updating the development session on Expo servers: ${results.statusText}.` 65 ); 66 } 67} 68