+
+If the plugin is not shown in the plugin manager, you can add it manually with the `pm add` command.
+
+```bash
+yarn pm add @my-project/plugin-hello
+```
## Code the plugin
-Look at the `packages/plugins/hello/src/server/plugin.ts` file and modify it to
+Look at the `packages/plugins/@my-project/plugin-hello/src/server/plugin.ts` file and modify it to
```ts
import { InstallOptions, Plugin } from '@nocobase/server';
-export class HelloPlugin extends Plugin {
+export class PluginHelloServer extends Plugin {
afterAdd() {}
beforeLoad() {}
@@ -62,9 +54,7 @@ export class HelloPlugin extends Plugin {
async load() {
this.db.collection({
name: 'hello',
- fields: [
- { type: 'string', name: 'name' }
- ],
+ fields: [{ type: 'string', name: 'name' }],
});
this.app.acl.allow('hello', '*');
}
@@ -78,24 +68,29 @@ export class HelloPlugin extends Plugin {
async remove() {}
}
-export default HelloPlugin;
-```
-
-## Register the plugin
-
-```bash
-yarn pm add hello
+export default PluginHelloServer;
```
## Activate the plugin
-When the plugin is activated, the hello table that you just configured is automatically created.
+**Operated by command**
```bash
-yarn pm enable hello
+yarn pm enable @my-project/plugin-hello
```
-## Start the application
+**Operated by UI**
+
+Visit the Plugin Manager to view the plugin you just added and click enable.
+The Plugin Manager page defaults to http://localhost:13000/admin/pm/list/local/
+
+
+
+Node: When the plugin is activated, the hello collection that you just configured is automatically created.
+
+## Debug the Plugin
+
+If the app is not started, you need to start the app first
```bash
# for development
@@ -106,9 +101,7 @@ yarn build
yarn start
```
-## Experience the plugin
-
-Insert data into the hello table of the plugin
+Insert data into the hello collection of the plugin
```bash
curl --location --request POST 'http://localhost:13000/api/hello:create' \
@@ -123,3 +116,21 @@ View the data
```bash
curl --location --request GET 'http://localhost:13000/api/hello:list'
```
+
+## Build the plugin
+
+```bash
+yarn build plugins/@my-project/plugin-hello --tar
+
+# step-by-step
+yarn build plugins/@my-project/plugin-hello
+yarn nocobase tar plugins/@my-project/plugin-hello
+```
+
+The default saved path for the plugin tar is `storage/tar/@my-project/plugin-hello.tar.gz`
+
+## Upload to other NocoBase applications
+
+Only supported in v0.14 and above
+
+
diff --git a/docs/en-US/welcome/release/v14-changelog.md b/docs/en-US/welcome/release/v14-changelog.md
new file mode 100644
index 000000000..7adb8017d
--- /dev/null
+++ b/docs/en-US/welcome/release/v14-changelog.md
@@ -0,0 +1,59 @@
+# v0.14: New plugin manager, supports adding plugins through UI
+
+This release enables plug-and-play plugins in production environments. You can now add plugins directly through the UI, and support downloading from the npm registry (which can be private), local uploads, and URL downloads.
+
+## New features
+
+### New plugin manager interface
+
+
+
+### Uploaded plugins are located in the storage/plugins directory.
+
+The storage/plugins directory is used to upload plugins, and is organized as npm packages.
+
+```bash
+|- /storage/
+ |- /plugins/
+ |- /@nocobase/
+ |- /plugin-hello1/
+ |- /plugin-hello2/
+ |- /@foo/
+ |- /bar/
+ |- /my-nocobase-plugin-hello/
+```
+
+### Plugin updates
+
+Currently, only plugins under storage/plugins can be updated, as shown here:
+
+
+
+Note: In order to facilitate maintenance and upgrading, and to avoid unavailability of the storage plugins due to upgrading, you can put the new plugin directly into storage/plugins and then perform the upgrade operation.
+
+## Incompatible changes
+
+### Changes to plugin names
+
+- PLUGIN_PACKAGE_PREFIX environment variable is no longer provided.
+- Plugin names and package names are unified, old plugin names can still exist as aliases.
+
+### Improvements to pm.add
+
+```bash
+# Use packageName instead of pluginName, lookup locally, error if not found
+pm add packageName
+
+# Download from remote only if registry is provided, can also specify version
+pm add packageName --registry=xx --auth-token=yy --version=zz
+
+# You can also provide a local zip, add multiple times and replace it with the last one
+pm add /a/plugin.zip
+
+# Remote zip, replace it with the same name
+pm add http://url/plugin.zip
+```
+
+## Plugin development guide
+
+[Develop the first plugin](/development/your-fisrt-plugin)
diff --git a/docs/zh-CN/development/your-fisrt-plugin.md b/docs/zh-CN/development/your-fisrt-plugin.md
index dd52ac407..5227c9d8d 100644
--- a/docs/zh-CN/development/your-fisrt-plugin.md
+++ b/docs/zh-CN/development/your-fisrt-plugin.md
@@ -9,16 +9,16 @@
## 创建插件
-首先,你可以通过 CLI 快速的创建一个空插件,命令如下:
+通过 CLI 快速地创建一个空插件,命令如下:
```bash
-yarn pm create hello
+yarn pm create @my-project/plugin-hello
```
-插件所在目录 `packages/plugins/hello`,插件目录结构为:
+插件所在目录 `packages/plugins/@my-project/plugin-hello`,插件目录结构为:
```bash
-|- /hello
+|- /packages/plugins/@my-project/plugin-hello
|- /src
|- /client # 插件客户端代码
|- /server # 插件服务端代码
@@ -29,32 +29,24 @@ yarn pm create hello
|- server.js
```
-package.json 信息
+访问插件管理器界面,查看刚添加的插件,默认地址为 http://localhost:13000/admin/pm/list/local/
-```json
-{
- "name": "@nocobase/plugin-hello",
- "version": "0.1.0",
- "main": "lib/server/index.js",
- "devDependencies": {
- "@nocobase/client": "0.8.0-alpha.1",
- "@nocobase/test": "0.8.0-alpha.1"
- }
-}
+
+
+如果创建的插件未在插件管理器里显示,可以通过 `pm add` 命令手动添加
+
+```bash
+yarn pm add @my-project/plugin-hello
```
-NocoBase 插件也是 NPM 包,插件名和 NPM 包名的对应规则为 `${PLUGIN_PACKAGE_PREFIX}-${pluginName}`。
-
-`PLUGIN_PACKAGE_PREFIX` 为插件包前缀,可以在 .env 里自定义,[点此查看 PLUGIN_PACKAGE_PREFIX 说明](/api/env#plugin_package_prefix)。
-
## 编写插件
-查看 `packages/plugins/hello/src/server/plugin.ts` 文件,并修改为:
+查看 `packages/plugins/@my-project/plugin-hello/src/server/plugin.ts` 文件,并修改为:
```ts
import { InstallOptions, Plugin } from '@nocobase/server';
-export class HelloPlugin extends Plugin {
+export class PluginHelloServer extends Plugin {
afterAdd() {}
beforeLoad() {}
@@ -62,9 +54,7 @@ export class HelloPlugin extends Plugin {
async load() {
this.db.collection({
name: 'hello',
- fields: [
- { type: 'string', name: 'name' }
- ],
+ fields: [{ type: 'string', name: 'name' }],
});
this.app.acl.allow('hello', '*');
}
@@ -78,24 +68,29 @@ export class HelloPlugin extends Plugin {
async remove() {}
}
-export default HelloPlugin;
-```
-
-## 注册插件
-
-```bash
-yarn pm add hello
+export default PluginHelloServer;
```
## 激活插件
-插件激活时,会自动创建刚才编辑插件配置的 hello 表。
+**通过命令操作**
```bash
-yarn pm enable hello
+yarn pm enable @my-project/plugin-hello
```
-## 启动应用
+**通过界面操作**
+
+访问插件管理器界面,查看刚添加的插件,点击激活。
+插件管理器页面默认为 http://localhost:13000/admin/pm/list/local/
+
+
+
+备注:插件激活时,会自动创建刚才编辑插件配置的 hello 表。
+
+## 调试插件
+
+如果应用未启动,需要先启动应用
```bash
# for development
@@ -106,8 +101,6 @@ yarn build
yarn start
```
-## 体验插件功能
-
向插件的 hello 表里插入数据
```bash
@@ -123,3 +116,21 @@ curl --location --request POST 'http://localhost:13000/api/hello:create' \
```bash
curl --location --request GET 'http://localhost:13000/api/hello:list'
```
+
+## 构建并打包插件
+
+```bash
+yarn build plugins/@my-project/plugin-hello --tar
+
+# 分步骤
+yarn build plugins/@my-project/plugin-hello
+yarn nocobase tar plugins/@my-project/plugin-hello
+```
+
+打包的插件默认保存路径为 `storage/tar/@my-project/plugin-hello.tar.gz`
+
+## 上传至其他 NocoBase 应用
+
+仅 v0.14 及以上版本支持
+
+
diff --git a/docs/zh-CN/welcome/release/v14-changelog.md b/docs/zh-CN/welcome/release/v14-changelog.md
new file mode 100644
index 000000000..6f130780c
--- /dev/null
+++ b/docs/zh-CN/welcome/release/v14-changelog.md
@@ -0,0 +1,101 @@
+# v0.14:全新的插件管理器,支持通过界面添加插件
+
+v0.14 实现了生产环境下插件的即插即用,可以直接通过界面添加插件,支持从 npm registry(可以是私有的)下载、本地上传、URL 下载。
+
+## 新特性
+
+### 全新的插件管理器界面
+
+
+
+### 上传的插件位于 storage/plugins 目录
+
+提供 storage/plugins 目录用于上传即插即用的插件,目录以 npm packages 的方式组织
+
+```bash
+|- /storage/
+ |- /plugins/
+ |- /@nocobase/
+ |- /plugin-hello1/
+ |- /plugin-hello2/
+ |- /my-nocobase-plugin-hello1/
+ |- /my-nocobase-plugin-hello2/
+```
+
+### 插件的更新
+
+目前仅 storage/plugins 下的插件才有更新操作,如图:
+
+
+
+备注:为了便于维护和升级,避免因为升级导致 storage 插件不可用,也可以直接将新插件放到 storage/plugins 目录下,再执行升级操作
+
+## 不兼容的变化
+
+### 插件目录变更
+
+开发中的插件统一都放到 packages/plugins 目录下,以 npm packages 的方式组织
+
+```diff
+|- /packages/
+- |- /plugins/acl/
++ |- /plugins/@nocobase/plugin-acl/
+- |- /samples/hello/
++ |- /plugins/@nocobase/plugin-sample-hello/
+```
+
+全新的目录结构为
+
+```bash
+# 开发中的插件
+|- /packages/
+ |- /plugins/
+ |- /@nocobase/
+ |- /plugin-hello1/
+ |- /plugin-hello2/
+ |- /my-nocobase-plugin-hello1/
+ |- /my-nocobase-plugin-hello2/
+
+# 通过界面添加的插件
+|- /storage/
+ |- /plugins/
+ |- /@nocobase/
+ |- /plugin-hello1/
+ |- /plugin-hello2/
+ |- /my-nocobase-plugin-hello1/
+ |- /my-nocobase-plugin-hello2/
+```
+
+### 插件名的变化
+
+- 不再提供 PLUGIN_PACKAGE_PREFIX 环境变量
+- 插件名和包名统一,旧的插件名仍然可以以别名的形式存在
+
+### pm add 的改进
+
+变更情况
+
+```diff
+- pm add sample-hello
++ pm add @nocobase/plugin-sample-hello
+```
+
+pm add 参数说明
+
+```bash
+# 用 packageName 代替 pluginName,从本地查找,找不到报错
+pm add packageName
+
+# 只有提供了 registry 时,才从远程下载,也可以指定版本
+pm add packageName --registry=xx --auth-token=yy --version=zz
+
+# 也可以提供本地压缩包,多次 add 用最后的替换
+pm add /a/plugin.zip
+
+# 远程压缩包,同名直接替换
+pm add http://url/plugin.zip
+```
+
+## 插件开发指南
+
+[编写第一个插件](/development/your-fisrt-plugin)
diff --git a/jest.config.js b/jest.config.js
index c3dcc996a..c22ea87d2 100644
--- a/jest.config.js
+++ b/jest.config.js
@@ -34,5 +34,6 @@ module.exports = {
'package.json',
'/demo/',
'package-lock.json',
+ '/storage/',
],
};
diff --git a/package.json b/package.json
index bfe620b3d..e578592a8 100644
--- a/package.json
+++ b/package.json
@@ -2,7 +2,8 @@
"name": "nocobase",
"private": true,
"workspaces": [
- "packages/*/*"
+ "packages/*/*",
+ "packages/*/*/*"
],
"license": "Apache-2.0",
"engines": {
@@ -21,6 +22,7 @@
"dev-server": "nocobase dev --server",
"start": "nocobase start",
"build": "nocobase build",
+ "tar": "nocobase tar",
"test": "nocobase test",
"test:client": "vitest",
"tc": "yarn test:client",
diff --git a/packages/core/build/package.json b/packages/core/build/package.json
index eda477e93..675183934 100755
--- a/packages/core/build/package.json
+++ b/packages/core/build/package.json
@@ -18,17 +18,17 @@
"@types/lerna__project": "5.1.0",
"@vercel/ncc": "0.36.1",
"chalk": "2.4.2",
- "fast-glob": "3.3.0",
- "glob": "^7.1.4",
+ "fast-glob": "^3.3.1",
"gulp": "4.0.2",
"gulp-typescript": "6.0.0-alpha.1",
- "pkg-up": "3.1.0",
"tsup": "7.2.0",
"typescript": "5.1.3",
"update-notifier": "3.0.0",
"vite-plugin-css-injected-by-js": "^3.2.1",
"vite-plugin-lib-inject-css": "1.2.0",
- "yargs-parser": "13.1.2"
+ "yargs-parser": "13.1.2",
+ "tar": "^6.2.0",
+ "@types/tar": "^6.1.5"
},
"license": "Apache-2.0",
"scripts": {
diff --git a/packages/core/build/src/build.ts b/packages/core/build/src/build.ts
index 2fbab6618..18c9463a7 100755
--- a/packages/core/build/src/build.ts
+++ b/packages/core/build/src/build.ts
@@ -17,8 +17,11 @@ import { buildDeclaration } from './buildDeclaration';
import { PkgLog, getPkgLog, toUnixPath, getPackageJson } from './utils';
import { getPackages } from './utils/getPackages';
import { Package } from '@lerna/package';
+import { tarPlugin } from './tarPlugin'
export async function build(pkgs: string[]) {
+ process.env.NODE_ENV = 'production';
+
const packages = getPackages(pkgs);
const pluginPackages = getPluginPackages(packages);
const cjsPackages = getCjsPackages(packages);
@@ -63,8 +66,17 @@ export async function buildPackage(
) {
const sourcemap = process.argv.includes('--sourcemap');
const noDeclaration = process.argv.includes('--no-dts');
+ const hasTar = process.argv.includes('--tar');
+ const onlyTar = process.argv.includes('--only-tar');
+
const log = getPkgLog(pkg.name);
const packageJson = getPackageJson(pkg.location);
+
+ if (onlyTar) {
+ await tarPlugin(pkg.location, log);
+ return;
+ }
+
log(`${chalk.bold(toUnixPath(pkg.location.replace(PACKAGES_PATH, '').slice(1)))} build start`);
// prebuild
@@ -88,6 +100,11 @@ export async function buildPackage(
log('postbuild');
await runScript(['postbuild'], pkg.location);
}
+
+ // tar
+ if (hasTar) {
+ await tarPlugin(pkg.location, log);
+ }
}
function runScript(args: string[], cwd: string, envs: Record