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