feat(smartacme): add forceRenew option for certificate issuance requests

This commit is contained in:
2026-04-03 19:02:47 +00:00
parent e830cb6252
commit 50f02bf81b
3 changed files with 14 additions and 5 deletions

View File

@@ -1,5 +1,11 @@
# Changelog # Changelog
## 2026-04-03 - 9.4.0 - feat(smartacme)
add forceRenew option for certificate issuance requests
- extends getCertificateForDomain() options with forceRenew to allow bypassing cached non-expired certificates
- preserves the existing certificate as a fallback during forced renewal instead of deleting it before successful issuance
## 2026-03-27 - 9.3.1 - fix(acme) ## 2026-03-27 - 9.3.1 - fix(acme)
parse issued certificate expiry from X.509 metadata and update build compatibility for dependency upgrades parse issued certificate expiry from X.509 metadata and update build compatibility for dependency upgrades

View File

@@ -3,6 +3,6 @@
*/ */
export const commitinfo = { export const commitinfo = {
name: '@push.rocks/smartacme', name: '@push.rocks/smartacme',
version: '9.3.1', version: '9.4.0',
description: 'A TypeScript-based ACME client and server for certificate management with built-in CA, supporting LetsEncrypt and custom ACME authorities.' description: 'A TypeScript-based ACME client and server for certificate management with built-in CA, supporting LetsEncrypt and custom ACME authorities.'
} }

View File

@@ -360,8 +360,9 @@ export class SmartAcme {
*/ */
public async getCertificateForDomain( public async getCertificateForDomain(
domainArg: string, domainArg: string,
options?: { includeWildcard?: boolean } options?: { includeWildcard?: boolean; forceRenew?: boolean }
): Promise<SmartacmeCert> { ): Promise<SmartacmeCert> {
const forceRenew = options?.forceRenew ?? false;
// Determine if this is a wildcard request (e.g., '*.example.com'). // Determine if this is a wildcard request (e.g., '*.example.com').
const isWildcardRequest = domainArg.startsWith('*.'); const isWildcardRequest = domainArg.startsWith('*.');
// Determine the base domain for certificate retrieval/issuance. // Determine the base domain for certificate retrieval/issuance.
@@ -381,12 +382,14 @@ export class SmartAcme {
// Retrieve any existing certificate record by base domain. // Retrieve any existing certificate record by base domain.
const retrievedCertificate = await this.certmanager.retrieveCertificate(certDomainName); const retrievedCertificate = await this.certmanager.retrieveCertificate(certDomainName);
if (retrievedCertificate && !retrievedCertificate.shouldBeRenewed()) { if (!forceRenew && retrievedCertificate && !retrievedCertificate.shouldBeRenewed()) {
return retrievedCertificate; return retrievedCertificate;
} else if (retrievedCertificate && retrievedCertificate.shouldBeRenewed()) { } else if (!forceRenew && retrievedCertificate && retrievedCertificate.shouldBeRenewed()) {
// Remove old certificate via certManager // Remove old certificate via certManager (safe — it needs renewal anyway)
await this.certmanager.deleteCertificate(certDomainName); await this.certmanager.deleteCertificate(certDomainName);
} }
// When forceRenew is true, keep the existing cert in place as fallback.
// The new cert will overwrite it upon successful issuance via certmanager.storeCertificate().
// Build issuance input and trigger the constrained task // Build issuance input and trigger the constrained task
const issuanceInput: ICertIssuanceInput = { const issuanceInput: ICertIssuanceInput = {