From 265ee8166697e132e577e0a8b9a227612e255a2a Mon Sep 17 00:00:00 2001 From: EYHN Date: Wed, 27 Dec 2023 02:49:59 +0000 Subject: [PATCH] refactor(infra): remove old plugin system (#5411) plugin system need redesign --- .eslintignore | 2 - .eslintrc.js | 2 - .github/actions/setup-node/action.yml | 9 - .github/labeler.yml | 15 - .github/workflows/build-test.yml | 41 - .github/workflows/deploy.yml | 2 - .github/workflows/publish-storybook.yml | 2 - .github/workflows/release-desktop.yml | 5 - README.md | 14 - docs/BUILDING.md | 8 +- docs/contributing/tutorial.md | 1 - package.json | 2 - packages/common/env/src/global.ts | 2 - packages/common/infra/package.json | 1 - .../common/infra/src/__internal__/plugin.ts | 53 - packages/common/infra/src/atom/index.ts | 4 - packages/common/infra/tsconfig.json | 3 - packages/common/infra/vite.config.ts | 1 - packages/common/sdk/.gitignore | 4 - packages/common/sdk/package.json | 37 - packages/common/sdk/project.json | 22 - packages/common/sdk/src/entry.ts | 64 - packages/common/sdk/src/server.ts | 4 - packages/common/sdk/tsconfig.json | 15 - packages/common/sdk/tsconfig.node.json | 12 - packages/common/sdk/vite.config.ts | 23 - .../frontend/core/.webpack/runtime-config.ts | 18 - .../frontend/core/.webpack/webpack.config.ts | 16 +- .../frontend/core/src/_plugin/index.test.tsx | 50 - .../bootstrap/plugins/endowments/fercher.ts | 86 -- .../src/bootstrap/plugins/endowments/timer.ts | 110 -- .../bootstrap/plugins/setup-imports-map.ts | 22 - .../core/src/bootstrap/plugins/setup.ts | 483 ------- .../core/src/bootstrap/register-plugins.ts | 134 -- .../general-setting/plugins/index.tsx | 97 -- .../general-setting/plugins/style.css.ts | 16 - .../image-preview}/hooks/use-zoom.tsx | 0 .../components/image-preview}/index.css.ts | 0 .../components/image-preview}/index.jotai.ts | 0 .../src/components/image-preview}/index.tsx | 10 +- .../src/components/page-detail-editor.tsx | 25 - .../components/pure/plugin-header/index.tsx | 44 - .../pure/plugin-header/styles.css.ts | 8 - packages/frontend/core/src/index.tsx | 8 - .../workspace/detail-page/detail-page.tsx | 5 + .../core/src/pages/workspace/trash-page.tsx | 1 - packages/frontend/core/tsconfig.json | 3 - packages/frontend/electron/package.json | 5 - packages/frontend/electron/project.json | 9 +- packages/frontend/electron/scripts/common.ts | 9 +- .../electron/scripts/generate-assets.ts | 8 - packages/frontend/electron/tsconfig.json | 3 - packages/frontend/electron/tsconfig.node.json | 6 +- packages/plugins/copilot/README.md | 3 - packages/plugins/copilot/package.json | 41 - packages/plugins/copilot/project.json | 26 - .../plugins/copilot/src/UI/debug-content.tsx | 37 - .../plugins/copilot/src/UI/detail-content.tsx | 72 -- .../plugins/copilot/src/UI/header-item.tsx | 47 - packages/plugins/copilot/src/UI/index.css.ts | 43 - packages/plugins/copilot/src/core/chat.ts | 101 -- .../components/conversation-list/index.css.ts | 9 - .../components/conversation-list/index.tsx | 22 - .../core/components/conversation/index.css.ts | 80 -- .../core/components/conversation/index.tsx | 73 -- .../copilot/src/core/components/divider.tsx | 5 - .../core/components/following-up/index.css.ts | 20 - .../core/components/following-up/index.tsx | 19 - .../plugins/copilot/src/core/hooks/index.ts | 179 --- .../src/core/langchain/message-history.ts | 154 --- .../plugins/copilot/src/core/prompts/index.ts | 30 - .../copilot/src/core/prompts/output-parser.ts | 8 - packages/plugins/copilot/src/index.ts | 40 - packages/plugins/copilot/tsconfig.json | 19 - packages/plugins/hello-world/package.json | 25 - packages/plugins/hello-world/project.json | 26 - packages/plugins/hello-world/src/app.tsx | 18 - packages/plugins/hello-world/src/index.ts | 32 - packages/plugins/hello-world/tsconfig.json | 17 - packages/plugins/image-preview/package.json | 29 - packages/plugins/image-preview/project.json | 26 - packages/plugins/image-preview/src/app.tsx | 11 - .../image-preview/src/component/toast.ts | 21 - packages/plugins/image-preview/src/index.ts | 18 - packages/plugins/image-preview/tsconfig.json | 17 - .../plugins/vue-hello-world/.eslintrc.json | 10 - packages/plugins/vue-hello-world/package.json | 26 - packages/plugins/vue-hello-world/project.json | 26 - packages/plugins/vue-hello-world/src/app.vue | 17 - .../plugins/vue-hello-world/src/global.d.ts | 5 - packages/plugins/vue-hello-world/src/index.ts | 18 - .../plugins/vue-hello-world/tsconfig.json | 14 - tests/affine-plugin/e2e/basic.spec.ts | 40 - tests/affine-plugin/package.json | 13 - tests/affine-plugin/playwright.config.ts | 63 - tests/affine-plugin/tsconfig.json | 16 - tests/kit/utils/load-page.ts | 4 - tests/storybook/.storybook/preview.tsx | 5 - tests/storybook/project.json | 1 - .../stories/image-preview-modal.stories.tsx | 3 +- tests/storybook/tsconfig.json | 3 - tools/cli/src/bin/dev-core.ts | 10 - tools/cli/src/util/infra.ts | 15 - tools/commitlint/.commitlintrc.json | 5 +- tools/plugin-cli/package.json | 23 - tools/plugin-cli/src/af.mjs | 16 - tools/plugin-cli/src/af.ts | 180 --- tools/plugin-cli/tsconfig.json | 15 - tsconfig.json | 25 - yarn.lock | 1127 +---------------- 110 files changed, 46 insertions(+), 4426 deletions(-) delete mode 100644 packages/common/infra/src/__internal__/plugin.ts delete mode 100644 packages/common/sdk/.gitignore delete mode 100644 packages/common/sdk/package.json delete mode 100644 packages/common/sdk/project.json delete mode 100644 packages/common/sdk/src/entry.ts delete mode 100644 packages/common/sdk/src/server.ts delete mode 100644 packages/common/sdk/tsconfig.json delete mode 100644 packages/common/sdk/tsconfig.node.json delete mode 100644 packages/common/sdk/vite.config.ts delete mode 100644 packages/frontend/core/src/_plugin/index.test.tsx delete mode 100644 packages/frontend/core/src/bootstrap/plugins/endowments/fercher.ts delete mode 100644 packages/frontend/core/src/bootstrap/plugins/endowments/timer.ts delete mode 100644 packages/frontend/core/src/bootstrap/plugins/setup-imports-map.ts delete mode 100644 packages/frontend/core/src/bootstrap/plugins/setup.ts delete mode 100644 packages/frontend/core/src/bootstrap/register-plugins.ts delete mode 100644 packages/frontend/core/src/components/affine/setting-modal/general-setting/plugins/index.tsx delete mode 100644 packages/frontend/core/src/components/affine/setting-modal/general-setting/plugins/style.css.ts rename packages/{plugins/image-preview/src/component => frontend/core/src/components/image-preview}/hooks/use-zoom.tsx (100%) rename packages/{plugins/image-preview/src/component => frontend/core/src/components/image-preview}/index.css.ts (100%) rename packages/{plugins/image-preview/src/component => frontend/core/src/components/image-preview}/index.jotai.ts (100%) rename packages/{plugins/image-preview/src/component => frontend/core/src/components/image-preview}/index.tsx (98%) delete mode 100644 packages/frontend/core/src/components/pure/plugin-header/index.tsx delete mode 100644 packages/frontend/core/src/components/pure/plugin-header/styles.css.ts delete mode 100644 packages/plugins/copilot/README.md delete mode 100644 packages/plugins/copilot/package.json delete mode 100644 packages/plugins/copilot/project.json delete mode 100644 packages/plugins/copilot/src/UI/debug-content.tsx delete mode 100644 packages/plugins/copilot/src/UI/detail-content.tsx delete mode 100644 packages/plugins/copilot/src/UI/header-item.tsx delete mode 100644 packages/plugins/copilot/src/UI/index.css.ts delete mode 100644 packages/plugins/copilot/src/core/chat.ts delete mode 100644 packages/plugins/copilot/src/core/components/conversation-list/index.css.ts delete mode 100644 packages/plugins/copilot/src/core/components/conversation-list/index.tsx delete mode 100644 packages/plugins/copilot/src/core/components/conversation/index.css.ts delete mode 100644 packages/plugins/copilot/src/core/components/conversation/index.tsx delete mode 100644 packages/plugins/copilot/src/core/components/divider.tsx delete mode 100644 packages/plugins/copilot/src/core/components/following-up/index.css.ts delete mode 100644 packages/plugins/copilot/src/core/components/following-up/index.tsx delete mode 100644 packages/plugins/copilot/src/core/hooks/index.ts delete mode 100644 packages/plugins/copilot/src/core/langchain/message-history.ts delete mode 100644 packages/plugins/copilot/src/core/prompts/index.ts delete mode 100644 packages/plugins/copilot/src/core/prompts/output-parser.ts delete mode 100644 packages/plugins/copilot/src/index.ts delete mode 100644 packages/plugins/copilot/tsconfig.json delete mode 100644 packages/plugins/hello-world/package.json delete mode 100644 packages/plugins/hello-world/project.json delete mode 100644 packages/plugins/hello-world/src/app.tsx delete mode 100644 packages/plugins/hello-world/src/index.ts delete mode 100644 packages/plugins/hello-world/tsconfig.json delete mode 100644 packages/plugins/image-preview/package.json delete mode 100644 packages/plugins/image-preview/project.json delete mode 100644 packages/plugins/image-preview/src/app.tsx delete mode 100644 packages/plugins/image-preview/src/component/toast.ts delete mode 100644 packages/plugins/image-preview/src/index.ts delete mode 100644 packages/plugins/image-preview/tsconfig.json delete mode 100644 packages/plugins/vue-hello-world/.eslintrc.json delete mode 100644 packages/plugins/vue-hello-world/package.json delete mode 100644 packages/plugins/vue-hello-world/project.json delete mode 100644 packages/plugins/vue-hello-world/src/app.vue delete mode 100644 packages/plugins/vue-hello-world/src/global.d.ts delete mode 100644 packages/plugins/vue-hello-world/src/index.ts delete mode 100644 packages/plugins/vue-hello-world/tsconfig.json delete mode 100644 tests/affine-plugin/e2e/basic.spec.ts delete mode 100644 tests/affine-plugin/package.json delete mode 100644 tests/affine-plugin/playwright.config.ts delete mode 100644 tests/affine-plugin/tsconfig.json delete mode 100644 tools/plugin-cli/package.json delete mode 100755 tools/plugin-cli/src/af.mjs delete mode 100644 tools/plugin-cli/src/af.ts delete mode 100644 tools/plugin-cli/tsconfig.json diff --git a/.eslintignore b/.eslintignore index c661e0c28..1b4baef2f 100644 --- a/.eslintignore +++ b/.eslintignore @@ -11,6 +11,4 @@ e2e-dist-* static web-static public -packages/common/sdk/src/*.d.ts -packages/common/sdk/src/*.js packages/frontend/i18n/src/i18n-generated.ts diff --git a/.eslintrc.js b/.eslintrc.js index 5e5566f17..3d6b4d2cb 100644 --- a/.eslintrc.js +++ b/.eslintrc.js @@ -69,10 +69,8 @@ const allPackages = [ 'packages/common/debug', 'packages/common/env', 'packages/common/infra', - 'packages/common/sdk', 'packages/common/theme', 'packages/common/y-indexeddb', - 'packages/plugins/copilot', 'tools/cli', 'tests/storybook', ]; diff --git a/.github/actions/setup-node/action.yml b/.github/actions/setup-node/action.yml index 79d2602c7..52ebc5814 100644 --- a/.github/actions/setup-node/action.yml +++ b/.github/actions/setup-node/action.yml @@ -25,10 +25,6 @@ inputs: description: 'Build infra' required: false default: 'true' - build-plugins: - description: 'Build plugins' - required: false - default: 'true' nmHoistingLimits: description: 'Set nmHoistingLimits in .yarnrc.yml' required: false @@ -195,8 +191,3 @@ runs: shell: bash if: inputs.build-infra == 'true' run: yarn run build:infra - - - name: Build Plugins - if: inputs.build-plugins == 'true' - shell: bash - run: yarn run build:plugins diff --git a/.github/labeler.yml b/.github/labeler.yml index 41ed2112f..6f0259a3a 100644 --- a/.github/labeler.yml +++ b/.github/labeler.yml @@ -19,26 +19,11 @@ mod:dev: - 'tools/cli/**/*' - 'packages/common/debug/**/*' -mod:plugin: - - changed-files: - - any-glob-to-any-file: - - 'packages/plugins/**/*' - -plugin:copilot: - - changed-files: - - any-glob-to-any-file: - - 'packages/plugins/copilot/**/*' - mod:infra: - changed-files: - any-glob-to-any-file: - 'packages/common/infra/**/*' -mod:sdk: - - changed-files: - - any-glob-to-any-file: - - 'packages/common/sdk/**/*' - mod:plugin-cli: - changed-files: - any-glob-to-any-file: diff --git a/.github/workflows/build-test.yml b/.github/workflows/build-test.yml index ad0978fa2..f2ab1e479 100644 --- a/.github/workflows/build-test.yml +++ b/.github/workflows/build-test.yml @@ -108,44 +108,6 @@ jobs: yarn set version $(node -e "console.log(require('./package.json').packageManager.split('@')[1])") git diff --exit-code - e2e-plugin-test: - name: E2E Plugin Test - runs-on: ubuntu-latest - env: - DISTRIBUTION: browser - steps: - - uses: actions/checkout@v4 - - name: Setup Node.js - uses: ./.github/actions/setup-node - with: - playwright-install: true - electron-install: false - full-cache: true - - name: Run playwright tests - run: yarn e2e --forbid-only - working-directory: tests/affine-plugin - env: - COVERAGE: true - - name: Collect code coverage report - run: yarn exec nyc report -t .nyc_output --report-dir .coverage --reporter=lcov - - - name: Upload e2e test coverage results - uses: codecov/codecov-action@v3 - with: - token: ${{ secrets.CODECOV_TOKEN }} - files: ./.coverage/lcov.info - flags: e2e-plugin-test - name: affine - fail_ci_if_error: false - - - name: Upload test results - if: ${{ failure() }} - uses: actions/upload-artifact@v4 - with: - name: test-results-e2e-plugin - path: ./test-results - if-no-files-found: ignore - e2e-test: name: E2E Test runs-on: ubuntu-latest @@ -255,7 +217,6 @@ jobs: extra-flags: workspaces focus @affine/native electron-install: false build-infra: false - build-plugins: false - name: Setup filename id: filename shell: bash @@ -288,7 +249,6 @@ jobs: extra-flags: workspaces focus @affine/storage electron-install: false build-infra: false - build-plugins: false - name: Build Rust uses: ./.github/actions/build-rust with: @@ -312,7 +272,6 @@ jobs: uses: ./.github/actions/setup-node with: electron-install: false - build-plugins: false full-cache: true - name: Build Core # always skip cache because its fast, and cache configuration is always changing diff --git a/.github/workflows/deploy.yml b/.github/workflows/deploy.yml index 328f00685..8606e23e2 100644 --- a/.github/workflows/deploy.yml +++ b/.github/workflows/deploy.yml @@ -48,8 +48,6 @@ jobs: uses: ./.github/actions/setup-version - name: Setup Node.js uses: ./.github/actions/setup-node - - name: Build Plugins - run: yarn run build:plugins - name: Build Core run: yarn nx build @affine/core --skip-nx-cache env: diff --git a/.github/workflows/publish-storybook.yml b/.github/workflows/publish-storybook.yml index 9d2b40df5..5ad11dc9c 100644 --- a/.github/workflows/publish-storybook.yml +++ b/.github/workflows/publish-storybook.yml @@ -32,8 +32,6 @@ jobs: uses: ./.github/actions/setup-node with: electron-install: false - - name: Build Plugins - run: yarn run build:plugins - uses: chromaui/action-next@v1 with: workingDir: tests/storybook diff --git a/.github/workflows/release-desktop.yml b/.github/workflows/release-desktop.yml index 78f96b09c..51c046585 100644 --- a/.github/workflows/release-desktop.yml +++ b/.github/workflows/release-desktop.yml @@ -102,7 +102,6 @@ jobs: with: extra-flags: workspaces focus @affine/electron @affine/monorepo hard-link-nm: false - build-plugins: false nmHoistingLimits: workspaces enableScripts: false - name: Build AFFiNE native @@ -179,7 +178,6 @@ jobs: with: extra-flags: workspaces focus @affine/electron @affine/monorepo hard-link-nm: false - build-plugins: false nmHoistingLimits: workspaces - name: Build AFFiNE native uses: ./.github/actions/build-rust @@ -192,9 +190,6 @@ jobs: name: core path: packages/frontend/electron/resources/web-static - - name: Build Plugins - run: yarn run build:plugins - - name: Build Desktop Layers run: yarn workspace @affine/electron build diff --git a/README.md b/README.md index c33ee9b26..645725c48 100644 --- a/README.md +++ b/README.md @@ -113,20 +113,6 @@ If you have questions, you are welcome to contact us. One of the best places to | [@toeverything/y-indexeddb](packages/common/y-indexeddb) | IndexedDB database adapter for Yjs | [![](https://img.shields.io/npm/dm/@toeverything/y-indexeddb?style=flat-square&color=eee)](https://www.npmjs.com/package/@toeverything/y-indexeddb) | | [@toeverything/theme](packages/common/theme) | AFFiNE theme | [![](https://img.shields.io/npm/dm/@toeverything/theme?style=flat-square&color=eee)](https://www.npmjs.com/package/@toeverything/theme) | -## Plugins - -> Plugins are a way to extend the functionality of AFFiNE. You can use plugins to add new blocks, new features, and even new ways to edit content. -> -> (Currently, the plugin system is under heavy development. You will see the plugin system in the canary release.) - -- [@affine/sdk](./packages/common/sdk) - SDK for developing plugins -- [@affine/plugin-cli](./tools/plugin-cli) - CLI for developing plugins - -| Official Plugin | Description | Status | -| ---------------------------------------------------------------- | ----------------------------------------- | ------ | -| [@affine/copilot-plugin](./packages/plugins/copilot) | AI Copilot that help you document writing | 🚧 | -| [@affine/image-preview-plugin](./packages/plugins/image-preview) | Component for previewing an image | ✅ | - ## Upstreams We would also like to give thanks to open-source projects that make AFFiNE possible: diff --git a/docs/BUILDING.md b/docs/BUILDING.md index d90d60965..28ac41d3a 100644 --- a/docs/BUILDING.md +++ b/docs/BUILDING.md @@ -73,12 +73,6 @@ yarn workspace @affine/native build yarn run build:infra ``` -### Build Plugins - -```sh -yarn run build:plugins -``` - ### Build Server Dependencies ```sh @@ -102,7 +96,7 @@ yarn test ### E2E Test ```shell -# there are `affine-local`, `affine-migration`, `affine-local`, `affine-plugin`, `affine-prototype` e2e tests, +# there are `affine-local`, `affine-migration`, `affine-local`, `affine-prototype` e2e tests, # which are run under different situations. cd tests/affine-local yarn e2e diff --git a/docs/contributing/tutorial.md b/docs/contributing/tutorial.md index 07bd19ad1..39be0c964 100644 --- a/docs/contributing/tutorial.md +++ b/docs/contributing/tutorial.md @@ -17,7 +17,6 @@ The codebase is organized as follows: - `packages/` contains all code running in production. - `backend/` contains backend code, more information from . - `frontend/` contains frontend code, including the web app, the electron app and business libraries. - - `plugins/` contains all build-in plugins. - `common` contains the isomorphic code or basic libraries without business. - `tools/` contains tools to help developing or CI, not used in production. - `tests/` contains testings across different libraries, including e2e testings and integration testings. diff --git a/package.json b/package.json index 171dfa619..9f47d575c 100644 --- a/package.json +++ b/package.json @@ -24,7 +24,6 @@ "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 --projects=tag:infra", - "build:plugins": "yarn nx run-many -t build --projects=tag:plugin", "build:storybook": "yarn nx build @affine/storybook", "start:web-static": "yarn workspace @affine/core static-server", "start:storybook": "yarn exec serve tests/storybook/storybook-static -l 6006", @@ -58,7 +57,6 @@ "devDependencies": { "@affine-test/kit": "workspace:*", "@affine/cli": "workspace:*", - "@affine/plugin-cli": "workspace:*", "@commitlint/cli": "^18.4.3", "@commitlint/config-conventional": "^18.4.3", "@faker-js/faker": "^8.3.1", diff --git a/packages/common/env/src/global.ts b/packages/common/env/src/global.ts index 8709d9800..7e9527be4 100644 --- a/packages/common/env/src/global.ts +++ b/packages/common/env/src/global.ts @@ -12,8 +12,6 @@ export const blockSuiteFeatureFlags = z.object({ }); export const runtimeFlagsSchema = z.object({ - enablePlugin: z.boolean(), - builtinPlugins: z.array(z.string()), enableTestProperties: z.boolean(), enableBroadcastChannelProvider: z.boolean(), enableDebugPage: z.boolean(), diff --git a/packages/common/infra/package.json b/packages/common/infra/package.json index 982672f29..5a6bff9a4 100644 --- a/packages/common/infra/package.json +++ b/packages/common/infra/package.json @@ -61,7 +61,6 @@ "dependencies": { "@affine/debug": "workspace:*", "@affine/env": "workspace:*", - "@affine/sdk": "workspace:*", "@blocksuite/blocks": "0.11.0-nightly-202312220916-e3abcbb", "@blocksuite/global": "0.11.0-nightly-202312220916-e3abcbb", "@blocksuite/store": "0.11.0-nightly-202312220916-e3abcbb", diff --git a/packages/common/infra/src/__internal__/plugin.ts b/packages/common/infra/src/__internal__/plugin.ts deleted file mode 100644 index 7071e8b9d..000000000 --- a/packages/common/infra/src/__internal__/plugin.ts +++ /dev/null @@ -1,53 +0,0 @@ -import type { CallbackMap } from '@affine/sdk/entry'; -import { assertExists } from '@blocksuite/global/utils'; -import { atomWithStorage } from 'jotai/utils'; -import { atom } from 'jotai/vanilla'; -import type { z } from 'zod'; - -import type { packageJsonOutputSchema } from '../type.js'; - -export const builtinPluginPaths = new Set(runtimeConfig.builtinPlugins); - -const pluginCleanupMap = new Map void>>(); - -export function addCleanup( - pluginName: string, - cleanup: () => void -): () => void { - if (!pluginCleanupMap.has(pluginName)) { - pluginCleanupMap.set(pluginName, new Set()); - } - const cleanupSet = pluginCleanupMap.get(pluginName); - assertExists(cleanupSet); - cleanupSet.add(cleanup); - return () => { - cleanupSet.delete(cleanup); - }; -} - -export function invokeCleanup(pluginName: string) { - pluginCleanupMap.get(pluginName)?.forEach(cleanup => cleanup()); - pluginCleanupMap.delete(pluginName); -} - -export const pluginPackageJson = atom< - z.infer[] ->([]); - -export const enabledPluginAtom = atomWithStorage('affine-enabled-plugin', [ - '@affine/image-preview-plugin', -]); - -export const pluginHeaderItemAtom = atom< - Record ->({}); - -export const pluginSettingAtom = atom>( - {} -); - -export const pluginEditorAtom = atom>({}); - -export const pluginWindowAtom = atom< - Record () => void> ->({}); diff --git a/packages/common/infra/src/atom/index.ts b/packages/common/infra/src/atom/index.ts index 978d7fa36..12fc228d9 100644 --- a/packages/common/infra/src/atom/index.ts +++ b/packages/common/infra/src/atom/index.ts @@ -1,6 +1,2 @@ -import { atom } from 'jotai'; - -export const loadedPluginNameAtom = atom([]); - export * from './root-store'; export * from './settings'; diff --git a/packages/common/infra/tsconfig.json b/packages/common/infra/tsconfig.json index 1e81c00cd..3deffb863 100644 --- a/packages/common/infra/tsconfig.json +++ b/packages/common/infra/tsconfig.json @@ -8,9 +8,6 @@ "outDir": "lib" }, "references": [ - { - "path": "../sdk" - }, { "path": "../env" }, diff --git a/packages/common/infra/vite.config.ts b/packages/common/infra/vite.config.ts index 03baf6f2a..6055b068f 100644 --- a/packages/common/infra/vite.config.ts +++ b/packages/common/infra/vite.config.ts @@ -19,7 +19,6 @@ export default defineConfig({ 'core/event-emitter': resolve(root, 'src/core/event-emitter.ts'), 'preload/electron': resolve(root, 'src/preload/electron.ts'), 'app-config-storage': resolve(root, 'src/app-config-storage.ts'), - '__internal__/plugin': resolve(root, 'src/__internal__/plugin.ts'), }, formats: ['es', 'cjs'], name: 'AffineInfra', diff --git a/packages/common/sdk/.gitignore b/packages/common/sdk/.gitignore deleted file mode 100644 index 3dca72d41..000000000 --- a/packages/common/sdk/.gitignore +++ /dev/null @@ -1,4 +0,0 @@ -src/entry.d.ts -src/entry.d.ts.map -src/entry.js -src/entry.js.map diff --git a/packages/common/sdk/package.json b/packages/common/sdk/package.json deleted file mode 100644 index 09e13d00e..000000000 --- a/packages/common/sdk/package.json +++ /dev/null @@ -1,37 +0,0 @@ -{ - "name": "@affine/sdk", - "version": "0.11.0", - "type": "module", - "scripts": { - "build": "vite build", - "dev": "vite build --watch" - }, - "exports": { - "./entry": { - "types": "./dist/src/entry.d.ts", - "import": "./dist/entry.js", - "require": "./dist/entry.cjs" - }, - "./server": { - "types": "./dist/src/server.d.ts", - "import": "./dist/server.js", - "require": "./dist/server.cjs" - } - }, - "files": [ - "dist" - ], - "dependencies": { - "@blocksuite/block-std": "0.11.0-nightly-202312220916-e3abcbb", - "@blocksuite/blocks": "0.11.0-nightly-202312220916-e3abcbb", - "@blocksuite/global": "0.11.0-nightly-202312220916-e3abcbb", - "@blocksuite/presets": "0.11.0-nightly-202312220916-e3abcbb", - "@blocksuite/store": "0.11.0-nightly-202312220916-e3abcbb", - "jotai": "^2.5.1", - "zod": "^3.22.4" - }, - "devDependencies": { - "vite": "^5.0.6", - "vite-plugin-dts": "3.6.0" - } -} diff --git a/packages/common/sdk/project.json b/packages/common/sdk/project.json deleted file mode 100644 index 749b2e7b5..000000000 --- a/packages/common/sdk/project.json +++ /dev/null @@ -1,22 +0,0 @@ -{ - "name": "sdk", - "$schema": "../../../node_modules/nx/schemas/project-schema.json", - "projectType": "library", - "sourceRoot": "packages/common/sdk/src", - "targets": { - "build": { - "executor": "@nx/vite:build", - "options": { - "outputPath": "packages/common/sdk/dist" - } - }, - "serve": { - "executor": "@nx/vite:build", - "options": { - "outputPath": "packages/common/sdk/dist", - "watch": true - } - } - }, - "tags": ["infra"] -} diff --git a/packages/common/sdk/src/entry.ts b/packages/common/sdk/src/entry.ts deleted file mode 100644 index 2cbda2c26..000000000 --- a/packages/common/sdk/src/entry.ts +++ /dev/null @@ -1,64 +0,0 @@ -import type { BaseSelection } from '@blocksuite/block-std'; -import type { AffineEditorContainer } from '@blocksuite/presets'; -import type { Page } from '@blocksuite/store'; -import type { Workspace } from '@blocksuite/store'; -import type { Atom, getDefaultStore } from 'jotai/vanilla'; -import type { WritableAtom } from 'jotai/vanilla/atom'; -import type { FunctionComponent } from 'react'; - -export type Part = 'headerItem' | 'editor' | 'setting' | 'formatBar'; - -export type CallbackMap = { - headerItem: (root: HTMLElement) => () => void; - editor: (root: HTMLElement, editor: AffineEditorContainer) => () => void; - setting: (root: HTMLElement) => () => void; - formatBar: ( - root: HTMLElement, - page: Page, - getBlockRange: () => BaseSelection[] - ) => () => void; -}; - -export interface PluginContext { - register: (part: T, callback: CallbackMap[T]) => void; - utils: { - PluginProvider: FunctionComponent; // make more clear - }; -} - -export type LayoutDirection = 'horizontal' | 'vertical'; -export type LayoutNode = LayoutParentNode | string; -export type LayoutParentNode = { - direction: LayoutDirection; - splitPercentage: number; // 0 - 100 - first: string; - second: LayoutNode; - maxWidth?: (number | undefined)[]; -}; - -export type ExpectedLayout = - | { - direction: 'horizontal'; - // the first element is always the editor - first: 'editor'; - second: LayoutNode; - // the percentage should be greater than 70 - splitPercentage: number; - } - | 'editor'; - -export declare const pushLayoutAtom: WritableAtom< - null, - | [ - string, - (div: HTMLDivElement) => () => void, - { - maxWidth: (number | undefined)[]; - }, - ] - | [string, (div: HTMLDivElement) => () => void], - void ->; -export declare const deleteLayoutAtom: WritableAtom; -export declare const currentWorkspaceAtom: Atom>; -export declare const rootStore: ReturnType; diff --git a/packages/common/sdk/src/server.ts b/packages/common/sdk/src/server.ts deleted file mode 100644 index f7f88e3c4..000000000 --- a/packages/common/sdk/src/server.ts +++ /dev/null @@ -1,4 +0,0 @@ -export interface ServerContext { - registerCommand: (command: string, fn: (...args: any[]) => any) => void; - unregisterCommand: (command: string) => void; -} diff --git a/packages/common/sdk/tsconfig.json b/packages/common/sdk/tsconfig.json deleted file mode 100644 index 33871974a..000000000 --- a/packages/common/sdk/tsconfig.json +++ /dev/null @@ -1,15 +0,0 @@ -{ - "extends": "../../../tsconfig.json", - "include": ["./src"], - "compilerOptions": { - "composite": true, - "noEmit": false, - "moduleResolution": "bundler", - "outDir": "lib" - }, - "references": [ - { - "path": "./tsconfig.node.json" - } - ] -} diff --git a/packages/common/sdk/tsconfig.node.json b/packages/common/sdk/tsconfig.node.json deleted file mode 100644 index 097adbc4e..000000000 --- a/packages/common/sdk/tsconfig.node.json +++ /dev/null @@ -1,12 +0,0 @@ -{ - "extends": "../../../tsconfig.json", - "compilerOptions": { - "composite": true, - "module": "ESNext", - "moduleResolution": "Node", - "allowSyntheticDefaultImports": true, - "outDir": "lib", - "noEmit": false - }, - "include": ["vite.config.ts"] -} diff --git a/packages/common/sdk/vite.config.ts b/packages/common/sdk/vite.config.ts deleted file mode 100644 index d158eff20..000000000 --- a/packages/common/sdk/vite.config.ts +++ /dev/null @@ -1,23 +0,0 @@ -import { resolve } from 'node:path'; - -import { fileURLToPath } from 'url'; -import { defineConfig } from 'vite'; -import dts from 'vite-plugin-dts'; - -const root = fileURLToPath(new URL('.', import.meta.url)); - -export default defineConfig({ - build: { - minify: false, - lib: { - entry: { - entry: resolve(root, 'src/entry.ts'), - server: resolve(root, 'src/server.ts'), - }, - }, - rollupOptions: { - external: [/^jotai/, /^@blocksuite/, 'zod'], - }, - }, - plugins: [dts()], -}); diff --git a/packages/frontend/core/.webpack/runtime-config.ts b/packages/frontend/core/.webpack/runtime-config.ts index 4921c3191..6c24f9680 100644 --- a/packages/frontend/core/.webpack/runtime-config.ts +++ b/packages/frontend/core/.webpack/runtime-config.ts @@ -13,8 +13,6 @@ const editorFlags: BlockSuiteFeatureFlags = { export function getRuntimeConfig(buildFlags: BuildFlags): RuntimeConfig { const buildPreset: Record = { stable: { - enablePlugin: true, - builtinPlugins: ['/plugins/image-preview'], enableTestProperties: false, enableBroadcastChannelProvider: true, enableDebugPage: true, @@ -57,13 +55,6 @@ export function getRuntimeConfig(buildFlags: BuildFlags): RuntimeConfig { }, // canary will be aggressive and enable all features canary: { - enablePlugin: true, - builtinPlugins: [ - '/plugins/copilot', - '/plugins/hello-world', - '/plugins/image-preview', - '/plugins/vue-hello-world', - ], enableTestProperties: true, enableBroadcastChannelProvider: true, enableDebugPage: true, @@ -99,15 +90,6 @@ export function getRuntimeConfig(buildFlags: BuildFlags): RuntimeConfig { const currentBuildPreset = buildPreset[currentBuild]; const environmentPreset = { - builtinPlugins: [ - '/plugins/copilot', - '/plugins/hello-world', - '/plugins/image-preview', - '/plugins/vue-hello-world', - ], - enablePlugin: process.env.ENABLE_PLUGIN - ? process.env.ENABLE_PLUGIN === 'true' - : currentBuildPreset.enablePlugin, enableTestProperties: process.env.ENABLE_TEST_PROPERTIES ? process.env.ENABLE_TEST_PROPERTIES === 'true' : currentBuildPreset.enableTestProperties, diff --git a/packages/frontend/core/.webpack/webpack.config.ts b/packages/frontend/core/.webpack/webpack.config.ts index b78b4545d..a9c82e0c3 100644 --- a/packages/frontend/core/.webpack/webpack.config.ts +++ b/packages/frontend/core/.webpack/webpack.config.ts @@ -1,4 +1,4 @@ -import { createConfiguration, rootPath, getPublicPath } from './config.js'; +import { createConfiguration, rootPath } from './config.js'; import { merge } from 'webpack-merge'; import { join, resolve } from 'node:path'; import type { BuildFlags } from '@affine/cli/config'; @@ -20,7 +20,6 @@ export default async function (cli_env: any, _: any) { return merge(config, { entry: { app: resolve(rootPath, 'src/index.tsx'), - '_plugin/index.test': resolve(rootPath, 'src/_plugin/index.test.tsx'), }, plugins: [ new HTMLPlugin({ @@ -35,19 +34,6 @@ export default async function (cli_env: any, _: any) { DESCRIPTION, }, }), - new HTMLPlugin({ - template: join(rootPath, '.webpack', 'template.html'), - inject: 'body', - scriptLoading: 'module', - minify: false, - publicPath: getPublicPath(flags), - chunks: ['_plugin/index.test'], - filename: '_plugin/index.html', - templateParameters: { - GIT_SHORT_SHA: gitShortHash(), - DESCRIPTION, - }, - }), ], }); } diff --git a/packages/frontend/core/src/_plugin/index.test.tsx b/packages/frontend/core/src/_plugin/index.test.tsx deleted file mode 100644 index 5c0b3cde7..000000000 --- a/packages/frontend/core/src/_plugin/index.test.tsx +++ /dev/null @@ -1,50 +0,0 @@ -import '../polyfill/intl-segmenter'; - -import { assertExists } from '@blocksuite/global/utils'; -import { - getCurrentStore, - loadedPluginNameAtom, -} from '@toeverything/infra/atom'; -import { use } from 'foxact/use'; -import { useAtomValue } from 'jotai'; -import { Provider } from 'jotai/react'; -import { StrictMode } from 'react'; -import { createRoot } from 'react-dom/client'; - -import { createSetup } from '../bootstrap/plugins/setup'; -import { bootstrapPluginSystem } from '../bootstrap/register-plugins'; - -async function main() { - const { setup } = await import('../bootstrap/setup'); - const rootStore = getCurrentStore(); - setup(); - createSetup(rootStore); - const pluginRegisterPromise = bootstrapPluginSystem(rootStore); - const root = document.getElementById('app'); - assertExists(root); - - const App = () => { - use(pluginRegisterPromise); - const plugins = useAtomValue(loadedPluginNameAtom); - return ( -
-
- Successfully loaded plugins: -
- {plugins.map(plugin => { - return
{plugin}
; - })} -
- ); - }; - - createRoot(root).render( - - - - - - ); -} - -await main(); diff --git a/packages/frontend/core/src/bootstrap/plugins/endowments/fercher.ts b/packages/frontend/core/src/bootstrap/plugins/endowments/fercher.ts deleted file mode 100644 index eee2d0abf..000000000 --- a/packages/frontend/core/src/bootstrap/plugins/endowments/fercher.ts +++ /dev/null @@ -1,86 +0,0 @@ -export interface FetchOptions { - fetch?: typeof fetch; - signal?: AbortSignal; - - normalizeURL?(url: string): string; - - /** - * Virtualize a url - * @param url URL to be rewrite - * @param direction Direction of this rewrite. - * 'in' means the url is from the outside world and should be virtualized. - * 'out' means the url is from the inside world and should be de-virtualized to fetch the real target. - */ - rewriteURL?(url: string, direction: 'in' | 'out'): string; - - replaceRequest?(request: Request): Request | PromiseLike; - - replaceResponse?(response: Response): Response | PromiseLike; - - canConnect?(url: string): boolean | PromiseLike; -} - -export function createFetch(options: FetchOptions) { - const { - fetch: _fetch = fetch, - signal, - rewriteURL, - replaceRequest, - replaceResponse, - canConnect, - normalizeURL, - } = options; - - return async function fetch(input: RequestInfo, init?: RequestInit) { - let request = new Request(input, { - ...init, - signal: getMergedSignal(init?.signal, signal) || null, - }); - - if (normalizeURL) request = new Request(normalizeURL(request.url), request); - if (canConnect && !(await canConnect(request.url))) - throw new TypeError('Failed to fetch'); - if (rewriteURL) - request = new Request(rewriteURL(request.url, 'out'), request); - if (replaceRequest) request = await replaceRequest(request); - - let response = await _fetch(request); - - if (rewriteURL) { - const { url, redirected, type } = response; - // Note: Response constructor does not allow us to set the url of a response. - // we have to define the own property on it. This is not a good simulation. - // To prevent get the original url by Response.prototype.[[get url]].call(response) - // we copy a response and set it's url to empty. - response = new Response(response.body, response); - Object.defineProperties(response, { - url: { value: url, configurable: true }, - redirected: { value: redirected, configurable: true }, - type: { value: type, configurable: true }, - }); - Object.defineProperty(response, 'url', { - configurable: true, - value: rewriteURL(url, 'in'), - }); - } - if (replaceResponse) response = await replaceResponse(response); - return response; - }; -} - -function getMergedSignal( - signal: AbortSignal | undefined | null, - signal2: AbortSignal | undefined | null -) { - if (!signal) return signal2; - if (!signal2) return signal; - - const abortController = new AbortController(); - signal.addEventListener('abort', () => abortController.abort(), { - once: true, - }); - signal2.addEventListener('abort', () => abortController.abort(), { - once: true, - }); - return abortController.signal; -} diff --git a/packages/frontend/core/src/bootstrap/plugins/endowments/timer.ts b/packages/frontend/core/src/bootstrap/plugins/endowments/timer.ts deleted file mode 100644 index cd7ea13ef..000000000 --- a/packages/frontend/core/src/bootstrap/plugins/endowments/timer.ts +++ /dev/null @@ -1,110 +0,0 @@ -type Handler = (...args: any[]) => void; - -export interface Timers { - setTimeout: (handler: Handler, timeout?: number, ...args: any[]) => number; - clearTimeout: (handle: number) => void; - setInterval: (handler: Handler, timeout?: number, ...args: any[]) => number; - clearInterval: (handle: number) => void; - requestAnimationFrame: (callback: Handler) => number; - cancelAnimationFrame: (handle: number) => void; - requestIdleCallback?: typeof window.requestIdleCallback | undefined; - cancelIdleCallback?: typeof window.cancelIdleCallback | undefined; - queueMicrotask: typeof window.queueMicrotask; -} - -export function createTimers( - abortSignal: AbortSignal, - originalTimes: Timers = { - requestAnimationFrame, - cancelAnimationFrame, - requestIdleCallback: - typeof requestIdleCallback === 'function' - ? requestIdleCallback - : undefined, - cancelIdleCallback: - typeof cancelIdleCallback === 'function' ? cancelIdleCallback : undefined, - setTimeout, - clearTimeout, - setInterval, - clearInterval, - queueMicrotask, - } -): Timers { - const { - requestAnimationFrame: _requestAnimationFrame, - cancelAnimationFrame: _cancelAnimationFrame, - setInterval: _setInterval, - clearInterval: _clearInterval, - setTimeout: _setTimeout, - clearTimeout: _clearTimeout, - cancelIdleCallback: _cancelIdleCallback, - requestIdleCallback: _requestIdleCallback, - queueMicrotask: _queueMicrotask, - } = originalTimes; - - const interval_timer_id: number[] = []; - const idle_id: number[] = []; - const raf_id: number[] = []; - - abortSignal.addEventListener( - 'abort', - () => { - raf_id.forEach(_cancelAnimationFrame); - interval_timer_id.forEach(_clearInterval); - _cancelIdleCallback && idle_id.forEach(_cancelIdleCallback); - }, - { once: true } - ); - - return { - // id is a positive number, it never repeats. - requestAnimationFrame(callback) { - raf_id[raf_id.length] = _requestAnimationFrame(callback); - return raf_id.length; - }, - cancelAnimationFrame(handle) { - const id = raf_id[handle - 1]; - if (!id) return; - _cancelAnimationFrame(id); - }, - setInterval(handler, timeout) { - interval_timer_id[interval_timer_id.length] = (_setInterval as any)( - handler, - timeout - ); - return interval_timer_id.length; - }, - clearInterval(id) { - if (!id) return; - const handle = interval_timer_id[id - 1]; - if (!handle) return; - _clearInterval(handle); - }, - setTimeout(handler, timeout) { - idle_id[idle_id.length] = (_setTimeout as any)(handler, timeout); - return idle_id.length; - }, - clearTimeout(id) { - if (!id) return; - const handle = idle_id[id - 1]; - if (!handle) return; - _clearTimeout(handle); - }, - requestIdleCallback: _requestIdleCallback - ? function requestIdleCallback(callback, options) { - idle_id[idle_id.length] = _requestIdleCallback(callback, options); - return idle_id.length; - } - : undefined, - cancelIdleCallback: _cancelIdleCallback - ? function cancelIdleCallback(handle) { - const id = idle_id[handle - 1]; - if (!id) return; - _cancelIdleCallback(id); - } - : undefined, - queueMicrotask(callback) { - _queueMicrotask(() => abortSignal.aborted || callback()); - }, - }; -} diff --git a/packages/frontend/core/src/bootstrap/plugins/setup-imports-map.ts b/packages/frontend/core/src/bootstrap/plugins/setup-imports-map.ts deleted file mode 100644 index 6e92f2fbf..000000000 --- a/packages/frontend/core/src/bootstrap/plugins/setup-imports-map.ts +++ /dev/null @@ -1,22 +0,0 @@ -type ExportsPromiseOrExports = - | Promise<{ [key: string]: any }> - | { [key: string]: any }; - -export async function setupImportsMap( - map: Map>, - imports: Record -) { - for (const [key, value] of Object.entries(imports)) { - let module: { [key: string]: any }; - if (value instanceof Promise) { - module = await value; - } else { - module = value; - } - const moduleMap = new Map(); - map.set(key, moduleMap); - for (const [exportName, exportValue] of Object.entries(module)) { - moduleMap.set(exportName, exportValue); - } - } -} diff --git a/packages/frontend/core/src/bootstrap/plugins/setup.ts b/packages/frontend/core/src/bootstrap/plugins/setup.ts deleted file mode 100644 index 15c473a89..000000000 --- a/packages/frontend/core/src/bootstrap/plugins/setup.ts +++ /dev/null @@ -1,483 +0,0 @@ -import { DebugLogger } from '@affine/debug'; -import type { CallbackMap, PluginContext } from '@affine/sdk/entry'; -import { AffineFormatBarWidget } from '@blocksuite/blocks'; -import { assertExists } from '@blocksuite/global/utils'; -import { - addCleanup, - pluginEditorAtom, - pluginHeaderItemAtom, - pluginSettingAtom, -} from '@toeverything/infra/__internal__/plugin'; -import { Provider } from 'jotai/react'; -import type { createStore } from 'jotai/vanilla'; -import { createElement, type PropsWithChildren } from 'react'; - -import { createFetch } from './endowments/fercher'; -import { createTimers } from './endowments/timer'; -import { setupImportsMap } from './setup-imports-map'; - -// DO NOT REMOVE INVISIBLE CHARACTERS -const dynamicImportKey = '$h‍_import'; - -const permissionLogger = new DebugLogger('plugins:permission'); -const importLogger = new DebugLogger('plugins:import'); -const entryLogger = new DebugLogger('plugins:entry'); - -const setupWeakMap = new WeakMap< - ReturnType, - ReturnType ->(); - -export function createSetup(rootStore: ReturnType) { - if (setupWeakMap.has(rootStore)) { - // eslint-disable-next-line @typescript-eslint/no-non-null-assertion - return setupWeakMap.get(rootStore)!; - } - const setup = createSetupImpl(rootStore); - setupWeakMap.set(rootStore, setup); - return setup; -} - -function createSetupImpl(rootStore: ReturnType) { - // module -> importName -> updater[] - const _rootImportsMap = new Map>(); - const rootImportsMapSetupPromise = setupImportsMap(_rootImportsMap, { - react: import('react'), - 'react/jsx-runtime': import('react/jsx-runtime'), - 'react-dom': import('react-dom'), - 'react-dom/client': import('react-dom/client'), - jotai: import('jotai'), - 'jotai/utils': import('jotai/utils'), - swr: import('swr'), - '@affine/component': import('@affine/component'), - '@blocksuite/icons': import('@blocksuite/icons'), - '@blocksuite/blocks': import('@blocksuite/blocks'), - '@blocksuite/inline': import('@blocksuite/inline'), - '@affine/sdk/entry': { - rootStore, - }, - '@blocksuite/global/utils': import('@blocksuite/global/utils'), - '@toeverything/infra/atom': import('@toeverything/infra/atom'), - '@affine/component/ui/button': import('@affine/component/ui/button'), - '@affine/component/ui/tooltip': import('@affine/component/ui/tooltip'), - }); - - // pluginName -> module -> importName -> updater[] - const _pluginNestedImportsMap = new Map< - string, - Map> - >(); - - const pluginImportsFunctionMap = new Map< - string, - (newUpdaters: [string, [string, ((val: any) => void)[]][]][]) => void - >(); - const createImports = (pluginName: string) => { - if (pluginImportsFunctionMap.has(pluginName)) { - // eslint-disable-next-line @typescript-eslint/no-non-null-assertion - return pluginImportsFunctionMap.get(pluginName)!; - } - const imports = ( - newUpdaters: [string, [string, ((val: any) => void)[]][]][] - ) => { - // eslint-disable-next-line @typescript-eslint/no-non-null-assertion - const currentImportMap = _pluginNestedImportsMap.get(pluginName)!; - importLogger.debug('currentImportMap', pluginName, currentImportMap); - - for (const [module, moduleUpdaters] of newUpdaters) { - importLogger.debug('imports module', module, moduleUpdaters); - let moduleImports = _rootImportsMap.get(module); - if (!moduleImports) { - moduleImports = currentImportMap.get(module); - } - if (moduleImports) { - for (const [importName, importUpdaters] of moduleUpdaters) { - const updateImport = (value: any) => { - for (const importUpdater of importUpdaters) { - importUpdater(value); - } - }; - if (moduleImports.has(importName)) { - const val = moduleImports.get(importName); - updateImport(val); - } - } - } else { - console.error( - 'cannot find module in plugin import map', - module, - currentImportMap, - _pluginNestedImportsMap - ); - } - } - }; - pluginImportsFunctionMap.set(pluginName, imports); - return imports; - }; - - const abortController = new AbortController(); - - const pluginFetch = createFetch({}); - const timer = createTimers(abortController.signal); - - const sharedGlobalThis = Object.assign(Object.create(null), timer, { - Object: globalThis.Object, - fetch: pluginFetch, - ReadableStream: globalThis.ReadableStream, - Symbol: globalThis.Symbol, - Error: globalThis.Error, - TypeError: globalThis.TypeError, - RangeError: globalThis.RangeError, - console: globalThis.console, - crypto: globalThis.crypto, - }); - - const dynamicImportMap = new Map< - string, - (moduleName: string) => Promise - >(); - - const createOrGetDynamicImport = (baseUrl: string, pluginName: string) => { - if (dynamicImportMap.has(pluginName)) { - // eslint-disable-next-line @typescript-eslint/no-non-null-assertion - return dynamicImportMap.get(pluginName)!; - } - const dynamicImport = async (moduleName: string): Promise => { - const codeUrl = `${baseUrl}/${moduleName}`; - const analysisUrl = `${baseUrl}/${moduleName}.json`; - const response = await fetch(codeUrl); - const analysisResponse = await fetch(analysisUrl); - const analysis = await analysisResponse.json(); - const exports = analysis.exports as string[]; - const code = await response.text(); - const moduleCompartment = new Compartment( - createOrGetGlobalThis( - pluginName, - // use singleton here to avoid infinite loop - createOrGetDynamicImport(pluginName, baseUrl) - ) - ); - const entryPoint = moduleCompartment.evaluate(code, { - __evadeHtmlCommentTest__: true, - }); - const moduleExports = {} as Record; - const setVarProxy = new Proxy( - {}, - { - get(_, p: string): any { - return (newValue: any) => { - moduleExports[p] = newValue; - }; - }, - } - ); - entryPoint({ - imports: createImports(pluginName), - liveVar: setVarProxy, - onceVar: setVarProxy, - }); - importLogger.debug('import', moduleName, exports, moduleExports); - return moduleExports; - }; - dynamicImportMap.set(pluginName, dynamicImport); - return dynamicImport; - }; - - const globalThisMap = new Map(); - - const createOrGetGlobalThis = ( - pluginName: string, - dynamicImport: (moduleName: string) => Promise - ) => { - if (globalThisMap.has(pluginName)) { - // eslint-disable-next-line @typescript-eslint/no-non-null-assertion - return globalThisMap.get(pluginName)!; - } - const pluginGlobalThis = Object.assign( - Object.create(null), - sharedGlobalThis, - { - // fixme: vite build output bundle will have this, we should remove it - process: Object.freeze({ - env: { - NODE_ENV: process.env.NODE_ENV, - }, - }), - // dynamic import function - [dynamicImportKey]: dynamicImport, - // UNSAFE: React will read `window` and `document` - window: new Proxy( - {}, - { - get(_, key) { - permissionLogger.debug(`${pluginName} is accessing window`, key); - if (sharedGlobalThis[key]) return sharedGlobalThis[key]; - const result = Reflect.get(window, key); - if (typeof result === 'function') { - if (result === ShadowRoot) { - return result; - } - return function (...args: any[]) { - permissionLogger.debug( - `${pluginName} is calling window`, - key, - args - ); - return result.apply(window, args); - }; - } - permissionLogger.debug('window', key, result); - return result; - }, - } - ), - document: new Proxy( - {}, - { - get(_, key) { - permissionLogger.debug( - `${pluginName} is accessing document`, - key - ); - if (sharedGlobalThis[key]) return sharedGlobalThis[key]; - const result = Reflect.get(document, key); - if (typeof result === 'function') { - return function (...args: any[]) { - permissionLogger.debug( - `${pluginName} is calling window`, - key, - args - ); - return result.apply(document, args); - }; - } - permissionLogger.debug('document', key, result); - return result; - }, - } - ), - navigator: globalThis.navigator, - - MouseEvent: globalThis.MouseEvent, - KeyboardEvent: globalThis.KeyboardEvent, - CustomEvent: globalThis.CustomEvent, - - // copilot uses these - Date: globalThis.Date, - Math: globalThis.Math, - URL: globalThis.URL, - URLSearchParams: globalThis.URLSearchParams, - Headers: globalThis.Headers, - TextEncoder: globalThis.TextEncoder, - TextDecoder: globalThis.TextDecoder, - Request: globalThis.Request, - - // image-preview uses these - Blob: globalThis.Blob, - ClipboardItem: globalThis.ClipboardItem, - - // vue uses these - Element: globalThis.Element, - SVGElement: globalThis.SVGElement, - - // fixme: use our own db api - indexedDB: globalThis.indexedDB, - IDBRequest: globalThis.IDBRequest, - IDBDatabase: globalThis.IDBDatabase, - IDBCursorWithValue: globalThis.IDBCursorWithValue, - IDBFactory: globalThis.IDBFactory, - IDBKeyRange: globalThis.IDBKeyRange, - IDBOpenDBRequest: globalThis.IDBOpenDBRequest, - IDBTransaction: globalThis.IDBTransaction, - IDBObjectStore: globalThis.IDBObjectStore, - IDBIndex: globalThis.IDBIndex, - IDBCursor: globalThis.IDBCursor, - IDBVersionChangeEvent: globalThis.IDBVersionChangeEvent, - } - ); - pluginGlobalThis.global = pluginGlobalThis; - globalThisMap.set(pluginName, pluginGlobalThis); - return pluginGlobalThis; - }; - - const setupPluginCode = async ( - baseUrl: string, - pluginName: string, - filename: string - ) => { - await rootImportsMapSetupPromise; - if (!_pluginNestedImportsMap.has(pluginName)) { - _pluginNestedImportsMap.set(pluginName, new Map()); - } - // eslint-disable-next-line @typescript-eslint/no-non-null-assertion - const currentImportMap = _pluginNestedImportsMap.get(pluginName)!; - const isMissingPackage = (name: string) => - _rootImportsMap.has(name) && !currentImportMap.has(name); - - const bundleAnalysis = await fetch(`${baseUrl}/${filename}.json`).then( - res => res.json() - ); - const moduleExports = bundleAnalysis.exports as Record; - const moduleImports = bundleAnalysis.imports as string[]; - const moduleReexports = bundleAnalysis.reexports as Record< - string, - [localName: string, exportedName: string][] - >; - await Promise.all( - moduleImports.map(name => { - if (isMissingPackage(name)) { - return Promise.resolve(); - } else { - importLogger.debug('missing package', name); - return setupPluginCode(baseUrl, pluginName, name); - } - }) - ); - const code = await fetch( - `${baseUrl}/${filename.replace(/^\.\//, '')}` - ).then(res => res.text()); - importLogger.debug('evaluating', filename); - const moduleCompartment = new Compartment( - createOrGetGlobalThis( - pluginName, - // use singleton here to avoid infinite loop - createOrGetDynamicImport(baseUrl, pluginName) - ) - ); - const entryPoint = moduleCompartment.evaluate(code, { - __evadeHtmlCommentTest__: true, - }); - const moduleExportsMap = new Map(); - const setVarProxy = new Proxy( - {}, - { - get(_, p: string): any { - return (newValue: any) => { - moduleExportsMap.set(p, newValue); - }; - }, - } - ); - currentImportMap.set(filename, moduleExportsMap); - entryPoint({ - imports: createImports(pluginName), - liveVar: setVarProxy, - onceVar: setVarProxy, - }); - - for (const [newExport, [originalExport]] of Object.entries(moduleExports)) { - if (newExport === originalExport) continue; - const value = moduleExportsMap.get(originalExport); - moduleExportsMap.set(newExport, value); - moduleExportsMap.delete(originalExport); - } - - for (const [name, reexports] of Object.entries(moduleReexports)) { - const targetExports = currentImportMap.get(filename); - const moduleExports = currentImportMap.get(name); - assertExists(targetExports); - assertExists(moduleExports); - for (const [exportedName, localName] of reexports) { - const exportedValue: any = moduleExports.get(exportedName); - assertExists(exportedValue); - targetExports.set(localName, exportedValue); - } - } - }; - - const PluginProvider = ({ children }: PropsWithChildren) => - createElement( - Provider, - { - store: rootStore, - }, - children - ); - - const evaluatePluginEntry = (pluginName: string) => { - // eslint-disable-next-line @typescript-eslint/no-non-null-assertion - const currentImportMap = _pluginNestedImportsMap.get(pluginName)!; - const pluginExports = currentImportMap.get('index.js'); - assertExists(pluginExports); - const entryFunction = pluginExports.get('entry'); - const cleanup = entryFunction({ - register: (part, callback) => { - entryLogger.info(`Registering ${pluginName} to ${part}`); - if (part === 'headerItem') { - rootStore.set(pluginHeaderItemAtom, items => ({ - ...items, - [pluginName]: callback as CallbackMap['headerItem'], - })); - addCleanup(pluginName, () => { - rootStore.set(pluginHeaderItemAtom, items => { - const newItems = { ...items }; - delete newItems[pluginName]; - return newItems; - }); - }); - } else if (part === 'editor') { - rootStore.set(pluginEditorAtom, items => ({ - ...items, - [pluginName]: callback as CallbackMap['editor'], - })); - addCleanup(pluginName, () => { - rootStore.set(pluginEditorAtom, items => { - const newItems = { ...items }; - delete newItems[pluginName]; - return newItems; - }); - }); - } else if (part === 'setting') { - rootStore.set(pluginSettingAtom, items => ({ - ...items, - [pluginName]: callback as CallbackMap['setting'], - })); - addCleanup(pluginName, () => { - rootStore.set(pluginSettingAtom, items => { - const newItems = { ...items }; - delete newItems[pluginName]; - return newItems; - }); - }); - } else if (part === 'formatBar') { - const register = (widget: AffineFormatBarWidget) => { - const div = document.createElement('div'); - const root = widget.host; - const cleanup = (callback as CallbackMap['formatBar'])( - div, - widget.page, - () => { - return root.selection.value; - } - ); - addCleanup(pluginName, () => { - AffineFormatBarWidget.customElements.delete(register); - cleanup(); - }); - return div; - }; - AffineFormatBarWidget.customElements.add(register); - } else { - throw new Error(`Unknown part: ${part}`); - } - }, - utils: { - PluginProvider, - }, - }); - if (typeof cleanup !== 'function') { - throw new Error('Plugin entry must return a function'); - } - addCleanup(pluginName, cleanup); - }; - return { - _rootImportsMap, - _pluginNestedImportsMap, - createImports, - createOrGetDynamicImport, - setupPluginCode, - evaluatePluginEntry, - createOrGetGlobalThis, - }; -} diff --git a/packages/frontend/core/src/bootstrap/register-plugins.ts b/packages/frontend/core/src/bootstrap/register-plugins.ts deleted file mode 100644 index 348208f60..000000000 --- a/packages/frontend/core/src/bootstrap/register-plugins.ts +++ /dev/null @@ -1,134 +0,0 @@ -import { DebugLogger } from '@affine/debug'; -import { - builtinPluginPaths, - enabledPluginAtom, - invokeCleanup, - pluginPackageJson, -} from '@toeverything/infra/__internal__/plugin'; -import { - getCurrentStore, - loadedPluginNameAtom, -} from '@toeverything/infra/atom'; -import { packageJsonOutputSchema } from '@toeverything/infra/type'; -import type { z } from 'zod'; - -import { createSetup } from './plugins/setup'; - -const logger = new DebugLogger('register-plugins'); - -declare global { - // eslint-disable-next-line no-var - var __pluginPackageJson__: unknown[]; -} - -Object.defineProperty(globalThis, '__pluginPackageJson__', { - get() { - return getCurrentStore().get(pluginPackageJson); - }, -}); - -export async function bootstrapPluginSystem( - rootStore: ReturnType -) { - const { evaluatePluginEntry, setupPluginCode } = createSetup(rootStore); - rootStore.sub(enabledPluginAtom, () => { - const added = new Set(); - const removed = new Set(); - const enabledPlugin = new Set(rootStore.get(enabledPluginAtom)); - enabledPlugin.forEach(pluginName => { - if (!enabledPluginSet.has(pluginName)) { - added.add(pluginName); - } - }); - enabledPluginSet.forEach(pluginName => { - if (!enabledPlugin.has(pluginName)) { - removed.add(pluginName); - } - }); - // update plugins - enabledPluginSet.clear(); - enabledPlugin.forEach(pluginName => { - enabledPluginSet.add(pluginName); - }); - added.forEach(pluginName => { - evaluatePluginEntry(pluginName); - }); - removed.forEach(pluginName => { - invokeCleanup(pluginName); - }); - }); - const enabledPluginSet = new Set(rootStore.get(enabledPluginAtom)); - const loadedAssets = new Set(); - - // we will load all plugins in parallel from builtinPlugins - return Promise.all( - [...builtinPluginPaths].map(url => { - return fetch(`${url}/package.json`) - .then(async res => { - const packageJson = (await res.json()) as z.infer< - typeof packageJsonOutputSchema - >; - packageJsonOutputSchema.parse(packageJson); - const { - name: pluginName, - affinePlugin: { - release, - entry: { core }, - assets, - }, - } = packageJson; - rootStore.set(pluginPackageJson, json => [...json, packageJson]); - logger.debug(`registering plugin ${pluginName}`); - logger.debug(`package.json: ${packageJson}`); - if (!release && !runtimeConfig.enablePlugin) { - return; - } - const baseURL = url; - const entryURL = `${baseURL}/${core}`; - rootStore.set(loadedPluginNameAtom, prev => [...prev, pluginName]); - await setupPluginCode(baseURL, pluginName, core); - console.log(`prepareImports for ${pluginName} done`); - await fetch(entryURL).then(async () => { - if (assets.length > 0) { - await Promise.all( - assets.map(async (asset: string) => { - const loadedAssetName = `${pluginName}_${asset}`; - // todo(himself65): add assets into shadow dom - if (loadedAssets.has(loadedAssetName)) { - return; - } - if (asset.endsWith('.css')) { - loadedAssets.add(loadedAssetName); - const res = await fetch(`${baseURL}/${asset}`); - if (res.ok) { - // todo: how to put css file into sandbox? - return res.text().then(text => { - const style = document.createElement('style'); - style.setAttribute('plugin-id', pluginName); - style.textContent = text; - document.head.append(style); - }); - } - return null; - } else { - return; - } - }) - ); - } - if (!enabledPluginSet.has(pluginName)) { - logger.debug(`plugin ${pluginName} is not enabled`); - } else { - logger.debug(`plugin ${pluginName} is enabled`); - evaluatePluginEntry(pluginName); - } - }); - }) - .catch(e => { - console.error(`error when fetch plugin from ${url}`, e); - }); - }) - ).then(() => { - console.info('All plugins loaded'); - }); -} diff --git a/packages/frontend/core/src/components/affine/setting-modal/general-setting/plugins/index.tsx b/packages/frontend/core/src/components/affine/setting-modal/general-setting/plugins/index.tsx deleted file mode 100644 index 02d29e954..000000000 --- a/packages/frontend/core/src/components/affine/setting-modal/general-setting/plugins/index.tsx +++ /dev/null @@ -1,97 +0,0 @@ -import { Switch } from '@affine/component'; -import { SettingHeader } from '@affine/component/setting-components'; -import { useAFFiNEI18N } from '@affine/i18n/hooks'; -import type { CallbackMap } from '@affine/sdk/entry'; -import { - addCleanup, - enabledPluginAtom, - pluginPackageJson, - pluginSettingAtom, -} from '@toeverything/infra/__internal__/plugin'; -import { loadedPluginNameAtom } from '@toeverything/infra/atom'; -import type { packageJsonOutputSchema } from '@toeverything/infra/type'; -import { useAtom, useAtomValue } from 'jotai/react'; -import { startTransition, useCallback, useMemo } from 'react'; -import type { z } from 'zod'; - -import { pluginItemStyle } from './style.css'; - -type PluginItemProps = { - json: z.infer; -}; - -type PluginSettingDetailProps = { - pluginName: string; - create: CallbackMap['setting']; -}; - -const PluginSettingDetail = ({ - pluginName, - create, -}: PluginSettingDetailProps) => { - return ( -
{ - if (ref) { - const cleanup = create(ref); - addCleanup(pluginName, cleanup); - } - }, - [pluginName, create] - )} - /> - ); -}; - -const PluginItem = ({ json }: PluginItemProps) => { - const [plugins, setEnabledPlugins] = useAtom(enabledPluginAtom); - const checked = useMemo( - () => plugins.includes(json.name), - [json.name, plugins] - ); - const create = useAtomValue(pluginSettingAtom)[json.name]; - return ( -
-
- {json.name} - { - startTransition(() => { - setEnabledPlugins(plugins => { - if (checked) { - return [...plugins, json.name]; - } else { - return plugins.filter(plugin => plugin !== json.name); - } - }); - }); - }, - [json.name, setEnabledPlugins] - )} - /> -
-
{json.description}
- {create && } -
- ); -}; - -export const Plugins = () => { - const t = useAFFiNEI18N(); - const loadedPlugins = useAtomValue(loadedPluginNameAtom); - return ( - <> - - {useAtomValue(pluginPackageJson).map(json => ( - - ))} - - ); -}; diff --git a/packages/frontend/core/src/components/affine/setting-modal/general-setting/plugins/style.css.ts b/packages/frontend/core/src/components/affine/setting-modal/general-setting/plugins/style.css.ts deleted file mode 100644 index 0f122181e..000000000 --- a/packages/frontend/core/src/components/affine/setting-modal/general-setting/plugins/style.css.ts +++ /dev/null @@ -1,16 +0,0 @@ -import { style } from '@vanilla-extract/css'; - -export const settingWrapperStyle = style({ - flexGrow: 1, - display: 'flex', - justifyContent: 'flex-end', - minWidth: '150px', - maxWidth: '250px', -}); - -export const pluginItemStyle = style({ - borderBottom: '1px solid var(--affine-border-color)', - transition: '0.3s', - padding: '24px 8px', - fontSize: 'var(--affine-font-sm)', -}); diff --git a/packages/plugins/image-preview/src/component/hooks/use-zoom.tsx b/packages/frontend/core/src/components/image-preview/hooks/use-zoom.tsx similarity index 100% rename from packages/plugins/image-preview/src/component/hooks/use-zoom.tsx rename to packages/frontend/core/src/components/image-preview/hooks/use-zoom.tsx diff --git a/packages/plugins/image-preview/src/component/index.css.ts b/packages/frontend/core/src/components/image-preview/index.css.ts similarity index 100% rename from packages/plugins/image-preview/src/component/index.css.ts rename to packages/frontend/core/src/components/image-preview/index.css.ts diff --git a/packages/plugins/image-preview/src/component/index.jotai.ts b/packages/frontend/core/src/components/image-preview/index.jotai.ts similarity index 100% rename from packages/plugins/image-preview/src/component/index.jotai.ts rename to packages/frontend/core/src/components/image-preview/index.jotai.ts diff --git a/packages/plugins/image-preview/src/component/index.tsx b/packages/frontend/core/src/components/image-preview/index.tsx similarity index 98% rename from packages/plugins/image-preview/src/component/index.tsx rename to packages/frontend/core/src/components/image-preview/index.tsx index c34f0804c..bc8197690 100644 --- a/packages/plugins/image-preview/src/component/index.tsx +++ b/packages/frontend/core/src/components/image-preview/index.tsx @@ -1,3 +1,4 @@ +import { toast } from '@affine/component'; import { Button, IconButton } from '@affine/component/ui/button'; import { Tooltip } from '@affine/component/ui/tooltip'; import type { ImageBlockModel } from '@blocksuite/blocks'; @@ -19,6 +20,7 @@ import { useAtom } from 'jotai'; import type { PropsWithChildren, ReactElement } from 'react'; import { Suspense, useCallback } from 'react'; import { useEffect, useRef, useState } from 'react'; +import ReactDOM from 'react-dom'; import type { FallbackProps } from 'react-error-boundary'; import { ErrorBoundary } from 'react-error-boundary'; import useSWR from 'swr'; @@ -41,7 +43,6 @@ import { unloaded, } from './index.css'; import { hasAnimationPlayedAtom, previewBlockIdAtom } from './index.jotai'; -import { toast } from './toast'; export type ImagePreviewModalProps = { workspace: Workspace; @@ -440,7 +441,7 @@ const ImagePreviewModalImpl = ( return; } const dataUrl = URL.createObjectURL(blob); - global.navigator.clipboard + navigator.clipboard .write([new ClipboardItem({ 'image/png': blob })]) .then(() => { console.log('Image copied to clipboard'); @@ -554,7 +555,7 @@ export const ImagePreviewModal = ( return null; } - return ( + return ReactDOM.createPortal(
-
+ , + document.body ); }; diff --git a/packages/frontend/core/src/components/page-detail-editor.tsx b/packages/frontend/core/src/components/page-detail-editor.tsx index 00a9a5538..3a0545d51 100644 --- a/packages/frontend/core/src/components/page-detail-editor.tsx +++ b/packages/frontend/core/src/components/page-detail-editor.tsx @@ -4,8 +4,6 @@ import { assertExists, DisposableGroup } from '@blocksuite/global/utils'; import type { AffineEditorContainer } from '@blocksuite/presets'; import type { Page, Workspace } from '@blocksuite/store'; import { useBlockSuiteWorkspacePage } from '@toeverything/hooks/use-block-suite-workspace-page'; -import { pluginEditorAtom } from '@toeverything/infra/__internal__/plugin'; -import { getCurrentStore } from '@toeverything/infra/atom'; import { fontStyleOptions } from '@toeverything/infra/atom'; import clsx from 'clsx'; import { useAtomValue } from 'jotai'; @@ -110,31 +108,8 @@ const PageDetailEditorMain = memo(function PageDetailEditorMain({ disposableGroup.add(onLoad(page, editor)); } - // todo: remove the following - // for now this is required for the image-preview plugin to work - const rootStore = getCurrentStore(); - const editorItems = rootStore.get(pluginEditorAtom); - let disposes: (() => void)[] = []; - const renderTimeout = window.setTimeout(() => { - disposes = Object.entries(editorItems).map(([id, editorItem]) => { - const div = document.createElement('div'); - div.setAttribute('plugin-id', id); - const cleanup = editorItem(div, editor); - assertExists(parent); - document.body.append(div); - return () => { - cleanup(); - div.remove(); - }; - }); - }); - return () => { disposableGroup.dispose(); - clearTimeout(renderTimeout); - window.setTimeout(() => { - disposes.forEach(dispose => dispose()); - }); }; }, [onLoad, page] diff --git a/packages/frontend/core/src/components/pure/plugin-header/index.tsx b/packages/frontend/core/src/components/pure/plugin-header/index.tsx deleted file mode 100644 index 615669154..000000000 --- a/packages/frontend/core/src/components/pure/plugin-header/index.tsx +++ /dev/null @@ -1,44 +0,0 @@ -import { - addCleanup, - pluginHeaderItemAtom, -} from '@toeverything/infra/__internal__/plugin'; -import { useAtomValue } from 'jotai'; -import { startTransition, useCallback, useRef } from 'react'; - -import * as styles from './styles.css'; -export const PluginHeader = () => { - const headerItem = useAtomValue(pluginHeaderItemAtom); - const pluginsRef = useRef([]); - - return ( -
{ - if (root) { - Object.entries(headerItem).forEach(([pluginName, create]) => { - if (pluginsRef.current.includes(pluginName)) { - return; - } - pluginsRef.current.push(pluginName); - const div = document.createElement('div'); - div.setAttribute('plugin-id', pluginName); - startTransition(() => { - const cleanup = create(div); - root.append(div); - addCleanup(pluginName, () => { - pluginsRef.current = pluginsRef.current.filter( - name => name !== pluginName - ); - div.remove(); - cleanup(); - }); - }); - }); - } - }, - [headerItem] - )} - /> - ); -}; diff --git a/packages/frontend/core/src/components/pure/plugin-header/styles.css.ts b/packages/frontend/core/src/components/pure/plugin-header/styles.css.ts deleted file mode 100644 index 254ef6618..000000000 --- a/packages/frontend/core/src/components/pure/plugin-header/styles.css.ts +++ /dev/null @@ -1,8 +0,0 @@ -import { style } from '@vanilla-extract/css'; - -export const pluginHeaderItems = style({ - display: 'flex', - gap: '12px', - alignItems: 'center', - height: '100%', -}); diff --git a/packages/frontend/core/src/index.tsx b/packages/frontend/core/src/index.tsx index 57d68e38d..1a1e95584 100644 --- a/packages/frontend/core/src/index.tsx +++ b/packages/frontend/core/src/index.tsx @@ -1,14 +1,11 @@ -import 'ses'; import './polyfill/intl-segmenter'; import './polyfill/request-idle-callback'; import { assertExists } from '@blocksuite/global/utils'; -import { getCurrentStore } from '@toeverything/infra/atom'; import { StrictMode } from 'react'; import { createRoot } from 'react-dom/client'; import { App } from './app'; -import { bootstrapPluginSystem } from './bootstrap/register-plugins'; import { setup } from './bootstrap/setup'; import { performanceLogger } from './shared'; @@ -18,14 +15,9 @@ function main() { // skip bootstrap setup for desktop onboarding if (window.appInfo?.windowName !== 'onboarding') { - const rootStore = getCurrentStore(); performanceMainLogger.info('setup start'); setup(); performanceMainLogger.info('setup done'); - - bootstrapPluginSystem(rootStore).catch(err => { - console.error('Failed to bootstrap plugin system', err); - }); } mountApp(); diff --git a/packages/frontend/core/src/pages/workspace/detail-page/detail-page.tsx b/packages/frontend/core/src/pages/workspace/detail-page/detail-page.tsx index fb850561b..d5ba576e7 100644 --- a/packages/frontend/core/src/pages/workspace/detail-page/detail-page.tsx +++ b/packages/frontend/core/src/pages/workspace/detail-page/detail-page.tsx @@ -30,6 +30,7 @@ import { currentModeAtom, currentPageIdAtom } from '../../../atoms/mode'; import { AffineErrorBoundary } from '../../../components/affine/affine-error-boundary'; import { HubIsland } from '../../../components/affine/hub-island'; import { GlobalPageHistoryModal } from '../../../components/affine/page-history-modal'; +import { ImagePreviewModal } from '../../../components/image-preview'; import { PageDetailEditor } from '../../../components/page-detail-editor'; import { TrashPageFooter } from '../../../components/pure/trash-page-footer'; import { TopTip } from '../../../components/top-tip'; @@ -193,6 +194,10 @@ const DetailPageImpl = memo(function DetailPageImpl({ page }: { page: Page }) { ) : null } /> + ); diff --git a/packages/frontend/core/src/pages/workspace/trash-page.tsx b/packages/frontend/core/src/pages/workspace/trash-page.tsx index 637fda921..4d6648f47 100644 --- a/packages/frontend/core/src/pages/workspace/trash-page.tsx +++ b/packages/frontend/core/src/pages/workspace/trash-page.tsx @@ -58,7 +58,6 @@ export const loader: LoaderFunction = async () => { export const TrashPage = () => { const currentWorkspace = useAtomValue(waitForCurrentWorkspaceAtom); - // todo(himself65): refactor to plugin const blockSuiteWorkspace = currentWorkspace.blockSuiteWorkspace; assertExists(blockSuiteWorkspace); diff --git a/packages/frontend/core/tsconfig.json b/packages/frontend/core/tsconfig.json index 36a7d8aba..c250ef7c0 100644 --- a/packages/frontend/core/tsconfig.json +++ b/packages/frontend/core/tsconfig.json @@ -29,9 +29,6 @@ { "path": "../../common/env" }, - { - "path": "../../plugins/copilot" - }, { "path": "./tsconfig.node.json" }, diff --git a/packages/frontend/electron/package.json b/packages/frontend/electron/package.json index 6928300a7..59fa098bb 100644 --- a/packages/frontend/electron/package.json +++ b/packages/frontend/electron/package.json @@ -23,14 +23,9 @@ "main": "./dist/main.js", "devDependencies": { "@affine-test/kit": "workspace:*", - "@affine/copilot-plugin": "workspace:*", "@affine/env": "workspace:*", - "@affine/hello-world-plugin": "workspace:*", - "@affine/image-preview-plugin": "workspace:*", "@affine/native": "workspace:*", - "@affine/sdk": "workspace:*", "@affine/templates": "workspace:*", - "@affine/vue-hello-world-plugin": "workspace:*", "@blocksuite/blocks": "0.11.0-nightly-202312220916-e3abcbb", "@blocksuite/lit": "0.11.0-nightly-202312220916-e3abcbb", "@blocksuite/presets": "0.11.0-nightly-202312220916-e3abcbb", diff --git a/packages/frontend/electron/project.json b/packages/frontend/electron/project.json index d2044e8ee..7f87ea538 100644 --- a/packages/frontend/electron/project.json +++ b/packages/frontend/electron/project.json @@ -7,14 +7,7 @@ "targets": { "build": { "executor": "nx:run-script", - "dependsOn": [ - { - "projects": ["tag:plugin"], - "target": "build", - "params": "ignore" - }, - "^build" - ], + "dependsOn": ["^build"], "options": { "script": "build" }, diff --git a/packages/frontend/electron/scripts/common.ts b/packages/frontend/electron/scripts/common.ts index bcb6d31ec..ab2b6f41b 100644 --- a/packages/frontend/electron/scripts/common.ts +++ b/packages/frontend/electron/scripts/common.ts @@ -28,14 +28,7 @@ export const config = (): BuildOptions => { bundle: true, target: `node${NODE_MAJOR_VERSION}`, platform: 'node', - external: [ - 'electron', - 'electron-updater', - '@toeverything/plugin-infra', - 'yjs', - 'semver', - 'tinykeys', - ], + external: ['electron', 'electron-updater', 'yjs', 'semver', 'tinykeys'], format: 'cjs', loader: { '.node': 'copy', diff --git a/packages/frontend/electron/scripts/generate-assets.ts b/packages/frontend/electron/scripts/generate-assets.ts index 3b7de92dd..7d0fdefb7 100755 --- a/packages/frontend/electron/scripts/generate-assets.ts +++ b/packages/frontend/electron/scripts/generate-assets.ts @@ -43,14 +43,6 @@ const cwd = repoRootDir; const { SKIP_NX_CACHE } = process.env; const nxFlag = SKIP_NX_CACHE ? '--skip-nx-cache' : ''; -if (!process.env.SKIP_PLUGIN_BUILD) { - spawnSync('yarn', ['build:plugins'], { - stdio: 'inherit', - env: process.env, - cwd, - }); -} - // step 1: build web dist if (!process.env.SKIP_WEB_BUILD) { spawnSync('yarn', ['nx', 'build', '@affine/core', nxFlag], { diff --git a/packages/frontend/electron/tsconfig.json b/packages/frontend/electron/tsconfig.json index 7d62f4f91..f207aca9f 100644 --- a/packages/frontend/electron/tsconfig.json +++ b/packages/frontend/electron/tsconfig.json @@ -22,9 +22,6 @@ { "path": "../../common/infra" }, - { - "path": "../../common/sdk" - }, { "path": "../../common/env" }, diff --git a/packages/frontend/electron/tsconfig.node.json b/packages/frontend/electron/tsconfig.node.json index a8afe56be..34fc8e164 100644 --- a/packages/frontend/electron/tsconfig.node.json +++ b/packages/frontend/electron/tsconfig.node.json @@ -12,11 +12,7 @@ "types": ["node"], "allowJs": true }, - "include": [ - "./scripts", - "esbuild.main.config.ts", - "esbuild.plugin.config.ts" - ], + "include": ["./scripts"], "ts-node": { "esm": true, "experimentalSpecifierResolution": "node" diff --git a/packages/plugins/copilot/README.md b/packages/plugins/copilot/README.md deleted file mode 100644 index 578c09e87..000000000 --- a/packages/plugins/copilot/README.md +++ /dev/null @@ -1,3 +0,0 @@ -# AFFiNE Copilot - -> AI Copilot Plugin for your writing diff --git a/packages/plugins/copilot/package.json b/packages/plugins/copilot/package.json deleted file mode 100644 index 9a17c7976..000000000 --- a/packages/plugins/copilot/package.json +++ /dev/null @@ -1,41 +0,0 @@ -{ - "name": "@affine/copilot-plugin", - "type": "module", - "private": true, - "description": "Copilot plugin", - "affinePlugin": { - "release": false, - "entry": { - "core": "./src/index.ts" - } - }, - "scripts": { - "dev": "af dev", - "build": "af build" - }, - "dependencies": { - "@affine/component": "workspace:*", - "@affine/sdk": "workspace:*", - "@blocksuite/icons": "2.1.36", - "@vanilla-extract/css": "^1.13.0", - "clsx": "^2.0.0", - "idb": "^8.0.0", - "langchain": "^0.0.166", - "marked": "^11.0.0", - "marked-gfm-heading-id": "^3.1.0", - "marked-mangle": "^1.1.4", - "zod": "^3.22.4" - }, - "devDependencies": { - "@affine/plugin-cli": "workspace:*", - "@types/marked": "^6.0.0", - "jotai": "^2.5.1", - "react": "18.2.0", - "react-dom": "18.2.0" - }, - "peerDependencies": { - "react": "*", - "react-dom": "*" - }, - "version": "0.11.0" -} diff --git a/packages/plugins/copilot/project.json b/packages/plugins/copilot/project.json deleted file mode 100644 index f683b4b6a..000000000 --- a/packages/plugins/copilot/project.json +++ /dev/null @@ -1,26 +0,0 @@ -{ - "name": "@affine/copilot-plugin", - "$schema": "../../../node_modules/nx/schemas/project-schema.json", - "namedInputs": { - "default": [ - "{projectRoot}/**/*", - "{workspaceRoot}/tools/plugin-cli/src/**/*", - "sharedGlobals" - ] - }, - "targets": { - "build": { - "executor": "nx:run-script", - "options": { - "script": "build" - }, - "dependsOn": ["^build"], - "inputs": ["default"], - "outputs": [ - "{workspaceRoot}/packages/frontend/core/public/plugins/copilot", - "{workspaceRoot}/packages/frontend/electron/dist/plugins/copilot" - ] - } - }, - "tags": ["plugin"] -} diff --git a/packages/plugins/copilot/src/UI/debug-content.tsx b/packages/plugins/copilot/src/UI/debug-content.tsx deleted file mode 100644 index 5ccea36fb..000000000 --- a/packages/plugins/copilot/src/UI/debug-content.tsx +++ /dev/null @@ -1,37 +0,0 @@ -import { FlexWrapper, Input } from '@affine/component'; -import { Button } from '@affine/component/ui/button'; -import { useAtom } from 'jotai'; -import { type ReactElement, useCallback } from 'react'; - -import { openAIApiKeyAtom } from '../core/hooks'; -import { conversationHistoryDBName } from '../core/langchain/message-history'; - -export const DebugContent = (): ReactElement => { - const [key, setKey] = useAtom(openAIApiKeyAtom); - return ( -
- - { - setKey(newValue); - }, - [setKey] - )} - placeholder="Enter your API_KEY here" - /> - - -
- ); -}; diff --git a/packages/plugins/copilot/src/UI/detail-content.tsx b/packages/plugins/copilot/src/UI/detail-content.tsx deleted file mode 100644 index 78855ff67..000000000 --- a/packages/plugins/copilot/src/UI/detail-content.tsx +++ /dev/null @@ -1,72 +0,0 @@ -import { IconButton } from '@affine/component/ui/button'; -import { SendIcon } from '@blocksuite/icons'; -import { useAtomValue, useSetAtom } from 'jotai'; -import type { ReactElement } from 'react'; -import { Suspense, useCallback, useState } from 'react'; - -import { ConversationList } from '../core/components/conversation-list'; -import { FollowingUp } from '../core/components/following-up'; -import { openAIApiKeyAtom, useChatAtoms } from '../core/hooks'; -import { - detailContentActionsStyle, - detailContentStyle, - sendButtonStyle, - textareaStyle, -} from './index.css'; - -const Actions = () => { - const { conversationAtom, followingUpAtoms } = useChatAtoms(); - const call = useSetAtom(conversationAtom); - const questions = useAtomValue(followingUpAtoms.questionsAtom); - const generateFollowingUp = useSetAtom(followingUpAtoms.generateChatAtom); - const [input, setInput] = useState(''); - return ( - <> - -
-