mirror of https://github.com/certd/certd
chore: 1
parent
5160b9fbd6
commit
dc9040a68e
|
@ -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 {
|
||||||
|
|
|
@ -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]);
|
||||||
|
|
|
@ -0,0 +1,10 @@
|
||||||
|
class CancelError extends Error {
|
||||||
|
constructor(message) {
|
||||||
|
super(message);
|
||||||
|
this.name = 'CancelError';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
module.exports = {
|
||||||
|
CancelError,
|
||||||
|
};
|
|
@ -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;
|
||||||
|
|
|
@ -5,5 +5,5 @@ async function wait(ms) {
|
||||||
}
|
}
|
||||||
|
|
||||||
module.exports = {
|
module.exports = {
|
||||||
wait
|
wait,
|
||||||
};
|
};
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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';
|
||||||
|
|
|
@ -0,0 +1,3 @@
|
||||||
|
export function isDev() {
|
||||||
|
return process.env.NODE_ENV === 'development' || process.env.NODE_ENV === 'local';
|
||||||
|
}
|
|
@ -0,0 +1,5 @@
|
||||||
|
export class CancelError extends Error {
|
||||||
|
constructor(message: string) {
|
||||||
|
super(message);
|
||||||
|
}
|
||||||
|
}
|
|
@ -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);
|
||||||
|
|
|
@ -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";
|
||||||
|
|
|
@ -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 组件事件监听(对原始事件包装)
|
|
||||||
* 样式:style、class等
|
|
||||||
*/
|
|
||||||
[key: string]: any;
|
|
||||||
};
|
|
|
@ -1,2 +0,0 @@
|
||||||
export * from "./pipeline";
|
|
||||||
export * from "./fast-crud";
|
|
|
@ -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;
|
|
||||||
};
|
|
|
@ -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("用户取消");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -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>
|
||||||
|
|
|
@ -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>
|
||||||
|
|
|
@ -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>
|
||||||
|
|
|
@ -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>
|
||||||
|
|
|
@ -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: {
|
||||||
|
|
|
@ -1,3 +1 @@
|
||||||
export function isDev() {
|
export { isDev } from '@certd/pipeline';
|
||||||
return process.env.NODE_ENV === 'development' || process.env.NODE_ENV === 'local';
|
|
||||||
}
|
|
||||||
|
|
Loading…
Reference in New Issue