Files
certd/packages/core/pipeline/src/plugin/api.ts

209 lines
4.7 KiB
TypeScript
Raw Normal View History

2024-07-15 00:30:33 +08:00
import { Registrable } from "../registry/index.js";
import { FileItem, FormItemProps, Pipeline, Runnable, Step } from "../dt/index.js";
import { FileStore } from "../core/file-store.js";
2023-06-25 23:25:56 +08:00
import { Logger } from "log4js";
2024-07-15 00:30:33 +08:00
import { IAccessService } from "../access/index.js";
import { ICnameProxyService, IEmailService } from "../service/index.js";
2024-09-30 18:00:51 +08:00
import { IContext, PluginRequestHandleReq, RunnableCollection } from "../core/index.js";
2024-09-27 02:15:41 +08:00
import { ILogger, logger, utils } from "../utils/index.js";
2024-10-08 19:02:51 +08:00
import { HttpClient } from "../utils/index.js";
2024-09-19 14:23:15 +08:00
import dayjs from "dayjs";
2024-09-27 02:15:41 +08:00
import _ from "lodash-es";
export type UserInfo = {
role: "admin" | "user";
id: any;
};
2022-10-26 09:02:47 +08:00
export enum ContextScope {
global,
pipeline,
runtime,
}
export type TaskOutputDefine = {
title: string;
value?: any;
2024-09-05 15:36:35 +08:00
type?: string;
2022-10-26 09:02:47 +08:00
};
2023-06-25 23:25:56 +08:00
2022-10-26 09:02:47 +08:00
export type TaskInputDefine = FormItemProps;
export type PluginDefine = Registrable & {
2022-12-27 12:32:09 +08:00
default?: any;
group?: string;
2024-09-19 17:38:51 +08:00
icon?: string;
2023-01-07 23:22:02 +08:00
input?: {
2022-10-26 09:02:47 +08:00
[key: string]: TaskInputDefine;
};
2023-01-07 23:22:02 +08:00
output?: {
2022-10-26 09:02:47 +08:00
[key: string]: TaskOutputDefine;
};
2022-12-27 12:32:09 +08:00
2023-01-07 23:22:02 +08:00
autowire?: {
[key: string]: any;
};
2023-06-25 16:25:23 +08:00
needPlus?: boolean;
2022-10-26 09:02:47 +08:00
};
2023-05-24 15:41:35 +08:00
export type ITaskPlugin = {
2023-05-09 10:16:49 +08:00
onInstance(): Promise<void>;
2022-12-27 12:32:09 +08:00
execute(): Promise<void>;
2024-09-27 02:15:41 +08:00
onRequest(req: PluginRequestHandleReq<any>): Promise<any>;
2023-05-24 15:41:35 +08:00
[key: string]: any;
};
export type TaskResult = {
clearLastStatus?: boolean;
2023-06-25 23:25:56 +08:00
files?: FileItem[];
pipelineVars: Record<string, any>;
2023-05-24 15:41:35 +08:00
};
2023-06-25 23:25:56 +08:00
export type TaskInstanceContext = {
//流水线定义
2023-06-25 23:25:56 +08:00
pipeline: Pipeline;
//步骤定义
2023-06-25 23:25:56 +08:00
step: Step;
//日志
2023-06-25 23:25:56 +08:00
logger: Logger;
//当前步骤输入参数跟上一次执行比较是否有变化
2024-09-09 16:01:42 +08:00
inputChanged: boolean;
//授权获取服务
2023-06-25 23:25:56 +08:00
accessService: IAccessService;
//邮件服务
2023-06-25 23:25:56 +08:00
emailService: IEmailService;
//cname记录服务
cnameProxyService: ICnameProxyService;
//流水线上下文
2023-06-25 23:25:56 +08:00
pipelineContext: IContext;
//用户上下文
2023-06-25 23:25:56 +08:00
userContext: IContext;
//http请求客户端
2024-09-09 16:01:42 +08:00
http: HttpClient;
//文件存储
2023-06-25 23:25:56 +08:00
fileStore: FileStore;
//上一次执行结果状态
2023-06-25 23:25:56 +08:00
lastStatus?: Runnable;
//用户取消信号
signal: AbortSignal;
//工具类
utils: typeof utils;
//用户信息
user: UserInfo;
2023-06-25 23:25:56 +08:00
};
2023-05-24 15:41:35 +08:00
export abstract class AbstractTaskPlugin implements ITaskPlugin {
_result: TaskResult = { clearLastStatus: false, files: [], pipelineVars: {} };
2023-06-25 23:25:56 +08:00
ctx!: TaskInstanceContext;
2024-08-13 20:30:42 +08:00
logger!: ILogger;
accessService!: IAccessService;
2023-05-24 15:41:35 +08:00
clearLastStatus() {
2023-06-25 23:25:56 +08:00
this._result.clearLastStatus = true;
}
getFiles() {
return this._result.files;
}
setCtx(ctx: TaskInstanceContext) {
this.ctx = ctx;
2024-08-13 20:30:42 +08:00
this.logger = ctx.logger;
this.accessService = ctx.accessService;
2023-05-24 15:41:35 +08:00
}
2023-06-25 23:25:56 +08:00
2024-09-27 02:15:41 +08:00
async getAccess(accessId: string) {
if (accessId == null) {
throw new Error("您还没有配置授权");
}
const res = await this.ctx.accessService.getById(accessId);
if (res == null) {
throw new Error("授权不存在,可能已被删除,请前往任务配置里面重新选择授权");
}
return res;
}
2023-06-28 23:15:37 +08:00
randomFileId() {
return Math.random().toString(36).substring(2, 9);
}
2023-06-25 23:25:56 +08:00
saveFile(filename: string, file: Buffer) {
const filePath = this.ctx.fileStore.writeFile(filename, file);
2024-05-30 10:12:48 +08:00
logger.info(`saveFile:${filePath}`);
2024-07-15 00:30:33 +08:00
this._result.files?.push({
2023-06-28 23:15:37 +08:00
id: this.randomFileId(),
2023-06-25 23:25:56 +08:00
filename,
path: filePath,
});
}
2024-07-15 00:30:33 +08:00
extendsFiles() {
if (this._result.files == null) {
this._result.files = [];
}
this._result.files.push(...(this.ctx.lastStatus?.status?.files || []));
}
2023-06-25 23:25:56 +08:00
get pipeline() {
return this.ctx.pipeline;
}
get step() {
return this.ctx.step;
}
2023-05-24 15:41:35 +08:00
async onInstance(): Promise<void> {
return;
}
2023-06-25 23:25:56 +08:00
2023-05-24 15:41:35 +08:00
abstract execute(): Promise<void>;
2024-09-19 14:23:15 +08:00
appendTimeSuffix(name?: string) {
if (name == null) {
name = "certd";
}
return name + "_" + dayjs().format("YYYYMMDDHHmmss");
}
2024-09-27 02:15:41 +08:00
async onRequest(req: PluginRequestHandleReq<any>) {
if (!req.action) {
throw new Error("action is required");
}
2024-09-30 18:00:51 +08:00
let methodName = req.action;
if (!req.action.startsWith("on")) {
methodName = `on${_.upperFirst(req.action)}`;
}
2024-09-27 02:15:41 +08:00
// @ts-ignore
const method = this[methodName];
if (method) {
// @ts-ignore
return await this[methodName](req.data);
}
throw new Error(`action ${req.action} not found`);
}
isAdmin() {
return this.ctx.user.role === "admin";
}
2024-09-30 18:00:51 +08:00
getStepFromPipeline(stepId: string) {
let found: any = null;
RunnableCollection.each(this.ctx.pipeline.stages, (step) => {
if (step.id === stepId) {
found = step;
return;
}
});
return found;
}
getStepIdFromRefInput(ref = ".") {
return ref.split(".")[1];
}
2022-10-26 09:02:47 +08:00
}
export type OutputVO = {
key: string;
title: string;
value: any;
};