@certd/plugin-lib 1.41.3 → 1.42.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/.mocharc.json CHANGED
@@ -1,5 +1,5 @@
1
1
  {
2
2
  "extension": ["ts"],
3
3
  "spec": "test/**/*.test.ts",
4
- "require": "ts-node/register"
4
+ "node-option": ["loader=ts-node/esm", "no-warnings"]
5
5
  }
package/CHANGELOG.md CHANGED
@@ -3,6 +3,25 @@
3
3
  All notable changes to this project will be documented in this file.
4
4
  See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
5
5
 
6
+ # [1.42.0](https://github.com/certd/certd/compare/v1.41.4...v1.42.0) (2026-07-05)
7
+
8
+ ### Bug Fixes
9
+
10
+ * 修复jdk证书格式的问题 ([260f5ae](https://github.com/certd/certd/commit/260f5ae777b83493b0c578fe30fd00ec0c873226))
11
+
12
+ ### Features
13
+
14
+ * 通过插件配置懒加载依赖,动态加载第三方依赖包,精简安装镜像大小 ([01568ca](https://github.com/certd/certd/commit/01568ca1489069046b5a89ebdd4ced2f7f6ddf93))
15
+
16
+ ### Performance Improvements
17
+
18
+ * 【破坏性更新】 证书压缩包不再生成文件存储,而是实时打包下载,证书申请插件不再输出certZip ([7cff1a9](https://github.com/certd/certd/commit/7cff1a98424120585205889874b3ef4956a30583))
19
+ * 新增橙域网络(asia-isp) CDN证书部署插件 ([b48831e](https://github.com/certd/certd/commit/b48831e60b0059bef7ef9a34ab61c9dd2f684641))
20
+
21
+ ## [1.41.4](https://github.com/certd/certd/compare/v1.41.3...v1.41.4) (2026-06-14)
22
+
23
+ **Note:** Version bump only for package @certd/plugin-lib
24
+
6
25
  ## [1.41.3](https://github.com/certd/certd/compare/v1.41.2...v1.41.3) (2026-06-11)
7
26
 
8
27
  **Note:** Version bump only for package @certd/plugin-lib
@@ -74,8 +74,10 @@ export declare class CertReader {
74
74
  saveToFile(type: "crt" | "key" | "pfx" | "der" | "oc" | "one" | "ic" | "jks" | "p7b", filepath?: string): string;
75
75
  readCertFile(opts: HandleOpts): Promise<void>;
76
76
  buildCertFileName(suffix: string, applyTime: any, prefix?: string): string;
77
- buildCertName(prefix?: string): string;
77
+ buildCertName(prefix?: string, useHash?: boolean): string;
78
78
  static appendTimeSuffix(name?: string): string;
79
- static buildCertName(cert: CertInfo): string;
79
+ static buildCertName(cert: CertInfo, useHash?: boolean): string;
80
+ buildZip(): Promise<Buffer>;
81
+ buildZipFilename(prefix?: string): string;
80
82
  }
81
83
  //# sourceMappingURL=cert-reader.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"cert-reader.d.ts","sourceRoot":"","sources":["../../src/cert/cert-reader.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,eAAe,EAAU,MAAM,oBAAoB,CAAC;AAE7D,OAAO,EAAE,OAAO,EAAE,MAAM,cAAc,CAAC;AAIvC,MAAM,WAAW,eAAe;IAC9B,eAAe,EAAE,CAAC,UAAU,EAAE,MAAM,KAAK,OAAO,CAAC,QAAQ,CAAC,CAAC;CAC5D;AACD,MAAM,MAAM,QAAQ,GAAG;IACrB,GAAG,EAAE,MAAM,CAAC;IACZ,GAAG,EAAE,MAAM,CAAC;IACZ,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,EAAE,CAAC,EAAE,MAAM,CAAC;IACZ,EAAE,CAAC,EAAE,MAAM,CAAC;IACZ,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,GAAG,CAAC,EAAE,MAAM,CAAC;CACd,CAAC;AAEF,MAAM,MAAM,uBAAuB,GAAG;IACpC,MAAM,EAAE,UAAU,CAAC;IACnB,UAAU,EAAE,MAAM,CAAC;IACnB,UAAU,EAAE,MAAM,CAAC;IACnB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,UAAU,CAAC,EAAE,MAAM,CAAC;CACrB,CAAC;AACF,MAAM,MAAM,gBAAgB,GAAG,CAAC,GAAG,EAAE,uBAAuB,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;AAC/E,MAAM,MAAM,UAAU,GAAG;IAAE,MAAM,EAAE,OAAO,CAAC;IAAC,MAAM,EAAE,gBAAgB,CAAA;CAAE,CAAC;AAWvE,MAAM,MAAM,gBAAgB,GAAG;IAC7B,SAAS,EAAE,IAAI,CAAC;IAChB,QAAQ,EAAE,IAAI,CAAC;IACf,OAAO,EAAE,MAAM,EAAE,CAAC;CACnB,CAAC;AACF,qBAAa,UAAU;IACrB,IAAI,EAAE,QAAQ,CAAC;IAEf,MAAM,EAAE,eAAe,CAAC;IAExB,SAAS,EAAE,MAAM,CAAC;IAElB,OAAO,EAAE,MAAM,CAAC;gBACJ,QAAQ,EAAE,QAAQ;IAyB9B,KAAK;IAgBL,KAAK;IAOL,UAAU,CAAC,MAAM,CAAC,EAAE,MAAM,GAAG,QAAQ;IAarC,YAAY,CAAC,GAAG,GAAE,MAAsB;;;;;IAIxC,eAAe;;;;;IASf,MAAM,CAAC,cAAc,CAAC,GAAG,EAAE,MAAM;;;;;IAejC,MAAM,CAAC,kBAAkB,CAAC,GAAG,EAAE,MAAM;;;;;IAgBrC,aAAa;IAWb,WAAW;IAKX,MAAM,CAAC,aAAa,CAAC,GAAG,EAAE,MAAM;IAKhC,aAAa;IAKb,MAAM,CAAC,uBAAuB,CAAC,MAAM,EAAE,eAAe;IAWtD,UAAU,CAAC,IAAI,EAAE,KAAK,GAAG,KAAK,GAAG,KAAK,GAAG,KAAK,GAAG,IAAI,GAAG,KAAK,GAAG,IAAI,GAAG,KAAK,GAAG,KAAK,EAAE,QAAQ,CAAC,EAAE,MAAM;IAsBjG,YAAY,CAAC,IAAI,EAAE,UAAU;IAiDnC,iBAAiB,CAAC,MAAM,EAAE,MAAM,EAAE,SAAS,EAAE,GAAG,EAAE,MAAM,SAAS;IAOjE,aAAa,CAAC,MAAM,GAAE,MAAW;IAMjC,MAAM,CAAC,gBAAgB,CAAC,IAAI,CAAC,EAAE,MAAM;IAOrC,MAAM,CAAC,aAAa,CAAC,IAAI,EAAE,QAAQ;CAGpC"}
1
+ {"version":3,"file":"cert-reader.d.ts","sourceRoot":"","sources":["../../src/cert/cert-reader.ts"],"names":[],"mappings":"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"}
@@ -5,6 +5,7 @@ import { crypto } from "@certd/acme-client";
5
5
  import cryptoLib from "crypto";
6
6
  import dayjs from "dayjs";
7
7
  import { uniq } from "lodash-es";
8
+ import JSZip from "jszip";
8
9
  const formats = {
9
10
  pem: ["crt", "key", "ic"],
10
11
  one: ["one"],
@@ -222,9 +223,14 @@ export class CertReader {
222
223
  const timeStr = dayjs(applyTime).format("YYYYMMDDHHmmss");
223
224
  return `${prefix}_${domain}_${timeStr}.${suffix}`;
224
225
  }
225
- buildCertName(prefix = "") {
226
+ buildCertName(prefix = "", useHash = false) {
226
227
  let domain = this.getMainDomain();
227
228
  domain = domain.replaceAll(".", "_").replaceAll("*", "_");
229
+ if (useHash) {
230
+ const domains = JSON.stringify(this.getAllDomains());
231
+ const hash = cryptoLib.createHash("md5").update(domains).digest("hex").slice(0, 16);
232
+ return `${prefix}_${domain}_${hash}`;
233
+ }
228
234
  return `${prefix}_${domain}_${dayjs().format("YYYYMMDDHHmmssSSS")}`;
229
235
  }
230
236
  static appendTimeSuffix(name) {
@@ -233,7 +239,64 @@ export class CertReader {
233
239
  }
234
240
  return name + "_" + dayjs().format("YYYYMMDDHHmmssSSS");
235
241
  }
236
- static buildCertName(cert) {
237
- return new CertReader(cert).buildCertName();
242
+ static buildCertName(cert, useHash = false) {
243
+ return new CertReader(cert).buildCertName("", useHash);
244
+ }
245
+ async buildZip() {
246
+ const cert = this.cert;
247
+ const zip = new JSZip();
248
+ if (cert.crt) {
249
+ zip.file("证书.pem", cert.crt);
250
+ }
251
+ if (cert.key) {
252
+ zip.file("私钥.pem", cert.key);
253
+ }
254
+ if (cert.ic) {
255
+ zip.file("中间证书.pem", cert.ic);
256
+ }
257
+ if (cert.crt) {
258
+ zip.file("cert.crt", cert.crt);
259
+ }
260
+ if (cert.key) {
261
+ zip.file("cert.key", cert.key);
262
+ }
263
+ if (cert.ic) {
264
+ zip.file("intermediate.crt", cert.ic);
265
+ }
266
+ if (cert.oc) {
267
+ zip.file("origin.crt", cert.oc);
268
+ }
269
+ if (cert.one) {
270
+ zip.file("one.pem", cert.one);
271
+ }
272
+ if (cert.p7b) {
273
+ zip.file("cert.p7b", cert.p7b);
274
+ }
275
+ if (cert.pfx) {
276
+ zip.file("cert.pfx", Buffer.from(cert.pfx, "base64"));
277
+ }
278
+ if (cert.der) {
279
+ zip.file("cert.der", Buffer.from(cert.der, "base64"));
280
+ }
281
+ if (cert.jks) {
282
+ zip.file("cert.jks", Buffer.from(cert.jks, "base64"));
283
+ }
284
+ zip.file("说明.txt", `证书文件说明
285
+ cert.crt:证书文件,包含证书链,pem格式
286
+ cert.key:私钥文件,pem格式
287
+ intermediate.crt:中间证书文件,pem格式
288
+ origin.crt:原始证书文件,不含证书链,pem格式
289
+ one.pem: 证书和私钥简单合并成一个文件,pem格式,crt正文+key正文
290
+ cert.pfx:pfx格式证书文件,iis服务器使用
291
+ cert.der:der格式证书文件
292
+ cert.jks:jks格式证书文件,java服务器使用
293
+ `);
294
+ return zip.generateAsync({ type: "nodebuffer" });
295
+ }
296
+ buildZipFilename(prefix = "cert") {
297
+ let domain = this.getMainDomain();
298
+ domain = domain.replaceAll(".", "_").replaceAll("*", "_");
299
+ const timeStr = dayjs().format("YYYYMMDDHHmmss");
300
+ return `${prefix}_${domain}_${timeStr}.zip`;
238
301
  }
239
302
  }
@@ -107,7 +107,7 @@ export class CertConverter {
107
107
  if (!fs.existsSync(dir)) {
108
108
  fs.mkdirSync(dir, { recursive: true });
109
109
  }
110
- await this.exec(`keytool -importkeystore -srckeystore ${p12Path} -srcstoretype PKCS12 -srcstorepass "${jksPassword}" -destkeystore ${jksPath} -deststoretype PKCS12 -deststorepass "${jksPassword}" `);
110
+ await this.exec(`keytool -importkeystore -srckeystore ${p12Path} -srcstoretype PKCS12 -srcstorepass "${jksPassword}" -destkeystore ${jksPath} -deststoretype JKS -deststorepass "${jksPassword}" `);
111
111
  fs.unlinkSync(p12Path);
112
112
  const fileBuffer = fs.readFileSync(jksPath);
113
113
  const certBase64 = fileBuffer.toString("base64");
@@ -3,6 +3,8 @@ import { IAccess, IAccessService, IServiceGetter, PageRes, PageSearch, Registrab
3
3
  export type DnsProviderDefine = Registrable & {
4
4
  accessType: string;
5
5
  icon?: string;
6
+ dependPlugins?: Record<string, string>;
7
+ dependPackages?: Record<string, string>;
6
8
  };
7
9
  export type CreateRecordOptions = {
8
10
  domain: string;
@@ -23,6 +25,7 @@ export type DnsProviderContext = {
23
25
  domainParser: IDomainParser;
24
26
  serviceGetter: IServiceGetter;
25
27
  accessGetter?: IAccessService;
28
+ define?: DnsProviderDefine;
26
29
  };
27
30
  export type DomainRecord = {
28
31
  id: string;
@@ -49,7 +52,7 @@ export interface IDnsProvider<T = any> {
49
52
  punyCodeDecode(domain: string): string;
50
53
  createRecord(options: CreateRecordOptions): Promise<T>;
51
54
  removeRecord(options: RemoveRecordOptions<T>): Promise<void>;
52
- setCtx(ctx: DnsProviderContext): void;
55
+ setCtx(ctx: DnsProviderContext): Promise<void>;
53
56
  usePunyCode(): boolean;
54
57
  getDomainListPage(pager: PageSearch): Promise<PageRes<DomainRecord>>;
55
58
  getRecordListPage?(domain: string, pager: PageSearch): Promise<PageRes<DnsResolveRecord>>;
@@ -1 +1 @@
1
- {"version":3,"file":"api.d.ts","sourceRoot":"","sources":["../../../src/cert/dns-provider/api.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"api.d.ts","sourceRoot":"","sources":["../../../src/cert/dns-provider/api.ts"],"names":[],"mappings":"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"}
@@ -1,10 +1,12 @@
1
1
  import { HttpClient, ILogger } from "@certd/basic";
2
- import { PageRes, PageSearch } from "@certd/pipeline";
2
+ import { IRuntimeDepsService, PageRes, PageSearch } from "@certd/pipeline";
3
3
  import { CreateRecordOptions, DnsProviderContext, DnsResolveRecord, DomainRecord, IDnsProvider, RemoveRecordOptions } from "./api.js";
4
4
  export declare abstract class AbstractDnsProvider<T = any> implements IDnsProvider<T> {
5
5
  ctx: DnsProviderContext;
6
6
  http: HttpClient;
7
7
  logger: ILogger;
8
+ runtimeDepsService?: IRuntimeDepsService;
9
+ importRuntime(specifier: string): Promise<any>;
8
10
  usePunyCode(): boolean;
9
11
  /**
10
12
  * 中文转英文
@@ -16,7 +18,7 @@ export declare abstract class AbstractDnsProvider<T = any> implements IDnsProvid
16
18
  * @param domain
17
19
  */
18
20
  punyCodeDecode(domain: string): any;
19
- setCtx(ctx: DnsProviderContext): void;
21
+ setCtx(ctx: DnsProviderContext): Promise<void>;
20
22
  parseDomain(fullDomain: string): Promise<string>;
21
23
  abstract createRecord(options: CreateRecordOptions): Promise<T>;
22
24
  abstract onInstance(): Promise<void>;
@@ -1 +1 @@
1
- {"version":3,"file":"base.d.ts","sourceRoot":"","sources":["../../../src/cert/dns-provider/base.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,OAAO,EAAE,MAAM,cAAc,CAAC;AACnD,OAAO,EAAkB,OAAO,EAAE,UAAU,EAAE,MAAM,iBAAiB,CAAC;AAEtE,OAAO,EAAE,mBAAmB,EAAE,kBAAkB,EAAqB,gBAAgB,EAAE,YAAY,EAAE,YAAY,EAAE,mBAAmB,EAAE,MAAM,UAAU,CAAC;AAEzJ,8BAAsB,mBAAmB,CAAC,CAAC,GAAG,GAAG,CAAE,YAAW,YAAY,CAAC,CAAC,CAAC;IAC3E,GAAG,EAAG,kBAAkB,CAAC;IACzB,IAAI,EAAG,UAAU,CAAC;IAClB,MAAM,EAAG,OAAO,CAAC;IAEjB,WAAW,IAAI,OAAO;IAMtB;;;OAGG;IACH,cAAc,CAAC,MAAM,EAAE,MAAM;IAI7B;;;OAGG;IACH,cAAc,CAAC,MAAM,EAAE,MAAM;IAI7B,MAAM,CAAC,GAAG,EAAE,kBAAkB;IAMxB,WAAW,CAAC,UAAU,EAAE,MAAM;IAIpC,QAAQ,CAAC,YAAY,CAAC,OAAO,EAAE,mBAAmB,GAAG,OAAO,CAAC,CAAC,CAAC;IAE/D,QAAQ,CAAC,UAAU,IAAI,OAAO,CAAC,IAAI,CAAC;IAEpC,QAAQ,CAAC,YAAY,CAAC,OAAO,EAAE,mBAAmB,CAAC,CAAC,CAAC,GAAG,OAAO,CAAC,IAAI,CAAC;IAE/D,iBAAiB,CAAC,GAAG,EAAE,UAAU,GAAG,OAAO,CAAC,OAAO,CAAC,YAAY,CAAC,CAAC;IAIlE,iBAAiB,CAAC,MAAM,EAAE,MAAM,EAAE,GAAG,EAAE,UAAU,GAAG,OAAO,CAAC,OAAO,CAAC,gBAAgB,CAAC,CAAC;CAG7F;AAED,wBAAsB,iBAAiB,CAAC,IAAI,EAAE;IAAE,eAAe,EAAE,MAAM,CAAC;IAAC,OAAO,EAAE,kBAAkB,CAAA;CAAE,GAAG,OAAO,CAAC,YAAY,CAAC,CAkB7H"}
1
+ {"version":3,"file":"base.d.ts","sourceRoot":"","sources":["../../../src/cert/dns-provider/base.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,OAAO,EAAE,MAAM,cAAc,CAAC;AACnD,OAAO,EAAkB,mBAAmB,EAAE,OAAO,EAAE,UAAU,EAAE,MAAM,iBAAiB,CAAC;AAE3F,OAAO,EAAE,mBAAmB,EAAE,kBAAkB,EAAqB,gBAAgB,EAAE,YAAY,EAAE,YAAY,EAAE,mBAAmB,EAAE,MAAM,UAAU,CAAC;AAEzJ,8BAAsB,mBAAmB,CAAC,CAAC,GAAG,GAAG,CAAE,YAAW,YAAY,CAAC,CAAC,CAAC;IAC3E,GAAG,EAAG,kBAAkB,CAAC;IACzB,IAAI,EAAG,UAAU,CAAC;IAClB,MAAM,EAAG,OAAO,CAAC;IACjB,kBAAkB,CAAC,EAAE,mBAAmB,CAAC;IAEnC,aAAa,CAAC,SAAS,EAAE,MAAM;IAOrC,WAAW,IAAI,OAAO;IAMtB;;;OAGG;IACH,cAAc,CAAC,MAAM,EAAE,MAAM;IAI7B;;;OAGG;IACH,cAAc,CAAC,MAAM,EAAE,MAAM;IAIvB,MAAM,CAAC,GAAG,EAAE,kBAAkB;IAY9B,WAAW,CAAC,UAAU,EAAE,MAAM;IAIpC,QAAQ,CAAC,YAAY,CAAC,OAAO,EAAE,mBAAmB,GAAG,OAAO,CAAC,CAAC,CAAC;IAE/D,QAAQ,CAAC,UAAU,IAAI,OAAO,CAAC,IAAI,CAAC;IAEpC,QAAQ,CAAC,YAAY,CAAC,OAAO,EAAE,mBAAmB,CAAC,CAAC,CAAC,GAAG,OAAO,CAAC,IAAI,CAAC;IAE/D,iBAAiB,CAAC,GAAG,EAAE,UAAU,GAAG,OAAO,CAAC,OAAO,CAAC,YAAY,CAAC,CAAC;IAIlE,iBAAiB,CAAC,MAAM,EAAE,MAAM,EAAE,GAAG,EAAE,UAAU,GAAG,OAAO,CAAC,OAAO,CAAC,gBAAgB,CAAC,CAAC;CAG7F;AAED,wBAAsB,iBAAiB,CAAC,IAAI,EAAE;IAAE,eAAe,EAAE,MAAM,CAAC;IAAC,OAAO,EAAE,kBAAkB,CAAA;CAAE,GAAG,OAAO,CAAC,YAAY,CAAC,CAmB7H"}
@@ -4,6 +4,13 @@ export class AbstractDnsProvider {
4
4
  ctx;
5
5
  http;
6
6
  logger;
7
+ runtimeDepsService;
8
+ async importRuntime(specifier) {
9
+ if (!this.runtimeDepsService) {
10
+ throw new Error("runtimeDepsService 未初始化");
11
+ }
12
+ return await this.runtimeDepsService.importRuntime(specifier, this.logger);
13
+ }
7
14
  usePunyCode() {
8
15
  //是否使用punycode来添加解析记录
9
16
  //默认都使用原始中文域名来添加
@@ -23,10 +30,16 @@ export class AbstractDnsProvider {
23
30
  punyCodeDecode(domain) {
24
31
  return punycode.toUnicode(domain);
25
32
  }
26
- setCtx(ctx) {
33
+ async setCtx(ctx) {
27
34
  this.ctx = ctx;
28
35
  this.logger = ctx.logger;
29
36
  this.http = ctx.http;
37
+ if (!this.runtimeDepsService && this.ctx.serviceGetter) {
38
+ this.runtimeDepsService = await this.ctx.serviceGetter.get("runtimeDepsService");
39
+ }
40
+ if (this.runtimeDepsService && this.ctx.define?.name) {
41
+ await this.runtimeDepsService.ensureRuntimeDependencies({ pluginKeys: `dnsProvider:${this.ctx.define.name}`, logger: this.logger });
42
+ }
30
43
  }
31
44
  async parseDomain(fullDomain) {
32
45
  return await this.ctx.domainParser.parse(fullDomain);
@@ -50,9 +63,10 @@ export async function createDnsProvider(opts) {
50
63
  const accessGetter = await context.serviceGetter.get("accessService");
51
64
  context.accessGetter = accessGetter;
52
65
  }
66
+ context.define = dnsProviderDefine;
53
67
  // @ts-ignore
54
68
  const dnsProvider = new DnsProviderClass();
55
- dnsProvider.setCtx(context);
69
+ await dnsProvider.setCtx(context);
56
70
  await dnsProvider.onInstance();
57
71
  return dnsProvider;
58
72
  }
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@certd/plugin-lib",
3
3
  "private": false,
4
- "version": "1.41.3",
4
+ "version": "1.42.0",
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",
7
7
  "types": "./dist/index.d.ts",
@@ -10,56 +10,40 @@
10
10
  "before-build": "rimraf dist && rimraf tsconfig.tsbuildinfo && rimraf .rollup.cache",
11
11
  "build": "npm run before-build && tsc -p tsconfig.build.json --skipLibCheck",
12
12
  "dev-build": "npm run build",
13
- "build3": "rollup -c",
14
- "build2": "vue-tsc --noEmit && vite build",
15
- "preview": "vite preview",
16
- "test:unit": "cross-env NODE_ENV=unittest mocha --no-config --node-option no-warnings --node-option loader=ts-node/esm \"src/**/*.test.ts\"",
13
+ "test:unit": "cross-env NODE_ENV=unittest mocha",
17
14
  "pub": "npm publish",
18
- "compile": "tsc --skipLibCheck --watch"
15
+ "compile": "tsc --skipLibCheck --watch",
16
+ "format": "prettier --write src",
17
+ "lint": "eslint --fix"
19
18
  },
20
19
  "dependencies": {
21
- "@alicloud/openapi-client": "^0.4.15",
22
- "@alicloud/openapi-util": "^0.3.2",
23
- "@alicloud/pop-core": "^1.7.10",
24
- "@alicloud/tea-util": "^1.4.11",
25
- "@aws-sdk/client-s3": "^3.964.0",
26
- "@certd/acme-client": "^1.41.3",
27
- "@certd/basic": "^1.41.3",
28
- "@certd/pipeline": "^1.41.3",
29
- "@certd/plus-core": "^1.41.3",
30
- "@kubernetes/client-node": "0.21.0",
31
- "ali-oss": "^6.22.0",
32
- "basic-ftp": "^5.0.5",
33
- "cos-nodejs-sdk-v5": "^2.15.4",
20
+ "@certd/acme-client": "^1.42.0",
21
+ "@certd/basic": "^1.42.0",
22
+ "@certd/pipeline": "^1.42.0",
34
23
  "dayjs": "^1.11.7",
35
- "iconv-lite": "^0.6.3",
24
+ "jszip": "^3.10.1",
36
25
  "lodash-es": "^4.17.21",
37
26
  "psl": "^1.15.0",
38
- "punycode.js": "^2.3.1",
39
- "qiniu": "^7.12.0",
40
- "rimraf": "^5.0.5",
41
- "socks": "^2.8.3",
42
- "socks-proxy-agent": "^8.0.4",
43
- "ssh2": "1.17.0",
44
- "strip-ansi": "^7.1.0",
45
- "tencentcloud-sdk-nodejs": "^4.1.166"
27
+ "punycode.js": "^2.3.1"
46
28
  },
47
29
  "devDependencies": {
48
- "@types/chai": "^4.3.3",
49
- "@types/mocha": "^10.0.0",
30
+ "@types/chai": "^4.3.12",
31
+ "@types/mocha": "^10.0.6",
50
32
  "@typescript-eslint/eslint-plugin": "^8.26.1",
51
33
  "@typescript-eslint/parser": "^8.26.1",
52
- "chai": "^4.3.6",
34
+ "chai": "^5.1.0",
53
35
  "cross-env": "^7.0.3",
54
- "eslint": "^8.24.0",
55
- "eslint-config-prettier": "^8.5.0",
56
- "eslint-plugin-prettier": "^4.2.1",
36
+ "eslint": "^8.57.0",
37
+ "eslint-config-prettier": "^9.1.0",
38
+ "eslint-plugin-prettier": "^5.1.3",
57
39
  "esmock": "^2.7.5",
58
- "mocha": "^10.1.0",
59
- "prettier": "^2.8.8",
40
+ "mocha": "^10.6.0",
41
+ "node-forge": "^1.3.1",
42
+ "prettier": "3.3.3",
43
+ "rimraf": "^5.0.5",
60
44
  "ts-node": "^10.9.2",
61
45
  "tslib": "^2.8.1",
62
46
  "typescript": "^5.4.2"
63
47
  },
64
- "gitHead": "6cbd62977731a3b72c42b5f88c49500631da0a46"
48
+ "gitHead": "b46948c0ba67069ebcd2bb71b21b6c289d99f1b8"
65
49
  }
@@ -0,0 +1,109 @@
1
+ /// <reference types="mocha" />
2
+ /// <reference types="node" />
3
+
4
+ import assert from "node:assert/strict";
5
+
6
+ import { CertReader } from "../src/cert/cert-reader.js";
7
+ import type { CertInfo } from "../src/cert/cert-reader.js";
8
+
9
+ // @ts-ignore
10
+ import forge from "node-forge";
11
+
12
+ /**
13
+ * Generate a minimal self-signed X.509 cert + key in PEM format for testing.
14
+ */
15
+ function createSelfSignedCert(commonName: string): { crt: string; key: string } {
16
+ const keypair = forge.pki.rsa.generateKeyPair(2048);
17
+
18
+ const cert = forge.pki.createCertificate();
19
+ cert.publicKey = keypair.publicKey;
20
+ cert.serialNumber = "01";
21
+ cert.validFrom = new Date("2025-01-01").toISOString();
22
+ cert.validTo = new Date("2026-01-01").toISOString();
23
+
24
+ const attrs = [{ name: "commonName", value: commonName }];
25
+ cert.setSubject(attrs);
26
+ cert.setIssuer(attrs);
27
+ cert.sign(keypair.privateKey, forge.md.sha256.create());
28
+
29
+ return {
30
+ crt: forge.pki.certificateToPem(cert),
31
+ key: forge.pki.privateKeyToPem(keypair.privateKey),
32
+ };
33
+ }
34
+
35
+ const testCert = createSelfSignedCert("example.com");
36
+ const testCertIc = createSelfSignedCert("intermediate.ca");
37
+ const mockCertInfo: CertInfo = {
38
+ crt: testCert.crt + "\n" + testCertIc.crt,
39
+ key: testCert.key,
40
+ oc: testCert.crt,
41
+ ic: testCertIc.crt,
42
+ one: testCert.crt + "\n" + testCert.key,
43
+ p7b: "PKCS7 test content",
44
+ pfx: Buffer.from("fake-pfx-data").toString("base64"),
45
+ der: Buffer.from("fake-der-data").toString("base64"),
46
+ jks: Buffer.from("fake-jks-data").toString("base64"),
47
+ };
48
+
49
+ describe("CertReader.buildZip", () => {
50
+ it("returns a non-empty Buffer", async () => {
51
+ const reader = new CertReader(mockCertInfo);
52
+ const buf = await reader.buildZip();
53
+ assert.ok(Buffer.isBuffer(buf));
54
+ assert.ok(buf.length > 0);
55
+ });
56
+
57
+ it("produces a valid zip containing expected files", async () => {
58
+ const reader = new CertReader(mockCertInfo);
59
+ const buf = await reader.buildZip();
60
+ const { default: JSZip } = await import("jszip");
61
+ const zip = await JSZip.loadAsync(buf);
62
+
63
+ assert.ok(zip.file("证书.pem"), "should contain 证书.pem");
64
+ assert.ok(zip.file("私钥.pem"), "should contain 私钥.pem");
65
+ assert.ok(zip.file("中间证书.pem"), "should contain 中间证书.pem");
66
+ assert.ok(zip.file("cert.crt"), "should contain cert.crt");
67
+ assert.ok(zip.file("cert.key"), "should contain cert.key");
68
+ assert.ok(zip.file("intermediate.crt"), "should contain intermediate.crt");
69
+ assert.ok(zip.file("origin.crt"), "should contain origin.crt");
70
+ assert.ok(zip.file("one.pem"), "should contain one.pem");
71
+ assert.ok(zip.file("cert.p7b"), "should contain cert.p7b");
72
+ assert.ok(zip.file("cert.pfx"), "should contain cert.pfx");
73
+ assert.ok(zip.file("cert.der"), "should contain cert.der");
74
+ assert.ok(zip.file("cert.jks"), "should contain cert.jks");
75
+ assert.ok(zip.file("说明.txt"), "should contain 说明.txt");
76
+
77
+ const pemContent = await zip.file("证书.pem").async("string");
78
+ assert.ok(pemContent.includes("-----BEGIN CERTIFICATE-----"));
79
+
80
+ const pfx = await zip.file("cert.pfx").async("nodebuffer");
81
+ assert.equal(pfx.toString(), "fake-pfx-data");
82
+ });
83
+ });
84
+
85
+ describe("CertReader.buildZipFilename", () => {
86
+ it("includes the main domain and timestamp", () => {
87
+ const reader = new CertReader(mockCertInfo);
88
+ const name = reader.buildZipFilename("cert");
89
+ assert.ok(name.startsWith("cert_example_com_"));
90
+ assert.ok(name.endsWith(".zip"));
91
+ const tsPart = name.replace("cert_example_com_", "").replace(".zip", "");
92
+ assert.match(tsPart, /^\d{14}$/);
93
+ });
94
+
95
+ it("uses the default prefix when not provided", () => {
96
+ const reader = new CertReader(mockCertInfo);
97
+ const name = reader.buildZipFilename();
98
+ assert.ok(name.startsWith("cert_example_com_"));
99
+ });
100
+
101
+ it("wildcard domain replaces asterisk", () => {
102
+ const wildcardCert = createSelfSignedCert("*.example.com");
103
+ const wcInfo: CertInfo = { crt: wildcardCert.crt, key: wildcardCert.key };
104
+ const reader = new CertReader(wcInfo);
105
+ const name = reader.buildZipFilename("cert");
106
+ assert.ok(name.startsWith("cert___example_com_"), "asterisk should be replaced, got: " + name);
107
+ assert.ok(!name.includes("*"));
108
+ });
109
+ });