Skip to content

Commit

Permalink
feat: basic picgo flow
Browse files Browse the repository at this point in the history
  • Loading branch information
terwer committed Mar 15, 2024
1 parent a7dad70 commit f09fb41
Show file tree
Hide file tree
Showing 13 changed files with 775 additions and 19 deletions.
22 changes: 20 additions & 2 deletions libs/Universal-PicGo-Core/.eslintrc.cjs
@@ -1,4 +1,22 @@
module.exports = {
root: true,
extends: ["./node_modules/@terwer/eslint-config-custom/typescript/index.cjs"],
extends: ["eslint:recommended", "plugin:@typescript-eslint/recommended", "turbo", "prettier"],

parser: "@typescript-eslint/parser",

plugins: ["@typescript-eslint", "prettier"],

rules: {
// Note: you must disable the base rule as it can report incorrect errors
semi: "off",
quotes: "off",
"no-undef": "off",
"@typescript-eslint/no-var-requires": "off",
"@typescript-eslint/no-this-alias": "off",
"@typescript-eslint/no-non-null-assertion": "off",
"@typescript-eslint/no-unused-vars": "off",
"@typescript-eslint/no-explicit-any": "off",
"@typescript-eslint/no-empty-function": "off",
"turbo/no-undeclared-env-vars": "off",
"prettier/prettier": "error",
},
}
17 changes: 17 additions & 0 deletions libs/Universal-PicGo-Core/src/core/Lifecycle.ts
@@ -0,0 +1,17 @@
/*
* GNU GENERAL PUBLIC LICENSE
* Version 3, 29 June 2007
*
* Copyright (C) 2024 Terwer, Inc. <https://terwer.space/>
* Everyone is permitted to copy and distribute verbatim copies
* of this license document, but changing it is not allowed.
*/

import { EventEmitter } from "../utils/nodePolyfill"
import { IPicGo } from "../types"

export class Lifecycle extends EventEmitter {
async start(input: any[]): Promise<IPicGo> {
throw new Error("Lifecycle.start is not implemented")
}
}
186 changes: 176 additions & 10 deletions libs/Universal-PicGo-Core/src/core/UniversalPicGo.ts
Expand Up @@ -7,9 +7,26 @@
* of this license document, but changing it is not allowed.
*/

import { simpleLogger } from "zhi-lib-base"
import { ILogger, simpleLogger } from "zhi-lib-base"
import { EventEmitter } from "../utils/nodePolyfill"
import { IPicGo } from "../types"
import {
IConfig,
IHelper,
II18nManager,
IImgInfo,
IPicGo,
IPicGoPlugin,
IPicGoPluginInterface,
IPluginLoader,
IStringKeyMap,
} from "../types"
import { Lifecycle } from "./Lifecycle"
import { PluginLoader } from "../lib/PluginLoader"
import { LifecyclePlugins } from "../lib/LifecyclePlugins"
import { PluginHandler } from "../lib/PluginHandler"
import _ from "lodash-es"
import getClipboardImage from "../utils/getClipboardImage"
import { IBuildInEvent } from "../utils/enums"

