perf: 通知管理

This commit is contained in:
xiaojunnuo
2024-11-22 17:12:39 +08:00
parent 131ed13df1
commit d9a00eeaf7
30 changed files with 1031 additions and 30 deletions
+9 -1
View File
@@ -2,7 +2,15 @@ import { Registrable } from "../registry/index.js";
import { FormItemProps } from "../dt/index.js";
import { HttpClient, ILogger, utils } from "@certd/basic";
import * as _ from "lodash-es";
import { AccessRequestHandleReq } from "../core";
import { PluginRequestHandleReq } from "../plugin/index.js";
export type AccessRequestHandleReqInput<T = any> = {
id?: number;
title?: string;
access: T;
};
export type AccessRequestHandleReq<T = any> = PluginRequestHandleReq<AccessRequestHandleReqInput<T>>;
export type AccessInputDefine = FormItemProps & {
title: string;
@@ -1,21 +0,0 @@
import { HttpClient, ILogger, utils } from "@certd/basic";
export type PluginRequestHandleReq<T = any> = {
typeName: string;
action: string;
input: T;
data: any;
};
export type AccessRequestHandleReqInput<T = any> = {
id?: number;
title?: string;
access: T;
};
export type AccessRequestHandleContext = {
http: HttpClient;
logger: ILogger;
utils: typeof utils;
};
export type AccessRequestHandleReq<T = any> = PluginRequestHandleReq<AccessRequestHandleReqInput<T>>;
-1
View File
@@ -3,5 +3,4 @@ export * from "./run-history.js";
export * from "./context.js";
export * from "./storage.js";
export * from "./file-store.js";
export * from "./handler.js";
export * from "./exceptions.js";
+1
View File
@@ -6,3 +6,4 @@ export * from "./plugin/index.js";
export * from "./context/index.js";
export * from "./decorator/index.js";
export * from "./service/index.js";
export * from "./notification/index.js";
@@ -0,0 +1,82 @@
import { PluginRequestHandleReq } from "../plugin";
import { Registrable } from "../registry/index.js";
import { FormItemProps } from "../dt/index.js";
import { HttpClient, ILogger, utils } from "@certd/basic";
import * as _ from "lodash-es";
import { IEmailService } from "../service";
export type NotificationBody = {
userId: number;
title: string;
content: string;
pipelineId: number;
historyId: number;
url: string;
extra?: any;
options?: any;
};
export type NotificationRequestHandleReqInput<T = any> = {
id?: number;
title?: string;
access: T;
};
export type NotificationRequestHandleReq<T = any> = PluginRequestHandleReq<NotificationRequestHandleReqInput<T>>;
export type NotificationInputDefine = FormItemProps & {
title: string;
required?: boolean;
encrypt?: boolean;
};
export type NotificationDefine = Registrable & {
input?: {
[key: string]: NotificationInputDefine;
};
};
export interface INotificationService {
send(body: NotificationBody): Promise<void>;
}
export interface INotification extends INotificationService {
ctx: NotificationContext;
[key: string]: any;
}
export type NotificationContext = {
http: HttpClient;
logger: ILogger;
utils: typeof utils;
emailService: IEmailService;
};
export abstract class BaseNotification implements INotification {
ctx!: NotificationContext;
http!: HttpClient;
logger!: ILogger;
abstract send(body: NotificationBody): Promise<void>;
setCtx(ctx: NotificationContext) {
this.ctx = ctx;
this.http = ctx.http;
this.logger = ctx.logger;
}
async onRequest(req: NotificationRequestHandleReq) {
if (!req.action) {
throw new Error("action is required");
}
let methodName = req.action;
if (!req.action.startsWith("on")) {
methodName = `on${_.upperFirst(req.action)}`;
}
// @ts-ignore
const method = this[methodName];
if (method) {
// @ts-ignore
return await this[methodName](req.data);
}
throw new Error(`action ${req.action} not found`);
}
}
@@ -0,0 +1,61 @@
// src/decorator/memoryCache.decorator.ts
import { Decorator } from "../decorator/index.js";
import * as _ from "lodash-es";
import { notificationRegistry } from "./registry.js";
import { http, logger, utils } from "@certd/basic";
import { NotificationContext, NotificationDefine, NotificationInputDefine } from "./api.js";
// 提供一个唯一 key
export const NOTIFICATION_CLASS_KEY = "pipeline:notification";
export const NOTIFICATION_INPUT_KEY = "pipeline:notification:input";
export function IsNotification(define: NotificationDefine): ClassDecorator {
return (target: any) => {
target = Decorator.target(target);
const inputs: any = {};
const properties = Decorator.getClassProperties(target);
for (const property in properties) {
const input = Reflect.getMetadata(NOTIFICATION_INPUT_KEY, target, property);
if (input) {
inputs[property] = input;
}
}
_.merge(define, { input: inputs });
Reflect.defineMetadata(NOTIFICATION_CLASS_KEY, define, target);
target.define = define;
notificationRegistry.register(define.name, {
define,
target,
});
};
}
export function NotificationInput(input?: NotificationInputDefine): PropertyDecorator {
return (target, propertyKey) => {
target = Decorator.target(target, propertyKey);
// const _type = Reflect.getMetadata("design:type", target, propertyKey);
Reflect.defineMetadata(NOTIFICATION_INPUT_KEY, input, target, propertyKey);
};
}
export function newNotification(type: string, input: any, ctx?: NotificationContext) {
const register = notificationRegistry.get(type);
if (register == null) {
throw new Error(`notification ${type} not found`);
}
// @ts-ignore
const access = new register.target();
for (const key in input) {
access[key] = input[key];
}
if (!ctx) {
ctx = {
http,
logger,
utils,
};
}
access.ctx = ctx;
return access;
}
@@ -0,0 +1,3 @@
export * from "./api.js";
export * from "./registry.js";
export * from "./decorator.js";
@@ -0,0 +1,4 @@
import { createRegistry } from "../registry/index.js";
// @ts-ignore
export const notificationRegistry = createRegistry("notification");
+9 -1
View File
@@ -3,12 +3,20 @@ import { FileItem, FormItemProps, Pipeline, Runnable, Step } from "../dt/index.j
import { FileStore } from "../core/file-store.js";
import { IAccessService } from "../access/index.js";
import { ICnameProxyService, IEmailService } from "../service/index.js";
import { CancelError, IContext, PluginRequestHandleReq, RunnableCollection } from "../core/index.js";
import { CancelError, IContext, RunnableCollection } from "../core/index.js";
import { HttpRequestConfig, ILogger, logger, utils } from "@certd/basic";
import { HttpClient } from "@certd/basic";
import dayjs from "dayjs";
import { IPluginConfigService } from "../service/config";
import { upperFirst } from "lodash-es";
export type PluginRequestHandleReq<T = any> = {
typeName: string;
action: string;
input: T;
data: any;
};
export type UserInfo = {
role: "admin" | "user";
id: any;