All files / packages/mkcert/src common.ts

100% Statements 62/62
82.35% Branches 14/17
100% Functions 4/4
100% Lines 62/62

Press n or j to go to the next uncovered block, b, p or k for the previous block.

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78  1x 1x 1x 1x   1x   1x   1x 19x 8x 8x 8x 8x 8x   19x 19x 19x 19x 19x 19x   1x 7x 7x 7x 7x 7x 7x 7x 4x 4x 4x 4x 7x         1x 6x 6x   6x 2x 2x   6x 6x   6x   6x 6x   6x 6x 6x 6x 6x 6x 6x 6x 6x 6x 6x 6x 6x 6x 6x 6x 6x 6x 6x  
import type { Certificate, CertificatePath, CreateOptions } from './type'
import fs from 'node:fs'
import path from 'node:path'
import process from 'node:process'
import { createCA, createCert } from 'mkcert'
 
import logger from './logger'
 
export const defaultCertificateBasePath = path.join(process.cwd(), 'cert')
 
export function processCertPath(certPath: Partial<CertificatePath> = { base: defaultCertificateBasePath }) {
  if ('cert' in certPath && 'key' in certPath && certPath.cert && certPath.key) {
    return {
      keyPath: certPath.key,
      certPath: certPath.cert,
    }
  }
 
  const basePath = ('base' in certPath && certPath.base) || defaultCertificateBasePath
  return {
    keyPath: path.join(basePath, 'key.pem'),
    certPath: path.join(basePath, 'cert.pem'),
  }
}
 
export function readCertificate(options?: CertificatePath) {
  try {
    const { keyPath, certPath } = processCertPath(options)
    return {
      key: fs.readFileSync(keyPath, { encoding: 'utf-8' }),
      cert: fs.readFileSync(certPath, { encoding: 'utf-8' }),
    }
  }
  catch (error) {
    logger.error(`${error}`)
    return null
  }
}
 
/**
 * 在项目根目录下创建一个 mkcert 目录,用于存放生成的证书和密钥文件
 */
export function saveCertificate(cert: string, key: string, options?: CertificatePath) {
  const { keyPath, certPath } = processCertPath(options)
  const CERTS_DIR = path.dirname(certPath)
 
  if (!fs.existsSync(CERTS_DIR)) {
    fs.mkdirSync(CERTS_DIR, { recursive: true })
  }
 
  fs.writeFileSync(keyPath, key, { encoding: 'utf-8' })
  fs.writeFileSync(certPath, cert, { encoding: 'utf-8' })
 
  logger.info(`Certificate saved to ${path.resolve(certPath)}`)
 
  return { keyPath, certPath }
}
 
export async function createCertificate(_options: CreateOptions, pathOptions?: CertificatePath, isCache = true): Promise<Certificate> {
  const { force, ...options } = _options
  return new Promise((resolve, reject) => {
    createCA(options)
      .then((ca) => {
        createCert({
          ca: { key: ca.key, cert: ca.cert },
          domains: Array.isArray(options.domains) ? options.domains : options.domains ? [options.domains] : [],
          validity: options.validity,
        })
          .then((cert) => {
            isCache && saveCertificate(cert.cert, cert.key, pathOptions)
            resolve(cert)
          })
          .catch(reject)
      })
      .catch(reject)
  })
}