/*
* 通用 PicGO 对象定义
Expand All @@ -18,23 +35,172 @@ import { IPicGo } from "../types"
* @since 1.4.5
*/
class UniversalPicGo extends EventEmitter implements IPicGo {
private logger = simpleLogger("universal-picgo-api", "universal-picgo", false)
private _config!: IConfig
private lifecycle!: Lifecycle
private _pluginLoader!: PluginLoader
configPath: string
baseDir!: string
helper!: IHelper
log: ILogger
// cmd: Commander
output: IImgInfo[]
input: any[]
pluginHandler: PluginHandler
i18n!: II18nManager
VERSION: string = process.env.PICGO_VERSION ?? "unknown"
// GUI_VERSION?: string

constructor(configPath = "") {
get pluginLoader(): IPluginLoader {
return this._pluginLoader
}

constructor(configPath = "", isDev?: boolean) {
super()
this.log = simpleLogger("universal-picgo-api", "universal-picgo", isDev ?? false)
this.configPath = configPath
this.logger.info("UniversalPicGo inited")
this.output = []
this.input = []
this.helper = {
transformer: new LifecyclePlugins("transformer"),
uploader: new LifecyclePlugins("uploader"),
beforeTransformPlugins: new LifecyclePlugins("beforeTransformPlugins"),
beforeUploadPlugins: new LifecyclePlugins("beforeUploadPlugins"),
afterUploadPlugins: new LifecyclePlugins("afterUploadPlugins"),
}
this.initConfigPath()
// this.cmd = new Commander(this)
this.pluginHandler = new PluginHandler(this)
this.initConfig()
this.init()

this.log.info("UniversalPicGo inited")
}

/**
* easily mannually load a plugin
* if provide plugin name, will register plugin by name
* or just instantiate a plugin
*/
use(plugin: IPicGoPlugin, name?: string): IPicGoPluginInterface {
if (name) {
this.pluginLoader.registerPlugin(name, plugin)
return this.pluginLoader.getPlugin(name)!
} else {
const pluginInstance = plugin(this)
return pluginInstance
}
}

// registerCommands(): void {
// if (this.configPath !== "") {
// this.cmd.init()
// this.cmd.loadCommands()
// }
// }

this.on("testEvent", () => {
this.logger.info("testEvent triggered")
})
getConfig<T>(name?: string): T {
if (!name) {
return this._config as unknown as T
} else {
return _.get(this._config, name)
}
}

public test() {
this.emit("testEvent")
saveConfig(config: IStringKeyMap<any>): void {
// if (!isInputConfigValid(config)) {
// this.log.warn("the format of config is invalid, please provide object")
// return
// }
// this.setConfig(config)
// this.db.saveConfig(config)
}

removeConfig(key: string, propName: string): void {
// if (!key || !propName) return
// if (isConfigKeyInBlackList(key)) {
// this.log.warn(`the config.${key} can't be removed`)
// return
// }
// this.unsetConfig(key, propName)
// this.db.unset(key, propName)
}

setConfig(config: IStringKeyMap<any>): void {
// if (!isInputConfigValid(config)) {
// this.log.warn("the format of config is invalid, please provide object")
// return
// }
// Object.keys(config).forEach((name: string) => {
// if (isConfigKeyInBlackList(name)) {
// this.log.warn(`the config.${name} can't be modified`)
// // eslint-disable-next-line @typescript-eslint/no-dynamic-delete
// delete config[name]
// }
// set(this._config, name, config[name])
// eventBus.emit(IBusEvent.CONFIG_CHANGE, {
// configName: name,
// value: config[name],
// })
// })
}

unsetConfig(key: string, propName: string): void {
// if (!key || !propName) return
// if (isConfigKeyInBlackList(key)) {
// this.log.warn(`the config.${key} can't be unset`)
// return
// }
// unset(this.getConfig(key), propName)
}

async upload(input?: any[]): Promise<IImgInfo[] | Error> {
if (this.configPath === "") {
this.log.error("The configuration file only supports JSON format.")
return []
}
// upload from clipboard
if (input === undefined || input.length === 0) {
try {
const { imgPath, shouldKeepAfterUploading } = await getClipboardImage(this)
if (imgPath === "no image") {
throw new Error("image not found in clipboard")
} else {
this.once(IBuildInEvent.FAILED, () => {
if (!shouldKeepAfterUploading) {
// 删除 picgo 生成的图片文件,例如 `~/.picgo/20200621205720.png`
// fs.remove(imgPath).catch((e) => {
// this.log.error(e)
// })
}
})
this.once("finished", () => {
if (!shouldKeepAfterUploading) {
// fs.remove(imgPath).catch((e) => {
// this.log.error(e)
// })
}
})
const { output } = await this.lifecycle.start([imgPath])
return output
}
} catch (e) {
this.emit(IBuildInEvent.FAILED, e)
throw e
}
} else {
// upload from path
const { output } = await this.lifecycle.start(input)
return output
}
}

// ===================================================================================================================

private initConfigPath(): void {}

private initConfig(): void {}

private init(): void {}
}

export { UniversalPicGo }
47 changes: 47 additions & 0 deletions libs/Universal-PicGo-Core/src/lib/LifecyclePlugins.ts
@@ -0,0 +1,47 @@
/*
* GNU GENERAL PUBLIC LICENSE
* Version 3, 29 June 2007
*
* Copyright (C) 2024 Terwer, Inc. <https://terwer.space/>
* Everyone is permitted to copy and distribute verbatim copies
* of this license document, but changing it is not allowed.
*/

import { ILifecyclePlugins, IPlugin } from "../types"

export class LifecyclePlugins implements ILifecyclePlugins {
static currentPlugin: string | null
private readonly list: Map<string, IPlugin>
private readonly pluginIdMap: Map<string, string[]>
private readonly name: string

constructor(name: string) {
this.name = name
this.list = new Map()
this.pluginIdMap = new Map()
}

get(id: string): IPlugin | undefined {
return undefined
}

getIdList(): string[] {
return []
}

getList(): IPlugin[] {
return []
}

getName(): string {
return ""
}

register(id: string, plugin: IPlugin): void {
return
}

unregister(id: string): void {
return
}
}
38 changes: 38 additions & 0 deletions libs/Universal-PicGo-Core/src/lib/PluginHandler.ts
@@ -0,0 +1,38 @@
/*
* GNU GENERAL PUBLIC LICENSE
* Version 3, 29 June 2007
*
* Copyright (C) 2024 Terwer, Inc. <https://terwer.space/>
* Everyone is permitted to copy and distribute verbatim copies
* of this license document, but changing it is not allowed.
*/

import { IPicGo, IPluginHandler, IPluginHandlerOptions, IPluginHandlerResult, IProcessEnv } from "../types"

export class PluginHandler implements IPluginHandler {
// Thanks to feflow -> https://github.com/feflow/feflow/blob/master/lib/internal/install/plugin.js
private readonly ctx: IPicGo
constructor(ctx: IPicGo) {
this.ctx = ctx
}

install(
plugins: string[],
options: IPluginHandlerOptions,
env: IProcessEnv | undefined
): Promise<IPluginHandlerResult<boolean>> {
throw new Error("Method not implemented")
}

uninstall(plugins: string[]): Promise<IPluginHandlerResult<boolean>> {
throw new Error("Method not implemented")
}

update(
plugins: string[],
options: IPluginHandlerOptions,
env: IProcessEnv | undefined
): Promise<IPluginHandlerResult<boolean>> {
throw new Error("Method not implemented")
}
}
39 changes: 39 additions & 0 deletions libs/Universal-PicGo-Core/src/lib/PluginLoader.ts
@@ -0,0 +1,39 @@
/*
* GNU GENERAL PUBLIC LICENSE
* Version 3, 29 June 2007
*
* Copyright (C) 2024 Terwer, Inc. <https://terwer.space/>
* Everyone is permitted to copy and distribute verbatim copies
* of this license document, but changing it is not allowed.
*/

import { IPicGoPlugin, IPicGoPluginInterface, IPluginLoader } from "../types"

/**
* Local plugin loader, file system is required
*/
export class PluginLoader implements IPluginLoader {
getFullList(): string[] {
return []
}

getList(): string[] {
return []
}

getPlugin(name: string): IPicGoPluginInterface | undefined {
return undefined
}

hasPlugin(name: string): boolean {
return false
}

registerPlugin(name: string, plugin: IPicGoPlugin | undefined): void {
return
}

unregisterPlugin(name: string): void {
return
}
}

0 comments on commit f09fb41

Please sign in to comment.