1import entries from 'lodash/entries';
2import keys from 'lodash/keys';
3import size from 'lodash/size';
4import values from 'lodash/values';
5
6import resourceSpecs from '~/public/static/resource-specs.json';
7import {
8  HardwareRSpec,
9  HardwareSpecKey,
10  ResourcePlatform,
11  ResourceSpecData,
12} from '~/types/resourceSpecs';
13import { markdownComponents } from '~/ui/components/Markdown';
14
15const {
16  hardware: hardwareSpecs,
17  vm: vmSpecs,
18  resources: { android, ios },
19} = resourceSpecs as ResourceSpecData;
20
21function formatHardware(hardwares: HardwareRSpec) {
22  return keys(hardwares).map(hardware => {
23    const { cpu, memory, description } = hardwareSpecs[hardware];
24    return `${cpu}, ${memory} (${description})`;
25  });
26}
27
28function formatVMs(hardwares: HardwareRSpec) {
29  return entries(hardwares)
30    .map(([hardware, { vm, extra }]) => {
31      const { cpu, memory } = vmSpecs[vm];
32      if (size(hardwares) === 1) return `${cpu}, ${memory}, ${extra}`;
33      return `${cpu}, ${memory}, ${extra} (for builds runnning on ${hardwareSpecs[hardware].name})`;
34    })
35    .join(' or ');
36}
37
38export const iosResourceClasses = values(ios).map(({ symbol }) => symbol);
39export const iosResources = values(ios).map(({ symbol, hardware }) => ({
40  symbol,
41  description: formatVMs(hardware),
42}));
43export const iosHardware = values(ios).flatMap(({ symbol, hardware }) =>
44  keys(hardware).map(name => ({ ...hardwareSpecs[name], symbol }))
45);
46
47export const androidResourceClasses = values(android).map(({ symbol }) => symbol);
48export const androidResources = values(android).map(({ symbol, hardware }) => ({
49  symbol,
50  description: formatHardware(hardware),
51}));
52export const androidHardware = values(android).flatMap(({ symbol, hardware }) =>
53  keys(hardware).map((name: HardwareSpecKey) => ({ ...hardwareSpecs[name], symbol }))
54);
55
56function buildResourceLink(symbol: string, platform: ResourcePlatform) {
57  const platformId = platform === 'ios' ? 2 : 1;
58  return (
59    <>
60      <markdownComponents.code>
61        <markdownComponents.a href={`eas-json/#resourceclass-${platformId}`}>
62          {symbol}
63        </markdownComponents.a>
64      </markdownComponents.code>
65      :
66    </>
67  );
68}
69
70function gcpLink(description: string) {
71  return description
72    .split(/(n2-standard-\d+)/)
73    .map((part: string) =>
74      part.match(/n2-standard-\d+/) ? (
75        <markdownComponents.a href="https://cloud.google.com/compute/docs/general-purpose-machines#n2_machines">
76          {part}
77        </markdownComponents.a>
78      ) : (
79        part
80      )
81    );
82}
83
84type HardwareListProps = { platform: ResourcePlatform };
85type BuildResourceListProps = { platform: ResourcePlatform };
86
87export function HardwareList({ platform }: HardwareListProps) {
88  const data = platform === 'ios' ? iosHardware : androidHardware;
89  const hardwareList = data.map(({ symbol, cpu, memory, description }, i) => {
90    const prefix = platform !== 'ios' && buildResourceLink(symbol, platform);
91    return (
92      <markdownComponents.li key={i}>
93        {prefix} {cpu}, {memory} ({gcpLink(description)})
94      </markdownComponents.li>
95    );
96  });
97  return <markdownComponents.ul>{hardwareList}</markdownComponents.ul>;
98}
99
100export function BuildResourceList({ platform }: BuildResourceListProps) {
101  const data = platform === 'ios' ? iosResources : androidResources;
102  const buildResources = data.map(({ symbol, description }, i) => (
103    <markdownComponents.li key={i}>
104      {buildResourceLink(symbol, platform)} {description}
105    </markdownComponents.li>
106  ));
107  return <markdownComponents.ul>{buildResources}</markdownComponents.ul>;
108}
109