1import { 2 convertKeyPairPEMToKeyPair, 3 convertCertificatePEMToCertificate, 4 validateSelfSignedCertificate, 5} from '@expo/code-signing-certificates'; 6import { ExpoConfig, getConfig } from '@expo/config'; 7import { promises as fs } from 'fs'; 8import path from 'path'; 9 10import { log } from './utils/log'; 11import { attemptModification } from './utils/modifyConfigAsync'; 12 13type Options = { certificateInput: string; keyInput: string; keyid: string | undefined }; 14 15export async function configureCodeSigningAsync( 16 projectRoot: string, 17 { certificateInput, keyInput, keyid }: Options 18) { 19 const certificateInputDir = path.resolve(projectRoot, certificateInput); 20 const keyInputDir = path.resolve(projectRoot, keyInput); 21 22 const [certificatePEM, privateKeyPEM, publicKeyPEM] = await Promise.all([ 23 fs.readFile(path.join(certificateInputDir, 'certificate.pem'), 'utf8'), 24 fs.readFile(path.join(keyInputDir, 'private-key.pem'), 'utf8'), 25 fs.readFile(path.join(keyInputDir, 'public-key.pem'), 'utf8'), 26 ]); 27 28 const certificate = convertCertificatePEMToCertificate(certificatePEM); 29 const keyPair = convertKeyPairPEMToKeyPair({ privateKeyPEM, publicKeyPEM }); 30 validateSelfSignedCertificate(certificate, keyPair); 31 32 const { exp } = getConfig(projectRoot, { skipSDKVersionRequirement: true }); 33 34 const fields: ExpoConfig['updates'] = { 35 codeSigningCertificate: `./${path.relative(projectRoot, certificateInputDir)}/certificate.pem`, 36 codeSigningMetadata: { 37 keyid: keyid ?? 'main', 38 alg: 'rsa-v1_5-sha256', 39 }, 40 }; 41 await attemptModification( 42 projectRoot, 43 { 44 updates: { 45 ...exp.updates, 46 ...fields, 47 }, 48 }, 49 { 50 updates: { 51 ...fields, 52 }, 53 } 54 ); 55 56 log(`Code signing configuration written to app configuration.`); 57} 58