mirror of
https://github.com/certd/certd.git
synced 2026-04-24 12:27:25 +08:00
perf: 通知管理
This commit is contained in:
@@ -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>>;
|
||||
@@ -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";
|
||||
|
||||
@@ -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");
|
||||
@@ -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;
|
||||
|
||||
Reference in New Issue
Block a user