pull/243/head
xiaojunnuo 2024-11-01 02:13:34 +08:00
parent 5160b9fbd6
commit dc9040a68e
25 changed files with 65 additions and 279 deletions

View File

@ -5,6 +5,7 @@
const { readCsrDomains } = require('./crypto');
const { log } = require('./logger');
const { wait } = require('./wait');
const { CancelError } = require('./error');
const defaultOpts = {
csr: null,
@ -250,7 +251,7 @@ module.exports = async (client, userOpts) => {
i += 1;
log(`开始第${i}`);
if (opts.signal && opts.signal.aborted) {
throw new Error('用户取消');
throw new CancelError('用户取消');
}
try {

View File

@ -12,6 +12,7 @@ const AcmeApi = require('./api');
const verify = require('./verify');
const util = require('./util');
const auto = require('./auto');
const { CancelError } = require('./error');
/**
* ACME states
@ -490,9 +491,10 @@ class AcmeClient {
const keyAuthorization = await this.getChallengeKeyAuthorization(challenge);
const verifyFn = async () => {
const verifyFn = async (abort) => {
if (this.opts.signal && this.opts.signal.aborted) {
throw new Error('用户取消');
abort();
throw new CancelError('用户取消');
}
await verify[challenge.type](authz, challenge, keyAuthorization);
};
@ -518,7 +520,7 @@ class AcmeClient {
async completeChallenge(challenge) {
if (this.opts.signal && this.opts.signal.aborted) {
throw new Error('用户取消');
throw new CancelError('用户取消');
}
const resp = await this.api.completeChallenge(challenge.url, {});
return resp.data;
@ -559,7 +561,7 @@ class AcmeClient {
const verifyFn = async (abort) => {
if (this.opts.signal && this.opts.signal.aborted) {
abort();
throw new Error('用户取消');
throw new CancelError('用户取消');
}
const resp = await this.api.apiRequest(item.url, null, [200]);

View File

@ -0,0 +1,10 @@
class CancelError extends Error {
constructor(message) {
super(message);
this.name = 'CancelError';
}
}
module.exports = {
CancelError,
};

View File

@ -48,3 +48,4 @@ exports.agents = require('./agents');
exports.setLogger = require('./logger').setLogger;
exports.walkTxtRecord = require('./verify').walkTxtRecord;
exports.CancelError = require('./error').CancelError;

View File

@ -5,5 +5,5 @@ async function wait(ms) {
}
module.exports = {
wait
wait,
};

View File

@ -198,6 +198,8 @@ export const agents: any;
* Logger
*/
export function setLogger(fn: (msg: string) => void): void;
export function setLogger(fn: (...msg: any) => void): void;
export function walkTxtRecord(record: any): Promise<string[]>;
export const CancelError: Error;

View File

@ -1,4 +1,5 @@
export * from './util.request.js';
export * from './util.env.js';
export * from './util.log.js';
export * from './util.file.js';
export * from './util.sp.js';

View File

@ -0,0 +1,3 @@
export function isDev() {
return process.env.NODE_ENV === 'development' || process.env.NODE_ENV === 'local';
}

View File

@ -0,0 +1,5 @@
export class CancelError extends Error {
constructor(message: string) {
super(message);
}
}

View File

@ -135,7 +135,12 @@ export class Executor {
this.runtime.success(runnable);
return ResultType.success;
} catch (e: any) {
this.runtime.error(runnable, e);
if (e.name === "CancelError" || this.abort.signal.aborted) {
this.runtime.cancel(runnable);
return ResultType.canceled;
} else {
this.runtime.error(runnable, e);
}
throw e;
} finally {
this.runtime.finally(runnable);

View File

@ -5,3 +5,4 @@ export * from "./storage.js";
export * from "./file-store.js";
export * from "./license.js";
export * from "./handler.js";
export * from "./exceptions.js";

View File

@ -1,115 +0,0 @@
/**
* [x]-col
*/
export type ColProps = {
span?: number;
[props: string]: any;
};
export type FormItemProps = {
/**
* label
*/
title?: string;
/**
*
*/
component?: ComponentProps;
/**
* [a|el|n]-col
* {span:24}
*/
col?: ColProps;
/**
*
*/
value?: any;
/**
*
*/
helper?: string | FormItemHelperProps;
/**
*
*/
order?: number;
/**
*
*/
show?: boolean;
/**
*
*/
blank?: boolean;
[key: string]: any;
};
/**
*
*/
export type FormItemHelperProps = {
/**
*
* @param scope
*/
render?: (scope: any) => any;
/**
*
*/
text?: string;
/**
* [ undefined | label]
*/
position?: string;
/**
* [a|el|n]-tooltip
*/
tooltip?: object;
[key: string]: any;
};
/**
*
*/
export type ComponentProps = {
/**
*
*/
name?: string | object;
/**
* vmodel
*/
vModel?: string;
/**
*
* :name
* ```
* component:{
* name:"组件的名称"
* props:{
* name:"组件的name属性" <-----------
* }
* }
* ```
*/
props?: {
[key: string]: any;
};
/**
*
*/
on?: {
[key: string]: (context?: any) => void;
};
/**
*
* onXxx:(event)=>void
* on.onXxx:(context)=>void ()
* styleclass
*/
[key: string]: any;
};

View File

@ -1,2 +0,0 @@
export * from "./pipeline";
export * from "./fast-crud";

View File

@ -1,140 +0,0 @@
export enum RunStrategy {
AlwaysRun,
SkipWhenSucceed,
}
export enum ConcurrencyStrategy {
Serial,
Parallel,
}
export enum NextStrategy {
AllSuccess,
OneSuccess,
}
export enum HandlerType {
//清空后续任务的状态
ClearFollowStatus,
SendEmail,
}
export type EventHandler = {
type: HandlerType;
params: {
[key: string]: any;
};
};
export type RunnableStrategy = {
runStrategy?: RunStrategy;
onSuccess?: EventHandler[];
onError?: EventHandler[];
};
export type Step = Runnable & {
type: string; //插件类型
input: {
[key: string]: any;
};
};
export type Task = Runnable & {
steps: Step[];
};
export type Stage = Runnable & {
tasks: Task[];
concurrency: ConcurrencyStrategy;
next: NextStrategy;
};
export type Trigger = {
id: string;
title: string;
cron: string;
type: string;
};
export type FileItem = {
id: string;
filename: string;
path: string;
};
export type Runnable = {
id: string;
title: string;
strategy?: RunnableStrategy;
runnableType?: string; // pipeline, stage, task , step
status?: HistoryResult;
timeout?: number;
default?: {
[key: string]: any;
};
context?: Context;
};
export type EmailOptions = {
receivers: string[];
};
export type NotificationWhen = "error" | "success" | "turnToSuccess" | "start";
export type NotificationType = "email" | "url";
export type Notification = {
type: NotificationType;
when: NotificationWhen[];
options: EmailOptions;
};
export type Pipeline = Runnable & {
version?: number;
userId: any;
stages: Stage[];
triggers: Trigger[];
notifications?: Notification[];
};
export type Context = {
[key: string]: any;
};
export type Log = {
title: string;
time: number;
level: string;
text: string;
};
export enum ResultType {
start = "start",
success = "success",
error = "error",
canceled = "canceled",
skip = "skip",
none = "none",
}
export type HistoryResultGroup = {
[key: string]: {
runnable: Runnable;
res: HistoryResult;
};
};
export type HistoryResult = {
input: any;
output: any;
files?: FileItem[];
/**
*
*/
status: ResultType;
startTime: number;
endTime?: number;
/**
*
*/
result?: ResultType; //success, error,skip
message?: string;
};
export type RunnableMap = {
[id: string]: Runnable;
};

View File

@ -4,7 +4,7 @@ import { FileStore } from "../core/file-store.js";
import { Logger } from "log4js";
import { IAccessService } from "../access/index.js";
import { ICnameProxyService, IEmailService } from "../service/index.js";
import { IContext, PluginRequestHandleReq, RunnableCollection } from "../core/index.js";
import { CancelError, IContext, PluginRequestHandleReq, RunnableCollection } from "../core/index.js";
import { ILogger, logger, utils } from "../utils/index.js";
import { HttpClient } from "../utils/index.js";
import dayjs from "dayjs";
@ -113,7 +113,7 @@ export abstract class AbstractTaskPlugin implements ITaskPlugin {
checkSignal() {
if (this.ctx.signal && this.ctx.signal.aborted) {
throw new Error("用户取消");
throw new CancelError("用户取消");
}
}

View File

@ -1,4 +1,4 @@
import { logger } from "../utils/index.js";
import { isDev, logger } from "../utils/index.js";
export type Registrable = {
name: string;

View File

@ -60,8 +60,8 @@ export class AcmeService {
this.sslProvider = options.sslProvider || "letsencrypt";
this.eab = options.eab;
this.skipLocalVerify = options.skipLocalVerify ?? false;
acme.setLogger((text: string) => {
this.logger.info(text);
acme.setLogger((...text: any) => {
this.logger.info(...text);
});
}

View File

@ -7,6 +7,7 @@ import { CertReader } from "./cert-reader.js";
import { CertApplyBasePlugin } from "./base.js";
import { GoogleClient } from "../../libs/google.js";
import { EabAccess } from "../../access";
import { CancelError } from "@certd/pipeline";
export type { CertInfo };
export * from "./cert-reader.js";
@ -293,6 +294,7 @@ export class CertApplyPlugin extends CertApplyBasePlugin {
useMappingProxy: this.useProxy,
reverseProxy: this.reverseProxy,
privateKeyType: this.privateKeyType,
signal: this.ctx.signal,
// cnameProxyService: this.ctx.cnameProxyService,
// dnsProviderCreator: this.createDnsProvider.bind(this),
});
@ -347,6 +349,9 @@ export class CertApplyPlugin extends CertApplyBasePlugin {
this.logger.error(e);
throw new Error(`通配符域名已经包含了普通域名,请删除其中一个(${message}`);
}
if (e.name === "CancelError") {
throw new CancelError(e.message);
}
throw e;
}
}

View File

@ -29,3 +29,11 @@
.fs-form-wrapper .fs-form-header {
padding-right: 30px !important;
}
.fs-values-format .fs-tag{
display: inline-flex;
.fs-icon{
margin-right: 3px;
}
}

View File

@ -1,6 +1,6 @@
<template>
<a-button class="cd-secret-plain-getter ml-5">
<fs-icon class="pointer" :icon="computedIcon" @click="showPlain" />
<a-button class="cd-secret-plain-getter ml-5" @click="showPlain">
<fs-icon class="pointer" :icon="computedIcon" />
</a-button>
</template>
<script lang="ts" setup>

View File

@ -14,7 +14,7 @@
</template>
</a-list-item-meta>
<div>
<a-textarea :value="item.content" rows="5" />
<a-textarea :value="item.content" :rows="5" />
</div>
</a-list-item>
</template>

View File

@ -1,7 +1,7 @@
<template>
<a-timeline-item v-if="status && runnable" class="pi-history-timeline-item" :color="status.color">
<a-timeline-item v-if="status && runnable" class="pi-history-timeline-item" :color="status.iconColor || status.color">
<template #dot>
<fs-icon v-bind="status" />
<fs-icon v-bind="status" :color="status.iconColor || status.color" />
</template>
<p>
<fs-date-format :model-value="runnable.status?.startTime"></fs-date-format>

View File

@ -1,7 +1,7 @@
<template>
<span v-if="statusRef" class="pi-status-show flex-o">
<template v-if="type === 'icon'">
<fs-icon class="status-icon" v-bind="statusRef" :style="{ color: statusRef.color }" />
<fs-icon class="status-icon" v-bind="statusRef" :style="{ color: statusRef.iconColor || statusRef.color }" />
</template>
<template v-if="type === 'tag'">
<a-tag :color="statusRef.color">{{ statusRef.label }}</a-tag>

View File

@ -42,6 +42,7 @@ const StatusEnum: StatusEnumType = {
value: "canceled",
label: "已取消",
color: "yellow",
iconColor: "#d4b106",
icon: "ant-design:minus-circle-twotone"
},
none: {

View File

@ -1,3 +1 @@
export function isDev() {
return process.env.NODE_ENV === 'development' || process.env.NODE_ENV === 'local';
}
export { isDev } from '@certd/pipeline';