import('./UI/index'),
- hotModuleReload: onHot =>
- import.meta.webpackHot &&
- import.meta.webpackHot.accept('./UI', () => onHot(import('./UI/index'))),
- }
-);
+import { DetailContent } from './UI/detail-content';
+import { HeaderItem } from './UI/header-item';
+
+export const entry = (context: PluginContext) => {
+ context.register('headerItem', div => {
+ const root = createRoot(div);
+ root.render(
+ createElement(context.utils.PluginProvider, {}, createElement(HeaderItem))
+ );
+ return () => {
+ root.unmount();
+ };
+ });
+
+ context.register('window', div => {
+ const root = createRoot(div);
+ root.render(
+ createElement(
+ context.utils.PluginProvider,
+ {},
+ createElement(DetailContent)
+ )
+ );
+ return () => {
+ root.unmount();
+ };
+ });
+ return () => {};
+};
diff --git a/plugins/hello-world/package.json b/plugins/hello-world/package.json
new file mode 100644
index 000000000..583fd4475
--- /dev/null
+++ b/plugins/hello-world/package.json
@@ -0,0 +1,16 @@
+{
+ "name": "@affine/hello-world-plugin",
+ "private": true,
+ "version": "0.0.1",
+ "affinePlugin": {
+ "release": false,
+ "entry": {
+ "core": "./src/index.ts"
+ }
+ },
+ "dependencies": {
+ "@affine/component": "workspace:*",
+ "@blocksuite/icons": "^2.1.25",
+ "@toeverything/plugin-infra": "workspace:*"
+ }
+}
diff --git a/plugins/hello-world/src/app.tsx b/plugins/hello-world/src/app.tsx
new file mode 100644
index 000000000..a809e3b49
--- /dev/null
+++ b/plugins/hello-world/src/app.tsx
@@ -0,0 +1,17 @@
+import { IconButton, Tooltip } from '@affine/component';
+import { AffineLogoSBlue2_1Icon } from '@blocksuite/icons';
+import { useCallback } from 'react';
+
+export const HeaderItem = () => {
+ return (
+
+ {
+ console.log('clicked hello world!');
+ }, [])}
+ >
+
+
+
+ );
+};
diff --git a/plugins/hello-world/src/index.ts b/plugins/hello-world/src/index.ts
new file mode 100644
index 000000000..b94b13eb7
--- /dev/null
+++ b/plugins/hello-world/src/index.ts
@@ -0,0 +1,26 @@
+import type { PluginContext } from '@toeverything/plugin-infra/entry';
+import {
+ currentWorkspaceIdAtom,
+ rootStore,
+} from '@toeverything/plugin-infra/manager';
+import { createElement } from 'react';
+import { createRoot } from 'react-dom/client';
+
+import { HeaderItem } from './app';
+
+export const entry = (context: PluginContext) => {
+ console.log('register');
+ console.log('hello, world!');
+ console.log(rootStore.get(currentWorkspaceIdAtom));
+ context.register('headerItem', div => {
+ const root = createRoot(div);
+ root.render(createElement(HeaderItem));
+ return () => {
+ root.unmount();
+ };
+ });
+
+ return () => {
+ console.log('unregister');
+ };
+};
diff --git a/plugins/hello-world/tsconfig.json b/plugins/hello-world/tsconfig.json
new file mode 100644
index 000000000..f2db0bc49
--- /dev/null
+++ b/plugins/hello-world/tsconfig.json
@@ -0,0 +1,17 @@
+{
+ "extends": "../../tsconfig.json",
+ "include": ["./src"],
+ "compilerOptions": {
+ "noEmit": false,
+ "outDir": "lib",
+ "jsx": "preserve"
+ },
+ "references": [
+ {
+ "path": "../../packages/plugin-infra"
+ },
+ {
+ "path": "../../packages/component"
+ }
+ ]
+}
diff --git a/tsconfig.node.json b/tsconfig.node.json
index 54d05f6a0..c8909a512 100644
--- a/tsconfig.node.json
+++ b/tsconfig.node.json
@@ -8,6 +8,7 @@
"outDir": "lib"
},
"include": [
+ "vite.config.ts",
"vitest.config.ts",
"scripts",
"apps/core/.webpack/runtime-config.ts"
diff --git a/vite.config.ts b/vite.config.ts
new file mode 100644
index 000000000..0e66984e7
--- /dev/null
+++ b/vite.config.ts
@@ -0,0 +1,92 @@
+import { createRequire } from 'node:module';
+import { resolve } from 'node:path';
+import { fileURLToPath } from 'node:url';
+
+import { vanillaExtractPlugin } from '@vanilla-extract/vite-plugin';
+import react from '@vitejs/plugin-react-swc';
+import { defineConfig } from 'vite';
+
+const root = fileURLToPath(new URL('.', import.meta.url));
+
+const require = createRequire(import.meta.url);
+
+const builtInPlugins = ['hello-world', 'bookmark', 'copilot'];
+
+const outputJson: [pluginName: string, output: string][] = [];
+
+const entry = builtInPlugins.reduce(
+ (acc, plugin) => {
+ const packageJson = require(resolve(
+ root,
+ 'plugins',
+ plugin,
+ 'package.json'
+ ));
+ const entry = packageJson.affinePlugin.entry.core;
+ acc[`${plugin}/index`] = resolve(root, 'plugins', plugin, entry);
+ packageJson.affinePlugin.entry.core = './index.js';
+ outputJson.push([plugin, JSON.stringify(packageJson, null, 2)]);
+ return acc;
+ },
+ {} as Record
+);
+
+export default defineConfig({
+ build: {
+ outDir: resolve(root, 'apps', 'core', 'public', 'plugins'),
+ emptyOutDir: true,
+ minify: false,
+ lib: {
+ entry,
+ formats: ['cjs'],
+ },
+ rollupOptions: {
+ output: {
+ manualChunks: () => 'plugin',
+ entryFileNames: '[name].js',
+ chunkFileNames: '[name].js',
+ },
+ external: [
+ // built-in packages
+ /^@affine/,
+ /^@blocksuite/,
+ /^@toeverything/,
+
+ // react
+ /^react/,
+ /^react-dom/,
+
+ // store
+ /^jotai/,
+
+ // css
+ /^@vanilla-extract/,
+ ],
+ plugins: [
+ vanillaExtractPlugin(),
+ {
+ name: 'generate-manifest',
+ generateBundle() {
+ this.emitFile({
+ type: 'asset',
+ fileName: `plugin-list.json`,
+ source: JSON.stringify(
+ builtInPlugins.map(plugin => ({
+ name: plugin,
+ }))
+ ),
+ });
+ outputJson.forEach(([name, json]) => {
+ this.emitFile({
+ type: 'asset',
+ fileName: `${name}/package.json`,
+ source: json,
+ });
+ });
+ },
+ },
+ ],
+ },
+ },
+ plugins: [react()],
+});
diff --git a/vitest.config.ts b/vitest.config.ts
index c6b955a0b..0df34bf95 100644
--- a/vitest.config.ts
+++ b/vitest.config.ts
@@ -2,7 +2,7 @@ import path, { resolve } from 'node:path';
import { fileURLToPath } from 'node:url';
import { vanillaExtractPlugin } from '@vanilla-extract/vite-plugin';
-import react from '@vitejs/plugin-react';
+import react from '@vitejs/plugin-react-swc';
import { defineConfig } from 'vitest/config';
const rootDir = fileURLToPath(new URL('.', import.meta.url));
diff --git a/yarn.lock b/yarn.lock
index 71913de8e..f6eda9f01 100644
--- a/yarn.lock
+++ b/yarn.lock
@@ -64,19 +64,23 @@ __metadata:
languageName: unknown
linkType: soft
-"@affine/bookmark-block@workspace:*, @affine/bookmark-block@workspace:plugins/bookmark-block":
+"@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"
dependencies:
"@affine/component": "workspace:*"
+ "@blocksuite/icons": ^2.1.25
"@toeverything/plugin-infra": "workspace:*"
foxact: ^0.2.11
- link-preview-js: ^3.0.4
- react: 18.2.0
- react-dom: 18.2.0
- peerDependencies:
- react: "*"
- react-dom: "*"
languageName: unknown
linkType: soft
@@ -165,8 +169,6 @@ __metadata:
"@affine/component": "workspace:*"
"@toeverything/plugin-infra": "workspace:*"
"@types/marked": ^5.0.0
- "@types/react": ^18.2.14
- "@types/react-dom": ^18.2.6
idb: ^7.1.1
jotai: ^2.2.2
langchain: ^0.0.107
@@ -187,7 +189,6 @@ __metadata:
resolution: "@affine/core@workspace:apps/core"
dependencies:
"@affine-test/fixtures": "workspace:*"
- "@affine/bookmark-block": "workspace:*"
"@affine/component": "workspace:*"
"@affine/copilot": "workspace:*"
"@affine/debug": "workspace:*"
@@ -241,6 +242,7 @@ __metadata:
react-resizable-panels: ^0.0.53
react-router-dom: ^6.14.1
rxjs: ^7.8.1
+ ses: ^0.18.5
style-loader: ^3.3.3
swc-loader: ^0.2.3
swc-plugin-coverage-instrument: ^0.0.19
@@ -373,6 +375,16 @@ __metadata:
languageName: unknown
linkType: soft
+"@affine/hello-world-plugin@workspace:plugins/hello-world":
+ version: 0.0.0-use.local
+ resolution: "@affine/hello-world-plugin@workspace:plugins/hello-world"
+ dependencies:
+ "@affine/component": "workspace:*"
+ "@blocksuite/icons": ^2.1.25
+ "@toeverything/plugin-infra": "workspace:*"
+ languageName: unknown
+ linkType: soft
+
"@affine/i18n@workspace:*, @affine/i18n@workspace:packages/i18n":
version: 0.0.0-use.local
resolution: "@affine/i18n@workspace:packages/i18n"
@@ -434,7 +446,7 @@ __metadata:
"@typescript-eslint/parser": ^5.60.1
"@vanilla-extract/vite-plugin": ^3.8.2
"@vanilla-extract/webpack-plugin": ^2.2.0
- "@vitejs/plugin-react": ^4.0.1
+ "@vitejs/plugin-react-swc": ^3.3.2
"@vitest/coverage-istanbul": ^0.32.2
"@vitest/ui": ^0.32.2
eslint: ^8.44.0
@@ -464,6 +476,7 @@ __metadata:
typescript: ^5.1.6
vite: ^4.3.9
vite-plugin-istanbul: ^4.1.0
+ vite-plugin-static-copy: ^0.17.0
vite-tsconfig-paths: ^4.2.0
vitest: ^0.32.2
vitest-fetch-mock: ^0.2.2
@@ -4657,6 +4670,13 @@ __metadata:
languageName: node
linkType: hard
+"@endo/env-options@npm:^0.1.1":
+ version: 0.1.1
+ resolution: "@endo/env-options@npm:0.1.1"
+ checksum: c721db3e2d3f9a52a5c391dc8e6d473ffc44cf2bb252fad3048551e35aac52484d612753211116ff9a7157a0768d7c61352c494f491e3463e78fef438beb1d42
+ languageName: node
+ linkType: hard
+
"@esbuild/android-arm64@npm:0.17.19":
version: 0.17.19
resolution: "@esbuild/android-arm64@npm:0.17.19"
@@ -11385,7 +11405,7 @@ __metadata:
languageName: node
linkType: hard
-"@swc/core@npm:^1.3.70":
+"@swc/core@npm:^1.3.61, @swc/core@npm:^1.3.70":
version: 1.3.70
resolution: "@swc/core@npm:1.3.70"
dependencies:
@@ -12841,6 +12861,17 @@ __metadata:
languageName: node
linkType: hard
+"@vitejs/plugin-react-swc@npm:^3.3.2":
+ version: 3.3.2
+ resolution: "@vitejs/plugin-react-swc@npm:3.3.2"
+ dependencies:
+ "@swc/core": ^1.3.61
+ peerDependencies:
+ vite: ^4
+ checksum: 1e44b1b7c50b6ae381e2ded9a7971af42286144bf257d7ed1a9dbf8acec0c4af78fe46982941566d31b80b7886649d9b1c06a873571d228e0b8fce68742b9ff4
+ languageName: node
+ linkType: hard
+
"@vitejs/plugin-react@npm:^3.0.1":
version: 3.1.0
resolution: "@vitejs/plugin-react@npm:3.1.0"
@@ -19460,8 +19491,8 @@ __metadata:
linkType: hard
"foxact@npm:^0.2.11":
- version: 0.2.11
- resolution: "foxact@npm:0.2.11"
+ version: 0.2.17
+ resolution: "foxact@npm:0.2.17"
dependencies:
client-only: ^0.0.1
server-only: ^0.0.1
@@ -19470,7 +19501,7 @@ __metadata:
peerDependenciesMeta:
react:
optional: true
- checksum: 711a5d1e287c45eb258a9003910d13fc2c82f3c6cd0e4e9c673dbe64c6a7d95da7cc983b5f143270bc6304b9ceb0de2d25c01588e066e01e8eb0dbb55e55eaa6
+ checksum: 9229ac42032dbce52c95f5583601ba5dbfe8e4bd40b6ec3b372d91793b7b621e01eb45bb953dfe077e65a2ecd4dcdaa42c8f1c60efbf43048a3cd0038a754b60
languageName: node
linkType: hard
@@ -29218,6 +29249,15 @@ __metadata:
languageName: node
linkType: hard
+"ses@npm:^0.18.5":
+ version: 0.18.5
+ resolution: "ses@npm:0.18.5"
+ dependencies:
+ "@endo/env-options": ^0.1.1
+ checksum: b41faaf28efc97c09b0322de5c12603e015238e4b2cf5195c8fc3f5fb9bc66169dd394c63bcdb30d8fa36a55d03eeda3df64857ab724b2297fb6b60c4f5dc0e2
+ languageName: node
+ linkType: hard
+
"set-blocking@npm:^2.0.0":
version: 2.0.0
resolution: "set-blocking@npm:2.0.0"
@@ -31924,6 +31964,20 @@ __metadata:
languageName: node
linkType: hard
+"vite-plugin-static-copy@npm:^0.17.0":
+ version: 0.17.0
+ resolution: "vite-plugin-static-copy@npm:0.17.0"
+ dependencies:
+ chokidar: ^3.5.3
+ fast-glob: ^3.2.11
+ fs-extra: ^11.1.0
+ picocolors: ^1.0.0
+ peerDependencies:
+ vite: ^3.0.0 || ^4.0.0
+ checksum: b73f001f080517d7c2342ad5b0779c1e5ec8b5820e85a57280e8f979d095946a32ab717a59eaae60e3f715784a138785208619aa6d936cd9a80e6a03e364e4fc
+ languageName: node
+ linkType: hard
+
"vite-tsconfig-paths@npm:^4.2.0":
version: 4.2.0
resolution: "vite-tsconfig-paths@npm:4.2.0"