diff --git a/apps/core/src/components/page-detail-editor.tsx b/apps/core/src/components/page-detail-editor.tsx index bfe1605df7..2fb3d78b26 100644 --- a/apps/core/src/components/page-detail-editor.tsx +++ b/apps/core/src/components/page-detail-editor.tsx @@ -9,13 +9,12 @@ import { useBlockSuitePageMeta } from '@toeverything/hooks/use-block-suite-page- import { useBlockSuiteWorkspacePage } from '@toeverything/hooks/use-block-suite-workspace-page'; import type { CallbackMap } from '@toeverything/plugin-infra/entry'; import { - affinePluginsAtom, contentLayoutAtom, editorItemsAtom, rootStore, windowItemsAtom, } from '@toeverything/plugin-infra/manager'; -import type { AffinePlugin, LayoutNode } from '@toeverything/plugin-infra/type'; +import type { LayoutNode } from '@toeverything/plugin-infra/type'; import clsx from 'clsx'; import { useAtomValue, useSetAtom } from 'jotai'; import type { CSSProperties, FC, ReactElement } from 'react'; @@ -164,7 +163,6 @@ const PluginContentAdapter = memo<{ type LayoutPanelProps = { node: LayoutNode; editorProps: PageDetailEditorProps; - plugins: AffinePlugin[]; }; const LayoutPanel = memo(function LayoutPanel( @@ -189,21 +187,13 @@ const LayoutPanel = memo(function LayoutPanel( > - + - + @@ -219,16 +209,11 @@ export const PageDetailEditor: FC = props => { } const layout = useAtomValue(contentLayoutAtom); - const affinePluginsMap = useAtomValue(affinePluginsAtom); - const plugins = useMemo( - () => Object.values(affinePluginsMap), - [affinePluginsMap] - ); return ( <> - + ); diff --git a/apps/electron/scripts/build-layers.mjs b/apps/electron/scripts/build-layers.mjs index f5584a8e3f..f4a37b1139 100644 --- a/apps/electron/scripts/build-layers.mjs +++ b/apps/electron/scripts/build-layers.mjs @@ -15,7 +15,6 @@ if (process.platform === 'win32') { async function buildLayers() { const common = config(); - await esbuild.build(common.workers); await esbuild.build({ ...common.layers, define: { diff --git a/apps/electron/scripts/common.mjs b/apps/electron/scripts/common.mjs index 3a0747c2b2..7e411b9a06 100644 --- a/apps/electron/scripts/common.mjs +++ b/apps/electron/scripts/common.mjs @@ -15,7 +15,7 @@ const DEV_SERVER_URL = process.env.DEV_SERVER_URL; /** @type 'production' | 'development'' */ const mode = (process.env.NODE_ENV = process.env.NODE_ENV || 'development'); -/** @return {{layers: import('esbuild').BuildOptions, workers: import('esbuild').BuildOptions}} */ +/** @return {{layers: import('esbuild').BuildOptions}} */ export const config = () => { const define = Object.fromEntries([ ['process.env.NODE_ENV', `"${mode}"`], @@ -52,23 +52,5 @@ export const config = () => { assetNames: '[name]', treeShaking: true, }, - workers: { - entryPoints: [ - resolve(electronDir, './src/main/workers/plugin.worker.ts'), - ], - entryNames: '[dir]/[name]', - outdir: resolve(electronDir, './dist/workers'), - bundle: true, - target: `node${NODE_MAJOR_VERSION}`, - platform: 'node', - external: ['@toeverything/plugin-infra', 'async-call-rpc'], - define: define, - format: 'cjs', - loader: { - '.node': 'copy', - }, - assetNames: '[name]', - treeShaking: true, - }, }; }; diff --git a/apps/electron/scripts/dev.mjs b/apps/electron/scripts/dev.mjs index 3c5c4c4bbb..99c552d61e 100644 --- a/apps/electron/scripts/dev.mjs +++ b/apps/electron/scripts/dev.mjs @@ -96,37 +96,8 @@ async function watchLayers() { }); } -async function watchWorkers() { - return new Promise(async resolve => { - let initialBuild = false; - - const buildContext = await esbuild.context({ - ...common.workers, - plugins: [ - ...(common.workers.plugins ?? []), - { - name: 'electron-dev:reload-app-on-workers-change', - setup(build) { - build.onEnd(() => { - if (initialBuild) { - console.log(`[workers] has changed, [re]launching electron...`); - spawnOrReloadElectron(); - } else { - resolve(); - initialBuild = true; - } - }); - }, - }, - ], - }); - await buildContext.watch(); - }); -} - async function main() { await watchLayers(); - await watchWorkers(); if (watchMode) { console.log(`Watching for changes...`); diff --git a/apps/electron/scripts/macos-arm64-output-check.mts b/apps/electron/scripts/macos-arm64-output-check.mts index 0b079e2886..9194ed6bb4 100644 --- a/apps/electron/scripts/macos-arm64-output-check.mts +++ b/apps/electron/scripts/macos-arm64-output-check.mts @@ -16,18 +16,10 @@ const outputList = [ 'preload.js', 'affine.darwin-arm64.node', 'plugins', - 'workers', ], ], - ['dist/plugins', ['bookmark-block']], - ['dist/plugins/bookmark-block', ['index.mjs']], - ['dist/workers', ['plugin.worker.js']], - [ - 'node_modules/@toeverything/plugin-infra/dist', - ['manager.js', 'manager.cjs'], - ], - ['node_modules/@blocksuite/global/dist', ['utils.js']], - ['node_modules/jotai', ['vanilla.js']], + ['dist/plugins', ['bookmark']], + ['dist/plugins/bookmark', ['index.js']], ] as [entry: string, expected: string[]][]; await Promise.all( diff --git a/apps/electron/src/main/plugin.ts b/apps/electron/src/main/plugin.ts index 337cda0619..4cc6cb1ce3 100644 --- a/apps/electron/src/main/plugin.ts +++ b/apps/electron/src/main/plugin.ts @@ -1,12 +1,8 @@ import { join, resolve } from 'node:path'; -import { Worker } from 'node:worker_threads'; import { logger } from '@affine/electron/main/logger'; -import { AsyncCall } from 'async-call-rpc'; import { ipcMain } from 'electron'; -import { MessageEventChannel } from './utils'; - declare global { // fixme(himself65): // remove this when bookmark block plugin is migrated to plugin-infra @@ -15,56 +11,25 @@ declare global { } export function registerPlugin() { - const pluginWorkerPath = join(__dirname, './workers/plugin.worker.js'); - const asyncCall = AsyncCall< - Record PromiseLike> - >( - { - log: (...args: any[]) => { - logger.log('Plugin Worker', ...args); - }, - }, - { - channel: new MessageEventChannel(new Worker(pluginWorkerPath)), - } - ); - globalThis.asyncCall = asyncCall; logger.info('import plugin manager'); - import('@toeverything/plugin-infra/manager') - .then(({ rootStore, affinePluginsAtom }) => { - logger.info('import plugin manager'); - const bookmarkPluginPath = join( - process.env.PLUGIN_DIR ?? resolve(__dirname, './plugins'), - './bookmark-block/index.mjs' - ); - logger.info('bookmark plugin path:', bookmarkPluginPath); - import('file://' + bookmarkPluginPath); - let dispose: () => void = () => { - // noop - }; - rootStore.sub(affinePluginsAtom, () => { - dispose(); - const plugins = rootStore.get(affinePluginsAtom); - Object.values(plugins).forEach(plugin => { - logger.info('register plugin', plugin.definition.id); - plugin.definition.commands.forEach(command => { - logger.info('register plugin command', command); - ipcMain.handle(command, (event, ...args) => - asyncCall[command](...args) - ); - }); - }); - dispose = () => { - Object.values(plugins).forEach(plugin => { - plugin.definition.commands.forEach(command => { - logger.info('unregister plugin command', command); - ipcMain.removeHandler(command); - }); - }); - }; - }); - }) - .catch(error => { - logger.error('import plugin manager error', error); - }); + globalThis.asyncCall = {}; + const bookmarkPluginPath = join( + process.env.PLUGIN_DIR ?? resolve(__dirname, './plugins'), + './bookmark/index.js' + ); + logger.info('bookmark plugin path:', bookmarkPluginPath); + // eslint-disable-next-line @typescript-eslint/no-var-requires + const { entry } = require(bookmarkPluginPath); + + entry({ + registerCommand: (command: string, handler: (...args: any[]) => any) => { + logger.info('register plugin command', command); + ipcMain.handle(command, (event, ...args) => handler(...args)); + globalThis.asyncCall[command] = handler; + }, + registerCommands: (command: string) => { + ipcMain.removeHandler(command); + delete globalThis.asyncCall[command]; + }, + }); } diff --git a/apps/electron/src/main/workers/plugin.worker.ts b/apps/electron/src/main/workers/plugin.worker.ts deleted file mode 100644 index a0af86929d..0000000000 --- a/apps/electron/src/main/workers/plugin.worker.ts +++ /dev/null @@ -1,69 +0,0 @@ -import { join, resolve } from 'node:path'; -import { parentPort } from 'node:worker_threads'; - -import { AsyncCall } from 'async-call-rpc'; - -import { MessageEventChannel } from '../utils'; - -const commandProxy: Record Promise> = {}; - -if (!parentPort) { - throw new Error('parentPort is undefined'); -} - -const mainThread = AsyncCall<{ - log: (...args: any[]) => Promise; -}>(commandProxy, { - channel: new MessageEventChannel(parentPort), -}); - -globalThis.console.log = mainThread.log; -globalThis.console.error = mainThread.log; -globalThis.console.info = mainThread.log; -globalThis.console.debug = mainThread.log; -globalThis.console.warn = mainThread.log; - -console.log('import plugin infra'); - -import('@toeverything/plugin-infra/manager') - .then(({ rootStore, affinePluginsAtom }) => { - const bookmarkPluginPath = join( - process.env.PLUGIN_DIR ?? resolve(__dirname, '../plugins'), - './bookmark-block/index.mjs' - ); - - console.log('import bookmark plugin', bookmarkPluginPath); - - import('file://' + bookmarkPluginPath).catch(console.log); - rootStore.sub(affinePluginsAtom, () => { - const plugins = rootStore.get(affinePluginsAtom); - Object.values(plugins).forEach(plugin => { - console.log('handle plugin', plugin.definition.id); - if (plugin.serverAdapter) { - try { - plugin.serverAdapter({ - registerCommand: (command, fn) => { - console.log('register command', command); - commandProxy[command] = fn; - }, - unregisterCommand: command => { - console.log('unregister command', command); - delete commandProxy[command]; - }, - }); - } catch (e) { - console.log( - 'error when handle plugin', - plugin.definition.id, - `${e}` - ); - } - } else { - console.log('no server adapter, skipping.'); - } - }); - }); - }) - .catch(err => { - console.error(err); - }); diff --git a/package.json b/package.json index b524898855..3f8138deb1 100644 --- a/package.json +++ b/package.json @@ -25,7 +25,7 @@ "build:electron": "yarn nx build @affine/electron", "build:storage": "yarn nx run-many -t build -p @affine/storage", "build:infra": "yarn nx run-many -t build -p plugin-infra infra", - "build:plugins": "yarn workspace @affine/bookmark-block build && node ./scripts/build-plugins.mjs", + "build:plugins": "node ./scripts/build-plugins.mjs", "build:storybook": "yarn nx build @affine/storybook", "start:web-static": "yarn workspace @affine/core static-server", "start:storybook": "yarn exec serve apps/storybook/storybook-static -l 6006", diff --git a/packages/cli/src/bin/dev-plugin.ts b/packages/cli/src/bin/dev-plugin.ts index 951868228e..8e650047fd 100644 --- a/packages/cli/src/bin/dev-plugin.ts +++ b/packages/cli/src/bin/dev-plugin.ts @@ -40,6 +40,7 @@ const packageJsonSchema = z.object({ release: z.boolean(), entry: z.object({ core: z.string(), + server: z.string().optional(), }), }), }); @@ -59,6 +60,9 @@ const external = [ // css /^@vanilla-extract/, + + // remove this when bookmark plugin is ready + 'link-preview-js', ]; const allPluginDir = path.resolve(projectRoot, 'plugins'); @@ -91,7 +95,7 @@ const metadata: Metadata = { assets: new Set(), }; -const outDir = path.resolve( +const coreOutDir = path.resolve( projectRoot, 'apps', 'core', @@ -100,15 +104,43 @@ const outDir = path.resolve( plugin ); -const pluginListJsonPath = path.resolve(outDir, '..', 'plugin-list.json'); +const serverOutDir = path.resolve( + projectRoot, + 'apps', + 'electron', + 'dist', + 'plugins', + plugin +); + +const pluginListJsonPath = path.resolve(coreOutDir, '..', 'plugin-list.json'); const coreEntry = path.resolve(pluginDir, json.affinePlugin.entry.core); +if (json.affinePlugin.entry.server) { + const serverEntry = path.resolve(pluginDir, json.affinePlugin.entry.server); + await build({ + build: { + watch: isWatch ? {} : undefined, + minify: false, + outDir: serverOutDir, + emptyOutDir: true, + lib: { + entry: serverEntry, + fileName: 'index', + formats: ['cjs'], + }, + rollupOptions: { + external, + }, + }, + }); +} await build({ build: { watch: isWatch ? {} : undefined, minify: false, - outDir, + outDir: coreOutDir, emptyOutDir: true, lib: { entry: coreEntry, diff --git a/packages/plugin-infra/src/manager.ts b/packages/plugin-infra/src/manager.ts index 6077b47d3e..d1bc3ab9c9 100644 --- a/packages/plugin-infra/src/manager.ts +++ b/packages/plugin-infra/src/manager.ts @@ -4,14 +4,7 @@ import { atom, createStore } from 'jotai/vanilla'; import { getWorkspace, waitForWorkspace } from './__internal__/workspace'; import type { CallbackMap } from './entry'; -import type { - AffinePlugin, - Definition, - ExpectedLayout, - ServerAdapter, -} from './type'; -import type { Loader, PluginUIAdapter } from './type'; -import type { PluginBlockSuiteAdapter } from './type'; +import type { ExpectedLayout } from './type'; // global store export const rootStore = createStore(); @@ -24,10 +17,6 @@ export const editorItemsAtom = atom>({}); export const registeredPluginAtom = atom([]); export const windowItemsAtom = atom>({}); -/** - * @deprecated - */ -export const affinePluginsAtom = atom>>({}); export const currentWorkspaceIdAtom = atom(null); export const currentPageIdAtom = atom(null); export const currentWorkspaceAtom = atom>(async get => { @@ -83,39 +72,3 @@ export const contentLayoutAtom = atom< }); } ); - -export function definePlugin( - definition: Definition, - uiAdapterLoader?: Loader>, - blockSuiteAdapter?: Loader>, - serverAdapter?: Loader -) { - const basePlugin = { - definition, - uiAdapter: undefined, - blockSuiteAdapter: undefined, - }; - - rootStore.set(affinePluginsAtom, plugins => ({ - ...plugins, - [definition.id]: basePlugin, - })); - - if (serverAdapter) { - console.log('register server adapter'); - serverAdapter - .load() - .then(({ default: adapter }) => { - rootStore.set(affinePluginsAtom, plugins => ({ - ...plugins, - [definition.id]: { - ...basePlugin, - serverAdapter: adapter, - }, - })); - }) - .catch(err => { - console.error(err); - }); - } -} diff --git a/packages/plugin-infra/src/server.ts b/packages/plugin-infra/src/server.ts new file mode 100644 index 0000000000..f7f88e3c48 --- /dev/null +++ b/packages/plugin-infra/src/server.ts @@ -0,0 +1,4 @@ +export interface ServerContext { + registerCommand: (command: string, fn: (...args: any[]) => any) => void; + unregisterCommand: (command: string) => void; +} diff --git a/packages/plugin-infra/src/type.ts b/packages/plugin-infra/src/type.ts index a18962622a..5f7b4dbd22 100644 --- a/packages/plugin-infra/src/type.ts +++ b/packages/plugin-infra/src/type.ts @@ -1,84 +1,4 @@ -// eslint-disable-next-line @typescript-eslint/triple-slash-reference -/// - -/** - * AFFiNE Plugin System Types - */ - -import type { EditorContainer } from '@blocksuite/editor'; -import type { Workspace } from '@blocksuite/store'; -import type { Page } from '@playwright/test'; import type { WritableAtom } from 'jotai'; -import type { ReactElement } from 'react'; - -/** - * A code loader interface of the plugin API. - * - * Plugin should be lazy-loaded. If a plugin is not enabled, it will not be loaded into the Mask. - * - * @example - * ```ts - * const loader = { - * load: () => import("./code"), - * hotModuleReload: hot => import.meta.webpackHot && import.meta.webpackHot.accept('./code', () => hot(import("./code"))) - * } - * ``` - * - * The `./code` should use `export default` to export what loader expects. - */ -export interface Loader { - /** - * The `load()` function will be called on demand. - * - * It should not have side effects (e.g. start some daemon, start a new HTTP request or WebSocket client), - * those work should be in the `.init()` function. - * @returns the actual definition of this plugin - * @example load: () => import('./path') - */ - load(): Promise<{ - default: DeferredModule; - }>; - - /** - * This provides the functionality for hot module reload on the plugin. - * When the callback is called, the old instance of the plugin will be unloaded, then the new instance will be init. - * @example hotModuleReload: hot => import.meta.webpackHot && import.meta.webpackHot.accept('./path', () => hot(import('./path'))) - */ - hotModuleReload( - onHot: ( - hot: Promise<{ - default: DeferredModule; - }> - ) => void - ): void; -} - -// eslint-disable-next-line @typescript-eslint/no-empty-interface, @typescript-eslint/no-unused-vars -interface AFFiNEPlugin { - // todo: add more fields -} - -export interface I18NStringField { - /** The i18n key of the string content. */ - i18nKey?: string; - /** The fallback content to display if there is no i18n string found. */ - fallback: string; -} - -/** The publisher of the plugin */ -export interface Publisher { - /** The name of the publisher */ - name: I18NStringField; - /** URL of the publisher */ - link: string; -} - -/** For what stage the plugin */ -export enum ReleaseStage { - NIGHTLY = 'nightly', - PROD = 'prod', - DEV = 'dev', -} export type LayoutDirection = 'horizontal' | 'vertical'; export type LayoutNode = LayoutParentNode | string; @@ -107,85 +27,3 @@ export type ContentLayoutAtom = WritableAtom< [SetStateAction], void >; - -export type Definition = { - /** - * ID of the plugin. It should be unique. - * @example "com.affine.pro" - */ - id: ID; - /** - * The human-readable name of the plugin. - * @example { i18nKey: "name", fallback: "Never gonna give you up" } - */ - name: I18NStringField; - /** - * A brief description of this plugin. - * @example { i18nKey: "description", fallback: "This plugin is going to replace every link in the page to https://www.youtube.com/watch?v=dQw4w9WgXcQ" } - */ - description?: I18NStringField; - /** - * Publisher of this plugin. - * @example { link: "https://affine.pro", name: { fallback: "AFFiNE", i18nKey: "org_name" } } - */ - publisher?: Publisher; - - /** - * The version of this plugin. - * @example "1.0.0" - */ - version: string; - - /** - * The loader of this plugin. - * @example ReleaseStage.PROD - */ - stage: ReleaseStage; - - /** - * Registered commands - */ - commands: string[]; -}; - -// todo(himself65): support Vue.js -export type Adapter> = ( - props: Props -) => ReactElement; - -export type AffinePluginContext = { - toast: (text: string) => void; -}; - -export type BaseProps = { - contentLayoutAtom: ContentLayoutAtom; -}; - -export type PluginUIAdapter = { - sidebarItem: Adapter; - headerItem: Adapter; - detailContent: Adapter; - debugContent: Adapter>; -}; - -type Cleanup = () => void; - -export type PluginBlockSuiteAdapter = { - storeDecorator: (currentWorkspace: Workspace) => Promise; - pageDecorator: (currentPage: Page) => Cleanup; - uiDecorator: (root: EditorContainer) => Cleanup; -}; - -type AFFiNEServer = { - registerCommand: (command: string, fn: (...args: any[]) => any) => void; - unregisterCommand: (command: string) => void; -}; - -export type ServerAdapter = (affine: AFFiNEServer) => () => void; - -export type AffinePlugin = { - definition: Definition; - uiAdapter: undefined; - blockSuiteAdapter: undefined; - serverAdapter?: ServerAdapter; -}; diff --git a/packages/plugin-infra/src/webpack-hmr.d.ts b/packages/plugin-infra/src/webpack-hmr.d.ts deleted file mode 100644 index 03c144c22f..0000000000 --- a/packages/plugin-infra/src/webpack-hmr.d.ts +++ /dev/null @@ -1,224 +0,0 @@ -// Copied from @types/webpack-env -/** - * Webpack module API - variables and global functions available inside modules - */ - -declare namespace __WebpackModuleApi { - type ModuleId = any; - interface HotNotifierInfo { - type: - | 'self-declined' - | 'declined' - | 'unaccepted' - | 'accepted' - | 'disposed' - | 'accept-errored' - | 'self-accept-errored' - | 'self-accept-error-handler-errored'; - /** - * The module in question. - */ - moduleId: number; - /** - * For errors: the module id owning the accept handler. - */ - dependencyId?: number | undefined; - /** - * For declined/accepted/unaccepted: the chain from where the update was propagated. - */ - chain?: number[] | undefined; - /** - * For declined: the module id of the declining parent - */ - parentId?: number | undefined; - /** - * For accepted: the modules that are outdated and will be disposed - */ - outdatedModules?: number[] | undefined; - /** - * For accepted: The location of accept handlers that will handle the update - */ - outdatedDependencies?: - | { - [dependencyId: number]: number[]; - } - | undefined; - /** - * For errors: the thrown error - */ - error?: Error | undefined; - /** - * For self-accept-error-handler-errored: the error thrown by the module - * before the error handler tried to handle it. - */ - originalError?: Error | undefined; - } - - interface Hot { - /** - * Accept code updates for the specified dependencies. The callback is called when dependencies were replaced. - * @param dependencies - * @param callback - * @param errorHandler - */ - accept( - dependencies: string[], - callback?: (updatedDependencies: ModuleId[]) => void, - errorHandler?: (err: Error) => void - ): void; - /** - * Accept code updates for the specified dependencies. The callback is called when dependencies were replaced. - * @param dependency - * @param callback - * @param errorHandler - */ - accept( - dependency: string, - callback?: () => void, - errorHandler?: (err: Error) => void - ): void; - /** - * Accept code updates for this module without notification of parents. - * This should only be used if the module doesn’t export anything. - * The errHandler can be used to handle errors that occur while loading the updated module. - * @param errHandler - */ - accept(errHandler?: (err: Error) => void): void; - /** - * Do not accept updates for the specified dependencies. If any dependencies is updated, the code update fails with code "decline". - */ - decline(dependencies: string[]): void; - /** - * Do not accept updates for the specified dependencies. If any dependencies is updated, the code update fails with code "decline". - */ - decline(dependency: string): void; - /** - * Flag the current module as not update-able. If updated the update code would fail with code "decline". - */ - decline(): void; - /** - * Add a one time handler, which is executed when the current module code is replaced. - * Here you should destroy/remove any persistent resource you have claimed/created. - * If you want to transfer state to the new module, add it to data object. - * The data will be available at module.hot.data on the new module. - * @param callback - */ - dispose(callback: (data: any) => void): void; - dispose(callback: (data: T) => void): void; - /** - * Add a one time handler, which is executed when the current module code is replaced. - * Here you should destroy/remove any persistent resource you have claimed/created. - * If you want to transfer state to the new module, add it to data object. - * The data will be available at module.hot.data on the new module. - * @param callback - */ - addDisposeHandler(callback: (data: any) => void): void; - addDisposeHandler(callback: (data: T) => void): void; - /** - * Remove a handler. - * This can useful to add a temporary dispose handler. You could i. e. replace code while in the middle of a multi-step async function. - * @param callback - */ - removeDisposeHandler(callback: (data: any) => void): void; - removeDisposeHandler(callback: (data: T) => void): void; - /** - * Throws an exceptions if status() is not idle. - * Check all currently loaded modules for updates and apply updates if found. - * If no update was found, the callback is called with null. - * If autoApply is truthy the callback will be called with all modules that were disposed. - * apply() is automatically called with autoApply as options parameter. - * If autoApply is not set the callback will be called with all modules that will be disposed on apply(). - * @param autoApply - * @param callback - */ - check( - autoApply: boolean, - callback: (err: Error, outdatedModules: ModuleId[]) => void - ): void; - /** - * Throws an exceptions if status() is not idle. - * Check all currently loaded modules for updates and apply updates if found. - * If no update was found, the callback is called with null. - * The callback will be called with all modules that will be disposed on apply(). - * @param callback - */ - check(callback: (err: Error, outdatedModules: ModuleId[]) => void): void; - /** - * If status() != "ready" it throws an error. - * Continue the update process. - * @param options - * @param callback - */ - apply( - options: AcceptOptions, - callback: (err: Error, outdatedModules: ModuleId[]) => void - ): void; - /** - * If status() != "ready" it throws an error. - * Continue the update process. - * @param callback - */ - apply(callback: (err: Error, outdatedModules: ModuleId[]) => void): void; - /** - * Return one of idle, check, watch, watch-delay, prepare, ready, dispose, apply, abort or fail. - */ - status(): string; - /** Register a callback on status change. */ - status(callback: (status: string) => void): void; - /** Register a callback on status change. */ - addStatusHandler(callback: (status: string) => void): void; - /** - * Remove a registered status change handler. - * @param callback - */ - removeStatusHandler(callback: (status: string) => void): void; - - active: boolean; - data: any; - } - - interface AcceptOptions { - /** - * If true the update process continues even if some modules are not accepted (and would bubble to the entry point). - */ - ignoreUnaccepted?: boolean | undefined; - /** - * Ignore changes made to declined modules. - */ - ignoreDeclined?: boolean | undefined; - /** - * Ignore errors throw in accept handlers, error handlers and while reevaluating module. - */ - ignoreErrored?: boolean | undefined; - /** - * Notifier for declined modules. - */ - onDeclined?: ((info: HotNotifierInfo) => void) | undefined; - /** - * Notifier for unaccepted modules. - */ - onUnaccepted?: ((info: HotNotifierInfo) => void) | undefined; - /** - * Notifier for accepted modules. - */ - onAccepted?: ((info: HotNotifierInfo) => void) | undefined; - /** - * Notifier for disposed modules. - */ - onDisposed?: ((info: HotNotifierInfo) => void) | undefined; - /** - * Notifier for errors. - */ - onErrored?: ((info: HotNotifierInfo) => void) | undefined; - /** - * Indicates that apply() is automatically called by check function - */ - autoApply?: boolean | undefined; - } -} -interface ImportMeta { - /** - * `import.meta.webpackHot` is an alias for` module.hot` which is also available in strict ESM - */ - webpackHot?: __WebpackModuleApi.Hot | undefined; -} diff --git a/plugins/bookmark-block/README.md b/plugins/bookmark-block/README.md deleted file mode 100644 index 09faa53788..0000000000 --- a/plugins/bookmark-block/README.md +++ /dev/null @@ -1,7 +0,0 @@ -# `@affine/bookmark-block` - -> Moved to [@affine/bookmark-plugin](../bookmark) -> -> A block for bookmarking a website - -![preview](assets/preview.png) diff --git a/plugins/bookmark-block/assets/preview.png b/plugins/bookmark-block/assets/preview.png deleted file mode 100644 index 7b5ea5c0a9..0000000000 Binary files a/plugins/bookmark-block/assets/preview.png and /dev/null differ diff --git a/plugins/bookmark-block/package.json b/plugins/bookmark-block/package.json deleted file mode 100644 index 8fc4155802..0000000000 --- a/plugins/bookmark-block/package.json +++ /dev/null @@ -1,19 +0,0 @@ -{ - "name": "@affine/bookmark-block", - "private": true, - "main": "./src/index.ts", - "module": "./src/index.ts", - "exports": { - ".": "./src/index.ts", - "./server": "./src/server.ts" - }, - "scripts": { - "build": "node ./scripts/build.mjs", - "dev": "node ./scripts/dev.mjs" - }, - "dependencies": { - "@toeverything/plugin-infra": "workspace:*", - "link-preview-js": "^3.0.4" - }, - "version": "0.7.0-canary.52" -} diff --git a/plugins/bookmark-block/project.json b/plugins/bookmark-block/project.json deleted file mode 100644 index b838f0aac5..0000000000 --- a/plugins/bookmark-block/project.json +++ /dev/null @@ -1,17 +0,0 @@ -{ - "name": "@affine/bookmark-block", - "$schema": "../../node_modules/nx/schemas/project-schema.json", - "projectType": "library", - "root": "plugins/bookmark-block", - "sourceRoot": "plugins/bookmark-block/src", - "targets": { - "build": { - "executor": "nx:run-script", - "dependsOn": ["^build"], - "options": { - "script": "build" - }, - "outputs": ["{workspaceRoot}/apps/electron/dist/plugins/bookmark-block"] - } - } -} diff --git a/plugins/bookmark-block/scripts/build.mjs b/plugins/bookmark-block/scripts/build.mjs deleted file mode 100755 index 4c73377a4e..0000000000 --- a/plugins/bookmark-block/scripts/build.mjs +++ /dev/null @@ -1,20 +0,0 @@ -#!/usr/bin/env node -import { build } from 'esbuild'; - -import { definePluginServerConfig } from './utils.mjs'; - -await build({ - ...definePluginServerConfig('bookmark-block'), - external: [ - // server.ts - 'link-preview-js', - // ui.ts - '@toeverything/plugin-infra', - '@affine/component', - '@blocksuite/store', - '@blocksuite/blocks', - 'react', - 'react-dom', - 'foxact', - ], -}); diff --git a/plugins/bookmark-block/scripts/dev.mjs b/plugins/bookmark-block/scripts/dev.mjs deleted file mode 100755 index e8159757e8..0000000000 --- a/plugins/bookmark-block/scripts/dev.mjs +++ /dev/null @@ -1,22 +0,0 @@ -#!/usr/bin/env node -import { context } from 'esbuild'; - -import { definePluginServerConfig } from './utils.mjs'; - -const plugin = await context({ - ...definePluginServerConfig('bookmark-block'), - external: [ - // server.ts - 'link-preview-js', - // ui.ts - '@toeverything/plugin-infra', - '@affine/component', - '@blocksuite/store', - '@blocksuite/blocks', - 'react', - 'react-dom', - 'foxact', - ], -}); - -await plugin.watch(); diff --git a/plugins/bookmark-block/scripts/utils.mjs b/plugins/bookmark-block/scripts/utils.mjs deleted file mode 100644 index e58e57f5cf..0000000000 --- a/plugins/bookmark-block/scripts/utils.mjs +++ /dev/null @@ -1,34 +0,0 @@ -import { resolve } from 'node:path'; -import { fileURLToPath } from 'node:url'; - -export const rootDir = fileURLToPath(new URL('../../..', import.meta.url)); -export const electronOutputDir = resolve( - rootDir, - 'apps', - 'electron', - 'dist', - 'plugins' -); -export const pluginDir = resolve(rootDir, 'plugins'); - -/** - * - * @param pluginDirName {string} - * @return {import('esbuild').BuildOptions} - */ -export function definePluginServerConfig(pluginDirName) { - const pluginRootDir = resolve(pluginDir, pluginDirName); - const mainEntryFile = resolve(pluginRootDir, 'src/index.ts'); - const serverOutputDir = resolve(electronOutputDir, pluginDirName); - return { - entryPoints: [mainEntryFile], - platform: 'neutral', - format: 'esm', - outExtension: { - '.js': '.mjs', - }, - outdir: serverOutputDir, - bundle: true, - splitting: true, - }; -} diff --git a/plugins/bookmark-block/src/index.ts b/plugins/bookmark-block/src/index.ts deleted file mode 100644 index 97faf8cbe5..0000000000 --- a/plugins/bookmark-block/src/index.ts +++ /dev/null @@ -1,30 +0,0 @@ -import { definePlugin } from '@toeverything/plugin-infra/manager'; -import { ReleaseStage } from '@toeverything/plugin-infra/type'; - -definePlugin( - { - id: 'com.blocksuite.bookmark-block', - name: { - fallback: 'BlockSuite Bookmark Block', - i18nKey: 'com.blocksuite.bookmark.name', - }, - description: { - fallback: 'Bookmark block', - }, - publisher: { - name: { - fallback: 'AFFiNE', - }, - link: 'https://affine.pro', - }, - stage: ReleaseStage.NIGHTLY, - version: '0.0.1', - commands: ['com.blocksuite.bookmark-block.get-bookmark-data-by-link'], - }, - undefined, - undefined, - { - load: () => import('./server'), - hotModuleReload: onHot => onHot(import('./server')), - } -); diff --git a/plugins/bookmark-block/tsconfig.json b/plugins/bookmark-block/tsconfig.json deleted file mode 100644 index 1c21e13084..0000000000 --- a/plugins/bookmark-block/tsconfig.json +++ /dev/null @@ -1,16 +0,0 @@ -{ - "extends": "../../tsconfig.json", - "include": ["./src"], - "compilerOptions": { - "noEmit": false, - "outDir": "lib" - }, - "references": [ - { - "path": "../../packages/component" - }, - { - "path": "../../packages/plugin-infra" - } - ] -} diff --git a/plugins/bookmark/package.json b/plugins/bookmark/package.json index 47ec49495d..f8f29c0da6 100644 --- a/plugins/bookmark/package.json +++ b/plugins/bookmark/package.json @@ -4,13 +4,15 @@ "affinePlugin": { "release": true, "entry": { - "core": "./src/index.ts" + "core": "./src/index.ts", + "server": "./src/server.ts" } }, "dependencies": { "@affine/component": "workspace:*", "@blocksuite/icons": "^2.1.27", "@toeverything/plugin-infra": "workspace:*", - "foxact": "^0.2.17" + "foxact": "^0.2.17", + "link-preview-js": "^3.0.4" } } diff --git a/plugins/bookmark-block/src/server.ts b/plugins/bookmark/src/server.ts similarity index 88% rename from plugins/bookmark-block/src/server.ts rename to plugins/bookmark/src/server.ts index 6e95ea381a..c6870fa0af 100644 --- a/plugins/bookmark-block/src/server.ts +++ b/plugins/bookmark/src/server.ts @@ -1,4 +1,4 @@ -import type { ServerAdapter } from '@toeverything/plugin-infra/type'; +import type { ServerContext } from '@toeverything/plugin-infra/server'; import { getLinkPreview } from 'link-preview-js'; type MetaData = { @@ -27,8 +27,8 @@ export interface PreviewType { favicons: string[]; } -const adapter: ServerAdapter = affine => { - affine.registerCommand( +export const entry = (context: ServerContext) => { + context.registerCommand( 'com.blocksuite.bookmark-block.get-bookmark-data-by-link', async (url: string): Promise => { const previewData = (await getLinkPreview(url, { @@ -58,10 +58,8 @@ const adapter: ServerAdapter = affine => { } ); return () => { - affine.unregisterCommand( + context.unregisterCommand( 'com.blocksuite.bookmark-block.get-bookmark-data-by-link' ); }; }; - -export default adapter; diff --git a/plugins/copilot/src/UI/debug-content.tsx b/plugins/copilot/src/UI/debug-content.tsx index 8bedb984de..2bc178ad9f 100644 --- a/plugins/copilot/src/UI/debug-content.tsx +++ b/plugins/copilot/src/UI/debug-content.tsx @@ -1,14 +1,13 @@ import { Button, FlexWrapper, Input } from '@affine/component'; import { SettingRow } from '@affine/component/setting-components'; import { SettingWrapper } from '@affine/component/setting-components'; -import type { PluginUIAdapter } from '@toeverything/plugin-infra/type'; import { useAtom } from 'jotai'; -import { useCallback } from 'react'; +import { type ReactElement, useCallback } from 'react'; import { openAIApiKeyAtom } from '../core/hooks'; import { conversationHistoryDBName } from '../core/langchain/message-history'; -export const DebugContent: PluginUIAdapter['debugContent'] = () => { +export const DebugContent = (): ReactElement => { const [key, setKey] = useAtom(openAIApiKeyAtom); const desc = ( <> diff --git a/plugins/copilot/src/UI/index.ts b/plugins/copilot/src/UI/index.ts deleted file mode 100644 index 4a1d49cecd..0000000000 --- a/plugins/copilot/src/UI/index.ts +++ /dev/null @@ -1,12 +0,0 @@ -import type { PluginUIAdapter } from '@toeverything/plugin-infra/type'; -import { createElement } from 'react'; - -import { DebugContent } from './debug-content'; -import { DetailContent } from './detail-content'; -import { HeaderItem } from './header-item'; - -export default { - headerItem: props => createElement(HeaderItem, props), - detailContent: props => createElement(DetailContent, props), - debugContent: props => createElement(DebugContent, props), -} satisfies Partial; diff --git a/tsconfig.json b/tsconfig.json index 5172333b43..7d795d0ddb 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -114,9 +114,6 @@ { "path": "./packages/plugin-infra" }, - { - "path": "./plugins/bookmark-block" - }, { "path": "./plugins/bookmark" }, diff --git a/yarn.lock b/yarn.lock index 28b5d8c966..2f961e63ad 100644 --- a/yarn.lock +++ b/yarn.lock @@ -64,15 +64,6 @@ __metadata: languageName: unknown linkType: soft -"@affine/bookmark-block@workspace:plugins/bookmark-block": - version: 0.0.0-use.local - resolution: "@affine/bookmark-block@workspace:plugins/bookmark-block" - dependencies: - "@toeverything/plugin-infra": "workspace:*" - link-preview-js: ^3.0.4 - languageName: unknown - linkType: soft - "@affine/bookmark-plugin@workspace:plugins/bookmark": version: 0.0.0-use.local resolution: "@affine/bookmark-plugin@workspace:plugins/bookmark" @@ -81,6 +72,7 @@ __metadata: "@blocksuite/icons": ^2.1.27 "@toeverything/plugin-infra": "workspace:*" foxact: ^0.2.17 + link-preview-js: ^3.0.4 languageName: unknown linkType: soft