#!/usr/bin/env node import fs from 'node:fs'; import path from 'node:path'; import { execSync } from 'node:child_process'; import { fileURLToPath } from 'node:url'; import { H5_HOST, TEST_HOSTS } from './local-test-config.mjs'; const root = path.join(path.dirname(fileURLToPath(import.meta.url)), '..'); function certReadable(keyPath, certPath) { try { fs.accessSync(keyPath, fs.constants.R_OK); fs.accessSync(certPath, fs.constants.R_OK); return true; } catch { return false; } } function resolveCertDir() { const candidates = [ path.join(root, '.local/local-test-tls'), path.join(root, `.local/local-test-tls-${process.getuid?.() ?? 'user'}`), ]; for (const certDir of candidates) { const keyPath = path.join(certDir, 'local-test.key.pem'); const certPath = path.join(certDir, 'local-test.cert.pem'); if (certReadable(keyPath, certPath)) { return { certDir, keyPath, certPath }; } } const certDir = path.join(root, `.local/local-test-tls-${process.getuid?.() ?? 'user'}`); return { certDir, keyPath: path.join(certDir, 'local-test.key.pem'), certPath: path.join(certDir, 'local-test.cert.pem'), }; } export function ensureLocalTestTls() { let { certDir, keyPath, certPath } = resolveCertDir(); if (certReadable(keyPath, certPath)) { return { keyPath, certPath, certDir }; } fs.mkdirSync(certDir, { recursive: true }); const sans = [ ...TEST_HOSTS.map((host) => `DNS:${host}`), 'DNS:localhost', 'IP:127.0.0.1', ].join(','); const openssl = `openssl req -x509 -newkey rsa:2048 -sha256 -days 825 -nodes \ -keyout "${keyPath}" -out "${certPath}" \ -subj "/CN=${H5_HOST}" \ -addext "subjectAltName=${sans}"`; execSync(openssl, { stdio: 'inherit' }); console.log(`已生成本地 TLS 证书:${certDir}`); console.log(`SAN: ${TEST_HOSTS.join(', ')}`); return { keyPath, certPath, certDir }; } if (process.argv[1] && path.resolve(process.argv[1]) === fileURLToPath(import.meta.url)) { ensureLocalTestTls(); }