BREAKING CHANGE(acme): Replace external acme-client with a built-in RFC8555-compliant ACME implementation and update public APIs accordingly
This commit is contained in:
99
ts/acme/acme.classes.client.ts
Normal file
99
ts/acme/acme.classes.client.ts
Normal file
@@ -0,0 +1,99 @@
|
||||
import { AcmeCrypto } from './acme.classes.crypto.js';
|
||||
import { ACME_DIRECTORY_URLS } from './acme.classes.directory.js';
|
||||
import { AcmeHttpClient, type TAcmeLogger } from './acme.classes.http-client.js';
|
||||
import { AcmeAccount } from './acme.classes.account.js';
|
||||
import { AcmeOrderManager } from './acme.classes.order.js';
|
||||
import { AcmeChallengeManager } from './acme.classes.challenge.js';
|
||||
import type {
|
||||
IAcmeAccount,
|
||||
IAcmeAccountCreateRequest,
|
||||
IAcmeAuthorization,
|
||||
IAcmeChallenge,
|
||||
IAcmeIdentifier,
|
||||
IAcmeOrder,
|
||||
} from './acme.interfaces.js';
|
||||
|
||||
export interface IAcmeClientOptions {
|
||||
directoryUrl: string;
|
||||
accountKeyPem: string;
|
||||
logger?: TAcmeLogger;
|
||||
}
|
||||
|
||||
/**
|
||||
* Top-level ACME client facade.
|
||||
* Composes HTTP transport, account management, order lifecycle, and challenge handling.
|
||||
*/
|
||||
export class AcmeClient {
|
||||
private httpClient: AcmeHttpClient;
|
||||
private account: AcmeAccount;
|
||||
private orderManager: AcmeOrderManager;
|
||||
private challengeManager: AcmeChallengeManager;
|
||||
|
||||
/** Well-known CA directory URLs */
|
||||
static directory = ACME_DIRECTORY_URLS;
|
||||
/** Crypto utilities */
|
||||
static crypto = AcmeCrypto;
|
||||
|
||||
constructor(options: IAcmeClientOptions) {
|
||||
this.httpClient = new AcmeHttpClient(options.directoryUrl, options.accountKeyPem, options.logger);
|
||||
this.account = new AcmeAccount(this.httpClient);
|
||||
this.orderManager = new AcmeOrderManager(this.httpClient);
|
||||
this.challengeManager = new AcmeChallengeManager(this.httpClient, options.accountKeyPem);
|
||||
}
|
||||
|
||||
/**
|
||||
* Register or retrieve an ACME account
|
||||
*/
|
||||
async createAccount(request: IAcmeAccountCreateRequest): Promise<IAcmeAccount> {
|
||||
return this.account.create(request);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new certificate order
|
||||
*/
|
||||
async createOrder(opts: { identifiers: IAcmeIdentifier[] }): Promise<IAcmeOrder> {
|
||||
return this.orderManager.create(opts);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get all authorizations for an order
|
||||
*/
|
||||
async getAuthorizations(order: IAcmeOrder): Promise<IAcmeAuthorization[]> {
|
||||
return this.orderManager.getAuthorizations(order);
|
||||
}
|
||||
|
||||
/**
|
||||
* Compute the key authorization string for a challenge (sync)
|
||||
*/
|
||||
getChallengeKeyAuthorization(challenge: IAcmeChallenge): string {
|
||||
return this.challengeManager.getKeyAuthorization(challenge);
|
||||
}
|
||||
|
||||
/**
|
||||
* Notify the ACME server to validate a challenge
|
||||
*/
|
||||
async completeChallenge(challenge: IAcmeChallenge): Promise<void> {
|
||||
return this.challengeManager.complete(challenge);
|
||||
}
|
||||
|
||||
/**
|
||||
* Poll an ACME resource until it reaches valid/ready status
|
||||
*/
|
||||
async waitForValidStatus(item: { url: string }): Promise<any> {
|
||||
return this.orderManager.waitForValidStatus(item);
|
||||
}
|
||||
|
||||
/**
|
||||
* Finalize an order by submitting the CSR
|
||||
*/
|
||||
async finalizeOrder(order: IAcmeOrder, csrPem: string): Promise<void> {
|
||||
return this.orderManager.finalize(order, csrPem);
|
||||
}
|
||||
|
||||
/**
|
||||
* Download the certificate chain (PEM)
|
||||
*/
|
||||
async getCertificate(order: IAcmeOrder): Promise<string> {
|
||||
return this.orderManager.getCertificate(order);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user