18d307f52SEvan Baconimport { certificateFor } from '@expo/devcert';
28d307f52SEvan Baconimport chalk from 'chalk';
38d307f52SEvan Baconimport fs from 'fs/promises';
4*29975bfdSEvan Baconimport path from 'path';
58d307f52SEvan Bacon
68d307f52SEvan Baconimport * as Log from '../../../log';
78d307f52SEvan Baconimport { ensureDirectoryAsync } from '../../../utils/dir';
88d307f52SEvan Baconimport { ensureDotExpoProjectDirectoryInitialized } from '../../project/dotExpo';
98d307f52SEvan Bacon
108d307f52SEvan Bacon// TODO: Move to doctor as a prereq.
118d307f52SEvan Bacon
128d307f52SEvan Bacon/** Ensure TLS is setup and environment variables are set. */
138d307f52SEvan Baconexport async function ensureEnvironmentSupportsTLSAsync(projectRoot: string) {
148d307f52SEvan Bacon  if (!process.env.SSL_CRT_FILE || !process.env.SSL_KEY_FILE) {
158d307f52SEvan Bacon    const tls = await getTLSCertAsync(projectRoot);
168d307f52SEvan Bacon    if (tls) {
178d307f52SEvan Bacon      process.env.SSL_CRT_FILE = tls.certPath;
188d307f52SEvan Bacon      process.env.SSL_KEY_FILE = tls.keyPath;
198d307f52SEvan Bacon    }
208d307f52SEvan Bacon  }
218d307f52SEvan Bacon}
228d307f52SEvan Bacon
238d307f52SEvan Bacon/** Create TLS and write to files in the temporary directory. Exposed for testing. */
248d307f52SEvan Baconexport async function getTLSCertAsync(
258d307f52SEvan Bacon  projectRoot: string
268d307f52SEvan Bacon): Promise<{ keyPath: string; certPath: string } | false> {
278d307f52SEvan Bacon  Log.log(
288d307f52SEvan Bacon    chalk`Creating TLS certificate for localhost. {dim This functionality may not work on all computers.}`
298d307f52SEvan Bacon  );
308d307f52SEvan Bacon
318d307f52SEvan Bacon  const name = 'localhost';
328d307f52SEvan Bacon  const result = await certificateFor(name);
338d307f52SEvan Bacon  if (result) {
348d307f52SEvan Bacon    const dotExpoDir = ensureDotExpoProjectDirectoryInitialized(projectRoot);
358d307f52SEvan Bacon
368d307f52SEvan Bacon    const { key, cert } = result;
378d307f52SEvan Bacon    const folder = path.join(dotExpoDir, 'tls');
388d307f52SEvan Bacon    const keyPath = path.join(folder, `key-${name}.pem`);
398d307f52SEvan Bacon    const certPath = path.join(folder, `cert-${name}.pem`);
408d307f52SEvan Bacon
418d307f52SEvan Bacon    await ensureDirectoryAsync(folder);
428d307f52SEvan Bacon    await Promise.allSettled([fs.writeFile(keyPath, key), fs.writeFile(certPath, cert)]);
438d307f52SEvan Bacon
448d307f52SEvan Bacon    return {
458d307f52SEvan Bacon      keyPath,
468d307f52SEvan Bacon      certPath,
478d307f52SEvan Bacon    };
488d307f52SEvan Bacon  }
498d307f52SEvan Bacon  return result;
508d307f52SEvan Bacon}
51