Skip to content

Commit d6f46a5

Browse files
Claudehotlong
andauthored
Add marketplace implementation documentation
Agent-Logs-Url: https://github.com/objectstack-ai/framework/sessions/be8b7759-e161-4928-b727-f64f0bcd6284 Co-authored-by: hotlong <50353452+hotlong@users.noreply.github.com>
1 parent 6eafa88 commit d6f46a5

1 file changed

Lines changed: 219 additions & 0 deletions

File tree

MARKETPLACE_IMPLEMENTATION.md

Lines changed: 219 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,219 @@
1+
# Marketplace 服务实施总结
2+
3+
## 概述
4+
5+
成功实施了基于 cloud 项目 marketplace 的远程插件加载服务,使 `apps/server` 可以在运行时动态安装和卸载插件,无需重新部署。
6+
7+
## 主要改动
8+
9+
### 1. 新增 `@objectstack/service-marketplace`
10+
11+
位置:`packages/services/service-marketplace/`
12+
13+
**核心组件:**
14+
15+
- **`RemotePluginLoader`**: 核心加载逻辑
16+
- 从 cloud marketplace API 获取插件清单
17+
- 动态 `import()` ESM 模块
18+
- 内存缓存 + 可选 Turso 持久化
19+
- 插件安装/卸载管理
20+
- 自动加载标记为 autoload 的插件
21+
22+
- **`MarketplaceServicePlugin`**: 服务插件包装器
23+
- 在 kernel init 阶段注册 marketplace 服务
24+
- 在 kernel start 阶段自动加载插件
25+
26+
**类型定义:**
27+
- `RemotePluginManifest`: 插件元数据(id, name, version, moduleUrl, etc.)
28+
- `MarketplaceConfig`: 服务配置(marketplaceUrl, authToken, caching, etc.)
29+
- `PluginInstallResult` / `PluginUninstallResult`: 操作结果
30+
- `InstalledPluginInfo`: 已安装插件信息
31+
32+
### 2. 增强 `ObjectKernel` 支持运行时卸载
33+
34+
文件:`packages/core/src/kernel.ts`
35+
36+
新增方法:`async unload(pluginName: string)`
37+
38+
**功能:**
39+
1. 调用插件的 `stop()` 钩子
40+
2. 调用插件的 `onDisable()` 钩子
41+
3. 注销插件注册的服务
42+
4. 清理插件钩子
43+
5. 从插件注册表移除
44+
6. 触发 `plugin:unloaded` 事件
45+
46+
### 3. 增强 `PluginLoader`
47+
48+
文件:`packages/core/src/plugin-loader.ts`
49+
50+
新增方法:`unregisterService(name: string)`
51+
52+
清理服务工厂、实例缓存和作用域服务。
53+
54+
### 4. 增强 `AppPlugin` 支持 onDisable 钩子
55+
56+
文件:`packages/runtime/src/app-plugin.ts`
57+
58+
新增方法:`async onDisable(ctx: PluginContext)`
59+
60+
- 调用用户定义的 `runtime.onDisable()` 函数
61+
- 优雅处理错误,不中断卸载流程
62+
63+
### 5. 修改 `apps/server` 配置
64+
65+
**package.json:**
66+
- ❌ 删除:`@example/app-crm`, `@example/app-todo`, `@example/plugin-bi`
67+
- ✅ 新增:`@objectstack/service-marketplace`
68+
69+
**objectstack.config.ts:**
70+
- ❌ 删除:静态 import 示例应用
71+
- ✅ 新增:`MarketplaceServicePlugin` 注册
72+
- ✅ 新增:开发模式下条件加载示例应用的逻辑
73+
74+
## 配置示例
75+
76+
### 环境变量
77+
78+
```bash
79+
# .env
80+
OBJECTSTACK_MARKETPLACE_URL=https://cloud.objectstack.ai
81+
OBJECTSTACK_AUTH_TOKEN=your-auth-token-here
82+
TURSO_DATABASE_URL=libsql://your-db.turso.io
83+
TURSO_AUTH_TOKEN=your-token
84+
```
85+
86+
### 代码配置
87+
88+
```typescript
89+
new MarketplaceServicePlugin({
90+
marketplaceUrl: 'https://cloud.objectstack.ai',
91+
authToken: process.env.OBJECTSTACK_AUTH_TOKEN,
92+
enableCache: true,
93+
cacheTTL: 3600,
94+
persistState: true,
95+
})
96+
```
97+
98+
## 使用流程
99+
100+
### 在 Cloud Marketplace 注册插件
101+
102+
```bash
103+
# 通过 cloud 项目的 API 或管理界面添加插件
104+
POST https://cloud.objectstack.ai/api/marketplace/plugins
105+
{
106+
"id": "com.example.crm",
107+
"name": "CRM Application",
108+
"version": "4.0.4",
109+
"namespace": "crm",
110+
"type": "app",
111+
"moduleUrl": "https://esm.sh/@example/app-crm@4.0.4",
112+
"autoload": false
113+
}
114+
```
115+
116+
### 运行时安装插件
117+
118+
```typescript
119+
// 通过服务 API
120+
const marketplace = kernel.getService('marketplace');
121+
await marketplace.installPlugin('com.example.crm');
122+
```
123+
124+
### 运行时卸载插件
125+
126+
```typescript
127+
await marketplace.uninstallPlugin('com.example.crm');
128+
```
129+
130+
### 查询已安装插件
131+
132+
```typescript
133+
const installed = await marketplace.getInstalledPlugins();
134+
console.log(installed);
135+
```
136+
137+
## 下一步工作
138+
139+
### Phase 1: 数据库模式(待完成)
140+
141+
`sys` 命名空间添加 `plugin_manifest` 对象定义:
142+
143+
```typescript
144+
// packages/spec/src/data/objects/sys-plugin-manifest.object.ts
145+
export const SysPluginManifestObject = defineObject({
146+
name: 'plugin_manifest',
147+
namespace: 'sys',
148+
label: 'Plugin Manifest',
149+
fields: [
150+
{ name: 'id', type: 'text', required: true },
151+
{ name: 'name', type: 'text', required: true },
152+
{ name: 'version', type: 'text', required: true },
153+
{ name: 'namespace', type: 'text', required: true },
154+
{ name: 'type', type: 'text', required: true },
155+
{ name: 'module_url', type: 'text', required: true },
156+
{ name: 'integrity', type: 'text' },
157+
{ name: 'enabled', type: 'boolean', defaultValue: false },
158+
{ name: 'autoload', type: 'boolean', defaultValue: false },
159+
{ name: 'description', type: 'text' },
160+
{ name: 'author', type: 'text' },
161+
]
162+
});
163+
```
164+
165+
### Phase 2: REST API 端点(可选)
166+
167+
如果需要通过 HTTP API 管理插件,可以在 `HttpDispatcher` 或专门的路由中添加:
168+
169+
- `GET /api/v1/marketplace/plugins` - 列出可用插件
170+
- `POST /api/v1/marketplace/plugins/:id/install` - 安装插件
171+
- `DELETE /api/v1/marketplace/plugins/:id` - 卸载插件
172+
- `GET /api/v1/marketplace/plugins/installed` - 列出已安装插件
173+
174+
### Phase 3: Studio UI 集成
175+
176+
`apps/studio` 中添加插件管理页面。
177+
178+
### Phase 4: Cloud 项目集成
179+
180+
确保 cloud 项目的 marketplace API 已实现:
181+
182+
- `GET /api/marketplace/plugins` - 返回所有可用插件
183+
- `GET /api/marketplace/plugins/:id` - 返回指定插件详情
184+
185+
## 优势
186+
187+
**完美适配 Vercel Serverless** - 无需文件系统写入
188+
**部署包最小化** - apps/server 不再包含示例代码
189+
**动态性** - 运行时启用/禁用插件,无需重新部署
190+
**开发体验** - 开发模式下仍可加载本地示例
191+
**与 cloud 项目集成** - 复用现有 marketplace 基础设施
192+
**可扩展** - 支持私有插件(通过 authToken)
193+
194+
## 测试建议
195+
196+
1. **单元测试**: 测试 `RemotePluginLoader` 的加载、缓存、持久化逻辑
197+
2. **集成测试**: 测试完整的安装/卸载流程
198+
3. **E2E 测试**: 测试与 cloud marketplace 的真实集成
199+
4. **性能测试**: 测试动态 import 的加载时间和缓存效果
200+
201+
## 兼容性
202+
203+
- ✅ Node.js 环境(apps/server)
204+
- ✅ Vercel Serverless
205+
- ✅ 本地开发环境
206+
- ⚠️ 需要 ESM 支持(dynamic import)
207+
208+
## 文档更新
209+
210+
需要更新以下文档:
211+
212+
1. `content/docs/guides/` - 添加插件安装指南
213+
2. `packages/services/service-marketplace/README.md` - 已完成
214+
3. `ARCHITECTURE.md` - 更新架构图,包含 marketplace 服务
215+
216+
---
217+
218+
**实施状态**: ✅ Phase 1 完成(核心功能)
219+
**下一步**: 添加 `sys__plugin_manifest` 表定义到 spec

0 commit comments

Comments
 (0)