diff --git a/packages/core/pipeline/package.json b/packages/core/pipeline/package.json index 09247574..63b9a88c 100644 --- a/packages/core/pipeline/package.json +++ b/packages/core/pipeline/package.json @@ -17,7 +17,8 @@ "lodash": "^4.17.21", "log4js": "^6.3.0", "node-forge": "^0.10.0", - "qs": "^6.9.4" + "qs": "^6.9.4", + "reflect-metadata": "^0.1.13" }, "devDependencies": { "@alicloud/cs20151215": "^3.0.3", diff --git a/packages/core/pipeline/src/access/api.ts b/packages/core/pipeline/src/access/api.ts index 4dd01933..905d2d91 100644 --- a/packages/core/pipeline/src/access/api.ts +++ b/packages/core/pipeline/src/access/api.ts @@ -13,3 +13,6 @@ export type AccessDefine = Registrable & { export interface IAccessService { getById(id: any): Promise; } + +// eslint-disable-next-line @typescript-eslint/no-empty-interface +export interface IAccess {} diff --git a/packages/core/pipeline/src/access/decorator.ts b/packages/core/pipeline/src/access/decorator.ts index 73c38893..10e1975d 100644 --- a/packages/core/pipeline/src/access/decorator.ts +++ b/packages/core/pipeline/src/access/decorator.ts @@ -1,71 +1,39 @@ // src/decorator/memoryCache.decorator.ts -import { - attachClassMetadata, - attachPropertyDataToClass, - getClassMetadata, - listModule, - listPropertyDataFromClass, - saveClassMetadata, - saveModule, -} from "@midwayjs/decorator"; import { AccessDefine, AccessInputDefine } from "./api"; +import { Decorator } from "../decorator"; import _ from "lodash"; import { accessRegistry } from "./registry"; // 提供一个唯一 key -export const ACCESS_CLASS_KEY = "decorator:access"; +export const ACCESS_CLASS_KEY = "pipeline:access"; +export const ACCESS_INPUT_KEY = "pipeline:access:input"; export function IsAccess(define: AccessDefine): ClassDecorator { - console.log("is access define:", define); return (target: any) => { - console.log("is access load:", target); - // 将装饰的类,绑定到该装饰器,用于后续能获取到 class - saveModule(ACCESS_CLASS_KEY, target); - // 保存一些元数据信息,任意你希望存的东西 - saveClassMetadata( - ACCESS_CLASS_KEY, - { - define, - }, - target - ); + target = Decorator.target(target); + + const inputs: any = {}; + const properties = Decorator.getClassProperties(target); + for (const property in properties) { + const input = Reflect.getMetadata(ACCESS_INPUT_KEY, target, property); + if (input) { + inputs[property] = input; + } + } + _.merge(define, { inputs }); + Reflect.defineMetadata(ACCESS_CLASS_KEY, define, target); + target.define = define; + accessRegistry.register(define.name, { + define, + target, + }); }; } -export const ACCESS_INPUT_KEY = "decorator:access:input"; - export function IsAccessInput(input?: AccessInputDefine): PropertyDecorator { return (target, propertyKey) => { - attachPropertyDataToClass(ACCESS_INPUT_KEY, { input }, target, propertyKey, propertyKey as string); - - attachClassMetadata( - ACCESS_CLASS_KEY, - { - inputs: { - [propertyKey]: input, - }, - }, - target - ); + target = Decorator.target(target); + // const _type = Reflect.getMetadata("design:type", target, propertyKey); + Reflect.defineMetadata(ACCESS_INPUT_KEY, input, target, propertyKey); }; } - -export function registerAccess() { - const modules = listModule(ACCESS_CLASS_KEY); - for (const mod of modules) { - console.log("mod", mod); - const define = getClassMetadata(ACCESS_CLASS_KEY, mod); - console.log("define", define); - const inputs = listPropertyDataFromClass(ACCESS_INPUT_KEY, mod); - console.log("inputs", inputs); - for (const input of inputs) { - define.inputs = {}; - _.merge(define.inputs, input.inputs); - } - - accessRegistry.register(define.name, { - define, - target: mod, - }); - } -} diff --git a/packages/core/pipeline/src/core/executor.ts b/packages/core/pipeline/src/core/executor.ts index 1cf1fbae..fa82dd5b 100644 --- a/packages/core/pipeline/src/core/executor.ts +++ b/packages/core/pipeline/src/core/executor.ts @@ -149,7 +149,7 @@ export class Executor { // @ts-ignore const define: PluginDefine = plugin.define; //从outputContext读取输入参数 - _.forEach(define.inputs, (item, key) => { + _.forEach(define.input, (item, key) => { if (item.component?.name === "pi-output-selector") { const contextKey = step.input[key]; if (contextKey != null) { @@ -164,12 +164,12 @@ export class Executor { instance[key] = context[key]; }); - const res = await instance.execute(); + await instance.execute(); //输出到output context - _.forEach(define.outputs, (item, key) => { + _.forEach(define.output, (item, key) => { const contextKey = `step.${step.id}.${key}`; - this.runtime.context[contextKey] = res[key]; + this.runtime.context[contextKey] = instance[key]; }); } } diff --git a/packages/core/pipeline/src/decorator/index.ts b/packages/core/pipeline/src/decorator/index.ts new file mode 100644 index 00000000..5947df5b --- /dev/null +++ b/packages/core/pipeline/src/decorator/index.ts @@ -0,0 +1,28 @@ +const propertyMap: any = {}; +function attachProperty(target: any, propertyKey: string | symbol) { + let props = propertyMap[target]; + if (props == null) { + props = {}; + propertyMap[target] = props; + } + props[propertyKey] = true; +} + +function getClassProperties(target: any) { + return propertyMap[target] || {}; +} + +function target(target: any, propertyKey?: string | symbol) { + if (typeof target === "object" && target.constructor) { + target = target.constructor; + } + if (propertyKey != null) { + attachProperty(target, propertyKey); + } + return target; +} +export const Decorator = { + target, + attachProperty, + getClassProperties, +}; diff --git a/packages/core/pipeline/src/dns-provider/decorator.ts b/packages/core/pipeline/src/dns-provider/decorator.ts index 9a24f1c5..1b1a1c54 100644 --- a/packages/core/pipeline/src/dns-provider/decorator.ts +++ b/packages/core/pipeline/src/dns-provider/decorator.ts @@ -1,42 +1,20 @@ // src/decorator/memoryCache.decorator.ts -import { getClassMetadata, listModule, Provide, saveClassMetadata, saveModule, Scope, ScopeEnum } from "@midwayjs/decorator"; import { dnsProviderRegistry } from "./registry"; import { DnsProviderDefine } from "./api"; +import { Decorator } from "../decorator"; // 提供一个唯一 key -export const DNS_PROVIDER_CLASS_KEY = "decorator:dnsProvider"; +export const DNS_PROVIDER_CLASS_KEY = "pipeline:dns-provider"; export function IsDnsProvider(define: DnsProviderDefine): ClassDecorator { - console.log("is task plugin define:", define); return (target: any) => { - console.log("is task plugin load:", target); - // 将装饰的类,绑定到该装饰器,用于后续能获取到 class - saveModule(DNS_PROVIDER_CLASS_KEY, target); - // 保存一些元数据信息,任意你希望存的东西 - saveClassMetadata( - DNS_PROVIDER_CLASS_KEY, - { - define, - }, - target - ); - // 指定 IoC 容器创建实例的作用域,这里注册为请求作用域,这样能取到 ctx - Scope(ScopeEnum.Prototype)(target); + target = Decorator.target(target); + Reflect.defineMetadata(DNS_PROVIDER_CLASS_KEY, define, target); - // 调用一下 Provide 装饰器,这样用户的 class 可以省略写 @Provide() 装饰器了 - Provide()(target); - }; -} - -export function registerDnsProviders() { - const modules = listModule(DNS_PROVIDER_CLASS_KEY); - for (const mod of modules) { - console.log("mod", mod); - const define = getClassMetadata(DNS_PROVIDER_CLASS_KEY, mod); - console.log("define", define); + target.define = define; dnsProviderRegistry.register(define.name, { define, - target: mod, + target, }); - } + }; } diff --git a/packages/core/pipeline/src/midway/configuration.ts b/packages/core/pipeline/src/midway/configuration.ts index dee5c5a8..ab94ab88 100644 --- a/packages/core/pipeline/src/midway/configuration.ts +++ b/packages/core/pipeline/src/midway/configuration.ts @@ -2,9 +2,6 @@ import { Config, Configuration, Inject, Logger } from "@midwayjs/decorator"; // @ts-ignore import { ILogger } from "@midwayjs/logger"; import { IMidwayContainer, MidwayDecoratorService } from "@midwayjs/core"; -import { registerPlugins } from "../plugin/decorator"; -import { registerAccess } from "../access/decorator"; -import { registerDnsProviders } from "../dns-provider"; // ... (see below) ... @Configuration({ @@ -26,9 +23,6 @@ export class PipelineConfiguration { async onReady(container: IMidwayContainer) { this.logger.info("pipeline install"); - registerPlugins(); - registerAccess(); - registerDnsProviders(); //this.implPropertyDecorator(container); this.logger.info("pipeline installed"); } diff --git a/packages/core/pipeline/src/plugin/api.ts b/packages/core/pipeline/src/plugin/api.ts index 58b1a5c1..2f8ce8fc 100644 --- a/packages/core/pipeline/src/plugin/api.ts +++ b/packages/core/pipeline/src/plugin/api.ts @@ -21,14 +21,16 @@ export type TaskInputDefine = FormItemProps; export type PluginDefine = Registrable & { default?: any; - inputs?: { + input?: { [key: string]: TaskInputDefine; }; - outputs?: { + output?: { [key: string]: TaskOutputDefine; }; - autowire?: any; + autowire?: { + [key: string]: any; + }; }; export interface ITaskPlugin { diff --git a/packages/core/pipeline/src/plugin/decorator.ts b/packages/core/pipeline/src/plugin/decorator.ts index e40be5ca..265a834f 100644 --- a/packages/core/pipeline/src/plugin/decorator.ts +++ b/packages/core/pipeline/src/plugin/decorator.ts @@ -1,136 +1,77 @@ -import { - attachClassMetadata, - attachPropertyDataToClass, - getClassMetadata, - listModule, - listPropertyDataFromClass, - saveClassMetadata, - saveModule, -} from "@midwayjs/decorator"; import _ from "lodash"; import { pluginRegistry } from "./registry"; import { PluginDefine, TaskInputDefine, TaskOutputDefine } from "./api"; +import { Decorator } from "../decorator"; // 提供一个唯一 key -export const PLUGIN_CLASS_KEY = "decorator:plugin"; +export const PLUGIN_CLASS_KEY = "pipeline:plugin"; export function IsTaskPlugin(define: PluginDefine): ClassDecorator { - console.log("is task plugin define:", define); return (target: any) => { - console.log("is task plugin load:", target); - // 将装饰的类,绑定到该装饰器,用于后续能获取到 class - saveModule(PLUGIN_CLASS_KEY, target); - // 保存一些元数据信息,任意你希望存的东西 - saveClassMetadata( - PLUGIN_CLASS_KEY, - { - define, - }, - target - ); - // // 指定 IoC 容器创建实例的作用域,这里注册为请求作用域,这样能取到 ctx - // Scope(ScopeEnum.Prototype)(target); + target = Decorator.target(target); - // 调用一下 Provide 装饰器,这样用户的 class 可以省略写 @Provide() 装饰器了 - // Provide()(target); + const inputs: any = {}; + const autowires: any = {}; + const outputs: any = {}; + const properties = Decorator.getClassProperties(target); + for (const property in properties) { + const input = Reflect.getMetadata(PLUGIN_INPUT_KEY, target, property); + if (input) { + inputs[property] = input; + } + + const autowire = Reflect.getMetadata(PLUGIN_AUTOWIRE_KEY, target, property); + if (autowire) { + autowires[property] = autowire; + } + + const output = Reflect.getMetadata(PLUGIN_OUTPUT_KEY, target, property); + if (output) { + outputs[property] = output; + } + } + _.merge(define, { input: inputs, autowire: autowires, output: outputs }); + + Reflect.defineMetadata(PLUGIN_CLASS_KEY, define, target); + + target.define = define; + pluginRegistry.register(define.name, { + define, + target, + }); }; } -export const PLUGIN_INPUT_KEY = "decorator:plugin:input"; +export const PLUGIN_INPUT_KEY = "pipeline:plugin:input"; export function TaskInput(input?: TaskInputDefine): PropertyDecorator { return (target, propertyKey) => { - attachPropertyDataToClass(PLUGIN_INPUT_KEY, { input }, target, propertyKey, propertyKey as string); - - attachClassMetadata( - PLUGIN_CLASS_KEY, - { - inputs: { - [propertyKey]: input, - }, - }, - target - ); + target = Decorator.target(target, propertyKey); + Reflect.defineMetadata(PLUGIN_INPUT_KEY, input, target, propertyKey); }; - // - // return createCustomPropertyDecorator(CLASS_PROPS_KEY, { - // input, - // }); } // 装饰器内部的唯一 id -export const PLUGIN_OUTPUT_KEY = "decorator:plugin:output"; +export const PLUGIN_OUTPUT_KEY = "pipeline:plugin:output"; export function TaskOutput(output?: TaskOutputDefine): PropertyDecorator { return (target, propertyKey) => { - attachPropertyDataToClass(PLUGIN_OUTPUT_KEY, { output }, target, propertyKey, propertyKey as string); - - attachClassMetadata( - PLUGIN_CLASS_KEY, - { - outputs: { - [propertyKey]: output, - }, - }, - target - ); + target = Decorator.target(target, propertyKey); + Reflect.defineMetadata(PLUGIN_OUTPUT_KEY, output, target, propertyKey); }; - // - // return createCustomPropertyDecorator(CLASS_PROPS_KEY, { - // input, - // }); } export type AutowireProp = { name?: string; + type?: any; }; -export const PLUGIN_AUTOWIRE_KEY = "decorator:plugin:autowire"; +export const PLUGIN_AUTOWIRE_KEY = "pipeline:plugin:autowire"; export function Autowire(props?: AutowireProp): PropertyDecorator { return (target, propertyKey) => { - attachPropertyDataToClass( - PLUGIN_AUTOWIRE_KEY, - { - autowire: { - [propertyKey]: props, - }, - }, - target, - propertyKey, - propertyKey as string - ); + const _type = Reflect.getMetadata("design:type", target, propertyKey); + target = Decorator.target(target, propertyKey); + props = props || {}; + props.type = _type; + Reflect.defineMetadata(PLUGIN_AUTOWIRE_KEY, props || {}, target, propertyKey); }; } - -export function registerPlugins() { - const modules = listModule(PLUGIN_CLASS_KEY); - for (const mod of modules) { - console.log("mod", mod); - const define: PluginDefine = getClassMetadata(PLUGIN_CLASS_KEY, mod); - console.log("define", define); - const inputs = listPropertyDataFromClass(PLUGIN_INPUT_KEY, mod); - console.log("inputs", inputs); - for (const input of inputs) { - define.inputs = {}; - _.merge(define.inputs, input.inputs); - } - - const outputs = listPropertyDataFromClass(PLUGIN_OUTPUT_KEY, mod); - console.log("outputs", outputs); - for (const output of outputs) { - define.outputs = {}; - _.merge(define.outputs, output.outputs); - } - - const autowire = listPropertyDataFromClass(PLUGIN_AUTOWIRE_KEY, mod); - console.log("autowire", autowire); - for (const auto of autowire) { - define.autowire = {}; - _.merge(define.autowire, auto.autowire); - } - - pluginRegistry.register(define.name, { - define, - target: mod, - }); - } -} diff --git a/packages/core/pipeline/test/echo-plugin.ts b/packages/core/pipeline/test/echo-plugin.ts index f24b82b9..b169316e 100644 --- a/packages/core/pipeline/test/echo-plugin.ts +++ b/packages/core/pipeline/test/echo-plugin.ts @@ -1,26 +1,30 @@ -import { AbstractPlugin, IsTask, TaskInput, TaskOutput, TaskPlugin } from "../src"; +import { IsTaskPlugin, TaskInput, ITaskPlugin, LOGGER, Autowire, TaskOutput } from "../src"; -@IsTask(() => { - return { - name: "EchoPlugin", - title: "测试插件【echo】", - input: { - cert: { - title: "cert", - component: { - name: "pi-output-selector", - }, - helper: "输出选择", - }, - }, - output: {}, - }; +@IsTaskPlugin({ + name: "EchoPlugin", + title: "测试插件【echo】", }) -export class EchoPlugin extends AbstractPlugin implements TaskPlugin { - async execute(input: TaskInput): Promise { - for (const key in input) { - this.logger.info("input :", key, input[key]); - } - return input; +export class EchoPlugin implements ITaskPlugin { + @TaskInput({ + title: "cert", + component: { + name: "pi-output-selector", + }, + helper: "输出选择", + }) + cert!: any; + + @Autowire() + logger!: LOGGER; + + @TaskOutput({ + title: "cert info", + }) + certInfo!: any; + + // eslint-disable-next-line @typescript-eslint/no-empty-function + async onInit(): Promise {} + async execute(): Promise { + console.log("input :cert", this.cert); } } diff --git a/packages/core/pipeline/test/index.test.ts b/packages/core/pipeline/test/index.test.ts index e44a6e60..e0584584 100644 --- a/packages/core/pipeline/test/index.test.ts +++ b/packages/core/pipeline/test/index.test.ts @@ -3,10 +3,14 @@ import "mocha"; import { EchoPlugin } from "./echo-plugin"; describe("task_plugin", function () { it("#taskplugin", function () { + console.log("before new plugin"); const echoPlugin = new EchoPlugin(); + console.log("before set property", echoPlugin); + echoPlugin.cert = { test: 1 }; + console.log("before execute"); // @ts-ignore - const define = echoPlugin.getDefine(); - echoPlugin.execute({ context: {}, input: { test: 111 } }); - expect(define.name).eq("EchoPlugin"); + echoPlugin.execute(); + console.log("after execute"); + expect(echoPlugin.cert).eq("EchoPlugin"); }); }); diff --git a/packages/core/pipeline/test/pipeline/access-service-test.ts b/packages/core/pipeline/test/pipeline/access-service-test.ts index bb55a964..8a293e30 100644 --- a/packages/core/pipeline/test/pipeline/access-service-test.ts +++ b/packages/core/pipeline/test/pipeline/access-service-test.ts @@ -1,7 +1,7 @@ -import { AbstractAccess, IAccessService } from "../../src"; +import { IAccess, IAccessService } from "../../src"; import { aliyunSecret } from "../user.secret"; export class AccessServiceTest implements IAccessService { - async getById(id: any): Promise { + async getById(id: any): Promise { return { ...aliyunSecret, } as any; diff --git a/packages/core/pipeline/tsconfig.json b/packages/core/pipeline/tsconfig.json index 62621e72..528911f6 100644 --- a/packages/core/pipeline/tsconfig.json +++ b/packages/core/pipeline/tsconfig.json @@ -12,7 +12,8 @@ "esModuleInterop": true, "lib": ["ESNext", "DOM"], "skipLibCheck": true, - "experimentalDecorators": true + "experimentalDecorators": true, + "emitDecoratorMetadata": true }, "include": ["src/**/*.ts", "src/**/*.d.ts", "src/**/*.tsx", "src/**/*.vue","test/**/*.ts"], } diff --git a/packages/server/certd-client b/packages/server/certd-client index 08f08022..b7422ab4 160000 --- a/packages/server/certd-client +++ b/packages/server/certd-client @@ -1 +1 @@ -Subproject commit 08f08022903aed6ba5150a80ea3484a8bc1830b7 +Subproject commit b7422ab48ef81f5c98129bacb69d0eefdfe50645 diff --git a/packages/server/certd-server b/packages/server/certd-server index 70f3fd53..5901fb5a 160000 --- a/packages/server/certd-server +++ b/packages/server/certd-server @@ -1 +1 @@ -Subproject commit 70f3fd5359ac27b6dbd452f30fbf6630d4c9fa26 +Subproject commit 5901fb5a440a7cebe3a2b6dfaec1b014e30b3a0c diff --git a/pnpm-workspace.yaml b/pnpm-workspace.yaml deleted file mode 100644 index 6936a0e0..00000000 --- a/pnpm-workspace.yaml +++ /dev/null @@ -1,6 +0,0 @@ -packages: - # all packages in direct subdirs of packages/ - - 'packages/*/*' - # exclude packages that are inside test directories - - '!**/test/**' - - '!packages/ui/*' \ No newline at end of file