@certd/plugin-cert 1.25.4 → 1.25.6

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.
Files changed (38) hide show
  1. package/CHANGELOG.md +10 -0
  2. package/dist/access/eab-access.d.ts +4 -4
  3. package/dist/access/eab-access.js +48 -48
  4. package/dist/access/index.d.ts +1 -1
  5. package/dist/access/index.js +1 -1
  6. package/dist/dns-provider/api.d.ts +27 -27
  7. package/dist/dns-provider/api.js +1 -1
  8. package/dist/dns-provider/base.d.ts +8 -8
  9. package/dist/dns-provider/base.js +6 -6
  10. package/dist/dns-provider/decorator.d.ts +3 -3
  11. package/dist/dns-provider/decorator.js +26 -26
  12. package/dist/dns-provider/index.d.ts +4 -4
  13. package/dist/dns-provider/index.js +4 -4
  14. package/dist/dns-provider/registry.d.ts +2 -2
  15. package/dist/dns-provider/registry.js +2 -2
  16. package/dist/index.d.ts +3 -3
  17. package/dist/index.js +3 -3
  18. package/dist/plugin/cert-plugin/acme.d.ts +66 -66
  19. package/dist/plugin/cert-plugin/acme.js +280 -280
  20. package/dist/plugin/cert-plugin/base.d.ts +46 -46
  21. package/dist/plugin/cert-plugin/base.js +281 -281
  22. package/dist/plugin/cert-plugin/cert-reader.d.ts +34 -34
  23. package/dist/plugin/cert-plugin/cert-reader.js +112 -112
  24. package/dist/plugin/cert-plugin/convert.d.ts +21 -21
  25. package/dist/plugin/cert-plugin/convert.js +71 -71
  26. package/dist/plugin/cert-plugin/index.d.ts +18 -18
  27. package/dist/plugin/cert-plugin/index.js +208 -208
  28. package/dist/plugin/cert-plugin/lego/dns.d.ts +1 -1
  29. package/dist/plugin/cert-plugin/lego/dns.js +1 -1
  30. package/dist/plugin/cert-plugin/lego/index.d.ts +17 -17
  31. package/dist/plugin/cert-plugin/lego/index.js +172 -172
  32. package/dist/plugin/index.d.ts +2 -2
  33. package/dist/plugin/index.js +2 -2
  34. package/package.json +9 -7
  35. package/tsconfig.tsbuildinfo +1 -1
  36. package/stats.html +0 -6177
  37. package/test/user.secret.js +0 -7
  38. package/test/user.secret.ts +0 -4
