From 8b24cee0f632b758e699c971e4b1f3b7c0abf10d Mon Sep 17 00:00:00 2001 From: Ryan Wang Date: Thu, 1 Dec 2022 01:15:50 +0800 Subject: [PATCH] refactor: plugin extension points of console plugin (#738) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit #### What type of PR is this? /kind improvement /milestone 2.0 #### What this PR does / why we need it: 重构 Console 端插件扩展点的定义方式。现在需要如下定义: ```ts extensionPoints: { "page:functional:create": () => { return [ { name: "链接", url: "/links", path: "/pages/functional/links", permissions: ["plugin:links:view"], }, ]; }, }, ``` #### Special notes for your reviewer: 可以用以下插件进行测试: - https://github.com/halo-sigs/plugin-links - https://github.com/halo-sigs/plugin-unsplash #### Does this PR introduce a user-facing change? ```release-note None ``` --- packages/shared/src/core/plugins.ts | 4 +- .../shared/src/states/attachment-selector.ts | 6 +- packages/shared/src/states/pages.ts | 6 +- packages/shared/src/types/plugin.ts | 26 ++++---- src/composables/usePlugins.ts | 23 ------- src/main.ts | 14 ++--- .../components/AttachmentSelectorModal.vue | 63 ++++++++++++------- src/modules/contents/attachments/module.ts | 1 - src/modules/contents/comments/module.ts | 1 - .../contents/pages/FunctionalPageList.vue | 36 ++++++++--- src/modules/contents/pages/module.ts | 1 - src/modules/contents/posts/module.ts | 1 - src/modules/dashboard/module.ts | 1 - src/modules/interface/menus/module.ts | 1 - src/modules/interface/themes/module.ts | 1 - src/modules/system/plugins/module.ts | 1 - src/modules/system/roles/module.ts | 1 - src/modules/system/settings/module.ts | 1 - src/modules/system/users/module.ts | 1 - src/stores/plugin.ts | 12 ++-- 20 files changed, 95 insertions(+), 106 deletions(-) delete mode 100644 src/composables/usePlugins.ts diff --git a/packages/shared/src/core/plugins.ts b/packages/shared/src/core/plugins.ts index 6fa5e635..1acfa522 100644 --- a/packages/shared/src/core/plugins.ts +++ b/packages/shared/src/core/plugins.ts @@ -1,5 +1,5 @@ -import type { Plugin } from "../types/plugin"; +import type { PluginModule } from "../types/plugin"; -export function definePlugin(plugin: Plugin): Plugin { +export function definePlugin(plugin: PluginModule): PluginModule { return plugin; } diff --git a/packages/shared/src/states/attachment-selector.ts b/packages/shared/src/states/attachment-selector.ts index 17be9910..eecf8cc0 100644 --- a/packages/shared/src/states/attachment-selector.ts +++ b/packages/shared/src/states/attachment-selector.ts @@ -1,10 +1,6 @@ import type { Attachment } from "@halo-dev/api-client"; import type { Component } from "vue"; -export interface AttachmentSelectorPublicState { - providers: AttachmentProvider[]; -} - export type AttachmentLike = | Attachment | string @@ -13,7 +9,7 @@ export type AttachmentLike = type: string; }; -export interface AttachmentProvider { +export interface AttachmentSelectProvider { id: string; label: string; component: Component | string; diff --git a/packages/shared/src/states/pages.ts b/packages/shared/src/states/pages.ts index dc217a2b..a0a721d3 100644 --- a/packages/shared/src/states/pages.ts +++ b/packages/shared/src/states/pages.ts @@ -1,8 +1,4 @@ -export interface PagesPublicState { - functionalPages: FunctionalPagesState[]; -} - -export interface FunctionalPagesState { +export interface FunctionalPage { name: string; path: string; url?: string; diff --git a/packages/shared/src/types/plugin.ts b/packages/shared/src/types/plugin.ts index fc317ea4..5629a4cd 100644 --- a/packages/shared/src/types/plugin.ts +++ b/packages/shared/src/types/plugin.ts @@ -1,22 +1,22 @@ -import type { Component, Ref } from "vue"; +import type { Component } from "vue"; import type { RouteRecordRaw, RouteRecordName } from "vue-router"; -import type { PagesPublicState } from "../states/pages"; -import type { AttachmentSelectorPublicState } from "../states/attachment-selector"; - -export type ExtensionPointName = "PAGES" | "POSTS" | "ATTACHMENT_SELECTOR"; - -export type ExtensionPointState = - | PagesPublicState - | AttachmentSelectorPublicState; +import type { FunctionalPage } from "../states/pages"; +import type { AttachmentSelectProvider } from "../states/attachment-selector"; export interface RouteRecordAppend { parentName: RouteRecordName; route: RouteRecordRaw; } -export interface Plugin { - name: string; +export interface ExtensionPoint { + "page:functional:create"?: () => FunctionalPage[] | Promise; + "attachment:selector:create"?: () => + | AttachmentSelectProvider[] + | Promise; +} + +export interface PluginModule { /** * These components will be registered when plugin is activated. */ @@ -34,7 +34,5 @@ export interface Plugin { routes?: RouteRecordRaw[] | RouteRecordAppend[]; - extensionPoints?: { - [key in ExtensionPointName]?: (state: Ref) => void; - }; + extensionPoints?: ExtensionPoint; } diff --git a/src/composables/usePlugins.ts b/src/composables/usePlugins.ts deleted file mode 100644 index 7c3ce7cd..00000000 --- a/src/composables/usePlugins.ts +++ /dev/null @@ -1,23 +0,0 @@ -import { usePluginStore } from "@/stores/plugin"; -import type { - ExtensionPointName, - ExtensionPointState, -} from "@halo-dev/console-shared"; -import type { Plugin } from "@halo-dev/api-client"; -import type { Ref } from "vue"; - -export function useExtensionPointsState( - point: ExtensionPointName, - state: Ref -) { - const { plugins } = usePluginStore(); - - plugins.forEach((plugin: Plugin) => { - // @ts-ignore - if (!plugin.spec.module?.extensionPoints?.[point]) { - return; - } - // @ts-ignore - plugin.spec.module.extensionPoints[point]?.(state); - }); -} diff --git a/src/main.ts b/src/main.ts index 7833dd03..fa0ffdf3 100644 --- a/src/main.ts +++ b/src/main.ts @@ -3,7 +3,7 @@ import type { DirectiveBinding } from "vue"; import { createPinia } from "pinia"; import App from "./App.vue"; import router from "./router"; -import type { Plugin, RouteRecordAppend } from "@halo-dev/console-shared"; +import type { PluginModule, RouteRecordAppend } from "@halo-dev/console-shared"; import { Toast } from "@halo-dev/components"; import { apiClient } from "@/utils/api-client"; // setup @@ -12,7 +12,7 @@ import { setupComponents } from "./setup/setupComponents"; // core modules import { coreModules } from "./modules"; import { useScriptTag } from "@vueuse/core"; -import { usePluginStore } from "@/stores/plugin"; +import { usePluginModuleStore } from "@/stores/plugin"; import { hasPermission } from "@/utils/permission"; import { useRoleStore } from "@/stores/role"; import type { RouteRecordRaw } from "vue-router"; @@ -26,7 +26,7 @@ setupComponents(app); app.use(createPinia()); -function registerModule(pluginModule: Plugin, core: boolean) { +function registerModule(pluginModule: PluginModule, core: boolean) { if (pluginModule.components) { Object.keys(pluginModule.components).forEach((key) => { const component = pluginModule.components?.[key]; @@ -38,7 +38,6 @@ function registerModule(pluginModule: Plugin, core: boolean) { if (pluginModule.routes) { if (!Array.isArray(pluginModule.routes)) { - console.error(`${pluginModule.name}: Plugin routes must be an array`); return; } @@ -86,7 +85,7 @@ function loadCoreModules() { }); } -const pluginStore = usePluginStore(); +const pluginModuleStore = usePluginModuleStore(); function loadStyle(href: string) { return new Promise(function (resolve, reject) { @@ -144,9 +143,8 @@ async function loadPluginModules() { const pluginModule = window[plugin.metadata.name]; if (pluginModule) { - // @ts-ignore - plugin.spec.module = pluginModule; registerModule(pluginModule, false); + pluginModuleStore.registerPluginModule(pluginModule); } } catch (e) { const message = `${plugin.metadata.name}: 加载插件入口文件失败`; @@ -164,8 +162,6 @@ async function loadPluginModules() { pluginErrorMessages.push(message); } } - - pluginStore.registerPlugin(plugin); } if (pluginErrorMessages.length > 0) { diff --git a/src/modules/contents/attachments/components/AttachmentSelectorModal.vue b/src/modules/contents/attachments/components/AttachmentSelectorModal.vue index 5ffa6086..2766268d 100644 --- a/src/modules/contents/attachments/components/AttachmentSelectorModal.vue +++ b/src/modules/contents/attachments/components/AttachmentSelectorModal.vue @@ -1,13 +1,14 @@