picgo
Version:
A tool for image uploading
983 lines (982 loc) • 31.1 kB
TypeScript
import { Command } from 'commander';
import { Inquirer } from 'inquirer';
import { IRequestPromiseOptions } from './oldRequest';
import type { Env, Handler, Hono, MiddlewareHandler } from 'hono';
/**
* Type definition for the plugin router setup callback.
* The plugin receives a Hono instance created by the Host.
*/
export type PluginRouterSetup = (router: Hono<any, any, any>) => void;
export interface IServerManager<E extends Env = any> {
/**
*
* @param port
* @param host
* @param ignoreExistingExternalServer PicGo GUI may start a server instance already, if you want to start a new one, set this to true
* @param secret shared secret for server authentication
* @returns
*/
listen: (port?: number, host?: string, ignoreExistingExternalServer?: boolean, secret?: string) => Promise<number | void>;
shutdown: () => void;
isListening: () => boolean;
/**
* Get current server listening address if running.
* e.g. "http://127.0.0.1:36677/"
*/
getServerInfo: () => string;
registerGet<P extends string>(path: P, handler: Handler<E, P>): void;
registerPost<P extends string>(path: P, handler: Handler<E, P>): void;
registerPut<P extends string>(path: P, handler: Handler<E, P>): void;
registerDelete<P extends string>(path: P, handler: Handler<E, P>): void;
registerMiddleware<P extends string>(path: P, handler: MiddlewareHandler<E, P>): void;
/**
* Register a static file server route.
* @param path - The URL prefix (e.g. '/static')
* @param root - The local file system path
*/
registerStatic: (path: string, root: string) => void;
/**
* Mount a sub-router for plugins.
*
* PicGo creates a new Hono instance (to ensure version consistency)
* and passes it to the setup callback for the plugin to configure.
*/
mount: (path: string, setup: PluginRouterSetup) => void;
}
export interface ICloudManager {
login: (token?: string) => Promise<void>;
logout: () => void;
disposeLoginFlow: () => void;
album: ICloudAlbumManager;
uploader: ICloudUploaderManager;
getUserInfo: () => Promise<ICloudUserInfo | null>;
refreshUserInfo: () => Promise<ICloudUserInfo | null>;
setAutoImport: (autoImport: boolean) => Promise<ICloudUserInfo>;
getUsage: () => Promise<CloudUsage | null>;
getBillingOverview: () => Promise<CloudBillingOverview | null>;
}
/**
* Entry point picgo-gui and external plugins use to manage pending multipart upload sessions.
* The state machine itself (runMultipartUpload) is intentionally not exposed here — uploads
* should always go through FileService's size dispatch, not bypass it.
*/
export interface ICloudUploaderManager {
/** Abort a remote multipart upload; fire-and-forget, errors swallowed (R2 lifecycle backstop). */
abort: (uploadId: string, objectKey: string) => Promise<void>;
/** List every pending multipart session for the current user (local state only). */
listPending: () => MultipartSession[];
/** Delete only the local entry (use abort() to also notify the remote). */
removePending: (fingerprint: string) => void;
}
export interface ICloudUserInfo {
user: string | null;
avatar?: string | null;
plan?: number;
autoImport?: boolean;
}
export type CloudUsageDimension = {
used: number;
limit: number | null;
};
export type CloudUsagePeriodInfo = {
used: number;
periodStart: string | null;
periodEnd: string | null;
};
export type CloudUsageConfigHistory = {
used: number;
limit: number;
appType: 'gui' | 'cli';
};
export type CloudUsage = {
/** Paid plan code(用于展示)。 */
plan: string;
/**
* 当前生效配额对应的 plan code(capabilityPlan)。grace/frozen/pending_cleanup
* 阶段会降级为 'free',此时 effectiveQuotaPlan !== plan。
*/
effectiveQuotaPlan: string;
storage: CloudUsageDimension;
mediaCount: CloudUsageDimension;
monthlyServes: CloudUsagePeriodInfo;
configHistory: CloudUsageConfigHistory;
};
export type CloudBillingPlanInfo = {
/** 来自 entitlement 的付费 plan code,用于展示 / billing portal。 */
paid: string;
/** 用于 capability / 配额检查的 plan code(admin grant + entitlement 合并结果)。 */
capability: string;
/** 订阅计费周期类型:'monthly' / 'yearly' / null(免费用户)。 */
billingPeriod: string | null;
source: 'entitlement' | 'admin_grant' | 'both' | 'free';
};
export type CloudLifecyclePhase = 'active' | 'grace' | 'frozen' | 'pending_cleanup';
export type CloudLifecycleFlags = {
customDomainDisabledByLifecycle: boolean;
autoImportDisabledByLifecycle: boolean;
};
export type CloudLifecycleInfo = {
phase: CloudLifecyclePhase;
daysRemaining: number | null;
graceEndsAt: string | null;
freezeEndsAt: string | null;
/**
* 当前 lifecycle phase 结束时间。客户端用此字段统一展示套餐到期:
* - active → max(activeEnt.validUntil, grant.validUntil);永久 entitlement 为 null
* - grace → 等同 graceEndsAt
* - frozen → 等同 freezeEndsAt
* - pending_cleanup → null
*/
currentPhaseEndsAt: string | null;
flags: CloudLifecycleFlags;
};
export type CloudSubscriptionInfo = {
status: string;
currentPeriodEnd: string | null;
};
export type CloudBillingOverview = {
plan: CloudBillingPlanInfo;
lifecycle: CloudLifecycleInfo;
subscription: CloudSubscriptionInfo | null;
};
export type ImportResult = {
total: number;
created: number;
skipped: number;
invalid: number;
failed: number;
pending: number;
items: IImgInfo[];
};
/**
* Generic progress base — the minimal common fields shared by every progress event payload.
* Consumers that only care about the ratio (CLI progress bar, future GUI progress widget) can
* read these three fields directly without having to discriminate on event type.
*/
export type IProgress = {
/**
* Current progress count. Unit depends on the event:
* - `FILE_UPLOAD_PROGRESS` → bytes uploaded so far
* - `CLOUD_IMPORT_PROGRESS` → items processed so far
*/
current: number;
/** Target total, same unit as current. */
total: number;
/** current / total clipped to [0, 1]. Provided so consumers don't have to divide. 0 when total is 0. */
fraction: number;
};
/**
* Per-file byte-level upload progress for the `FILE_UPLOAD_PROGRESS` event.
* current / total are bytes; multipart uploads also fill partsCompleted / totalParts,
* non-multipart paths use -1 to signal N/A.
*/
export type IFileUploadProgress = IProgress & {
/** The file name currently being uploaded (= IImgInfo.fileName; lets consumers disambiguate multi-file flows). */
fileName: string;
/** Multipart: number of parts already completed. Non-multipart path uses -1. */
partsCompleted: number;
/** Multipart: total part count. Non-multipart path uses -1. */
totalParts: number;
/** Whether this is a resumed upload (multipart only). Always false on the non-resume path. */
resumed: boolean;
};
export type CloudImportProgress = IProgress & {
batchIndex: number;
batchTotal: number;
created: number;
skipped: number;
failed: number;
};
/**
* Metadata for a single multipart part. partNumber is 1-based; url is a server-presigned
* R2 endpoint the client PUTs the part bytes to.
*/
export type MultipartPartInfo = {
partNumber: number;
url: string;
method: 'PUT';
headers: Record<string, string>;
};
/**
* Minimal record the client keeps after a single part finishes uploading.
* partNumber is 1-based; etag comes from the part PUT response header.
*/
export type MultipartCompletedPart = {
partNumber: number;
etag: string;
};
/**
* Locally persisted multipart upload session. Drives resume across process crashes / restarts.
* `v` is a schema version field for future migrations.
*/
export type MultipartSession = {
/** Schema version, currently 1. */
v: 1;
uploadId: string;
objectKey: string;
publicId: string;
url: string;
filename: string;
/** Total bytes. */
size: number;
contentType: string;
/** Per-part size (the last part may be smaller). */
partSize: number;
/** Total part count = Math.ceil(size / partSize). */
partCount: number;
/** Parts already finished, with their server-returned ETag, ready to submit at complete time. */
completedParts: MultipartCompletedPart[];
/** Epoch ms used for the 7-day TTL sweep. */
createdAt: number;
};
export declare enum AlbumListOrder {
ASC = "asc",
DESC = "desc"
}
export declare enum AlbumListSort {
NEWEST = "newest",
OLDEST = "oldest",
FILE_NAME = "fileName"
}
export type AlbumListQuery = {
contentType?: string;
type?: string;
ext?: string;
search?: string;
fileName?: string;
limit?: number;
offset?: number;
sort?: AlbumListSort | string;
order?: AlbumListOrder;
};
export type AlbumListResponse<T = IImgInfo> = {
success: boolean;
items: T[];
total: number;
limit: number;
offset: number;
};
export type AlbumFiltersResponse = {
success: boolean;
contentTypes: string[];
exts: string[];
};
export type BatchUpdateResult = {
updated: number;
skipped: number;
items: IImgInfo[];
};
export type AlbumStatsResponse = {
total: number;
types: {
type: string;
count: number;
}[];
};
export interface ICloudAlbumManager {
import: (items: IImgInfo[]) => Promise<ImportResult>;
list: (query?: AlbumListQuery) => Promise<AlbumListResponse>;
get: (id: string) => Promise<IImgInfo>;
update: (id: string, data: Partial<IImgInfo>) => Promise<IImgInfo>;
batchUpdate: (items: {
id: string;
data: Partial<IImgInfo>;
}[]) => Promise<BatchUpdateResult>;
delete: (id: string | string[]) => Promise<void>;
getStats: () => Promise<AlbumStatsResponse>;
getFilters: () => Promise<AlbumFiltersResponse>;
getPending: () => Promise<IImgInfo[]>;
addToPending: (items: IImgInfo[]) => Promise<IImgInfo[]>;
retryPending: () => Promise<ImportResult>;
}
export interface IPicGo extends NodeJS.EventEmitter {
/**
* picgo configPath
*
* if do not provide, then it will use default configPath
*/
configPath: string;
/**
* the picgo configPath's baseDir
*/
baseDir: string;
/**
* picgo logger factory
*/
log: ILogger;
/**
* picgo commander, for cli
*/
cmd: ICommander;
/**
* picgo server manager
*/
server: IServerManager;
/**
* picgo cloud manager
*/
cloud: ICloudManager;
/**
* after transformer, the input will be output
*/
output: IImgInfo[];
/**
* the origin input
*/
input: any[];
/**
* register\unregister\get picgo's plugin
*/
pluginLoader: IPluginLoader;
/**
* install\uninstall\update picgo's plugin via npm
*/
pluginHandler: IPluginHandler;
/**
* @deprecated will be removed in v1.5.0+
*
* use request instead.
*
* http request tool
*/
Request: IRequest;
/**
* plugin system core part transformer\uploader\beforeTransformPlugins...
*/
helper: IHelper;
/**
* uploader multi-config manager
*/
uploaderConfig: IUploaderConfigManager;
/**
* picgo-core version
*/
VERSION: string;
/**
* electron picgo's version
*/
GUI_VERSION?: string;
/**
* will be released in v1.5.0+
*
* replace old Request
*
* http request tool
*/
request: IRequest['request'];
/**
* Opens a URL in the default browser.
*
* Default implementation uses the `open` package in Node.js.
* Consumers (Electron/VSCode extensions) can overwrite this method.
*/
openUrl: (url: string) => Promise<void>;
i18n: II18nManager;
/**
* get picgo config
*/
getConfig: <T = unknown>(name?: string) => T;
/**
* save picgo config to configPath
*/
saveConfig: (config: IStringKeyMap<any>) => void;
/**
* remove some [propName] in config[key] && save config to configPath
*/
removeConfig: (key: string, propName: string) => void;
/**
* set picgo config to ctx && will not save to configPath
*/
setConfig: (config: IStringKeyMap<any>) => void;
/**
* unset picgo config to ctx && will not save to configPath
*/
unsetConfig: (key: string, propName: string) => void;
/**
* upload gogogo
*/
upload: (input?: any[], options?: UploadOptions) => Promise<IImgInfo[] | Error>;
}
export declare enum OutputFormat {
PRETTY = "pretty",
JSON = "json"
}
export interface UploadOptions {
/** Output format for the success message. Defaults to 'pretty'. */
outputFormat?: OutputFormat;
}
export interface IUploaderConfigItem {
_id: string;
_configName: string;
_createdAt: number;
_updatedAt: number;
[key: string]: unknown;
}
export interface IUploaderTypeConfigs {
configList: IUploaderConfigItem[];
defaultId: string;
}
export interface IUploaderConfigManager {
listUploaderTypes: () => string[];
getConfigList: (type: string) => IUploaderConfigItem[];
getActiveConfig: (type: string) => IUploaderConfigItem | undefined;
use: (type: string, configName?: string) => IUploaderConfigItem;
createOrUpdate: (type: string, configName?: string, configPatch?: IStringKeyMap<unknown>) => IUploaderConfigItem;
copy: (type: string, configName: string, newConfigName: string) => IUploaderConfigItem;
rename: (type: string, oldName: string, newName: string) => IUploaderConfigItem;
remove: (type: string, configName: string) => void;
}
/**
* Snapshot of the currently displayed values for all fields in a plugin config form.
*
* Passed to function-form `choices` / `default` so reactive fields can derive
* their value space from other fields. In the GUI this is the form's merged
* view (stored config + schema defaults + user edits); in the CLI this is
* inquirer's accumulated `answers`.
*/
export type PluginConfigAnswers = Record<string, unknown>;
/**
* One choice for a `list` / `checkbox` field. May be a bare string (used as
* both label and value) or an object form.
*/
export type IPluginConfigChoice = string | {
name?: string;
value: unknown;
checked?: boolean;
};
/**
* for plugin config
*
* @example Reactive cascading dropdown
* const config = (ctx) => [
* { name: 'uploader', type: 'list', required: true, choices: ['github', 'gitee'] },
* {
* name: 'repo',
* type: 'list',
* required: true,
* dependsOn: ['uploader'],
* choices: (answers) => {
* return answers.uploader === 'github'
* ? ['my-org/repo-a', 'my-org/repo-b']
* : ['gitee-org/repo-c']
* }
* }
* ]
*
* @example Multi-line text via `type: 'editor'` (3.0.0+)
* const config = (ctx) => [
* {
* name: 'script',
* type: 'editor',
* alias: 'Compression script',
* required: true,
* message: 'Enter your compression script (multi-line supported)'
* }
* ]
*/
export interface IPluginConfig {
name: string;
/**
* Field widget kind. The string is forwarded to inquirer in the CLI path and
* used by the GUI renderer to pick a control. Kept as `string` so plugin
* authors can pass through any inquirer-supported value PicGo has not
* documented. PicGo guarantees behavior for these known values:
*
* - `'input'` single-line text. CLI: inquirer text prompt; GUI: text input.
* - `'password'` single-line text rendered masked. CLI: inquirer password
* prompt; GUI: password input with show/hide toggle.
* - `'list'` pick one from `choices`. CLI: inquirer list prompt; GUI:
* single-select dropdown.
* - `'checkbox'` pick many from `choices`. CLI: inquirer checkbox prompt;
* GUI: multi-select combobox.
* - `'confirm'` boolean. CLI: inquirer confirm prompt; GUI: switch.
* - `'editor'` multi-line text (3.0.0+). Value is a `string` and MAY
* contain `\n`. CLI: inquirer editor prompt — spawns the
* user's external editor via `VISUAL` / `EDITOR` env vars
* (falls back to platform default: `vi` / `nano` on Unix,
* `notepad` on Windows); GUI: shadcn `<Textarea>` with
* user-resizable height.
*/
type: string;
required: boolean;
/**
* Default value for the field. May be a plain value or a function that
* receives the current `answers` snapshot and returns the value.
*/
default?: any | ((answers: PluginConfigAnswers) => any);
/**
* Available options for `list` / `checkbox` fields. May be a static array
* or a function that receives the current `answers` snapshot and returns
* the array.
*/
choices?: IPluginConfigChoice[] | ((answers: PluginConfigAnswers) => IPluginConfigChoice[]);
/**
* Names of other fields in the same schema this field's `choices` /
* `default` depends on. When any listed field's value changes, the GUI
* will re-evaluate this field. Has no effect in the CLI path (inquirer
* already passes the latest `answers` to every prompt).
*/
dependsOn?: string[];
alias?: string;
message?: string;
prefix?: string;
[propName: string]: any;
}
/**
* for lifecycle plugins
*/
export interface ILifecyclePlugins {
register: (id: string, plugin: IPlugin) => void;
unregister: (id: string) => void;
getName: () => string;
get: (id: string) => IPlugin | undefined;
getList: () => IPlugin[];
getIdList: () => string[];
}
export interface IHelper {
transformer: ILifecyclePlugins;
uploader: ILifecyclePlugins;
beforeTransformPlugins: ILifecyclePlugins;
beforeUploadPlugins: ILifecyclePlugins;
afterUploadPlugins: ILifecyclePlugins;
afterFinishPlugins: ILifecyclePlugins;
}
export interface ICommander extends ILifecyclePlugins {
program: Command;
inquirer: Inquirer;
}
export interface IPluginLoader {
/**
* register [local plugin] or [provided plugin]
*
* if the second param (plugin) is provided
*
* then picgo will register this plugin and enable it by default
*
* but picgo won't write any config to config file
*
* you should use ctx.setConfig to change the config context
*/
registerPlugin: (name: string, plugin?: IPicGoPlugin) => void;
unregisterPlugin: (name: string) => void;
getPlugin: (name: string) => IPicGoPluginInterface | undefined;
/**
* get enabled plugin list
*/
getList: () => string[];
/**
* get all plugin list (enabled or not)
*/
getFullList: () => string[];
hasPlugin: (name: string) => boolean;
}
export interface IRequestOld {
request: import('axios').AxiosInstance;
}
export type IOldReqOptions = Omit<IRequestPromiseOptions & {
url: string;
}, 'auth'>;
export type IOldReqOptionsWithFullResponse = IOldReqOptions & {
resolveWithFullResponse: true;
};
export type IOldReqOptionsWithJSON = IOldReqOptions & {
json: true;
};
/**
* for PicGo new request api, the response will be json format
*/
export type IReqOptions<T = any> = AxiosRequestConfig<T> & {
resolveWithFullResponse: true;
};
/**
* for PicGo new request api, the response will be Buffer
*/
export type IReqOptionsWithArrayBufferRes<T = any> = IReqOptions<T> & {
responseType: 'arraybuffer';
};
/**
* for PicGo new request api, the response will be just response data. (not statusCode, headers, etc.)
*/
export type IReqOptionsWithBodyResOnly<T = any> = AxiosRequestConfig<T>;
export type IFullResponse<T = any, U = any> = AxiosResponse<T, U> & {
statusCode: number;
body: T;
};
type AxiosResponse<T = any, U = any> = import('axios').AxiosResponse<T, U>;
type AxiosRequestConfig<T = any> = import('axios').AxiosRequestConfig<T>;
interface IRequestOptionsWithFullResponse {
resolveWithFullResponse: true;
}
interface IRequestOptionsWithJSON {
json: true;
}
interface IRequestOptionsWithResponseTypeArrayBuffer {
responseType: 'arraybuffer';
}
/**
* T is the response data type
* U is the config type
*/
export type IResponse<T, U> = U extends IRequestOptionsWithFullResponse ? IFullResponse<T, U> : U extends IRequestOptionsWithJSON ? T : U extends IRequestOptionsWithResponseTypeArrayBuffer ? Buffer : U extends IOldReqOptionsWithFullResponse ? IFullResponse<T, U> : U extends IOldReqOptionsWithJSON ? T : U extends IOldReqOptions ? string : U extends IReqOptionsWithBodyResOnly ? T : string;
/**
* the old request lib will be removed in v1.5.0+
* the request options have the following properties
*/
export interface IRequestLibOnlyOptions {
proxy?: string;
body?: any;
formData?: {
[key: string]: any;
} | undefined;
form?: {
[key: string]: any;
} | string | undefined;
}
export type IRequestConfig<T> = T extends IRequestLibOnlyOptions ? IOldReqOptions : AxiosRequestConfig;
export interface IRequest {
request: <T, U extends (IRequestConfig<U> extends IOldReqOptions ? IOldReqOptions : IRequestConfig<U> extends AxiosRequestConfig ? AxiosRequestConfig : never)>(config: U) => Promise<IResponse<T, U>>;
}
export type ILogColor = 'blue' | 'green' | 'yellow' | 'red';
/**
* for uploading image info
*/
export interface IImgInfo {
id?: string;
buffer?: Buffer;
base64Image?: string;
fileName?: string;
width?: number;
height?: number;
extname?: string;
imgUrl?: string;
/**
* if the imgUrl has been overwrite by url rewrite rule, then originImgUrl is the original url before rewrite
*/
originImgUrl?: string;
/** @deprecated use `contentType` */
mimeType?: string;
_importToPicGoCloud?: boolean;
contentType?: string;
filePath?: string;
size?: number;
createdAt?: number | string | Date;
updatedAt?: number | string | Date;
/** the origin input of the image, before any processing or uploading */
origin?: string;
[propName: string]: any;
}
export interface IUrlRewriteRule {
match: string;
replace: string;
enable?: boolean;
global?: boolean;
ignoreCase?: boolean;
}
export interface IPathTransformedImgInfo extends IImgInfo {
success: boolean;
}
export interface IStringKeyMap<T> {
[key: string]: T extends T ? T : any;
}
export interface ICLIConfigs {
[module: string]: IStringKeyMap<any>;
}
/** SM.MS 图床配置项 */
export interface ISmmsConfig {
token: string;
backupDomain?: string;
}
/** 七牛云图床配置项 */
export interface IQiniuConfig {
accessKey: string;
secretKey: string;
/** 存储空间名 */
bucket: string;
/** 自定义域名 */
url: string;
/** 存储区域编号 */
area: 'z0' | 'z1' | 'z2' | 'na0' | 'as0' | string;
/** 网址后缀,比如使用 `?imageslim` 可进行[图片瘦身](https://developer.qiniu.com/dora/api/1271/image-thin-body-imageslim) */
options: string;
/** 自定义存储路径,比如 `img/` */
path: string;
}
/** 又拍云图床配置项 */
export interface IUpyunConfig {
/** 存储空间名,及你的服务名 */
bucket: string;
/** 操作员 */
operator: string;
/** 密码 */
password: string;
/** 针对图片的一些后缀处理参数 */
options: string;
/** 自定义存储路径,比如 `img/` */
path: string;
/** 加速域名,注意要加 `http://` 或者 `https://` */
url: string;
}
/** 腾讯云图床配置项 */
export interface ITcyunConfig {
secretId: string;
secretKey: string;
/** 存储桶名,v4 和 v5 版本不一样 */
bucket: string;
appId: string;
/** 存储区域,例如 ap-beijing-1 */
area: string;
/** 请求的 ENDPOINT,设置后 `area` 字段会失效 */
endpoint: string;
/** 自定义存储路径,比如 img/ */
path: string;
/** 自定义域名,注意要加 `http://` 或者 `https://` */
customUrl: string;
/** COS 版本,v4 或者 v5 */
version: 'v5' | 'v4';
/** 针对图片的一些后缀处理参数 PicGo 2.4.0+ PicGo-Core 1.5.0+ */
options: string;
/** 是否支持极智压缩 */
slim: boolean;
}
/** GitHub 图床配置项 */
export interface IGithubConfig {
/** 仓库名,格式是 `username/reponame` */
repo: string;
/** github token */
token: string;
/** 自定义存储路径,比如 `img/` */
path: string;
/** 自定义域名,注意要加 `http://` 或者 `https://` */
customUrl: string;
/** 分支名,默认是 `main` */
branch: string;
}
/** 阿里云图床配置项 */
export interface IAliyunConfig {
accessKeyId: string;
accessKeySecret: string;
/** 存储空间名 */
bucket: string;
/** 存储区域代号 */
area: string;
/** 自定义存储路径 */
path: string;
/** 自定义域名,注意要加 `http://` 或者 `https://` */
customUrl: string;
/** 针对图片的一些后缀处理参数 PicGo 2.2.0+ PicGo-Core 1.4.0+ */
options: string;
}
/** Imgur 图床配置项 */
export interface IImgurConfig {
/** imgur 的 `clientId` */
clientId: string;
/** 代理地址,仅支持 http 代理 */
proxy: string;
}
/** PicGo 配置文件类型定义 */
export interface IConfig {
picBed: {
uploader: string;
current?: string;
smms?: ISmmsConfig;
qiniu?: IQiniuConfig;
upyun?: IUpyunConfig;
tcyun?: ITcyunConfig;
github?: IGithubConfig;
aliyun?: IAliyunConfig;
imgur?: IImgurConfig;
transformer?: string;
/** for uploader */
proxy?: string;
[others: string]: any;
};
picgoPlugins: {
[pluginName: string]: boolean;
};
debug?: boolean;
silent?: boolean;
settings?: {
logLevel?: string[];
logPath?: string;
/** for npm */
npmRegistry?: string;
/** for npm */
npmProxy?: string;
picgoCloud?: {
token?: string;
[others: string]: any;
};
server?: {
port?: number;
host?: string;
enable?: boolean;
secret?: string;
[others: string]: any;
};
[others: string]: any;
};
[configOptions: string]: any;
}
/**
* for an uploader/transformer/beforeTransformHandler/beforeUploadHandler/afterUploadHandler
*/
export interface IPlugin {
handle: ((ctx: IPicGo) => Promise<any>) | ((ctx: IPicGo) => void);
/** The name of this handler */
name?: string;
/** The config of this handler */
config?: (ctx: IPicGo) => IPluginConfig[];
[propName: string]: any;
}
export type IPluginNameType = 'simple' | 'scope' | 'normal' | 'unknown';
export interface IPluginProcessResult {
success: boolean;
/**
* the package.json's name filed
*/
pkgName: string;
/**
* the plugin name or the fs absolute path
*/
fullName: string;
}
export interface IPluginHandler {
install: (plugins: string[], options: IPluginHandlerOptions, env?: IProcessEnv) => Promise<IPluginHandlerResult<boolean>>;
update: (plugins: string[], options: IPluginHandlerOptions, env?: IProcessEnv) => Promise<IPluginHandlerResult<boolean>>;
uninstall: (plugins: string[], env?: IProcessEnv) => Promise<IPluginHandlerResult<boolean>>;
}
export interface IPluginHandlerResult<T> {
success: T;
body: T extends true ? string[] : string;
}
export interface IPluginHandlerOptions {
npmProxy?: string;
npmRegistry?: string;
}
/**
* for picgo npm plugins
*/
export type IPicGoPlugin = (ctx: IPicGo) => IPicGoPluginInterface;
/**
* interfaces for PicGo plugin
*/
export interface IPicGoPluginInterface {
/**
* since PicGo-Core v1.5, register will inject ctx
*/
register: (ctx: IPicGo) => void;
/**
* this plugin's config
*/
config?: (ctx: IPicGo) => IPluginConfig[];
/**
* register uploader name
*/
uploader?: string;
/**
* register transformer name
*/
transformer?: string;
/**
* for picgo gui plugins
*/
guiMenu?: (ctx: IPicGo) => IGuiMenuItem[];
/**
* for picgo gui plugins
* short key -> command
*/
commands?: (ctx: IPicGo) => ICommandItem[];
[propName: string]: any;
}
export interface IGuiMenuItem {
label: string;
handle: (ctx: IPicGo, guiApi: any) => Promise<void>;
}
export interface ICommandItem {
label: string;
name: string;
key: string;
handle: (ctx: IPicGo, guiApi: any) => Promise<void>;
}
/**
* for spawn output
*/
export interface IResult {
code: number;
data: string;
}
/**
* for transformer - path
*/
export interface IImgSize {
width: number;
height: number;
real?: boolean;
extname?: string;
}
/**
* for clipboard image
*/
export interface IClipboardImage {
imgPath: string;
/**
* if the path is generate by picgo -> false
* if the path is a real file path in system -> true
*/
shouldKeepAfterUploading: boolean;
}
/**
* for install command environment variable
*/
export interface IProcessEnv {
[propName: string]: Undefinable<string>;
}
export type ILogArgvType = string | number;
export type ILogArgvTypeWithError = ILogArgvType | Error | unknown;
export type Nullable<T> = T | null;
export type Undefinable<T> = T | undefined;
export interface ILogger {
success: (...msg: ILogArgvType[]) => void;
info: (...msg: ILogArgvType[]) => void;
error: (...msg: ILogArgvTypeWithError[]) => void;
warn: (...msg: ILogArgvType[]) => void;
debug: (...msg: ILogArgvType[]) => void;
createLogger?: (options?: {
logPath?: string;
consoleOutput?: boolean;
respectSilent?: boolean;
}) => ILogger;
}
export interface IConfigChangePayload<T> {
configName: string;
value: T;
}
export interface ILocale {
[key: string]: any;
}
export interface II18nManager {
/**
* translate text
*/
translate: <T extends string>(key: T, args?: IStringKeyMap<string>) => string;
/**
* add locale to current i18n language
* default locale list
* - zh-CN
* - en
*/
addLocale: (language: string, locales: ILocale) => boolean;
/**
* set current language
*/
setLanguage: (language: string) => void;
/**
* dynamic add new language & locales
*/
addLanguage: (language: string, locales: ILocale) => boolean;
/**
* get language list
*/
getLanguageList: () => string[];
}
export {};