1import { certificateFor } from '@expo/devcert'; 2import chalk from 'chalk'; 3import fs from 'fs/promises'; 4import path from 'path'; 5 6import * as Log from '../../../log'; 7import { ensureDirectoryAsync } from '../../../utils/dir'; 8import { ensureDotExpoProjectDirectoryInitialized } from '../../project/dotExpo'; 9 10// TODO: Move to doctor as a prereq. 11 12/** Ensure TLS is setup and environment variables are set. */ 13export async function ensureEnvironmentSupportsTLSAsync(projectRoot: string) { 14 if (!process.env.SSL_CRT_FILE || !process.env.SSL_KEY_FILE) { 15 const tls = await getTLSCertAsync(projectRoot); 16 if (tls) { 17 process.env.SSL_CRT_FILE = tls.certPath; 18 process.env.SSL_KEY_FILE = tls.keyPath; 19 } 20 } 21} 22 23/** Create TLS and write to files in the temporary directory. Exposed for testing. */ 24export async function getTLSCertAsync( 25 projectRoot: string 26): Promise<{ keyPath: string; certPath: string } | false> { 27 Log.log( 28 chalk`Creating TLS certificate for localhost. {dim This functionality may not work on all computers.}` 29 ); 30 31 const name = 'localhost'; 32 const result = await certificateFor(name); 33 if (result) { 34 const dotExpoDir = ensureDotExpoProjectDirectoryInitialized(projectRoot); 35 36 const { key, cert } = result; 37 const folder = path.join(dotExpoDir, 'tls'); 38 const keyPath = path.join(folder, `key-${name}.pem`); 39 const certPath = path.join(folder, `cert-${name}.pem`); 40 41 await ensureDirectoryAsync(folder); 42 await Promise.allSettled([fs.writeFile(keyPath, key), fs.writeFile(certPath, cert)]); 43 44 return { 45 keyPath, 46 certPath, 47 }; 48 } 49 return result; 50} 51