xref: /expo/packages/@expo/cli/src/api/getVersions.ts (revision be37628c)
1import { EXPO_BETA } from '../utils/env';
2import { CommandError } from '../utils/errors';
3import { pickBy } from '../utils/obj';
4import { createCachedFetch } from './rest/client';
5
6/** Represents version info for a particular SDK. */
7export type SDKVersion = {
8  /** @example "2.16.1" */
9  iosVersion?: string;
10  /** @example "https://dpq5q02fu5f55.cloudfront.net/Exponent-2.17.4.tar.gz" */
11  iosClientUrl?: string;
12  /** @example "https://dev.to/expo/expo-sdk-38-is-now-available-5aa0" */
13  releaseNoteUrl?: string;
14  /** @example "2.17.4" */
15  iosClientVersion?: string;
16  /** @example "https://d1ahtucjixef4r.cloudfront.net/Exponent-2.16.1.apk" */
17  androidClientUrl?: string;
18  /** @example "2.16.1" */
19  androidClientVersion?: string;
20  /** @example { "typescript": "~3.9.5" } */
21  relatedPackages?: Record<string, string>;
22  beta?: boolean;
23};
24
25export type SDKVersions = Record<string, SDKVersion>;
26
27export type Versions = {
28  androidUrl: string;
29  androidVersion: string;
30  iosUrl: string;
31  iosVersion: string;
32  sdkVersions: SDKVersions;
33};
34
35/** Get versions from remote endpoint. */
36export async function getVersionsAsync(): Promise<Versions> {
37  // Reconstruct the cached fetch since caching could be disabled.
38  const fetchAsync = createCachedFetch({
39    cacheDirectory: 'versions-cache',
40    // We'll use a 1 week cache for versions so older versions get flushed out eventually.
41    ttl: 1000 * 60 * 60 * 24 * 7,
42  });
43
44  const results = await fetchAsync('versions/latest');
45  if (!results.ok) {
46    throw new CommandError(
47      'API',
48      `Unexpected response when fetching version info from Expo servers: ${results.statusText}.`
49    );
50  }
51  const json = await results.json();
52  return json.data;
53}
54
55/** Get the currently released version while also accounting for if the user is running in `EXPO_BETA` mode. */
56export async function getReleasedVersionsAsync(): Promise<SDKVersions> {
57  // NOTE(brentvatne): it is possible for an unreleased version to be published to
58  // the versions endpoint, but in some cases we only want to list out released
59  // versions
60  const { sdkVersions } = await getVersionsAsync();
61  return pickBy(
62    sdkVersions,
63    (data, _sdkVersionString) => !!data.releaseNoteUrl || (EXPO_BETA && data.beta)
64  );
65}
66