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

View File

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

View File

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

View File

@ -198,6 +198,8 @@ export const agents: any;
* Logger * 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 function walkTxtRecord(record: any): Promise<string[]>;
export const CancelError: Error;

View File

@ -1,4 +1,5 @@
export * from './util.request.js'; export * from './util.request.js';
export * from './util.env.js';
export * from './util.log.js'; export * from './util.log.js';
export * from './util.file.js'; export * from './util.file.js';
export * from './util.sp.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); this.runtime.success(runnable);
return ResultType.success; return ResultType.success;
} catch (e: any) { } 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; throw e;
} finally { } finally {
this.runtime.finally(runnable); this.runtime.finally(runnable);

View File

@ -5,3 +5,4 @@ export * from "./storage.js";
export * from "./file-store.js"; export * from "./file-store.js";
export * from "./license.js"; export * from "./license.js";
export * from "./handler.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 { Logger } from "log4js";
import { IAccessService } from "../access/index.js"; import { IAccessService } from "../access/index.js";
import { ICnameProxyService, IEmailService } from "../service/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 { ILogger, logger, utils } from "../utils/index.js";
import { HttpClient } from "../utils/index.js"; import { HttpClient } from "../utils/index.js";
import dayjs from "dayjs"; import dayjs from "dayjs";
@ -113,7 +113,7 @@ export abstract class AbstractTaskPlugin implements ITaskPlugin {
checkSignal() { checkSignal() {
if (this.ctx.signal && this.ctx.signal.aborted) { 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 = { export type Registrable = {
name: string; name: string;

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -1,7 +1,7 @@
<template> <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> <template #dot>
<fs-icon v-bind="status" /> <fs-icon v-bind="status" :color="status.iconColor || status.color" />
</template> </template>
<p> <p>
<fs-date-format :model-value="runnable.status?.startTime"></fs-date-format> <fs-date-format :model-value="runnable.status?.startTime"></fs-date-format>

View File

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

View File

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

View File

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