diff --git a/AGENTS.md b/AGENTS.md index 5fc36a580..bcb223cc9 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -204,5 +204,8 @@ Get-ChildItem packages\ui\certd-client\src\views\certd - 做前端任务时,先定位 `packages/ui/certd-client/src/views/certd` 下的页面,再找对应 `src/api`。 - 做服务商、DNS、部署、通知相关任务时,先看 `packages/ui/certd-server/src/plugins`,再看 `packages/plugins/plugin-lib` 里的共享辅助能力。 - 做数据库结构变更时,添加或更新迁移脚本,不要依赖 TypeORM 自动同步。 +- 实现新功能或修复行为缺陷前,先补对应单元测试,并先运行测试确认它处于失败状态;再实现功能或修复代码,反复运行聚焦单元测试直到通过。若某项改动确实不适合先写单元测试,应在回复中说明原因和替代验证方式。 +- 后补单元测试时,应先基于对正确行为的实际预期编写测试,而不是为了迎合现有实现改写预期;如果运行后出现红灯,且通过测试需要修改已有实现,应先向用户确认这是确实的 bug,还是原本需求/既有行为就是如此;确认后再修改原始实现,避免把测试补充变成未经确认的行为改动。 +- 后端纯单元测试用例放在 `src` 目录内,并尽量与被测文件相邻,例如 `src/utils/random.test.ts`;对应 `test:unit` 只跑 `src/**/*.test.ts`,构建/打包配置应排除这些 `*.test.ts` 文件。 - 前端 TS/Vue/locale 等文件改动后,优先只对本次改动文件运行项目现有自动格式化/修复,例如 `corepack pnpm --dir packages\ui\certd-client exec prettier --write ` 和 `corepack pnpm --dir packages\ui\certd-client exec eslint --fix `;不要为了格式化无关文件而扩大 diff。项目保留了 `tslint` 依赖,但当前主要使用 ESLint + Prettier。 - 优先对改动包运行聚焦的测试或类型检查;只有跨包影响明显时再考虑全 monorepo 构建。 diff --git a/docs/guide/plugins/deploy.md b/docs/guide/plugins/deploy.md index 898d95e4c..610d636d3 100644 --- a/docs/guide/plugins/deploy.md +++ b/docs/guide/plugins/deploy.md @@ -1,5 +1,5 @@ # 任务插件 -共 `131` 款任务插件 +共 `132` 款任务插件 ## 1. 证书申请 | 序号 | 名称 | 说明 | @@ -134,8 +134,9 @@ | 4.| **火山引擎-部署证书至DCDN** | 部署至火山引擎全站加速 | | 5.| **火山引擎-部署证书至Live** | 部署至火山引擎视频直播 | | 6.| **火山引擎-部署证书至TOS自定义域名** | 仅限TOS自定义域名,加速域名请选择火山引擎的CDN插件 | -| 7.| **火山引擎-部署证书至VOD** | 部署至火山引擎视频点播 | -| 8.| **火山引擎-上传证书至证书中心** | 上传证书至火山引擎证书中心 | +| 7.| **火山引擎-替换VKE证书** | 替换火山引擎VKE集群中的TLS Secret证书 | +| 8.| **火山引擎-部署证书至VOD** | 部署至火山引擎视频点播 | +| 9.| **火山引擎-上传证书至证书中心** | 上传证书至火山引擎证书中心 | ## 9. 京东云 | 序号 | 名称 | 说明 | diff --git a/packages/core/basic/package.json b/packages/core/basic/package.json index d955b65c4..c9ac8efa7 100644 --- a/packages/core/basic/package.json +++ b/packages/core/basic/package.json @@ -13,6 +13,7 @@ "dev-build": "npm run build", "preview": "vite preview", "test": "mocha --loader=ts-node/esm", + "test:unit": "mocha --node-option no-warnings --node-option loader=ts-node/esm \"src/**/*.test.ts\"", "pub": "npm publish", "compile": "tsc --skipLibCheck --watch" }, @@ -42,8 +43,10 @@ "eslint": "^8.41.0", "eslint-config-prettier": "^8.8.0", "eslint-plugin-prettier": "^4.2.1", + "mocha": "^10.2.0", "prettier": "^2.8.8", "rimraf": "^5.0.5", + "ts-node": "^10.9.2", "tslib": "^2.8.1", "typescript": "^5.4.2" }, diff --git a/packages/core/basic/src/utils/util.amount.test.ts b/packages/core/basic/src/utils/util.amount.test.ts new file mode 100644 index 000000000..76fbc0651 --- /dev/null +++ b/packages/core/basic/src/utils/util.amount.test.ts @@ -0,0 +1,31 @@ +/// + +import { expect } from "chai"; + +import { amountUtils } from "./util.amount.js"; + +describe("amountUtils", () => { + describe("toCent", () => { + it("converts yuan values to cents", () => { + expect(amountUtils.toCent(1)).to.equal(100); + expect(amountUtils.toCent(12.34)).to.equal(1234); + }); + + it("rounds to the nearest cent", () => { + expect(amountUtils.toCent(1.235)).to.equal(124); + expect(amountUtils.toCent(1.234)).to.equal(123); + }); + }); + + describe("toYuan", () => { + it("converts cent values to yuan", () => { + expect(amountUtils.toYuan(100)).to.equal(1); + expect(amountUtils.toYuan(1234)).to.equal(12.34); + }); + + it("rounds yuan values to two decimal places", () => { + expect(amountUtils.toYuan(1235)).to.equal(12.35); + expect(amountUtils.toYuan(1)).to.equal(0.01); + }); + }); +}); diff --git a/packages/core/basic/src/utils/util.domain.test.ts b/packages/core/basic/src/utils/util.domain.test.ts new file mode 100644 index 000000000..214ebb88a --- /dev/null +++ b/packages/core/basic/src/utils/util.domain.test.ts @@ -0,0 +1,43 @@ +/// + +import { expect } from "chai"; + +import { domainUtils } from "./util.domain.js"; + +describe("domainUtils", () => { + describe("match", () => { + it("matches exact domains", () => { + expect(domainUtils.match("example.com", ["example.com"])).to.equal(true); + expect(domainUtils.match("api.example.com", ["example.com"])).to.equal(false); + }); + + it("matches wildcard domains by suffix", () => { + expect(domainUtils.match("api.example.com", ["*.example.com"])).to.equal(true); + expect(domainUtils.match("deep.api.example.com", ["*.example.com"])).to.equal(false); + expect(domainUtils.match("example.com", ["*.example.com"])).to.equal(false); + }); + + it("requires every target domain to match", () => { + expect(domainUtils.match(["api.example.com", "admin.example.com"], ["*.example.com"])).to.equal(true); + expect(domainUtils.match(["api.example.com", "other.com"], ["*.example.com"])).to.equal(false); + }); + }); + + describe("isIp", () => { + it("detects valid IPv4 addresses", () => { + expect(domainUtils.isIpv4("127.0.0.1")).to.equal(true); + expect(domainUtils.isIpv4("255.255.255.255")).to.equal(true); + }); + + it("rejects invalid IPv4 addresses", () => { + expect(domainUtils.isIpv4("999.1.1.1")).to.equal(false); + expect(domainUtils.isIpv4("1.2.3")).to.equal(false); + expect(domainUtils.isIpv4("example.com")).to.equal(false); + }); + + it("detects IPv6 addresses", () => { + expect(domainUtils.isIpv6("2001:db8::1")).to.equal(true); + expect(domainUtils.isIp("2001:db8::1")).to.equal(true); + }); + }); +}); diff --git a/packages/core/basic/src/utils/util.domain.ts b/packages/core/basic/src/utils/util.domain.ts index 6a3c676b7..61d558298 100644 --- a/packages/core/basic/src/utils/util.domain.ts +++ b/packages/core/basic/src/utils/util.domain.ts @@ -51,7 +51,10 @@ function isIpv4(d: string) { return false; } const isIPv4Regex = /^(\d{1,3}\.){3}\d{1,3}$/; - return isIPv4Regex.test(d); + if (!isIPv4Regex.test(d)) { + return false; + } + return d.split(".").every(item => Number(item) <= 255); } function isIpv6(d: string) { diff --git a/packages/core/basic/src/utils/util.options.test.ts b/packages/core/basic/src/utils/util.options.test.ts new file mode 100644 index 000000000..720dbca4b --- /dev/null +++ b/packages/core/basic/src/utils/util.options.test.ts @@ -0,0 +1,40 @@ +/// + +import { expect } from "chai"; + +import { optionsUtils } from "./util.options.js"; + +describe("optionsUtils", () => { + describe("groupByDomain", () => { + it("splits options by domain match", () => { + const matchedOption = { value: "matched", domain: "api.example.com" }; + const wildcardMatchedOption = { value: "wildcard", domain: "admin.example.com" }; + const unmatchedOption = { value: "unmatched", domain: "other.com" }; + + const result = optionsUtils.groupByDomain([matchedOption, wildcardMatchedOption, unmatchedOption], ["api.example.com", "*.example.com"]); + + expect(result.matched).to.deep.equal([matchedOption, wildcardMatchedOption]); + expect(result.notMatched).to.deep.equal([unmatchedOption]); + }); + + it("treats options without matching domains as not matched", () => { + const optionWithoutDomain = { value: "empty" }; + + const result = optionsUtils.groupByDomain([optionWithoutDomain], ["example.com"]); + + expect(result.matched).to.deep.equal([]); + expect(result.notMatched).to.deep.equal([optionWithoutDomain]); + }); + }); + + describe("buildGroupOptions", () => { + it("builds disabled group labels around matched and unmatched options", () => { + const matchedOption = { value: "matched", domain: "api.example.com" }; + const unmatchedOption = { value: "unmatched", domain: "other.com" }; + + const result = optionsUtils.buildGroupOptions([matchedOption, unmatchedOption], ["api.example.com"]); + + expect(result).to.deep.equal([{ value: "matched", disabled: true, label: "----已匹配----" }, matchedOption, { value: "unmatched", disabled: true, label: "----未匹配----" }, unmatchedOption]); + }); + }); +}); diff --git a/packages/core/basic/src/utils/util.string.test.ts b/packages/core/basic/src/utils/util.string.test.ts new file mode 100644 index 000000000..1cdf564ab --- /dev/null +++ b/packages/core/basic/src/utils/util.string.test.ts @@ -0,0 +1,36 @@ +/// + +import { expect } from "chai"; + +import { stringUtils } from "./util.string.js"; + +describe("stringUtils", () => { + describe("maxLength", () => { + it("returns an empty string for empty input", () => { + expect(stringUtils.maxLength()).to.equal(""); + expect(stringUtils.maxLength("")).to.equal(""); + }); + + it("returns the original string when it is within the limit", () => { + expect(stringUtils.maxLength("certd", 5)).to.equal("certd"); + expect(stringUtils.maxLength("certd", 6)).to.equal("certd"); + }); + + it("truncates strings longer than the limit and appends ellipsis", () => { + expect(stringUtils.maxLength("certificate", 4)).to.equal("cert..."); + }); + }); + + describe("appendTimeSuffix", () => { + it("returns an empty string for empty input", () => { + expect(stringUtils.appendTimeSuffix()).to.equal(""); + expect(stringUtils.appendTimeSuffix("")).to.equal(""); + }); + + it("appends a millisecond timestamp suffix", () => { + const result = stringUtils.appendTimeSuffix("certd"); + + expect(result).to.match(/^certd-\d{17}$/); + }); + }); +}); diff --git a/packages/core/basic/tsconfig.json b/packages/core/basic/tsconfig.json index cc024d9b0..4a0b70f77 100644 --- a/packages/core/basic/tsconfig.json +++ b/packages/core/basic/tsconfig.json @@ -7,7 +7,7 @@ "esModuleInterop": true, "experimentalDecorators": true, "emitDecoratorMetadata": true, - "inlineSourceMap":false, + "inlineSourceMap": false, "sourceMap": false, "noImplicitThis": true, "noUnusedLocals": true, @@ -22,21 +22,11 @@ "composite": false, "useDefineForClassFields": true, "strict": true, - "typeRoots": [ "./typings", "./node_modules/@types"], + "typeRoots": ["./typings", "./node_modules/@types"], "resolveJsonModule": true, "isolatedModules": false, - "lib": ["ESNext", "DOM"], + "lib": ["ESNext", "DOM"] }, - "include": [ - "src/**/*.ts", - "src/**/*.json" - ], - "exclude": [ - "*.js", - "*.ts", - "*.spec.ts", - "dist", - "node_modules", - "test" - ], + "include": ["src/**/*.ts", "src/**/*.json"], + "exclude": ["*.js", "*.ts", "*.spec.ts", "dist", "node_modules", "src/**/*.test.ts", "test"] } diff --git a/packages/core/pipeline/package.json b/packages/core/pipeline/package.json index 1efbae26f..a2b7e3274 100644 --- a/packages/core/pipeline/package.json +++ b/packages/core/pipeline/package.json @@ -14,6 +14,7 @@ "build3": "rollup -c", "preview": "vite preview", "test": "mocha --loader=ts-node/esm", + "test:unit": "mocha --no-config --node-option no-warnings --node-option loader=ts-node/esm \"src/**/*.test.ts\"", "pub": "npm publish", "compile": "tsc --skipLibCheck --watch" }, @@ -42,6 +43,7 @@ "mocha": "^10.2.0", "prettier": "^2.8.8", "rimraf": "^5.0.5", + "ts-node": "^10.9.2", "tslib": "^2.8.1", "typescript": "^5.4.2" }, diff --git a/packages/core/pipeline/src/plugin/group.test.ts b/packages/core/pipeline/src/plugin/group.test.ts new file mode 100644 index 000000000..e63352c58 --- /dev/null +++ b/packages/core/pipeline/src/plugin/group.test.ts @@ -0,0 +1,23 @@ +/// + +import { expect } from "chai"; + +import { PluginGroup, pluginGroups } from "./group.js"; + +describe("PluginGroup", () => { + it("initializes a group with defaults", () => { + const group = new PluginGroup("custom", "Custom"); + + expect(group.key).to.equal("custom"); + expect(group.title).to.equal("Custom"); + expect(group.order).to.equal(0); + expect(group.icon).to.equal(""); + expect(group.plugins).to.deep.equal([]); + }); + + it("exposes built-in groups with stable keys", () => { + expect(pluginGroups.cert.key).to.equal("cert"); + expect(pluginGroups.host.key).to.equal("host"); + expect(pluginGroups.other.order).to.equal(10); + }); +}); diff --git a/packages/core/pipeline/tsconfig.json b/packages/core/pipeline/tsconfig.json index c6a7a39df..a373edbd8 100644 --- a/packages/core/pipeline/tsconfig.json +++ b/packages/core/pipeline/tsconfig.json @@ -7,7 +7,7 @@ "esModuleInterop": true, "experimentalDecorators": true, "emitDecoratorMetadata": true, - "inlineSourceMap":false, + "inlineSourceMap": false, "sourceMap": false, "noImplicitThis": true, "noUnusedLocals": true, @@ -22,22 +22,11 @@ "composite": false, "useDefineForClassFields": true, "strict": true, -// "sourceMap": true, + // "sourceMap": true, "resolveJsonModule": true, "isolatedModules": false, - "lib": ["ESNext", "DOM"], + "lib": ["ESNext", "DOM"] }, - "include": [ - "src/**/*.ts", - "src/**/*.d.ts", - "src/**/*.json" - ], - "exclude": [ - "*.js", - "*.ts", - "*.spec.ts", - "dist", - "node_modules", - "test" - ], + "include": ["src/**/*.ts", "src/**/*.d.ts", "src/**/*.json"], + "exclude": ["*.js", "*.ts", "*.spec.ts", "dist", "node_modules", "src/**/*.test.ts", "test"] } diff --git a/packages/libs/lib-server/package.json b/packages/libs/lib-server/package.json index f99a754a6..fb3709b06 100644 --- a/packages/libs/lib-server/package.json +++ b/packages/libs/lib-server/package.json @@ -12,6 +12,7 @@ "build": "npm run before-build && tsc --skipLibCheck", "dev-build": "npm run build", "test": "midway-bin test --ts -V", + "test:unit": "mocha --no-config --node-option no-warnings --node-option loader=ts-node/esm \"src/**/*.test.ts\"", "test1": "midway-bin test --ts -V -f test/blank.test.ts -t 'hash-check'", "cov": "midway-bin cov --ts", "lint": "mwts check", @@ -52,14 +53,17 @@ }, "devDependencies": { "@types/chai": "^4.3.3", + "@types/mocha": "^10.0.1", "@types/node": "^18", "@typescript-eslint/eslint-plugin": "^8.26.1", "@typescript-eslint/parser": "^8.26.1", "eslint": "^8.24.0", "eslint-config-prettier": "^8.5.0", "eslint-plugin-prettier": "^4.2.1", + "mocha": "^10.2.0", "prettier": "^2.8.8", "rimraf": "^5.0.5", + "ts-node": "^10.9.2", "tslib": "^2.8.1", "typeorm": "^0.3.11", "typescript": "^5.4.2" diff --git a/packages/libs/lib-server/src/basic/result.test.ts b/packages/libs/lib-server/src/basic/result.test.ts new file mode 100644 index 000000000..046b8347a --- /dev/null +++ b/packages/libs/lib-server/src/basic/result.test.ts @@ -0,0 +1,32 @@ +/// +/// + +import assert from "node:assert/strict"; + +import { Constants } from "./constants.js"; +import { ParamException } from "./exception/param-exception.js"; +import { Result } from "./result.js"; + +describe("lib-server basic helpers", () => { + it("builds success and error results", () => { + const success = Result.success("ok", { id: 1 }); + assert.ok(success instanceof Result); + assert.equal(success.code, 0); + assert.equal(success.message, "ok"); + assert.deepEqual(success.data, { id: 1 }); + + const error = Result.error(400, "bad request"); + assert.ok(error instanceof Result); + assert.equal(error.code, 400); + assert.equal(error.message, "bad request"); + assert.equal(error.data, undefined); + }); + + it("uses default param exception metadata", () => { + const error = new ParamException(undefined); + + assert.equal(error.name, "ParamException"); + assert.equal(error.code, Constants.res.param.code); + assert.equal(error.message, Constants.res.param.message); + }); +}); diff --git a/packages/libs/lib-server/tsconfig.json b/packages/libs/lib-server/tsconfig.json index 02cb80b89..eb9e15f0a 100644 --- a/packages/libs/lib-server/tsconfig.json +++ b/packages/libs/lib-server/tsconfig.json @@ -8,7 +8,7 @@ "isolatedModules": true, "experimentalDecorators": true, "emitDecoratorMetadata": true, - "inlineSourceMap":false, + "inlineSourceMap": false, "sourceMap": false, "noImplicitThis": true, "noUnusedLocals": true, @@ -17,25 +17,15 @@ "pretty": true, "declaration": true, "forceConsistentCasingInFileNames": true, - "typeRoots": [ "./typings", "./node_modules/@types"], + "typeRoots": ["./typings", "./node_modules/@types"], "outDir": "dist", "rootDir": "src", "composite": false, "useDefineForClassFields": true, "strict": false, "resolveJsonModule": true, - "lib": ["ESNext", "DOM"], + "lib": ["ESNext", "DOM"] }, - "include": [ - "src/**/*.ts", - "src/**/*.d.ts", - "src/**/*.json" - ], - "exclude": [ - "*.js", - "*.ts", - "dist", - "node_modules", - "test" - ], + "include": ["src/**/*.ts", "src/**/*.d.ts", "src/**/*.json"], + "exclude": ["*.js", "*.ts", "dist", "node_modules", "src/**/*.test.ts", "test"] } diff --git a/packages/plugins/plugin-lib/package.json b/packages/plugins/plugin-lib/package.json index 4750bcaee..a55205377 100644 --- a/packages/plugins/plugin-lib/package.json +++ b/packages/plugins/plugin-lib/package.json @@ -13,6 +13,7 @@ "build3": "rollup -c", "build2": "vue-tsc --noEmit && vite build", "preview": "vite preview", + "test:unit": "mocha --no-config --node-option no-warnings --node-option loader=ts-node/esm \"src/**/*.test.ts\"", "pub": "npm publish", "compile": "tsc --skipLibCheck --watch" }, @@ -54,6 +55,7 @@ "eslint-plugin-prettier": "^4.2.1", "mocha": "^10.1.0", "prettier": "^2.8.8", + "ts-node": "^10.9.2", "tslib": "^2.8.1", "typescript": "^5.4.2" }, diff --git a/packages/plugins/plugin-lib/src/common/util.test.ts b/packages/plugins/plugin-lib/src/common/util.test.ts new file mode 100644 index 000000000..5da43de09 --- /dev/null +++ b/packages/plugins/plugin-lib/src/common/util.test.ts @@ -0,0 +1,55 @@ +/// + +import { expect } from "chai"; + +import { createCertDomainGetterInputDefine, createRemoteSelectInputDefine } from "./util.js"; + +describe("plugin-lib common util", () => { + it("builds cert domain getter input define with defaults", () => { + const define = createCertDomainGetterInputDefine(); + + expect(define.title).to.equal("当前证书域名"); + expect(define.component.name).to.equal("cert-domains-getter"); + expect(define.required).to.equal(true); + expect(define.template).to.equal(false); + expect(define.mergeScript).to.contain("form.cert"); + }); + + it("allows overriding cert input key and props", () => { + const define = createCertDomainGetterInputDefine({ + certInputKey: "customCert", + props: { + title: "自定义域名", + required: false, + }, + }); + + expect(define.title).to.equal("自定义域名"); + expect(define.required).to.equal(false); + expect(define.mergeScript).to.contain("form.customCert"); + }); + + it("builds remote select input define with expected component options", () => { + const define = createRemoteSelectInputDefine({ + title: "选择资源", + action: "ListResource", + typeName: "resource", + multi: false, + search: true, + watches: ["region"], + }); + + expect(define.title).to.equal("选择资源"); + expect(define.required).to.equal(true); + expect(define.component).to.include({ + name: "remote-select", + vModel: "value", + action: "ListResource", + typeName: "resource", + mode: "default", + multi: false, + search: true, + }); + expect(define.component.watches).to.deep.equal(["certDomains", "accessId", "region"]); + }); +}); diff --git a/packages/plugins/plugin-lib/tsconfig.json b/packages/plugins/plugin-lib/tsconfig.json index 1bbe778b5..5c89236a6 100644 --- a/packages/plugins/plugin-lib/tsconfig.json +++ b/packages/plugins/plugin-lib/tsconfig.json @@ -7,7 +7,7 @@ "esModuleInterop": true, "experimentalDecorators": true, "emitDecoratorMetadata": true, - "inlineSourceMap":false, + "inlineSourceMap": false, "sourceMap": false, "noImplicitThis": true, "noUnusedLocals": true, @@ -16,27 +16,17 @@ "pretty": true, "declaration": true, "forceConsistentCasingInFileNames": true, - "typeRoots": [ "./typings", "./node_modules/@types"], + "typeRoots": ["./typings", "./node_modules/@types"], "outDir": "dist", "rootDir": "src", "composite": false, "useDefineForClassFields": true, "strict": false, -// "sourceMap": true, + // "sourceMap": true, "resolveJsonModule": true, "isolatedModules": false, - "lib": ["ESNext", "DOM"], + "lib": ["ESNext", "DOM"] }, - "include": [ - "src/**/*.ts", - "src/**/*.d.ts", - "src/**/*.json" - ], - "exclude": [ - "*.js", - "*.ts", - "dist", - "node_modules", - "test" - ], + "include": ["src/**/*.ts", "src/**/*.d.ts", "src/**/*.json"], + "exclude": ["*.js", "*.ts", "dist", "node_modules", "src/**/*.test.ts", "test"] } diff --git a/packages/ui/certd-server/metadata/deploy_VolcengineDeployToVKE.yaml b/packages/ui/certd-server/metadata/deploy_VolcengineDeployToVKE.yaml new file mode 100644 index 000000000..37297b8e5 --- /dev/null +++ b/packages/ui/certd-server/metadata/deploy_VolcengineDeployToVKE.yaml @@ -0,0 +1,178 @@ +showRunStrategy: false +default: + strategy: + runStrategy: 1 +name: VolcengineDeployToVKE +title: 火山引擎-替换VKE证书 +icon: svg:icon-volcengine +group: volcengine +desc: 替换火山引擎VKE集群中的TLS Secret证书 +input: + cert: + title: 域名证书 + helper: 请选择前置任务输出的域名证书 + component: + name: output-selector + from: + - ':cert:' + required: true + order: 0 + certDomains: + title: 当前证书域名 + component: + name: cert-domains-getter + mergeScript: |2- + + return { + component:{ + inputKey: ctx.compute(({form})=>{ + return form.cert + }), + } + } + + template: false + required: false + order: 0 + accessId: + title: Access授权 + helper: 火山引擎AccessKeyId、AccessKeySecret + component: + name: access-selector + type: volcengine + required: true + order: 0 + regionId: + title: Region + helper: VKE集群所在地域 + component: + name: a-select + options: + - label: 北京 + value: cn-beijing + - label: 上海 + value: cn-shanghai + - label: 广州 + value: cn-guangzhou + - label: 香港 + value: cn-hongkong + - label: 柔佛 + value: ap-southeast-1 + - label: 雅加达 + value: ap-southeast-3 + value: cn-beijing + required: true + order: 0 + clusterId: + title: VKE集群 + component: + name: remote-select + vModel: value + mode: tags + type: plugin + action: onGetClusterList + search: false + pager: false + multi: true + watches: + - certDomains + - accessId + - accessId + - regionId + required: true + mergeScript: |2- + + return { + component:{ + form: ctx.compute(({form})=>{ + return form + }) + }, + } + + helper: 选择要替换证书的VKE集群,也可以手动输入集群ID + order: 0 + kubeconfigType: + title: Kubeconfig类型 + helper: Public需要集群API Server已开启公网访问;Private需要Certd能访问集群私网地址 + component: + name: a-select + options: + - label: 公网 + value: Public + - label: 私网 + value: Private + - label: 集群内 + value: TargetCluster + value: Public + required: true + order: 0 + namespace: + title: 命名空间 + value: default + component: + placeholder: 命名空间 + required: true + order: 0 + targetType: + title: 替换方式 + helper: 按Ingress会自动读取spec.tls[].secretName;按Secret需要手动填写Secret名称 + component: + name: a-select + options: + - label: 按Ingress替换 + value: ingress + - label: 按Secret替换 + value: secret + value: ingress + required: true + order: 0 + ingressName: + title: IngressName + required: true + helper: 根据Ingress名称查找TLS Secret并替换 + mergeScript: |2- + + return { + show: ctx.compute(({form}) => form.targetType === 'ingress'), + required: ctx.compute(({form}) => form.targetType === 'ingress') + } + + order: 0 + secretName: + title: Secret名称 + required: true + helper: 存储TLS证书的Secret名称,可填写多个 + component: + name: a-select + vModel: value + mode: tags + open: false + mergeScript: |2- + + return { + show: ctx.compute(({form}) => form.targetType === 'secret'), + required: ctx.compute(({form}) => form.targetType === 'secret') + } + + order: 0 + createOnNotFound: + title: Secret自动创建 + helper: 如果Secret不存在,则创建kubernetes.io/tls类型Secret + value: false + component: + name: a-switch + vModel: checked + order: 0 + skipTLSVerify: + title: 忽略证书校验 + helper: 连接Kubernetes API Server时跳过TLS校验 + value: false + component: + name: a-switch + vModel: checked + order: 0 +output: {} +pluginType: deploy +type: builtIn +scriptFilePath: /plugins/plugin-volcengine/plugins/plugin-deploy-to-vke.js diff --git a/packages/ui/certd-server/package.json b/packages/ui/certd-server/package.json index 0595516e3..4984a4d2e 100644 --- a/packages/ui/certd-server/package.json +++ b/packages/ui/certd-server/package.json @@ -19,6 +19,7 @@ "dev-new": "cross-env NODE_ENV=dev-new mwtsc --watch --run @midwayjs/mock/app", "rm-newdb": "rimraf ./data/db-new.sqlite", "test": "cross-env NODE_ENV=unittest mocha", + "test:unit": "cross-env NODE_ENV=unittest mocha --no-config --node-option no-warnings --node-option loader=ts-node/esm \"src/**/*.test.ts\"", "cov": "cross-env c8 --all --reporter=text --reporter=lcovonly pnpm run test", "lint": "mwts check", "lint:fix": "mwts fix", @@ -161,6 +162,7 @@ "mocha": "^10.2.0", "prettier": "^2.8.8", "rimraf": "^5.0.5", + "ts-node": "^10.9.2", "tslib": "^2.8.1", "typescript": "^5.4.2", "why-is-node-running": "^3.2.2" diff --git a/packages/ui/certd-server/src/utils/random.test.ts b/packages/ui/certd-server/src/utils/random.test.ts new file mode 100644 index 000000000..6c961669a --- /dev/null +++ b/packages/ui/certd-server/src/utils/random.test.ts @@ -0,0 +1,54 @@ +/// +/// + +import assert from "node:assert/strict"; + +import { RandomUtil } from "./random.js"; + +describe("RandomUtil.randomStr", () => { + it("generates an 8-character alphanumeric string by default", () => { + const result = RandomUtil.randomStr(); + + assert.equal(result.length, 8); + assert.match(result, /^[A-Za-z0-9]+$/); + }); + + it("uses the requested length", () => { + assert.equal(RandomUtil.randomStr(0), ""); + assert.equal(RandomUtil.randomStr(1).length, 1); + assert.equal(RandomUtil.randomStr(16).length, 16); + }); + + it("supports a custom character set", () => { + assert.equal(RandomUtil.randomStr(6, "A"), "AAAAAA"); + }); + + it("supports the legacy true option as alphanumeric mode", () => { + const result = RandomUtil.randomStr(32, true); + + assert.match(result, /^[A-Za-z0-9]+$/); + }); + + it("can generate from numbers only", () => { + const result = RandomUtil.randomStr(12, { letters: false }); + + assert.match(result, /^[0-9]+$/); + }); + + it("can generate from caller-provided option character sets", () => { + assert.equal(RandomUtil.randomStr(4, { numbers: "7", letters: false }), "7777"); + assert.equal(RandomUtil.randomStr(4, { numbers: false, letters: "x" }), "xxxx"); + assert.equal(RandomUtil.randomStr(4, { numbers: false, letters: false, specials: "!" }), "!!!!"); + }); + + it("can generate from built-in specials only", () => { + const result = RandomUtil.randomStr(20, { numbers: false, letters: false, specials: true }); + + assert.match(result, /^[~!@#$%^*()_+\-=[\]{}|;:,./<>?]+$/); + }); + + it("rejects an empty character set", () => { + assert.throws(() => RandomUtil.randomStr(4, ""), /at least one available character/); + assert.throws(() => RandomUtil.randomStr(4, { numbers: false, letters: false }), /at least one available character/); + }); +}); diff --git a/packages/ui/certd-server/src/utils/random.ts b/packages/ui/certd-server/src/utils/random.ts index 53a616926..e44109cce 100644 --- a/packages/ui/certd-server/src/utils/random.ts +++ b/packages/ui/certd-server/src/utils/random.ts @@ -2,14 +2,16 @@ const numbers = "0123456789"; const letters = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz"; const specials = "~!@#$%^*()_+-=[]{}|;:,./<>?"; +type RandomStrOptions = true | string | { numbers?: false | string; letters?: false | string; specials?: boolean | string }; + /** * Generate random string * @param {Number} length * @param {Object} options */ -function randomStr(length, options?) { - length || (length = 8); - options || (options = {}); +function randomStr(length?: number, options?: RandomStrOptions) { + length ?? (length = 8); + options ?? (options = {}); let chars = ""; let result = ""; @@ -32,6 +34,10 @@ function randomStr(length, options?) { } } + if (chars.length === 0) { + throw new Error("randomStr requires at least one available character"); + } + while (length > 0) { length--; result += chars[Math.floor(Math.random() * chars.length)]; @@ -40,4 +46,3 @@ function randomStr(length, options?) { } export const RandomUtil = { randomStr }; - diff --git a/packages/ui/certd-server/tsconfig.json b/packages/ui/certd-server/tsconfig.json index 048ec20bd..d09119a81 100644 --- a/packages/ui/certd-server/tsconfig.json +++ b/packages/ui/certd-server/tsconfig.json @@ -16,16 +16,10 @@ "pretty": true, "declaration": true, "forceConsistentCasingInFileNames": true, - "typeRoots": [ "./typings", "./node_modules/@types"], + "typeRoots": ["./typings", "./node_modules/@types"], "outDir": "dist", "rootDir": "src", "preserveWatchOutput": true }, - "exclude": [ - "*.js", - "*.ts", - "dist", - "node_modules", - "test" - ] + "exclude": ["*.js", "*.ts", "dist", "node_modules", "src/**/*.test.ts", "test"] } diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index c91f6010c..97bf0d262 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -49,7 +49,7 @@ importers: packages/core/acme-client: dependencies: '@certd/basic': - specifier: ^1.39.11 + specifier: ^1.39.12 version: link:../basic '@peculiar/x509': specifier: ^1.11.0 @@ -197,12 +197,18 @@ importers: eslint-plugin-prettier: specifier: ^4.2.1 version: 4.2.1(eslint-config-prettier@8.10.0(eslint@8.57.0))(eslint@8.57.0)(prettier@2.8.8) + mocha: + specifier: ^10.2.0 + version: 10.8.2 prettier: specifier: ^2.8.8 version: 2.8.8 rimraf: specifier: ^5.0.5 version: 5.0.10 + ts-node: + specifier: ^10.9.2 + version: 10.9.2(@types/node@25.0.3)(typescript@5.9.3) tslib: specifier: ^2.8.1 version: 2.8.1 @@ -213,11 +219,11 @@ importers: packages/core/pipeline: dependencies: '@certd/basic': - specifier: ^1.39.11 + specifier: ^1.39.12 version: link:../basic '@certd/plus-core': - specifier: ^1.39.11 - version: 1.39.11 + specifier: ^1.39.12 + version: link:../../pro/plus-core dayjs: specifier: ^1.11.7 version: 1.11.13 @@ -279,6 +285,9 @@ importers: rimraf: specifier: ^5.0.5 version: 5.0.10 + ts-node: + specifier: ^10.9.2 + version: 10.9.2(@types/node@25.0.3)(typescript@5.9.3) tslib: specifier: ^2.8.1 version: 2.8.1 @@ -412,7 +421,7 @@ importers: packages/libs/lib-k8s: dependencies: '@certd/basic': - specifier: ^1.39.11 + specifier: ^1.39.12 version: link:../../core/basic '@kubernetes/client-node': specifier: 0.21.0 @@ -452,20 +461,20 @@ importers: packages/libs/lib-server: dependencies: '@certd/acme-client': - specifier: ^1.39.11 + specifier: ^1.39.12 version: link:../../core/acme-client '@certd/basic': - specifier: ^1.39.11 + specifier: ^1.39.12 version: link:../../core/basic '@certd/pipeline': - specifier: ^1.39.11 + specifier: ^1.39.12 version: link:../../core/pipeline '@certd/plugin-lib': - specifier: ^1.39.11 + specifier: ^1.39.12 version: link:../../plugins/plugin-lib '@certd/plus-core': - specifier: ^1.39.11 - version: 1.39.11 + specifier: ^1.39.12 + version: link:../../pro/plus-core '@midwayjs/cache': specifier: 3.14.0 version: 3.14.0 @@ -518,6 +527,9 @@ importers: '@types/chai': specifier: ^4.3.3 version: 4.3.20 + '@types/mocha': + specifier: ^10.0.1 + version: 10.0.10 '@types/node': specifier: ^18 version: 18.19.100 @@ -536,12 +548,18 @@ importers: eslint-plugin-prettier: specifier: ^4.2.1 version: 4.2.1(eslint-config-prettier@8.10.0(eslint@8.57.0))(eslint@8.57.0)(prettier@2.8.8) + mocha: + specifier: ^10.2.0 + version: 10.8.2 prettier: specifier: ^2.8.8 version: 2.8.8 rimraf: specifier: ^5.0.5 version: 5.0.10 + ts-node: + specifier: ^10.9.2 + version: 10.9.2(@types/node@18.19.100)(typescript@5.9.3) tslib: specifier: ^2.8.1 version: 2.8.1 @@ -610,16 +628,16 @@ importers: packages/plugins/plugin-cert: dependencies: '@certd/acme-client': - specifier: ^1.39.11 + specifier: ^1.39.12 version: link:../../core/acme-client '@certd/basic': - specifier: ^1.39.11 + specifier: ^1.39.12 version: link:../../core/basic '@certd/pipeline': - specifier: ^1.39.11 + specifier: ^1.39.12 version: link:../../core/pipeline '@certd/plugin-lib': - specifier: ^1.39.11 + specifier: ^1.39.12 version: link:../plugin-lib psl: specifier: ^1.9.0 @@ -683,17 +701,17 @@ importers: specifier: ^3.964.0 version: 3.964.0(aws-crt@1.26.2) '@certd/acme-client': - specifier: ^1.39.11 + specifier: ^1.39.12 version: link:../../core/acme-client '@certd/basic': - specifier: ^1.39.11 + specifier: ^1.39.12 version: link:../../core/basic '@certd/pipeline': - specifier: ^1.39.11 + specifier: ^1.39.12 version: link:../../core/pipeline '@certd/plus-core': - specifier: ^1.39.11 - version: 1.39.11 + specifier: ^1.39.12 + version: link:../../pro/plus-core '@kubernetes/client-node': specifier: 0.21.0 version: 0.21.0 @@ -773,6 +791,9 @@ importers: prettier: specifier: ^2.8.8 version: 2.8.8 + ts-node: + specifier: ^10.9.2 + version: 10.9.2(@types/node@25.0.3)(typescript@5.9.3) tslib: specifier: ^2.8.1 version: 2.8.1 @@ -783,16 +804,16 @@ importers: packages/pro/commercial-core: dependencies: '@certd/basic': - specifier: ^1.39.7 + specifier: ^1.39.12 version: link:../../core/basic '@certd/lib-server': - specifier: ^1.39.7 + specifier: ^1.39.12 version: link:../../libs/lib-server '@certd/pipeline': - specifier: ^1.39.7 + specifier: ^1.39.12 version: link:../../core/pipeline '@certd/plus-core': - specifier: ^1.39.7 + specifier: ^1.39.12 version: link:../plus-core '@midwayjs/core': specifier: 3.20.11 @@ -828,6 +849,9 @@ importers: '@types/chai': specifier: ^4.3.3 version: 4.3.20 + '@types/mocha': + specifier: ^10.0.1 + version: 10.0.10 '@types/node': specifier: ^18 version: 18.19.100 @@ -846,6 +870,9 @@ importers: eslint-plugin-prettier: specifier: ^4.2.1 version: 4.2.1(eslint-config-prettier@8.10.0(eslint@8.57.0))(eslint@8.57.0)(prettier@2.8.8) + mocha: + specifier: ^10.2.0 + version: 10.8.2 prettier: specifier: ^2.8.8 version: 2.8.8 @@ -858,6 +885,9 @@ importers: rollup-plugin-visualizer: specifier: ^5.8.2 version: 5.14.0(rollup@3.29.5) + ts-node: + specifier: ^10.9.2 + version: 10.9.2(@types/node@18.19.100)(typescript@5.9.3) tslib: specifier: ^2.8.1 version: 2.8.1 @@ -868,16 +898,16 @@ importers: packages/pro/plugin-plus: dependencies: '@certd/basic': - specifier: ^1.39.7 + specifier: ^1.39.12 version: link:../../core/basic '@certd/pipeline': - specifier: ^1.39.7 + specifier: ^1.39.12 version: link:../../core/pipeline '@certd/plugin-lib': - specifier: ^1.39.7 + specifier: ^1.39.12 version: link:../../plugins/plugin-lib '@certd/plus-core': - specifier: ^1.39.7 + specifier: ^1.39.12 version: link:../plus-core crypto-js: specifier: ^4.2.0 @@ -943,6 +973,9 @@ importers: rollup: specifier: ^3.7.4 version: 3.29.5 + ts-node: + specifier: ^10.9.2 + version: 10.9.2(@types/node@18.19.100)(typescript@5.9.3) tslib: specifier: ^2.8.1 version: 2.8.1 @@ -953,7 +986,7 @@ importers: packages/pro/plus-core: dependencies: '@certd/basic': - specifier: ^1.39.7 + specifier: ^1.39.12 version: link:../../core/basic dayjs: specifier: ^1.11.7 @@ -1007,6 +1040,9 @@ importers: rollup: specifier: ^3.7.4 version: 3.29.5 + ts-node: + specifier: ^10.9.2 + version: 10.9.2(@types/node@18.19.100)(typescript@5.9.3) tslib: specifier: ^2.8.1 version: 2.8.1 @@ -1249,10 +1285,10 @@ importers: version: 0.1.3(zod@3.24.4) devDependencies: '@certd/lib-iframe': - specifier: ^1.39.11 + specifier: ^1.39.12 version: link:../../libs/lib-iframe '@certd/pipeline': - specifier: ^1.39.11 + specifier: ^1.39.12 version: link:../../core/pipeline '@rollup/plugin-commonjs': specifier: ^25.0.7 @@ -1453,47 +1489,47 @@ importers: specifier: ^4.13.1 version: 4.13.1 '@certd/acme-client': - specifier: ^1.39.11 + specifier: ^1.39.12 version: link:../../core/acme-client '@certd/basic': - specifier: ^1.39.11 + specifier: ^1.39.12 version: link:../../core/basic '@certd/commercial-core': - specifier: ^1.39.11 - version: 1.39.11(better-sqlite3@11.10.0)(mysql2@3.14.1)(pg@8.16.0)(reflect-metadata@0.2.2)(ts-node@10.9.2(@types/node@18.19.100)(typescript@5.9.3)) + specifier: ^1.39.12 + version: link:../../pro/commercial-core '@certd/cv4pve-api-javascript': specifier: ^8.4.2 version: 8.4.2 '@certd/jdcloud': - specifier: ^1.39.11 + specifier: ^1.39.12 version: link:../../libs/lib-jdcloud '@certd/lib-huawei': - specifier: ^1.39.11 + specifier: ^1.39.12 version: link:../../libs/lib-huawei '@certd/lib-k8s': - specifier: ^1.39.11 + specifier: ^1.39.12 version: link:../../libs/lib-k8s '@certd/lib-server': - specifier: ^1.39.11 + specifier: ^1.39.12 version: link:../../libs/lib-server '@certd/midway-flyway-js': - specifier: ^1.39.11 + specifier: ^1.39.12 version: link:../../libs/midway-flyway-js '@certd/pipeline': - specifier: ^1.39.11 + specifier: ^1.39.12 version: link:../../core/pipeline '@certd/plugin-cert': - specifier: ^1.39.11 + specifier: ^1.39.12 version: link:../../plugins/plugin-cert '@certd/plugin-lib': - specifier: ^1.39.11 + specifier: ^1.39.12 version: link:../../plugins/plugin-lib '@certd/plugin-plus': - specifier: ^1.39.11 - version: 1.39.11 + specifier: ^1.39.12 + version: link:../../pro/plugin-plus '@certd/plus-core': - specifier: ^1.39.11 - version: 1.39.11 + specifier: ^1.39.12 + version: link:../../pro/plus-core '@google-cloud/dns': specifier: ^5.3.1 version: 5.3.1 @@ -1771,6 +1807,9 @@ importers: prettier: specifier: ^2.8.8 version: 2.8.8 + ts-node: + specifier: ^10.9.2 + version: 10.9.2(@types/node@18.19.100)(typescript@5.9.3) tslib: specifier: ^2.8.1 version: 2.8.1 @@ -2907,18 +2946,9 @@ packages: '@better-scroll/zoom@2.5.1': resolution: {integrity: sha512-aGvFY5ooeZWS4RcxQLD+pGLpQHQxpPy0sMZV3yadcd2QK53PK9gS4Dp+BYfRv8lZ4/P2LoNEhr6Wq1DN6+uPlA==} - '@certd/commercial-core@1.39.11': - resolution: {integrity: sha512-sX0WOF+FflGcx3aeBt1f/meu8plnHqC7UnPivJr9gMx54PRdyTC/zQ5jKvcSTUlivp8xX9Mm2qLmevb5XlN8uQ==} - '@certd/cv4pve-api-javascript@8.4.2': resolution: {integrity: sha512-udGce7ewrVl4DmZvX+17PjsnqsdDIHEDatr8QP0AVrY2p+8JkaSPW4mXCKiLGf82C9K2+GXgT+qNIqgW7tfF9Q==} - '@certd/plugin-plus@1.39.11': - resolution: {integrity: sha512-oi3+0gcyHswI97+cAY7dNXPP66sQga9n98STQYtaDQ5d2LY8dXYpXQl9V1L7IvfAafc1ZAcQLTrfwKA+b9kAZg==} - - '@certd/plus-core@1.39.11': - resolution: {integrity: sha512-DOi7mTUTEK4iFhfLjmxSL7gcF/LMlFguERBPyd7YHI7QBkkufTodLu3l8SuXYwFtp3O883XzlDkcBlnQNAdkwA==} - '@certd/vue-js-cron-core@6.0.3': resolution: {integrity: sha512-kqzoAMhYz9j6FGNWEODRYtt4NpUEUwjpkU89z5WVg2tCtOcI5VhwyUGOd8AxiBCRfd6PtXvzuqw85PaOps9wrQ==} @@ -12562,6 +12592,7 @@ packages: uuid@10.0.0: resolution: {integrity: sha512-8XkAphELsDnEGrDxUOHB3RGvXz6TeuYSGEZBOjtTtPm2lwhGBjLgOzLHB63IUWfBpNucQjND6d3AOudO+H3RWQ==} + deprecated: uuid@10 and below is no longer supported. For ESM codebases, update to uuid@latest. For CommonJS codebases, use uuid@11 (but be aware this version will likely be deprecated in 2028). hasBin: true uuid@11.1.0: @@ -12570,15 +12601,17 @@ packages: uuid@3.4.0: resolution: {integrity: sha512-HjSDRw6gZE5JMggctHBcjVak08+KEVhSIiDzFnT9S9aegmp85S/bReBVTb4QTFaRNptJ9kuYaNhnbNEOkbKb/A==} - deprecated: Please upgrade to version 7 or higher. Older versions may use Math.random() in certain circumstances, which is known to be problematic. See https://v8.dev/blog/math-random for details. + deprecated: uuid@10 and below is no longer supported. For ESM codebases, update to uuid@latest. For CommonJS codebases, use uuid@11 (but be aware this version will likely be deprecated in 2028). hasBin: true uuid@8.3.2: resolution: {integrity: sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg==} + deprecated: uuid@10 and below is no longer supported. For ESM codebases, update to uuid@latest. For CommonJS codebases, use uuid@11 (but be aware this version will likely be deprecated in 2028). hasBin: true uuid@9.0.1: resolution: {integrity: sha512-b+1eJOlsR9K8HJpow9Ok3fiWOWSIcIzXodvv0rQjVoOVNpWMpxf1wZNpt4y9h10odCNrqnYp1OBzRktckBe3sA==} + deprecated: uuid@10 and below is no longer supported. For ESM codebases, update to uuid@latest. For CommonJS codebases, use uuid@11 (but be aware this version will likely be deprecated in 2028). hasBin: true v8-compile-cache-lib@3.0.1: @@ -15464,64 +15497,12 @@ snapshots: dependencies: '@better-scroll/core': 2.5.1 - '@certd/commercial-core@1.39.11(better-sqlite3@11.10.0)(mysql2@3.14.1)(pg@8.16.0)(reflect-metadata@0.2.2)(ts-node@10.9.2(@types/node@18.19.100)(typescript@5.9.3))': - dependencies: - '@certd/basic': link:packages/core/basic - '@certd/lib-server': link:packages/libs/lib-server - '@certd/pipeline': link:packages/core/pipeline - '@certd/plus-core': 1.39.11 - '@midwayjs/core': 3.20.11 - '@midwayjs/koa': 3.20.13 - '@midwayjs/logger': 3.4.2 - '@midwayjs/swagger': 3.20.11 - '@midwayjs/typeorm': 3.20.11 - dayjs: 1.11.13 - typeorm: 0.3.24(better-sqlite3@11.10.0)(mysql2@3.14.1)(pg@8.16.0)(reflect-metadata@0.2.2)(ts-node@10.9.2(@types/node@18.19.100)(typescript@5.9.3)) - transitivePeerDependencies: - - '@google-cloud/spanner' - - '@sap/hana-client' - - babel-plugin-macros - - better-sqlite3 - - hdb-pool - - ioredis - - mongodb - - mssql - - mysql2 - - oracledb - - pg - - pg-native - - pg-query-stream - - redis - - reflect-metadata - - sql.js - - sqlite3 - - supports-color - - ts-node - - typeorm-aurora-data-api-driver - '@certd/cv4pve-api-javascript@8.4.2': dependencies: debug: 4.4.3(supports-color@8.1.1) transitivePeerDependencies: - supports-color - '@certd/plugin-plus@1.39.11': - dependencies: - '@certd/basic': link:packages/core/basic - '@certd/pipeline': link:packages/core/pipeline - '@certd/plugin-lib': link:packages/plugins/plugin-lib - '@certd/plus-core': 1.39.11 - crypto-js: 4.2.0 - dayjs: 1.11.13 - form-data: 4.0.2 - jsrsasign: 11.1.0 - querystring: 0.2.1 - - '@certd/plus-core@1.39.11': - dependencies: - '@certd/basic': link:packages/core/basic - dayjs: 1.11.13 - '@certd/vue-js-cron-core@6.0.3': dependencies: mustache: 4.2.0 @@ -26527,6 +26508,24 @@ snapshots: v8-compile-cache-lib: 3.0.1 yn: 3.1.1 + ts-node@10.9.2(@types/node@25.0.3)(typescript@5.9.3): + dependencies: + '@cspotcode/source-map-support': 0.8.1 + '@tsconfig/node10': 1.0.11 + '@tsconfig/node12': 1.0.11 + '@tsconfig/node14': 1.0.3 + '@tsconfig/node16': 1.0.4 + '@types/node': 25.0.3 + acorn: 8.14.1 + acorn-walk: 8.3.4 + arg: 4.1.3 + create-require: 1.1.1 + diff: 4.0.2 + make-error: 1.3.6 + typescript: 5.9.3 + v8-compile-cache-lib: 3.0.1 + yn: 3.1.1 + tsc-alias@1.8.16: dependencies: chokidar: 3.6.0