import { generateKeyPairSync, type KeyObject } from 'crypto'; /** * 시험용 FCM 서비스 계정 키 — 프로세스마다 RSA 2048 을 한 번 만들어 쓴다(진짜 키가 아니다 — Google 에 보내지 않는다). * 단위 시험(fcm-*.spec.ts · env.validation.spec.ts)이 env 값(base64 한 줄) · 서명 확인(공개 키)에 쓴다 */ export interface TestServiceAccount { /** 키 파일 JSON — 칸을 바꿔 틀린 키를 만든다 */ readonly json: Record; /** env 에 넣는 값 — JSON 을 통째로 base64 한 줄 */ readonly base64: string; readonly publicKey: KeyObject; readonly privateKeyPem: string; } let pair: { publicKey: KeyObject; privateKeyPem: string } | null = null; function keyPair(): { publicKey: KeyObject; privateKeyPem: string } { if (!pair) { const { publicKey, privateKey } = generateKeyPairSync('rsa', { modulusLength: 2048, }); pair = { publicKey, privateKeyPem: privateKey .export({ type: 'pkcs8', format: 'pem' }) .toString(), }; } return pair; } /** JSON → env 값 (base64 한 줄) */ export function toEnvValue(json: unknown): string { return Buffer.from(JSON.stringify(json)).toString('base64'); } /** 시험용 키 — `overrides` 로 칸을 바꾸거나(undefined 면 그 칸을 뺀다) 더한다 */ export function testServiceAccount( overrides: Record = {}, ): TestServiceAccount { const { publicKey, privateKeyPem } = keyPair(); const json: Record = { type: 'service_account', project_id: 'arasystem-push-test', private_key_id: '0123456789abcdef0123456789abcdef01234567', private_key: privateKeyPem, client_email: 'arasystem-push@arasystem-push-test.iam.gserviceaccount.com', client_id: '100000000000000000000', auth_uri: 'https://accounts.google.com/o/oauth2/auth', token_uri: 'https://oauth2.googleapis.com/token', ...overrides, }; for (const [key, value] of Object.entries(overrides)) { if (value === undefined) delete json[key]; } return { json, base64: toEnvValue(json), publicKey, privateKeyPem }; }