@@ -1,281 +1,281 @@
1
- var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
2
- var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
3
- if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
4
- else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
5
- return c > 3 && r && Object.defineProperty(target, key, r), r;
6
- };
7
- var __metadata = (this && this.__metadata) || function (k, v) {
8
- if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
9
- };
10
- import { AbstractTaskPlugin, TaskInput, TaskOutput } from "@certd/pipeline";
11
- import dayjs from "dayjs";
12
- import { CertReader } from "./cert-reader.js";
13
- import JSZip from "jszip";
14
- import { CertConverter } from "./convert.js";
15
- import fs from "fs";
16
- export { CertReader };
17
- export class CertApplyBasePlugin extends AbstractTaskPlugin {
18
- domains;
19
- email;
20
- pfxPassword;
21
- renewDays;
22
- forceUpdate;
23
- successNotify = true;
24
- // @TaskInput({
25
- // title: "CsrInfo",
26
- // helper: "暂时没有用",
27
- // })
28
- csrInfo;
29
- userContext;
30
- http;
31
- lastStatus;
32
- cert;
33
- async onInstance() {
34
- this.userContext = this.ctx.userContext;
35
- this.http = this.ctx.http;
36
- this.lastStatus = this.ctx.lastStatus;
37
- await this.onInit();
38
- }
39
- async execute() {
40
- const oldCert = await this.condition();
41
- if (oldCert != null) {
42
- return await this.output(oldCert, false);
43
- }
44
- const cert = await this.doCertApply();
45
- if (cert != null) {
46
- await this.output(cert, true);
47
- //清空后续任务的状态,让后续任务能够重新执行
48
- this.clearLastStatus();
49
- if (this.successNotify) {
50
- await this.sendSuccessEmail();
51
- }
52
- }
53
- else {
54
- throw new Error("申请证书失败");
55
- }
56
- }
57
- async output(certReader, isNew) {
58
- const cert = certReader.toCertInfo();
59
- this.cert = cert;
60
- this._result.pipelineVars.certExpiresTime = dayjs(certReader.detail.notAfter).valueOf();
61
- if (cert.pfx == null || cert.der == null) {
62
- try {
63
- const converter = new CertConverter({ logger: this.logger });
64
- const res = await converter.convert({
65
- cert,
66
- pfxPassword: this.pfxPassword,
67
- });
68
- const pfxBuffer = fs.readFileSync(res.pfxPath);
69
- cert.pfx = pfxBuffer.toString("base64");
70
- const derBuffer = fs.readFileSync(res.derPath);
71
- cert.der = derBuffer.toString("base64");
72
- this.logger.info("转换证书格式成功");
73
- isNew = true;
74
- }
75
- catch (e) {
76
- this.logger.error("转换证书格式失败", e);
77
- }
78
- }
79
- if (isNew) {
80
- const zipFileName = certReader.buildCertFileName("zip", certReader.detail.notBefore);
81
- await this.zipCert(cert, zipFileName);
82
- }
83
- else {
84
- this.extendsFiles();
85
- }
86
- }
87
- async zipCert(cert, filename) {
88
- const zip = new JSZip();
89
- zip.file("cert.crt", cert.crt);
90
- zip.file("cert.key", cert.key);
91
- zip.file("intermediate.crt", cert.ic);
92
- if (cert.pfx) {
93
- zip.file("cert.pfx", Buffer.from(cert.pfx, "base64"));
94
- }
95
- if (cert.der) {
96
- zip.file("cert.der", Buffer.from(cert.der, "base64"));
97
- }
98
- const content = await zip.generateAsync({ type: "nodebuffer" });
99
- this.saveFile(filename, content);
100
- this.logger.info(`已保存文件:${filename}`);
101
- }
102
- /**
103
- * 是否更新证书
104
- */
105
- async condition() {
106
- if (this.forceUpdate) {
107
- this.logger.info("强制更新证书选项已勾选,准备申请新证书");
108
- return null;
109
- }
110
- const inputChanged = this.ctx.inputChanged;
111
- if (inputChanged) {
112
- this.logger.info("输入参数变更,准备申请新证书");
113
- return null;
114
- }
115
- let oldCert = undefined;
116
- try {
117
- oldCert = await this.readLastCert();
118
- }
119
- catch (e) {
120
- this.logger.warn("读取cert失败:", e);
121
- }
122
- if (oldCert == null) {
123
- this.logger.info("还未申请过,准备申请新证书");
124
- return null;
125
- }
126
- const ret = this.isWillExpire(oldCert.expires, this.renewDays);
127
- if (!ret.isWillExpire) {
128
- this.logger.info(`证书还未过期:过期时间${dayjs(oldCert.expires).format("YYYY-MM-DD HH:mm:ss")},剩余${ret.leftDays}天`);
129
- return oldCert;
130
- }
131
- this.logger.info("即将过期,开始更新证书");
132
- return null;
133
- }
134
- formatCert(pem) {
135
- pem = pem.replace(/\r/g, "");
136
- pem = pem.replace(/\n\n/g, "\n");
137
- pem = pem.replace(/\n$/g, "");
138
- return pem;
139
- }
140
- formatCerts(cert) {
141
- const newCert = {
142
- crt: this.formatCert(cert.crt),
143
- key: this.formatCert(cert.key),
144
- csr: this.formatCert(cert.csr),
145
- };
146
- return newCert;
147
- }
148
- async readLastCert() {
149
- const cert = this.lastStatus?.status?.output?.cert;
150
- if (cert == null) {
151
- return undefined;
152
- }
153
- return new CertReader(cert);
154
- }
155
- /**
156
- * 检查是否过期,默认提前20天
157
- * @param expires
158
- * @param maxDays
159
- * @returns {boolean}
160
- */
161
- isWillExpire(expires, maxDays = 20) {
162
- if (expires == null) {
163
- throw new Error("过期时间不能为空");
164
- }
165
- // 检查有效期
166
- const leftDays = dayjs(expires).diff(dayjs(), "day");
167
- return {
168
- isWillExpire: leftDays < maxDays,
169
- leftDays,
170
- };
171
- }
172
- async sendSuccessEmail() {
173
- try {
174
- this.logger.info("发送成功邮件通知:" + this.email);
175
- const subject = `【CertD】证书申请成功【${this.domains[0]}】`;
176
- await this.ctx.emailService.send({
177
- userId: this.ctx.pipeline.userId,
178
- receivers: [this.email],
179
- subject: subject,
180
- content: `证书申请成功,域名:${this.domains.join(",")}`,
181
- });
182
- }
183
- catch (e) {
184
- this.logger.error("send email error", e);
185
- }
186
- }
187
- }
188
- __decorate([
189
- TaskInput({
190
- title: "域名",
191
- component: {
192
- name: "a-select",
193
- vModel: "value",
194
- mode: "tags",
195
- open: false,
196
- tokenSeparators: [",", " ", ",", "、", "|"],
197
- },
198
- required: true,
199
- col: {
200
- span: 24,
201
- },
202
- order: -1,
203
- helper: "1、支持通配符域名,例如: *.foo.com、foo.com、*.test.handsfree.work\n" +
204
- "2、支持多个域名、多个子域名、多个通配符域名打到一个证书上(域名必须是在同一个DNS提供商解析)\n" +
205
- "3、多级子域名要分成多个域名输入(*.foo.com的证书不能用于xxx.yyy.foo.com、foo.com)\n" +
206
- "4、输入一个空格之后,再输入下一个",
207
- }),
208
- __metadata("design:type", Array)
209
- ], CertApplyBasePlugin.prototype, "domains", void 0);
210
- __decorate([
211
- TaskInput({
212
- title: "邮箱",
213
- component: {
214
- name: "a-input",
215
- vModel: "value",
216
- },
217
- required: true,
218
- order: -1,
219
- helper: "请输入邮箱",
220
- }),
221
- __metadata("design:type", String)
222
- ], CertApplyBasePlugin.prototype, "email", void 0);
223
- __decorate([
224
- TaskInput({
225
- title: "PFX证书密码",
226
- component: {
227
- name: "a-input-password",
228
- vModel: "value",
229
- },
230
- required: false,
231
- order: 100,
232
- helper: "PFX格式证书是否需要加密",
233
- }),
234
- __metadata("design:type", String)
235
- ], CertApplyBasePlugin.prototype, "pfxPassword", void 0);
236
- __decorate([
237
- TaskInput({
238
- title: "更新天数",
239
- value: 20,
240
- component: {
241
- name: "a-input-number",
242
- vModel: "value",
243
- },
244
- required: true,
245
- order: 100,
246
- helper: "到期前多少天后更新证书,注意:流水线默认不会自动运行,请设置定时器,每天定时运行本流水线",
247
- }),
248
- __metadata("design:type", Number)
249
- ], CertApplyBasePlugin.prototype, "renewDays", void 0);
250
- __decorate([
251
- TaskInput({
252
- title: "强制更新",
253
- component: {
254
- name: "a-switch",
255
- vModel: "checked",
256
- },
257
- order: 100,
258
- helper: "是否强制重新申请证书",
259
- }),
260
- __metadata("design:type", String)
261
- ], CertApplyBasePlugin.prototype, "forceUpdate", void 0);
262
- __decorate([
263
- TaskInput({
264
- title: "成功后邮件通知",
265
- value: true,
266
- component: {
267
- name: "a-switch",
268
- vModel: "checked",
269
- },
270
- order: 100,
271
- helper: "申请成功后是否发送邮件通知",
272
- }),
273
- __metadata("design:type", Object)
274
- ], CertApplyBasePlugin.prototype, "successNotify", void 0);
275
- __decorate([
276
- TaskOutput({
277
- title: "域名证书",
278
- }),
279
- __metadata("design:type", Object)
280
- ], CertApplyBasePlugin.prototype, "cert", void 0);
281
- //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiYmFzZS5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uL3NyYy9wbHVnaW4vY2VydC1wbHVnaW4vYmFzZS50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiOzs7Ozs7Ozs7QUFBQSxPQUFPLEVBQUUsa0JBQWtCLEVBQThCLFNBQVMsRUFBRSxVQUFVLEVBQUUsTUFBTSxpQkFBaUIsQ0FBQztBQUN4RyxPQUFPLEtBQUssTUFBTSxPQUFPLENBQUM7QUFFMUIsT0FBTyxFQUFFLFVBQVUsRUFBRSxNQUFNLGtCQUFrQixDQUFDO0FBQzlDLE9BQU8sS0FBSyxNQUFNLE9BQU8sQ0FBQztBQUMxQixPQUFPLEVBQUUsYUFBYSxFQUFFLE1BQU0sY0FBYyxDQUFDO0FBQzdDLE9BQU8sRUFBRSxNQUFNLElBQUksQ0FBQztBQUVwQixPQUFPLEVBQUUsVUFBVSxFQUFFLENBQUM7QUFHdEIsTUFBTSxPQUFnQixtQkFBb0IsU0FBUSxrQkFBa0I7SUFxQmxFLE9BQU8sQ0FBWTtJQVluQixLQUFLLENBQVU7SUFZZixXQUFXLENBQVU7SUFhckIsU0FBUyxDQUFVO0lBV25CLFdBQVcsQ0FBVTtJQVlyQixhQUFhLEdBQUcsSUFBSSxDQUFDO0lBRXJCLGVBQWU7SUFDZixzQkFBc0I7SUFDdEIscUJBQXFCO0lBQ3JCLEtBQUs7SUFDTCxPQUFPLENBQVU7SUFFakIsV0FBVyxDQUFZO0lBQ3ZCLElBQUksQ0FBYztJQUNsQixVQUFVLENBQVE7SUFLbEIsSUFBSSxDQUFZO0lBRWhCLEtBQUssQ0FBQyxVQUFVO1FBQ2QsSUFBSSxDQUFDLFdBQVcsR0FBRyxJQUFJLENBQUMsR0FBRyxDQUFDLFdBQVcsQ0FBQztRQUN4QyxJQUFJLENBQUMsSUFBSSxHQUFHLElBQUksQ0FBQyxHQUFHLENBQUMsSUFBSSxDQUFDO1FBQzFCLElBQUksQ0FBQyxVQUFVLEdBQUcsSUFBSSxDQUFDLEdBQUcsQ0FBQyxVQUFrQixDQUFDO1FBQzlDLE1BQU0sSUFBSSxDQUFDLE1BQU0sRUFBRSxDQUFDO0lB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
1
+ var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
2
+ var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
3
+ if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
4
+ else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
5
+ return c > 3 && r && Object.defineProperty(target, key, r), r;
6
+ };
7
+ var __metadata = (this && this.__metadata) || function (k, v) {
8
+ if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
9
+ };
10
+ import { AbstractTaskPlugin, TaskInput, TaskOutput } from "@certd/pipeline";
11
+ import dayjs from "dayjs";
12
+ import { CertReader } from "./cert-reader.js";
13
+ import JSZip from "jszip";
14
+ import { CertConverter } from "./convert.js";
15
+ import fs from "fs";
16
+ export { CertReader };
17
+ export class CertApplyBasePlugin extends AbstractTaskPlugin {
18
+ domains;
19
+ email;
20
+ pfxPassword;
21
+ renewDays;
22
+ forceUpdate;
23
+ successNotify = true;
24
+ // @TaskInput({
25
+ // title: "CsrInfo",
26
+ // helper: "暂时没有用",
27
+ // })
28
+ csrInfo;
29
+ userContext;
30
+ http;
31
+ lastStatus;
32
+ cert;
33
+ async onInstance() {
34
+ this.userContext = this.ctx.userContext;
35
+ this.http = this.ctx.http;
36
+ this.lastStatus = this.ctx.lastStatus;
37
+ await this.onInit();
38
+ }
39
+ async execute() {
40
+ const oldCert = await this.condition();
41
+ if (oldCert != null) {
42
+ return await this.output(oldCert, false);
43
+ }
44
+ const cert = await this.doCertApply();
45
+ if (cert != null) {
46
+ await this.output(cert, true);
47
+ //清空后续任务的状态,让后续任务能够重新执行
48
+ this.clearLastStatus();
49
+ if (this.successNotify) {
50
+ await this.sendSuccessEmail();
51
+ }
52
+ }
53
+ else {
54
+ throw new Error("申请证书失败");
55
+ }
56
+ }
57
+ async output(certReader, isNew) {
58
+ const cert = certReader.toCertInfo();
59
+ this.cert = cert;
60
+ this._result.pipelineVars.certExpiresTime = dayjs(certReader.detail.notAfter).valueOf();
61
+ if (cert.pfx == null || cert.der == null) {
62
+ try {
63
+ const converter = new CertConverter({ logger: this.logger });
64
+ const res = await converter.convert({
65
+ cert,
66
+ pfxPassword: this.pfxPassword,
67
+ });
68
+ const pfxBuffer = fs.readFileSync(res.pfxPath);
69
+ cert.pfx = pfxBuffer.toString("base64");
70
+ const derBuffer = fs.readFileSync(res.derPath);
71
+ cert.der = derBuffer.toString("base64");
72
+ this.logger.info("转换证书格式成功");
73
+ isNew = true;
74
+ }
75
+ catch (e) {
76
+ this.logger.error("转换证书格式失败", e);
77
+ }
78
+ }
79
+ if (isNew) {
80
+ const zipFileName = certReader.buildCertFileName("zip", certReader.detail.notBefore);
81
+ await this.zipCert(cert, zipFileName);
82
+ }
83
+ else {
84
+ this.extendsFiles();
85
+ }
86
+ }
87
+ async zipCert(cert, filename) {
88
+ const zip = new JSZip();
89
+ zip.file("cert.crt", cert.crt);
90
+ zip.file("cert.key", cert.key);
91
+ zip.file("intermediate.crt", cert.ic);
92
+ if (cert.pfx) {
93
+ zip.file("cert.pfx", Buffer.from(cert.pfx, "base64"));
94
+ }
95
+ if (cert.der) {
96
+ zip.file("cert.der", Buffer.from(cert.der, "base64"));
97
+ }
98
+ const content = await zip.generateAsync({ type: "nodebuffer" });
99
+ this.saveFile(filename, content);
100
+ this.logger.info(`已保存文件:${filename}`);
101
+ }
102
+ /**
103
+ * 是否更新证书
104
+ */
105
+ async condition() {
106
+ if (this.forceUpdate) {
107
+ this.logger.info("强制更新证书选项已勾选,准备申请新证书");
108
+ return null;
109
+ }
110
+ const inputChanged = this.ctx.inputChanged;
111
+ if (inputChanged) {
112
+ this.logger.info("输入参数变更,准备申请新证书");
113
+ return null;
114
+ }
115
+ let oldCert = undefined;
116
+ try {
117
+ oldCert = await this.readLastCert();
118
+ }
119
+ catch (e) {
120
+ this.logger.warn("读取cert失败:", e);
121
+ }
122
+ if (oldCert == null) {
123
+ this.logger.info("还未申请过,准备申请新证书");
124
+ return null;
125
+ }
126
+ const ret = this.isWillExpire(oldCert.expires, this.renewDays);
127
+ if (!ret.isWillExpire) {
128
+ this.logger.info(`证书还未过期:过期时间${dayjs(oldCert.expires).format("YYYY-MM-DD HH:mm:ss")},剩余${ret.leftDays}天`);
129
+ return oldCert;
130
+ }
131
+ this.logger.info("即将过期,开始更新证书");
132
+ return null;
133
+ }
134
+ formatCert(pem) {
135
+ pem = pem.replace(/\r/g, "");
136
+ pem = pem.replace(/\n\n/g, "\n");
137
+ pem = pem.replace(/\n$/g, "");
138
+ return pem;
139
+ }
140
+ formatCerts(cert) {
141
+ const newCert = {
142
+ crt: this.formatCert(cert.crt),
143
+ key: this.formatCert(cert.key),
144
+ csr: this.formatCert(cert.csr),
145
+ };
146
+ return newCert;
147
+ }
148
+ async readLastCert() {
149
+ const cert = this.lastStatus?.status?.output?.cert;
150
+ if (cert == null) {
151
+ return undefined;
152
+ }
153
+ return new CertReader(cert);
154
+ }
155
+ /**
156
+ * 检查是否过期,默认提前20天
157
+ * @param expires
158
+ * @param maxDays
159
+ * @returns {boolean}
160
+ */
161
+ isWillExpire(expires, maxDays = 20) {
162
+ if (expires == null) {
163
+ throw new Error("过期时间不能为空");
164
+ }
165
+ // 检查有效期
166
+ const leftDays = dayjs(expires).diff(dayjs(), "day");
167
+ return {
168
+ isWillExpire: leftDays < maxDays,
169
+ leftDays,
170
+ };
171
+ }
172
+ async sendSuccessEmail() {
173
+ try {
174
+ this.logger.info("发送成功邮件通知:" + this.email);
175
+ const subject = `【CertD】证书申请成功【${this.domains[0]}】`;
176
+ await this.ctx.emailService.send({
177
+ userId: this.ctx.pipeline.userId,
178
+ receivers: [this.email],
179
+ subject: subject,
180
+ content: `证书申请成功,域名:${this.domains.join(",")}`,
181
+ });
182
+ }
183
+ catch (e) {
184
+ this.logger.error("send email error", e);
185
+ }
186
+ }
187
+ }
188
+ __decorate([
189
+ TaskInput({
190
+ title: "域名",
191
+ component: {
192
+ name: "a-select",
193
+ vModel: "value",
194
+ mode: "tags",
195
+ open: false,
196
+ tokenSeparators: [",", " ", ",", "、", "|"],
197
+ },
198
+ required: true,
199
+ col: {
200
+ span: 24,
201
+ },
202
+ order: -1,
203
+ helper: "1、支持通配符域名,例如: *.foo.com、foo.com、*.test.handsfree.work\n" +
204
+ "2、支持多个域名、多个子域名、多个通配符域名打到一个证书上(域名必须是在同一个DNS提供商解析)\n" +
205
+ "3、多级子域名要分成多个域名输入(*.foo.com的证书不能用于xxx.yyy.foo.com、foo.com)\n" +
206
+ "4、输入一个空格之后,再输入下一个",
207
+ }),
208
+ __metadata("design:type", Array)
209
+ ], CertApplyBasePlugin.prototype, "domains", void 0);
210
+ __decorate([
211
+ TaskInput({
212
+ title: "邮箱",
213
+ component: {
214
+ name: "a-input",
215
+ vModel: "value",
216
+ },
217
+ required: true,
218
+ order: -1,
219
+ helper: "请输入邮箱",
220
+ }),
221
+ __metadata("design:type", String)
222
+ ], CertApplyBasePlugin.prototype, "email", void 0);
223
+ __decorate([
224
+ TaskInput({
225
+ title: "PFX证书密码",
226
+ component: {
227
+ name: "a-input-password",
228
+ vModel: "value",
229
+ },
230
+ required: false,
231
+ order: 100,
232
+ helper: "PFX格式证书是否需要加密",
233
+ }),
234
+ __metadata("design:type", String)
235
+ ], CertApplyBasePlugin.prototype, "pfxPassword", void 0);
236
+ __decorate([
237
+ TaskInput({
238
+ title: "更新天数",
239
+ value: 20,
240
+ component: {
241
+ name: "a-input-number",
242
+ vModel: "value",
243
+ },
244
+ required: true,
245
+ order: 100,
246
+ helper: "到期前多少天后更新证书,注意:流水线默认不会自动运行,请设置定时器,每天定时运行本流水线",
247
+ }),
248
+ __metadata("design:type", Number)
249
+ ], CertApplyBasePlugin.prototype, "renewDays", void 0);
250
+ __decorate([
251
+ TaskInput({
252
+ title: "强制更新",
253
+ component: {
254
+ name: "a-switch",
255
+ vModel: "checked",
256
+ },
257
+ order: 100,
258
+ helper: "是否强制重新申请证书",
259
+ }),
260
+ __metadata("design:type", String)
261
+ ], CertApplyBasePlugin.prototype, "forceUpdate", void 0);
262
+ __decorate([
263
+ TaskInput({
264
+ title: "成功后邮件通知",
265
+ value: true,
266
+ component: {
267
+ name: "a-switch",
268
+ vModel: "checked",
269
+ },
270
+ order: 100,
271
+ helper: "申请成功后是否发送邮件通知",
272
+ }),
273
+ __metadata("design:type", Object)
274
+ ], CertApplyBasePlugin.prototype, "successNotify", void 0);
275
+ __decorate([
276
+ TaskOutput({
277
+ title: "域名证书",
278
+ }),
279
+ __metadata("design:type", Object)
280
+ ], CertApplyBasePlugin.prototype, "cert", void 0);
281
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiYmFzZS5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uL3NyYy9wbHVnaW4vY2VydC1wbHVnaW4vYmFzZS50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiOzs7Ozs7Ozs7QUFBQSxPQUFPLEVBQUUsa0JBQWtCLEVBQThCLFNBQVMsRUFBRSxVQUFVLEVBQUUsTUFBTSxpQkFBaUIsQ0FBQztBQUN4RyxPQUFPLEtBQUssTUFBTSxPQUFPLENBQUM7QUFFMUIsT0FBTyxFQUFFLFVBQVUsRUFBRSxNQUFNLGtCQUFrQixDQUFDO0FBQzlDLE9BQU8sS0FBSyxNQUFNLE9BQU8sQ0FBQztBQUMxQixPQUFPLEVBQUUsYUFBYSxFQUFFLE1BQU0sY0FBYyxDQUFDO0FBQzdDLE9BQU8sRUFBRSxNQUFNLElBQUksQ0FBQztBQUVwQixPQUFPLEVBQUUsVUFBVSxFQUFFLENBQUM7QUFHdEIsTUFBTSxPQUFnQixtQkFBb0IsU0FBUSxrQkFBa0I7SUFxQmxFLE9BQU8sQ0FBWTtJQVluQixLQUFLLENBQVU7SUFZZixXQUFXLENBQVU7SUFhckIsU0FBUyxDQUFVO0lBV25CLFdBQVcsQ0FBVTtJQVlyQixhQUFhLEdBQUcsSUFBSSxDQUFDO0lBRXJCLGVBQWU7SUFDZixzQkFBc0I7SUFDdEIscUJBQXFCO0lBQ3JCLEtBQUs7SUFDTCxPQUFPLENBQVU7SUFFakIsV0FBVyxDQUFZO0lBQ3ZCLElBQUksQ0FBYztJQUNsQixVQUFVLENBQVE7SUFLbEIsSUFBSSxDQUFZO0lBRWhCLEtBQUssQ0FBQyxVQUFVO1FBQ2QsSUFBSSxDQUFDLFdBQVcsR0FBRyxJQUFJLENBQUMsR0FBRyxDQUFDLFdBQVcsQ0FBQztRQUN4QyxJQUFJLENBQUMsSUFBSSxHQUFHLElBQUksQ0FBQyxHQUFHLENBQUMsSUFBSSxDQUFDO1FBQzFCLElBQUksQ0FBQyxVQUFVLEdBQUcsSUFBSSxDQUFDLEdBQUcsQ0FBQyxVQUFrQixDQUFDO1FBQzlDLE1BQU0sSUFBSSxDQUFDLE1BQU0sRUFBRSxDQUFDO0lB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