1import { Platform } from 'react-native';
2
3import { restClient, restClientWithTimeout } from '../apiClient';
4import { DevSession } from '../types';
5
6// TODO -- move this into context / make it settable via JS
7const baseAddress = Platform.select({
8  ios: 'http://localhost',
9  android: 'http://10.0.2.2',
10});
11
12const statusPage = 'status';
13const portsToCheck = [8081, 8082, 8083, 8084, 8085, 19000, 19001, 19002];
14
15export async function getDevSessionsAsync({
16  isAuthenticated = false,
17  installationID = '',
18  isDevice = false,
19  timeout,
20}: {
21  isAuthenticated?: boolean;
22  installationID?: string;
23  isDevice?: boolean;
24  timeout?: number;
25}): Promise<DevSession[]> {
26  let devSessions: DevSession[] = [];
27
28  if (isAuthenticated) {
29    const sessions = await fetchDevSessions(null, timeout);
30    devSessions = devSessions.concat(sessions);
31  }
32
33  if (!devSessions.length && installationID) {
34    const sessions = await fetchDevSessions(installationID, timeout);
35    devSessions = devSessions.concat(sessions);
36  }
37
38  if (!devSessions.length && !isDevice) {
39    const localPackagers = await getLocalPackagersAsync();
40    devSessions = devSessions.concat(localPackagers);
41  }
42
43  return devSessions;
44}
45
46export async function getLocalPackagersAsync(): Promise<DevSession[]> {
47  const onlineDevSessions: DevSession[] = [];
48
49  await Promise.all(
50    portsToCheck.map(async (port) => {
51      try {
52        const address = `${baseAddress}:${port}`;
53        const { status } = await fetch(`${address}/${statusPage}`);
54        if (status === 200) {
55          onlineDevSessions.push({
56            url: address,
57            description: address,
58            source: 'desktop',
59          });
60        }
61      } catch {}
62    })
63  );
64
65  return onlineDevSessions;
66}
67
68export async function fetchDevSessions(installationID?: string | null, timeout?: number) {
69  let devSessionsEndpoint = `/development-sessions`;
70  const headers = {};
71
72  if (installationID != null) {
73    devSessionsEndpoint += `?deviceId=${installationID}`;
74    headers['Expo-Dev-Client-ID'] = installationID;
75  }
76
77  if (timeout) {
78    const sessions = await restClientWithTimeout<{ data: DevSession[] }>(
79      devSessionsEndpoint,
80      timeout,
81      {
82        headers,
83      }
84    );
85    return sessions.data ?? [];
86  } else {
87    const sessions = await restClient<{ data: DevSession[] }>(devSessionsEndpoint, {
88      headers,
89    });
90    return sessions.data ?? [];
91  }
92}
93