feat(core): Refactor SmartAcme core to centralize interest coordination and update dependencies

This commit is contained in:
2025-05-01 09:15:19 +00:00
parent f814038a6a
commit 6fedf0505e
12 changed files with 96 additions and 118 deletions

View File

@ -3,6 +3,6 @@
*/
export const commitinfo = {
name: '@push.rocks/smartacme',
version: '7.1.0',
version: '7.2.0',
description: 'A TypeScript-based ACME client for LetsEncrypt certificate management with a focus on simplicity and power.'
}

2
ts/certmanagers/index.ts Normal file
View File

@ -0,0 +1,2 @@
export * from './memory.js';
export * from './mongo.js';

49
ts/certmanagers/memory.ts Normal file
View File

@ -0,0 +1,49 @@
import * as plugins from '../smartacme.plugins.js';
import type { ICertManager } from '../interfaces/certmanager.js';
import { SmartacmeCert } from '../smartacme.classes.cert.js';
/**
* In-memory certificate manager for mongoless mode.
* Stores certificates in memory only and does not connect to MongoDB.
*/
export class MemoryCertManager implements ICertManager {
public interestMap: plugins.lik.InterestMap<string, SmartacmeCert>;
private certs: Map<string, SmartacmeCert> = new Map();
constructor() {
this.interestMap = new plugins.lik.InterestMap((domain) => domain);
}
public async init(): Promise<void> {
// no-op for in-memory store
}
public async retrieveCertificate(domainName: string): Promise<SmartacmeCert | null> {
return this.certs.get(domainName) ?? null;
}
public async storeCertificate(cert: SmartacmeCert): Promise<void> {
this.certs.set(cert.domainName, cert);
const interest = this.interestMap.findInterest(cert.domainName);
if (interest) {
interest.fullfillInterest(cert);
interest.markLost();
}
}
public async deleteCertificate(domainName: string): Promise<void> {
this.certs.delete(domainName);
}
public async close(): Promise<void> {
// no-op
}
/**
* Wipe all certificates from the in-memory store (for testing)
*/
public async wipe(): Promise<void> {
this.certs.clear();
// reset interest map
this.interestMap = new plugins.lik.InterestMap((domain) => domain);
}
}

View File

@ -1,52 +1,6 @@
import * as plugins from './smartacme.plugins.js';
import type { ICertManager } from './interfaces/certmanager.js';
import { SmartacmeCert } from './smartacme.classes.cert.js';
/**
* In-memory certificate manager for mongoless mode.
* Stores certificates in memory only and does not connect to MongoDB.
*/
export class MemoryCertManager implements ICertManager {
public interestMap: plugins.lik.InterestMap<string, SmartacmeCert>;
private certs: Map<string, SmartacmeCert> = new Map();
constructor() {
this.interestMap = new plugins.lik.InterestMap((domain) => domain);
}
public async init(): Promise<void> {
// no-op for in-memory store
}
public async retrieveCertificate(domainName: string): Promise<SmartacmeCert | null> {
return this.certs.get(domainName) ?? null;
}
public async storeCertificate(cert: SmartacmeCert): Promise<void> {
this.certs.set(cert.domainName, cert);
const interest = this.interestMap.findInterest(cert.domainName);
if (interest) {
interest.fullfillInterest(cert);
interest.markLost();
}
}
public async deleteCertificate(domainName: string): Promise<void> {
this.certs.delete(domainName);
}
public async close(): Promise<void> {
// no-op
}
/**
* Wipe all certificates from the in-memory store (for testing)
*/
public async wipe(): Promise<void> {
this.certs.clear();
// reset interest map
this.interestMap = new plugins.lik.InterestMap((domain) => domain);
}
}
import * as plugins from '../smartacme.plugins.js';
import type { ICertManager } from '../interfaces/certmanager.js';
import { SmartacmeCert } from '../smartacme.classes.cert.js';
/**
* MongoDB-backed certificate manager using EasyStore from smartdata.
@ -104,4 +58,4 @@ export class MongoCertManager implements ICertManager {
// reset interest map
this.interestMap = new plugins.lik.InterestMap((domain) => domain);
}
}
}

View File

@ -1,4 +1,4 @@
export * from './smartacme.classes.smartacme.js';
export { SmartacmeCert as Cert } from './smartacme.classes.cert.js';
export type { ICertManager } from './interfaces/certmanager.js';
export { MemoryCertManager, MongoCertManager } from './certmanagers.js';
export { MemoryCertManager, MongoCertManager } from './certmanagers/index.js';

View File

@ -1,4 +1,3 @@
import type { InterestMap } from '@push.rocks/lik';
import type { SmartacmeCert } from '../smartacme.classes.cert.js';
// (ICertRecord removed; use SmartacmeCert directly)
@ -9,10 +8,6 @@ import type { SmartacmeCert } from '../smartacme.classes.cert.js';
* file-based, Redis, etc.).
*/
export interface ICertManager {
/**
* Map for coordinating concurrent certificate requests.
*/
interestMap: InterestMap<string, SmartacmeCert>;
/**
* Initialize the store (e.g., connect to database).
*/
@ -37,5 +32,5 @@ export interface ICertManager {
/**
* Optional: wipe all stored certificates (e.g., for integration testing)
*/
wipe?(): Promise<void>;
wipe(): Promise<void>;
}

View File

@ -63,7 +63,7 @@ export class SmartAcme {
// certificate manager for persistence (implements ICertManager)
private certmanager: ICertManager;
public certmanager: ICertManager;
private certmatcher: SmartacmeCertMatcher;
// retry/backoff configuration (resolved with defaults)
private retryOptions: { retries: number; factor: number; minTimeoutMs: number; maxTimeoutMs: number };
@ -116,11 +116,6 @@ export class SmartAcme {
}
this.certmanager = this.options.certManager;
await this.certmanager.init();
// For integration environment, clear any existing certificates to avoid stale entries
if (this.options.environment === 'integration' && typeof (this.certmanager as any).wipe === 'function') {
// this.logger.log('warn', 'Wiping existing certificates for integration environment');
// await (this.certmanager as any).wipe();
}
// CertMatcher
this.certmatcher = new SmartacmeCertMatcher();