diff --git a/changelog.md b/changelog.md index 0129751..1e84028 100644 --- a/changelog.md +++ b/changelog.md @@ -1,5 +1,14 @@ # Changelog +## 2025-04-30 - 7.1.0 - feat(certmanagers/integration) +Add optional wipe methods to certificate managers and update integration tests, plus bump tapbundle dependency + +- Introduce wipe() in ICertManager to support integration testing by clearing stored certificates +- Implement wipe() in MemoryCertManager and MongoCertManager for resetting internal state +- Refactor SmartAcme constructor to consider wiping certificates in integration mode (commented out for now) +- Update integration test assertions and add console logging for domain certificate retrieval +- Upgrade @push.rocks/tapbundle from ^6.0.0 to ^6.0.1 + ## 2025-04-30 - 7.0.0 - BREAKING CHANGE(SmartAcme (Cert Management)) Refactor certificate management and challenge handling API to use a unified certManager interface, remove legacy storage, and update challenge workflows. diff --git a/package.json b/package.json index fed28ef..3148dbb 100644 --- a/package.json +++ b/package.json @@ -59,7 +59,7 @@ "@git.zone/tsrun": "^1.3.3", "@git.zone/tstest": "^1.0.96", "@push.rocks/qenv": "^6.1.0", - "@push.rocks/tapbundle": "^6.0.0", + "@push.rocks/tapbundle": "^6.0.1", "@types/node": "^22.15.3" }, "files": [ diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 1bfa8de..d665271 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -64,8 +64,8 @@ importers: specifier: ^6.1.0 version: 6.1.0 '@push.rocks/tapbundle': - specifier: ^6.0.0 - version: 6.0.0(@aws-sdk/credential-providers@3.797.0)(socks@2.8.4) + specifier: ^6.0.1 + version: 6.0.1(@aws-sdk/credential-providers@3.797.0)(socks@2.8.4) '@types/node': specifier: ^22.15.3 version: 22.15.3 @@ -821,8 +821,8 @@ packages: '@push.rocks/smartexpect@1.6.1': resolution: {integrity: sha512-NFQXEPkGiMNxyvFwKyzDWe3ADYdf8KNvIcV7TGNZZT3uPQtk65te4Q+a1cWErjP/61yE9XdYiQA66QQp+TV9IQ==} - '@push.rocks/smartexpect@2.2.2': - resolution: {integrity: sha512-s2zJlLc6Wub7P/jgKSM51kW2UjslxQwx2BXoyJVO95OgiOwarde0AuxPR0lfRA/FvHdBfTmJf4upiWtcjYMB/Q==} + '@push.rocks/smartexpect@2.3.2': + resolution: {integrity: sha512-cKRPl8GTU4j0zwiQsq8+NiAzBv2iJ9laoGkjEpTs37XhkHIN/EympenvMkXWE4/2HDAlyQm1ZwIl4NRzPBzXbA==} '@push.rocks/smartfeed@1.0.11': resolution: {integrity: sha512-02uhXxQamgfBo3T12FsAdfyElnpoWuDUb08B2AE60DbIaukVx/7Mi17xwobApY1flNSr5StZDt8N8vxPhBhIXw==} @@ -959,8 +959,8 @@ packages: '@push.rocks/tapbundle@5.6.3': resolution: {integrity: sha512-hFzsf59rg1K70i45llj7PCyyCZp7JW19XRR+Q1gge1T0pBN8Wi53aYqP/2qtxdMiNVe2s3ESp6VJZv3sLOMYPQ==} - '@push.rocks/tapbundle@6.0.0': - resolution: {integrity: sha512-ARIs189TysvI8EsPAC7LH6O0WbBYI9E7XxdihwmM6LRgLvzAbp1agfO6lOjpKrAYWKjT3KdlUEihilxOBrgTYQ==} + '@push.rocks/tapbundle@6.0.1': + resolution: {integrity: sha512-GeReOjCSF+X+dnHgG+yxl7Tbc9Hk9HKWMqAGLo/B5g8/u4B+V6C+ZA/Sb6Nks8aQlZLm1wXc2ZwxffoYjUHTig==} '@push.rocks/taskbuffer@3.1.7': resolution: {integrity: sha512-QktGVJPucqQmW/QNGnscf4FAigT1H7JWKFGFdRuDEaOHKFh9qN+PXG3QY7DtZ4jfXdGLxPN4yAufDuPSAJYFnw==} @@ -5830,7 +5830,7 @@ snapshots: '@push.rocks/smartpromise': 4.2.3 fast-deep-equal: 3.1.3 - '@push.rocks/smartexpect@2.2.2': + '@push.rocks/smartexpect@2.3.2': dependencies: '@push.rocks/smartdelay': 3.0.5 '@push.rocks/smartpromise': 4.2.3 @@ -6240,7 +6240,7 @@ snapshots: - supports-color - utf-8-validate - '@push.rocks/tapbundle@6.0.0(@aws-sdk/credential-providers@3.797.0)(socks@2.8.4)': + '@push.rocks/tapbundle@6.0.1(@aws-sdk/credential-providers@3.797.0)(socks@2.8.4)': dependencies: '@open-wc/testing': 4.0.0 '@push.rocks/consolecolor': 2.0.2 @@ -6248,7 +6248,7 @@ snapshots: '@push.rocks/smartcrypto': 2.0.4 '@push.rocks/smartdelay': 3.0.5 '@push.rocks/smartenv': 5.0.12 - '@push.rocks/smartexpect': 2.2.2 + '@push.rocks/smartexpect': 2.3.2 '@push.rocks/smartfile': 11.2.0 '@push.rocks/smartjson': 5.0.20 '@push.rocks/smartmongo': 2.0.12(@aws-sdk/credential-providers@3.797.0)(socks@2.8.4) diff --git a/test/test.smartacme.integration.ts b/test/test.smartacme.integration.ts index 8b66744..aee83d5 100644 --- a/test/test.smartacme.integration.ts +++ b/test/test.smartacme.integration.ts @@ -14,6 +14,7 @@ const mongoDbName = (await testQenv.getEnvVarOnDemand('MONGODB_DATABASE'))!; const mongoDbPass = (await testQenv.getEnvVarOnDemand('MONGODB_PASSWORD'))!; const mongoDbUrl = (await testQenv.getEnvVarOnDemand('MONGODB_URL'))!; + let smartAcmeInstance: SmartAcme; tap.test('create SmartAcme instance with DNS-01 handler and start', async () => { @@ -33,9 +34,10 @@ tap.test('get a domain certificate via DNS-01 challenge', async () => { // Replace 'bleu.de' with your test domain if different const domain = 'bleu.de'; const cert = await smartAcmeInstance.getCertificateForDomain(domain); - expect(cert).toHaveProperty('domainName'); - expect(cert).toEqual(domain); - expect(cert).toHaveProperty('publicKey'); + console.log(cert); + expect(cert).object.toHaveOwnProperty('domainName'); + expect(cert.domainName).toEqual(domain); + expect(cert).object.toHaveOwnProperty('publicKey'); expect(typeof cert.publicKey).toEqual('string'); expect(cert.publicKey.length).toBeGreaterThan(0); }); diff --git a/ts/00_commitinfo_data.ts b/ts/00_commitinfo_data.ts index aad7cec..03bb1be 100644 --- a/ts/00_commitinfo_data.ts +++ b/ts/00_commitinfo_data.ts @@ -3,6 +3,6 @@ */ export const commitinfo = { name: '@push.rocks/smartacme', - version: '7.0.0', + version: '7.1.0', description: 'A TypeScript-based ACME client for LetsEncrypt certificate management with a focus on simplicity and power.' } diff --git a/ts/certmanagers.ts b/ts/certmanagers.ts index f1ce95f..73c1725 100644 --- a/ts/certmanagers.ts +++ b/ts/certmanagers.ts @@ -38,6 +38,14 @@ export class MemoryCertManager implements ICertManager { public async close(): Promise { // no-op } + /** + * Wipe all certificates from the in-memory store (for testing) + */ + public async wipe(): Promise { + this.certs.clear(); + // reset interest map + this.interestMap = new plugins.lik.InterestMap((domain) => domain); + } } /** @@ -87,4 +95,13 @@ export class MongoCertManager implements ICertManager { public async close(): Promise { await this.db.close(); } + /** + * Wipe all certificates from the persistent store (for integration testing) + */ + public async wipe(): Promise { + // clear all keys in the easy store + await this.store.wipe(); + // reset interest map + this.interestMap = new plugins.lik.InterestMap((domain) => domain); + } } \ No newline at end of file diff --git a/ts/interfaces/certmanager.ts b/ts/interfaces/certmanager.ts index 55ac968..e036c08 100644 --- a/ts/interfaces/certmanager.ts +++ b/ts/interfaces/certmanager.ts @@ -34,4 +34,8 @@ export interface ICertManager { * Close the store (e.g., disconnect database). */ close(): Promise; + /** + * Optional: wipe all stored certificates (e.g., for integration testing) + */ + wipe?(): Promise; } \ No newline at end of file diff --git a/ts/smartacme.classes.smartacme.ts b/ts/smartacme.classes.smartacme.ts index f1e74e6..f7c4401 100644 --- a/ts/smartacme.classes.smartacme.ts +++ b/ts/smartacme.classes.smartacme.ts @@ -116,6 +116,11 @@ 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();