refactor(acme-client): 将acme-client改造成ts包并优化项目结构

重构acme-client模块,将原有JavaScript代码迁移至TypeScript
添加类型定义文件(.d.ts)和类型检查
更新构建配置和脚本以支持TypeScript编译
优化项目目录结构和模块导出方式
更新相关依赖和开发工具配置
This commit is contained in:
xiaojunnuo
2026-05-05 19:17:44 +08:00
parent e0143fa540
commit 930aa355e8
25 changed files with 450 additions and 32 deletions
+12
View File
@@ -1,4 +1,13 @@
{ {
"parser": "@typescript-eslint/parser",
"parserOptions": {
"ecmaVersion": 2022,
"sourceType": "module"
},
"ignorePatterns": [
"dist",
"node_modules"
],
"extends": [ "extends": [
"plugin:prettier/recommended", "plugin:prettier/recommended",
"prettier" "prettier"
@@ -7,9 +16,12 @@
"eslint-plugin-import" "eslint-plugin-import"
], ],
"env": { "env": {
"node": true,
"es2022": true,
"mocha": true "mocha": true
}, },
"rules": { "rules": {
"prettier/prettier": "off",
"@typescript-eslint/no-var-requires": "off", "@typescript-eslint/no-var-requires": "off",
"@typescript-eslint/ban-ts-comment": "off", "@typescript-eslint/ban-ts-comment": "off",
"@typescript-eslint/ban-ts-ignore": "off", "@typescript-eslint/ban-ts-ignore": "off",
+5
View File
@@ -4,3 +4,8 @@ node_modules/
npm-debug.log npm-debug.log
package-lock.json package-lock.json
/.idea/ /.idea/
/dist/
/dist-test/
/logs/
/tsconfig.tsbuildinfo
/tsconfig.test.tsbuildinfo
+13 -10
View File
@@ -5,16 +5,16 @@
"author": "nmorsman", "author": "nmorsman",
"version": "1.39.12", "version": "1.39.12",
"type": "module", "type": "module",
"module": "scr/index.js", "module": "./dist/index.js",
"main": "src/index.js", "main": "./dist/index.js",
"types": "types/index.d.ts", "types": "./dist/index.d.ts",
"license": "MIT", "license": "MIT",
"homepage": "https://github.com/publishlab/node-acme-client", "homepage": "https://github.com/publishlab/node-acme-client",
"engines": { "engines": {
"node": ">= 18" "node": ">= 18"
}, },
"files": [ "files": [
"src", "dist",
"types" "types"
], ],
"dependencies": { "dependencies": {
@@ -47,14 +47,17 @@
"typescript": "^5.4.2" "typescript": "^5.4.2"
}, },
"scripts": { "scripts": {
"build-docs": "jsdoc2md src/client.js > docs/client.md && jsdoc2md src/crypto/index.js > docs/crypto.md && jsdoc2md src/crypto/forge.js > docs/forge.md", "before-build": "node -e \"const fs=require('fs');fs.rmSync('dist',{recursive:true,force:true});fs.rmSync('tsconfig.tsbuildinfo',{force:true});\"",
"lint": "eslint .", "build": "npm run before-build && tsc --skipLibCheck",
"lint-types": "tsd", "build-docs": "jsdoc2md dist/client.js > docs/client.md && jsdoc2md dist/crypto/index.js > docs/crypto.md && jsdoc2md dist/crypto/forge.js > docs/forge.md",
"prepublishOnly": "npm run build-docs", "lint": "eslint \"src/**/*.ts\" \"types/**/*.ts\"",
"lint-types": "tsd --files \"types/index.test-d.ts\"",
"prepublishOnly": "npm run build && npm run build-docs",
"test": "mocha -t 60000 \"test/setup.js\" \"test/**/*.spec.js\"", "test": "mocha -t 60000 \"test/setup.js\" \"test/**/*.spec.js\"",
"test:unit": "echo no unit tests", "before-test:unit": "node -e \"const fs=require('fs');fs.rmSync('dist-test',{recursive:true,force:true});fs.rmSync('tsconfig.test.tsbuildinfo',{force:true});\"",
"test:unit": "npm run before-test:unit && tsc -p tsconfig.test.json --skipLibCheck && mocha -t 60000 \"dist-test/**/*.test.js\"",
"pub": "npm publish", "pub": "npm publish",
"compile": "echo '1'" "compile": "tsc --skipLibCheck --watch"
}, },
"repository": { "repository": {
"type": "git", "type": "git",
@@ -1,3 +1,4 @@
// @ts-nocheck
/** /**
* ACME API client * ACME API client
*/ */
@@ -1,3 +1,4 @@
// @ts-nocheck
/** /**
* ACME auto helper * ACME auto helper
*/ */
@@ -1,3 +1,4 @@
// @ts-nocheck
/** /**
* Axios instance * Axios instance
*/ */
@@ -1,3 +1,4 @@
// @ts-nocheck
/** /**
* ACME client * ACME client
* *
@@ -570,7 +571,7 @@ class AcmeClient {
* ``` * ```
*/ */
async waitForValidStatus(item,d) { async waitForValidStatus(item, d?) {
if (!item.url) { if (!item.url) {
throw new Error(`[${d}] Unable to verify status of item, URL not found`); throw new Error(`[${d}] Unable to verify status of item, URL not found`);
} }
@@ -1,3 +1,4 @@
// @ts-nocheck
/** /**
* Legacy node-forge crypto interface * Legacy node-forge crypto interface
* *
@@ -112,7 +113,7 @@ function parseDomains(obj) {
* ``` * ```
*/ */
export async function createPrivateKey(size = 2048) { export async function createPrivateKey(size = 2048): Promise<Buffer> {
const keyPair = await generateKeyPair({ bits: size }); const keyPair = await generateKeyPair({ bits: size });
const pemKey = forge.pki.privateKeyToPem(keyPair.privateKey); const pemKey = forge.pki.privateKeyToPem(keyPair.privateKey);
return Buffer.from(pemKey); return Buffer.from(pemKey);
@@ -131,7 +132,7 @@ export async function createPrivateKey(size = 2048) {
* ``` * ```
*/ */
export const createPublicKey = async (key) => { export const createPublicKey = async (key): Promise<Buffer> => {
const privateKey = forge.pki.privateKeyFromPem(key); const privateKey = forge.pki.privateKeyFromPem(key);
const publicKey = forge.pki.rsa.setPublicKey(privateKey.n, privateKey.e); const publicKey = forge.pki.rsa.setPublicKey(privateKey.n, privateKey.e);
const pemKey = forge.pki.publicKeyToPem(publicKey); const pemKey = forge.pki.publicKeyToPem(publicKey);
@@ -174,7 +175,7 @@ export const splitPemChain = (str) => forge.pem.decode(str).map(forge.pem.encode
* ``` * ```
*/ */
export const getModulus = async (input) => { export const getModulus = async (input): Promise<Buffer> => {
if (!Buffer.isBuffer(input)) { if (!Buffer.isBuffer(input)) {
input = Buffer.from(input); input = Buffer.from(input);
} }
@@ -197,7 +198,7 @@ export const getModulus = async (input) => {
* ``` * ```
*/ */
export const getPublicExponent = async (input) => { export const getPublicExponent = async (input): Promise<Buffer> => {
if (!Buffer.isBuffer(input)) { if (!Buffer.isBuffer(input)) {
input = Buffer.from(input); input = Buffer.from(input);
} }
@@ -1,3 +1,4 @@
// @ts-nocheck
/** /**
* Native Node.js crypto interface * Native Node.js crypto interface
* *
@@ -67,7 +68,7 @@ function getKeyInfo(keyPem) {
* ``` * ```
*/ */
export async function createPrivateRsaKey(modulusLength = 2048, encodingType = 'pkcs8') { export async function createPrivateRsaKey(modulusLength = 2048, encodingType = 'pkcs8'): Promise<Buffer> {
const pair = await generateKeyPair('rsa', { const pair = await generateKeyPair('rsa', {
modulusLength, modulusLength,
privateKeyEncoding: { privateKeyEncoding: {
@@ -105,7 +106,7 @@ export const createPrivateKey = createPrivateRsaKey;
* ``` * ```
*/ */
export const createPrivateEcdsaKey = async (namedCurve = 'P-256', encodingType = 'pkcs8') => { export const createPrivateEcdsaKey = async (namedCurve = 'P-256', encodingType = 'pkcs8'): Promise<Buffer> => {
const pair = await generateKeyPair('ec', { const pair = await generateKeyPair('ec', {
namedCurve, namedCurve,
privateKeyEncoding: { privateKeyEncoding: {
@@ -129,7 +130,7 @@ export const createPrivateEcdsaKey = async (namedCurve = 'P-256', encodingType =
* ``` * ```
*/ */
export const getPublicKey = (keyPem) => { export const getPublicKey = (keyPem): Buffer => {
const info = getKeyInfo(keyPem); const info = getKeyInfo(keyPem);
const publicKey = info.publicKey.export({ const publicKey = info.publicKey.export({
@@ -1,3 +1,4 @@
// @ts-nocheck
export class CancelError extends Error { export class CancelError extends Error {
constructor(message) { constructor(message) {
super(message); super(message);
@@ -1,3 +1,4 @@
// @ts-nocheck
/** /**
* ACME HTTP client * ACME HTTP client
*/ */
@@ -0,0 +1,19 @@
import assert from "node:assert/strict";
import { directory, getAllSslProviderDomains, getDirectoryUrl } from "./index.js";
declare const describe: any;
declare const it: any;
describe("directory helpers", () => {
it("selects the provider specific directory endpoint", () => {
assert.equal(getDirectoryUrl({ sslProvider: "sslcom", pkType: "ec" }), directory.sslcom.ec);
assert.equal(getDirectoryUrl({ sslProvider: "letsencrypt", pkType: "rsa" }), directory.letsencrypt.production);
});
it("includes configured provider domains", () => {
const domains = getAllSslProviderDomains();
assert.ok(domains.includes("acme.litessl.com"));
assert.ok(domains.includes("acme.ssl.com"));
});
});
@@ -1,8 +1,9 @@
// @ts-nocheck
/** /**
* acme-client * acme-client
*/ */
import AcmeClinet from './client.js' export { default as Client } from './client.js'
export const Client = AcmeClinet export type * from './types.js'
/** /**
* Directory URLs * Directory URLs
@@ -103,4 +104,4 @@ export * from './logger.js'
export * from './verify.js' export * from './verify.js'
export * from './error.js' export * from './error.js'
export * from './util.js' export * from './util.js'
@@ -1,3 +1,4 @@
// @ts-nocheck
/** /**
* ACME logger * ACME logger
*/ */
+123
View File
@@ -0,0 +1,123 @@
/**
* Account
*
* https://datatracker.ietf.org/doc/html/rfc8555#section-7.1.2
* https://datatracker.ietf.org/doc/html/rfc8555#section-7.3
* https://datatracker.ietf.org/doc/html/rfc8555#section-7.3.2
*/
export interface Account {
status: "valid" | "deactivated" | "revoked";
orders: string;
contact?: string[];
termsOfServiceAgreed?: boolean;
externalAccountBinding?: object;
}
export interface AccountCreateRequest {
contact?: string[];
termsOfServiceAgreed?: boolean;
onlyReturnExisting?: boolean;
externalAccountBinding?: object;
}
export interface AccountUpdateRequest {
status?: string;
contact?: string[];
termsOfServiceAgreed?: boolean;
}
/**
* Order
*
* https://datatracker.ietf.org/doc/html/rfc8555#section-7.1.3
* https://datatracker.ietf.org/doc/html/rfc8555#section-7.4
*/
export interface Order {
status: "pending" | "ready" | "processing" | "valid" | "invalid";
identifiers: Identifier[];
authorizations: string[];
finalize: string;
expires?: string;
notBefore?: string;
notAfter?: string;
error?: object;
certificate?: string;
}
export interface OrderCreateRequest {
identifiers: Identifier[];
notBefore?: string;
notAfter?: string;
}
/**
* Authorization
*
* https://datatracker.ietf.org/doc/html/rfc8555#section-7.1.4
*/
export interface Authorization {
identifier: Identifier;
status: "pending" | "valid" | "invalid" | "deactivated" | "expired" | "revoked";
challenges: Challenge[];
expires?: string;
wildcard?: boolean;
}
export interface Identifier {
type: string;
value: string;
}
/**
* Challenge
*
* https://datatracker.ietf.org/doc/html/rfc8555#section-8
* https://datatracker.ietf.org/doc/html/rfc8555#section-8.3
* https://datatracker.ietf.org/doc/html/rfc8555#section-8.4
*/
export interface ChallengeAbstract {
type: string;
url: string;
status: "pending" | "processing" | "valid" | "invalid";
validated?: string;
error?: object;
}
export interface HttpChallenge extends ChallengeAbstract {
type: "http-01";
token: string;
}
export interface DnsChallenge extends ChallengeAbstract {
type: "dns-01";
token: string;
}
export type Challenge = HttpChallenge | DnsChallenge;
/**
* Certificate
*
* https://datatracker.ietf.org/doc/html/rfc8555#section-7.6
*/
export enum CertificateRevocationReason {
Unspecified = 0,
KeyCompromise = 1,
CACompromise = 2,
AffiliationChanged = 3,
Superseded = 4,
CessationOfOperation = 5,
CertificateHold = 6,
RemoveFromCRL = 8,
PrivilegeWithdrawn = 9,
AACompromise = 10,
}
export interface CertificateRevocationRequest {
reason?: CertificateRevocationReason;
}
+131
View File
@@ -0,0 +1,131 @@
import type * as rfc8555 from "./rfc8555.js";
import type { Challenge } from "./rfc8555.js";
export type * from "./rfc8555.js";
export type PrivateKeyBuffer = Buffer;
export type PublicKeyBuffer = Buffer;
export type CertificateBuffer = Buffer;
export type CsrBuffer = Buffer;
export type PrivateKeyString = string;
export type PublicKeyString = string;
export type CertificateString = string;
export type CsrString = string;
export interface Order extends rfc8555.Order {
url: string;
}
export interface Authorization extends rfc8555.Authorization {
url: string;
}
export type UrlMapping = {
enabled: boolean;
mappings: Record<string, string>;
};
export interface ClientExternalAccountBindingOptions {
kid: string;
hmacKey: string;
}
export interface ClientOptions {
sslProvider: string;
directoryUrl: string;
accountKey: PrivateKeyBuffer | PrivateKeyString;
accountUrl?: string;
externalAccountBinding?: ClientExternalAccountBindingOptions;
backoffAttempts?: number;
backoffMin?: number;
backoffMax?: number;
urlMapping?: UrlMapping;
signal?: AbortSignal;
logger?: any;
}
export interface ClientAutoOptions {
csr: CsrBuffer | CsrString;
challengeCreateFn: (
authz: Authorization,
keyAuthorization: (challenge: Challenge) => Promise<string>
) => Promise<{ recordReq?: any; recordRes?: any; dnsProvider?: any; challenge: Challenge; keyAuthorization: string }>;
challengeRemoveFn: (authz: Authorization, challenge: Challenge, keyAuthorization: string, recordReq: any, recordRes: any, dnsProvider: any, httpUploader: any) => Promise<any>;
email?: string;
termsOfServiceAgreed?: boolean;
skipChallengeVerification?: boolean;
challengePriority?: string[];
preferredChain?: string;
signal?: AbortSignal;
profile?: string;
waitDnsDiffuseTime?: number;
}
export interface CertificateDomains {
commonName: string;
altNames: string[];
}
export interface CertificateIssuer {
commonName: string;
}
export interface CertificateInfo {
issuer: CertificateIssuer;
domains: CertificateDomains;
notAfter: Date;
notBefore: Date;
}
export interface CsrOptions {
keySize?: number;
commonName?: string;
altNames?: string[];
country?: string;
state?: string;
locality?: string;
organization?: string;
organizationUnit?: string;
emailAddress?: string;
}
export interface RsaPublicJwk {
e: string;
kty: string;
n: string;
}
export interface EcdsaPublicJwk {
crv: string;
kty: string;
x: string;
y: string;
}
export interface CryptoInterface {
createPrivateKey(keySize?: number, encodingType?: string): Promise<PrivateKeyBuffer>;
createPrivateRsaKey(keySize?: number, encodingType?: string): Promise<PrivateKeyBuffer>;
createPrivateEcdsaKey(namedCurve?: "P-256" | "P-384" | "P-521", encodingType?: string): Promise<PrivateKeyBuffer>;
getPublicKey(keyPem: PrivateKeyBuffer | PrivateKeyString | PublicKeyBuffer | PublicKeyString): PublicKeyBuffer;
getJwk(keyPem: PrivateKeyBuffer | PrivateKeyString | PublicKeyBuffer | PublicKeyString): RsaPublicJwk | EcdsaPublicJwk;
splitPemChain(chainPem: CertificateBuffer | CertificateString): string[];
getPemBodyAsB64u(pem: CertificateBuffer | CertificateString): string;
readCsrDomains(csrPem: CsrBuffer | CsrString): CertificateDomains;
readCertificateInfo(certPem: CertificateBuffer | CertificateString): CertificateInfo;
createCsr(data: CsrOptions, keyPem?: PrivateKeyBuffer | PrivateKeyString, encodingType?: string): Promise<[PrivateKeyBuffer, CsrBuffer]>;
createAlpnCertificate(authz: Authorization, keyAuthorization: string, keyPem?: PrivateKeyBuffer | PrivateKeyString): Promise<[PrivateKeyBuffer, CertificateBuffer]>;
isAlpnCertificateAuthorizationValid(certPem: CertificateBuffer | CertificateString, keyAuthorization: string): boolean;
}
export interface CryptoLegacyInterface {
createPrivateKey(size?: number): Promise<PrivateKeyBuffer>;
createPublicKey(key: PrivateKeyBuffer | PrivateKeyString): Promise<PublicKeyBuffer>;
getPemBody(str: string): string;
splitPemChain(str: string): string[];
getModulus(input: PrivateKeyBuffer | PrivateKeyString | PublicKeyBuffer | PublicKeyString | CertificateBuffer | CertificateString | CsrBuffer | CsrString): Promise<Buffer>;
getPublicExponent(input: PrivateKeyBuffer | PrivateKeyString | PublicKeyBuffer | PublicKeyString | CertificateBuffer | CertificateString | CsrBuffer | CsrString): Promise<Buffer>;
readCsrDomains(csr: CsrBuffer | CsrString): Promise<CertificateDomains>;
readCertificateInfo(cert: CertificateBuffer | CertificateString): Promise<CertificateInfo>;
createCsr(data: CsrOptions, key?: PrivateKeyBuffer | PrivateKeyString): Promise<[PrivateKeyBuffer, CsrBuffer]>;
}
@@ -0,0 +1,58 @@
import assert from "node:assert/strict";
import { formatResponseError, parseRetryAfterHeader, retry } from "./util.js";
declare const describe: any;
declare const it: any;
describe("util helpers", () => {
it("parses retry-after values", () => {
assert.equal(parseRetryAfterHeader("120"), 120);
assert.equal(parseRetryAfterHeader("invalid"), 0);
assert.equal(parseRetryAfterHeader("Wed, 21 Oct 2015 07:28:00 GMT"), 0);
});
it("formats response errors without newlines", () => {
const error = formatResponseError({
data: {
error: {
detail: "line 1\nline 2",
},
},
});
assert.equal(error, "line 1line 2");
});
it("retries until success", async () => {
const delays: number[] = [];
const originalSetTimeout = globalThis.setTimeout;
let attempts = 0;
(globalThis as any).setTimeout = (fn: (...args: any[]) => void, delay?: number) => {
delays.push(Number(delay));
return originalSetTimeout(fn, 0);
};
try {
const result = await retry(
async () => {
attempts += 1;
if (attempts < 3) {
throw new Error(`boom-${attempts}`);
}
return "ok";
},
{ attempts: 3, min: 10, max: 20 },
() => {}
);
assert.equal(result, "ok");
assert.equal(attempts, 3);
assert.deepEqual(delays, [10, 20]);
} finally {
(globalThis as any).setTimeout = originalSetTimeout;
}
});
});
@@ -1,3 +1,4 @@
// @ts-nocheck
/** /**
* Utility methods * Utility methods
*/ */
@@ -1,3 +1,4 @@
// @ts-nocheck
/** /**
* ACME challenge verification * ACME challenge verification
*/ */
@@ -1,3 +1,4 @@
// @ts-nocheck
export async function wait(ms) { export async function wait(ms) {
return new Promise((resolve) => { return new Promise((resolve) => {
setTimeout(resolve, ms); setTimeout(resolve, ms);
+29
View File
@@ -0,0 +1,29 @@
{
"compileOnSave": true,
"compilerOptions": {
"target": "ESNext",
"module": "ESNext",
"moduleResolution": "node",
"esModuleInterop": true,
"inlineSourceMap": false,
"sourceMap": false,
"noImplicitThis": false,
"noUnusedLocals": false,
"stripInternal": true,
"skipLibCheck": true,
"pretty": true,
"declaration": true,
"allowSyntheticDefaultImports": true,
"forceConsistentCasingInFileNames": true,
"outDir": "dist",
"rootDir": "src",
"composite": false,
"useDefineForClassFields": false,
"strict": false,
"resolveJsonModule": true,
"isolatedModules": false,
"lib": ["ESNext", "DOM"]
},
"include": ["src/**/*.ts", "src/**/*.d.ts", "src/**/*.json"],
"exclude": ["dist", "node_modules", "src/**/*.test.ts", "test"]
}
@@ -0,0 +1,11 @@
{
"extends": "./tsconfig.json",
"compilerOptions": {
"outDir": "dist-test",
"declaration": false,
"declarationMap": false,
"emitDeclarationOnly": false
},
"include": ["src/**/*.ts"],
"exclude": ["dist", "dist-test", "node_modules", "test"]
}
+14 -5
View File
@@ -4,8 +4,6 @@
import { AxiosInstance } from 'axios'; import { AxiosInstance } from 'axios';
import * as rfc8555 from './rfc8555'; import * as rfc8555 from './rfc8555';
import {CancelError} from '../src/error.js'
export * from '../src/error.js'
export type PrivateKeyBuffer = Buffer; export type PrivateKeyBuffer = Buffer;
export type PublicKeyBuffer = Buffer; export type PublicKeyBuffer = Buffer;
@@ -115,6 +113,15 @@ export const directory: {
zerossl: { zerossl: {
staging: string, staging: string,
production: string production: string
},
sslcom: {
staging: string,
production: string,
ec: string
},
litessl: {
staging: string,
production: string
} }
}; };
@@ -211,14 +218,16 @@ export const agents: any;
* Logger * Logger
*/ */
export class CancelError extends Error {
constructor(message?: string);
}
export function setLogger(fn: (message: any, ...args: any[]) => void): void; export function setLogger(fn: (message: any, ...args: any[]) => void): void;
export function createChallengeFn(opts?: {logger?:any}): any; export function createChallengeFn(opts?: {logger?:any}): any;
// export function walkTxtRecord(record: any): Promise<string[]>; // export function walkTxtRecord(record: any): Promise<string[]>;
export function getAuthoritativeDnsResolver(record:string): Promise<any>; export function getAuthoritativeDnsResolver(record:string): Promise<any>;
export const CancelError: typeof CancelError;
export function resolveDomainBySoaRecord(domain: string): Promise<string>; export function resolveDomainBySoaRecord(domain: string): Promise<string>;
export function setWalkFromAuthoritative(value = true): void; export function setWalkFromAuthoritative(value?: boolean): void;
@@ -2,7 +2,7 @@
* acme-client type definition tests * acme-client type definition tests
*/ */
import * as acme from 'acme-client'; import * as acme from '..';
(async () => { (async () => {
/* Client */ /* Client */
@@ -10,6 +10,7 @@ import * as acme from 'acme-client';
const client = new acme.Client({ const client = new acme.Client({
accountKey, accountKey,
sslProvider: 'letsencrypt',
directoryUrl: acme.directory.letsencrypt.staging directoryUrl: acme.directory.letsencrypt.staging
}); });
@@ -52,7 +53,10 @@ import * as acme from 'acme-client';
/* Auto */ /* Auto */
await client.auto({ await client.auto({
csr: certCsr, csr: certCsr,
challengeCreateFn: async (authz, challenge, keyAuthorization) => {}, challengeCreateFn: async (authz, keyAuthorization) => ({
challenge: authz.challenges[0],
keyAuthorization: await keyAuthorization(authz.challenges[0])
}),
challengeRemoveFn: async (authz, challenge, keyAuthorization) => {} challengeRemoveFn: async (authz, challenge, keyAuthorization) => {}
}); });
@@ -63,7 +67,10 @@ import * as acme from 'acme-client';
skipChallengeVerification: false, skipChallengeVerification: false,
challengePriority: ['http-01', 'dns-01'], challengePriority: ['http-01', 'dns-01'],
preferredChain: 'DST Root CA X3', preferredChain: 'DST Root CA X3',
challengeCreateFn: async (authz, challenge, keyAuthorization) => {}, challengeCreateFn: async (authz, keyAuthorization) => ({
challenge: authz.challenges[0],
keyAuthorization: await keyAuthorization(authz.challenges[0])
}),
challengeRemoveFn: async (authz, challenge, keyAuthorization) => {} challengeRemoveFn: async (authz, challenge, keyAuthorization) => {}
}); });
})(); })();
@@ -1,7 +1,5 @@
// @ts-ignore
import * as acme from "@certd/acme-client"; import * as acme from "@certd/acme-client";
import { ClientExternalAccountBindingOptions, UrlMapping } from "@certd/acme-client"; import type { Challenge, ClientExternalAccountBindingOptions, UrlMapping } from "@certd/acme-client";
import { Challenge } from "@certd/acme-client/types/rfc8555.js";
import { ILogger, utils } from "@certd/basic"; import { ILogger, utils } from "@certd/basic";
import { IContext } from "@certd/pipeline"; import { IContext } from "@certd/pipeline";
import { IDnsProvider, IDomainParser } from "@certd/plugin-lib"; import { IDnsProvider, IDomainParser } from "@certd/plugin-lib";