Skip to content

Commit 9db9733

Browse files
author
GCWing
committed
Add Mini App
1. Add MiniApp Runtime 2. Add MiniApp init tool 3. Add MiniApp dev Skill & Demo
1 parent e126187 commit 9db9733

81 files changed

Lines changed: 12876 additions & 37 deletions

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

MiniApp/Demo/git-graph/README.md

Lines changed: 181 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,181 @@
1+
# Git Graph Demo MiniApp / Git Graph 示例 MiniApp
2+
3+
[English](#english) | [中文](#中文)
4+
5+
---
6+
7+
## English
8+
9+
This demo showcases BitFun MiniApp's full-stack collaboration capability — specifically, using a third-party npm package (`simple-git`) inside a Node.js/Bun Worker to read a local Git repository and render an interactive commit graph.
10+
11+
### Features
12+
13+
- **Pick a repository** — opens a native directory picker via `app.dialog.open({ directory: true })`
14+
- **Commit graph** — Worker fetches `git.graphData` (log + refs + stashes + uncommitted in one call); UI renders commit nodes and branch lines as SVG
15+
- **Branches & status** — shows current branch, full branch list, and workspace status (modified / staged / untracked)
16+
- **Commit detail** — click any commit to view author, timestamp, diff stat, and per-file diff
17+
- **Branch management** — create, delete, rename, checkout local/remote branches
18+
- **Merge / Rebase** — merge a branch into HEAD, rebase HEAD onto a branch
19+
- **Cherry-pick / Revert / Reset** — cherry-pick a commit, revert with a new commit, or hard/mixed/soft reset
20+
- **Push / Fetch** — push to remote, fetch with prune, fetch a remote branch into a local branch
21+
- **Remote management** — add, remove, update remote URLs via the Remotes panel
22+
- **Stash** — push, apply, pop, drop, and branch-from-stash operations
23+
- **Search commits** — filter commit list by message, hash, or author
24+
- **Tag management** — add lightweight or annotated tags, delete tags, push tags
25+
26+
### Data Flow
27+
28+
1. **UI → Bridge**: `app.call('git.log', { cwd, maxCount })` etc. via `window.app` (JSON-RPC)
29+
2. **Bridge → Tauri**: postMessage intercepted by the host `useMiniAppBridge`, which calls `miniapp_worker_call`
30+
3. **Tauri → Worker**: Rust writes the request to Worker stdin (JSON-RPC)
31+
4. **Worker**: `worker_host.js` loads `source/worker.js`; exported handlers are invoked — primarily `git.graphData` (returns commits + refs + stashes + uncommitted in one response), plus `git.show`, `git.checkout`, `git.merge`, `git.push`, `git.stashPush`, and 20+ other methods — all backed by the `simple-git` npm package
32+
5. **Worker → Tauri → Bridge → UI**: response travels back via stderr → Rust → postMessage to iframe → UI refreshes graph and detail panel
33+
34+
### Directory Structure
35+
36+
```
37+
miniapps/git-graph/
38+
├── README.md # this file
39+
├── meta.json # metadata & permissions (fs/shell/node)
40+
├── package.json # npm deps (simple-git) + build script
41+
├── storage.json # app KV (e.g. last opened repo path)
42+
└── source/
43+
├── index.html # UI skeleton
44+
├── build.js # build script: concat ui/*.js → ui.js, styles/*.css → style.css
45+
├── ui.js # frontend entry (generated by build, do not edit directly)
46+
├── style.css # style entry (generated by build, do not edit directly)
47+
├── ui/ # frontend modules (run `npm run build` after editing)
48+
│ ├── state.js, theme.js, main.js, bootstrap.js
49+
│ ├── graph/layout.js, graph/renderRowSvg.js
50+
│ ├── components/contextMenu.js, modal.js, findWidget.js
51+
│ ├── panels/detailPanel.js, remotePanel.js
52+
│ └── services/gitClient.js
53+
├── styles/ # style modules (run `npm run build` after editing)
54+
│ ├── tokens.css, layout.css, graph.css
55+
│ ├── detail-panel.css, overlay.css
56+
│ └── (merge order defined in build.js)
57+
├── worker.js # backend CJS (simple-git wrapper)
58+
└── esm_dependencies.json # ESM deps (empty for this demo)
59+
```
60+
61+
**During development**: after editing `source/ui/*.js` or `source/styles/*.css`, run `npm run build` inside the `miniapps/git-graph` directory to regenerate `source/ui.js` and `source/style.css`. BitFun will pick up the latest build on next load.
62+
63+
### Running in BitFun
64+
65+
1. **Install to user data directory**: copy this folder into BitFun's MiniApp data directory under an `app_id` subdirectory, e.g.:
66+
- The data directory is typically `{user_data}/miniapps/`
67+
- Create a subdirectory like `git-graph-sample` and place all files from this folder inside it (i.e. `meta.json`, `package.json`, `source/` etc. at the root of that subdirectory)
68+
69+
2. **Or import via API**: if BitFun supports path-based import, use `create_miniapp` or equivalent, pointing to this directory as the source; make sure the `id` in `meta.json` matches the directory name.
70+
71+
3. **Install dependencies**: inside the MiniApp's app directory, run:
72+
- `bun install` or `npm install` (matching the runtime BitFun detected)
73+
- Or use the "Install Dependencies" action in Toolbox (calls `miniapp_install_deps`)
74+
75+
4. **Compile**: to regenerate `compiled.html`, call `miniapp_recompile` or let BitFun compile automatically when the MiniApp is opened.
76+
77+
5. Open the MiniApp in the Toolbox scene, pick a repository, and the Git Graph will appear.
78+
79+
### Permissions
80+
81+
| Permission | Value | Purpose |
82+
|---|---|---|
83+
| `fs.read` | `{appdata}`, `{workspace}`, `{user-selected}` | Read app data, workspace, and user-selected repo |
84+
| `fs.write` | `{appdata}` | Write app-own data only (e.g. storage) |
85+
| `shell.allow` | `["git"]` | `simple-git` needs to invoke the system `git` binary |
86+
| `node.enabled` | `true` | Enable JS Worker to execute `simple-git` logic in `worker.js` |
87+
88+
### Technical Highlights
89+
90+
- **Client-side third-party library**: `require('simple-git')` in `worker.js` runs inside a Bun or Node.js Worker process — no need to reimplement Git in Rust
91+
- **Zero custom dialect**: UI is plain concatenated JavaScript (IIFE modules sharing `window.__GG`), Worker is standard CJS — no custom framework or transpiler required; `window.app` is the unified Bridge API
92+
- **ESM dependencies**: this demo uses plain vanilla JS; `esm_dependencies.json` is empty — add React, D3, etc. there to have them served via Import Map from esm.sh
93+
94+
---
95+
96+
## 中文
97+
98+
本示例展示 BitFun MiniApp 的前后端协同能力,尤其是通过 Node.js/Bun 在端侧使用三方 npm 库(`simple-git`)读取 Git 仓库并渲染交互式提交图谱。
99+
100+
### 功能
101+
102+
- **选择仓库**:通过 `app.dialog.open({ directory: true })` 打开原生目录选择器,选择本地 Git 仓库
103+
- **提交图谱**:Worker 端通过 `git.graphData`(一次调用返回提交列表 + refs + stash + 未提交变更),UI 端用 SVG 绘制提交节点与分支线
104+
- **分支与状态**:展示当前分支、所有分支列表及工作区状态(modified/staged/untracked)
105+
- **提交详情**:点击某个 commit 可查看作者、时间、diff stat 及逐文件 diff
106+
- **分支管理**:创建、删除、重命名、checkout 本地/远程分支
107+
- **Merge / Rebase**:将分支合并到 HEAD,或将 HEAD rebase 到目标分支
108+
- **Cherry-pick / Revert / Reset**:cherry-pick 指定 commit,revert 生成新提交,或 hard/mixed/soft reset
109+
- **Push / Fetch**:推送到远程,带 prune 的 fetch,将远程分支 fetch 到本地分支
110+
- **远程管理**:通过远程面板添加、删除、修改远程 URL
111+
- **Stash**:push、apply、pop、drop 及从 stash 创建分支
112+
- **搜索提交**:按消息、hash 或作者过滤提交列表
113+
- **Tag 管理**:添加轻量/注解 tag,删除 tag,推送 tag
114+
115+
### 前后端协同流程
116+
117+
1. **UI → Bridge**`app.call('git.log', { cwd, maxCount })` 等通过 `window.app` 发起 RPC
118+
2. **Bridge → Tauri**:postMessage 被宿主 `useMiniAppBridge` 接收,调用 `miniapp_worker_call`
119+
3. **Tauri → Worker**:Rust 将请求写入 Worker 进程 stdin(JSON-RPC)
120+
4. **Worker**`worker_host.js` 加载本目录 `source/worker.js`,其导出的处理函数被调用 — 主要是 `git.graphData`(一次返回提交 + refs + stash + 未提交变更),以及 `git.show``git.checkout``git.merge``git.push``git.stashPush` 等 20+ 个方法 — 均基于 `simple-git` npm 包
121+
5. **Worker → Tauri → Bridge → UI**:响应经 stderr 回传 Rust,再 postMessage 回 iframe,UI 更新图谱与详情
122+
123+
### 目录结构
124+
125+
```
126+
miniapps/git-graph/
127+
├── README.md # 本说明
128+
├── meta.json # 元数据与权限(fs/shell/node)
129+
├── package.json # npm 依赖(simple-git)及 build 脚本
130+
├── storage.json # 应用 KV(如最近打开的仓库路径)
131+
└── source/
132+
├── index.html # UI 骨架
133+
├── build.js # 构建脚本:合并 ui/*.js → ui.js,styles/*.css → style.css
134+
├── ui.js # 前端入口(由 build 生成,勿直接编辑)
135+
├── style.css # 样式入口(由 build 生成,勿直接编辑)
136+
├── ui/ # 前端模块(编辑后需运行 npm run build)
137+
│ ├── state.js, theme.js, main.js, bootstrap.js
138+
│ ├── graph/layout.js, graph/renderRowSvg.js
139+
│ ├── components/contextMenu.js, modal.js, findWidget.js
140+
│ ├── panels/detailPanel.js, remotePanel.js
141+
│ └── services/gitClient.js
142+
├── styles/ # 样式模块(编辑后需运行 npm run build)
143+
│ ├── tokens.css, layout.css, graph.css
144+
│ ├── detail-panel.css, overlay.css
145+
│ └── (合并顺序见 build.js)
146+
├── worker.js # 后端 CJS(simple-git 封装)
147+
└── esm_dependencies.json # ESM 依赖(本示例为空)
148+
```
149+
150+
**开发时**:修改 `source/ui/*.js``source/styles/*.css` 后,在 `miniapps/git-graph` 目录执行 `npm run build` 生成 `source/ui.js``source/style.css`,BitFun 加载时会使用最新构建结果。
151+
152+
### 在 BitFun 中运行
153+
154+
1. **安装到用户数据目录**:将本目录复制到 BitFun 的 MiniApp 数据目录下,并赋予一个 app_id 子目录,例如:
155+
- 数据目录一般为 `{user_data}/miniapps/`
156+
- 新建子目录如 `git-graph-sample`,将本目录中所有文件按相同结构放入其中(即 `meta.json``package.json``source/` 等在该子目录下)
157+
158+
2. **或通过 API 创建**:若 BitFun 支持从路径导入,可使用 `create_miniapp` 或等价方式,将本目录作为 source 路径导入,并确保 `meta.json` 中的 `id` 与目录名一致。
159+
160+
3. **安装依赖**:在 MiniApp 的 app 目录下执行:
161+
- `bun install``npm install`(与 BitFun 检测到的运行时一致)
162+
- 或在 Toolbox 中对该 MiniApp 执行「安装依赖」操作(调用 `miniapp_install_deps`
163+
164+
4. **编译**:若需重新生成 `compiled.html`,可调用 `miniapp_recompile` 或由 BitFun 在打开该 MiniApp 时自动编译。
165+
166+
5. 在 Toolbox 场景中打开该 MiniApp,选择仓库后即可查看 Git Graph。
167+
168+
### 权限说明
169+
170+
| 权限 || 用途 |
171+
|---|---|---|
172+
| `fs.read` | `{appdata}``{workspace}``{user-selected}` | 读取应用数据、工作区及用户选择的仓库目录 |
173+
| `fs.write` | `{appdata}` | 仅写入应用自身数据(如 storage) |
174+
| `shell.allow` | `["git"]` | `simple-git` 需调用系统 `git` 命令 |
175+
| `node.enabled` | `true` | 启用 JS Worker,以便执行 `worker.js` 中的 `simple-git` 逻辑 |
176+
177+
### 技术要点
178+
179+
- **端侧三方库**`worker.js``require('simple-git')`,在 Bun 或 Node.js Worker 进程中运行,无需在 Rust 中重新实现 Git 能力
180+
- **无自定义方言**:UI 为普通拼接脚本(IIFE 模块通过 `window.__GG` 共享状态),Worker 为标准 CJS,无需自定义框架或转译器;`window.app` 为统一 Bridge API
181+
- **ESM 依赖**:本示例 UI 使用纯 vanilla JS,`esm_dependencies.json` 为空;若需 React/D3 等,可在其中声明并由 Import Map 从 esm.sh 加载

MiniApp/Demo/git-graph/meta.json

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
{
2+
"id": "git-graph-sample",
3+
"name": "Git Graph",
4+
"description": "交互式 Git 提交图谱,通过 Worker 端 simple-git 读取仓库,UI 端 SVG 渲染。展示前后端协同与端侧三方库使用。",
5+
"icon": "📊",
6+
"category": "developer",
7+
"tags": ["git", "graph", "example"],
8+
"version": 1,
9+
"created_at": 0,
10+
"updated_at": 0,
11+
"permissions": {
12+
"fs": {
13+
"read": ["{appdata}", "{workspace}", "{user-selected}"],
14+
"write": ["{appdata}"]
15+
},
16+
"shell": { "allow": ["git"] },
17+
"net": { "allow": [] },
18+
"node": {
19+
"enabled": true,
20+
"max_memory_mb": 256,
21+
"timeout_ms": 30000
22+
}
23+
},
24+
"ai_context": null
25+
}
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
{
2+
"name": "miniapp-git-graph",
3+
"private": true,
4+
"scripts": {
5+
"build": "node source/build.js"
6+
},
7+
"dependencies": {
8+
"simple-git": "^3.27.0"
9+
}
10+
}
Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
/**
2+
* Git Graph MiniApp — build: concatenate source/ui/*.js → ui.js, source/styles/*.css → style.css.
3+
* Run from miniapps/git-graph: node source/build.js
4+
*/
5+
const fs = require('fs');
6+
const path = require('path');
7+
8+
const SOURCE_DIR = path.join(__dirname);
9+
const ROOT = path.dirname(SOURCE_DIR);
10+
11+
const UI_ORDER = [
12+
'ui/state.js',
13+
'ui/theme.js',
14+
'ui/graph/layout.js',
15+
'ui/graph/renderRowSvg.js',
16+
'ui/services/gitClient.js',
17+
'ui/components/contextMenu.js',
18+
'ui/components/modal.js',
19+
'ui/components/findWidget.js',
20+
'ui/panels/remotePanel.js',
21+
'ui/panels/detailPanel.js',
22+
'ui/main.js',
23+
'ui/bootstrap.js',
24+
];
25+
26+
const STYLES_ORDER = [
27+
'styles/tokens.css',
28+
'styles/layout.css',
29+
'styles/graph.css',
30+
'styles/detail-panel.css',
31+
'styles/overlay.css',
32+
];
33+
34+
function concat(files, dir) {
35+
let out = '';
36+
for (const f of files) {
37+
const full = path.join(dir, f);
38+
if (!fs.existsSync(full)) {
39+
console.warn('Missing:', full);
40+
continue;
41+
}
42+
out += '/* ' + f + ' */\n' + fs.readFileSync(full, 'utf8') + '\n';
43+
}
44+
return out;
45+
}
46+
47+
const uiOut = path.join(SOURCE_DIR, 'ui.js');
48+
const styleOut = path.join(SOURCE_DIR, 'style.css');
49+
50+
fs.writeFileSync(uiOut, concat(UI_ORDER, SOURCE_DIR), 'utf8');
51+
fs.writeFileSync(styleOut, concat(STYLES_ORDER, SOURCE_DIR), 'utf8');
52+
53+
console.log('Built', uiOut, 'and', styleOut);
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
[]

0 commit comments

Comments
 (0)