# 扩展开发

## 功能

BT 扩展用于把可复用能力打包成 `.bts` 文件，并安装到项目根目录的 `extensions/` 目录中。项目启动时，BT 会扫描 `extensions/*.bts` 和 `extensions/<name>/*.bts` 扩展包，校验包内的 `manifest.json` 和 `bindings.json`，再把公开入口注入到脚本全局环境。

扩展适合封装通用业务能力、计算模块、文件处理能力、协议适配层或需要独立发布的项目内组件。脚本调用扩展时仍保持 BT 的链式风格，例如：

```bt
result = calc(1).add(2).value()

// 输出：3
print result
```

## 学习顺序

| 文档 | 说明 |
| ------ | ------ |
| [快速开始](/docs/extensions/quick-start) | 从零创建、打包、安装并调用第一个扩展。 |
| [运行机制](/docs/extensions/mechanism) | 理解 `.bts` 包、加载流程、全局入口、Runner 和调用分发。 |
| [manifest.json](/docs/extensions/manifest) | 描述扩展包身份、后端类型、入口文件、权限和资源上限。 |
| [bindings.json](/docs/extensions/bindings) | 描述脚本能调用哪些入口、对象和方法。 |
| [纯 BT 扩展](/docs/extensions/bt) | 用 BT 源码编写扩展，适合普通脚本能力封装。 |
| [WASM 扩展](/docs/extensions/wasm) | 用 Rust SDK 编写 `kind=wasm` 扩展。 |
| [SQLite shared 示例](/docs/extensions/sqlite) | 用 shared WASM 扩展验证 SQLite 连接、事务和结果限制。 |
| [权限与路径](/docs/extensions/permissions) | 说明文件权限、路径参数 role 和 WASI 路径转换。 |
| [打包与安装](/docs/extensions/cli) | 说明 `bt ext` 工具链命令和安装目录规则。 |
| [官方扩展库](/ext) | 查看官网可安装扩展、版本、权限和安装命令。 |

## 语法

一个 `.bts` 扩展包本质上是一个受校验的 zip 包，至少包含三个文件：

```text
manifest.json
bindings.json
后端入口文件
```

`manifest.json` 说明这个扩展是谁、用哪种后端运行、入口文件在哪里、需要哪些权限。`bindings.json` 说明这个扩展对 BT 脚本公开哪些函数、对象和方法。后端入口文件则是真正执行业务逻辑的源码或 WASM 模块。

`manifest.kind` 表示扩展后端类型，`manifest.abi` 表示该后端和 BT 宿主之间使用的调用协议版本。两者必须匹配：

| kind | abi | 入口文件 | 适合场景 |
| ------ | ------ | ------ | ------ |
| `bt` | `bts-bt-1` | BT 源码，例如 `src/lib.bt` | 纯 BT 逻辑、业务规则、简单可复用模块。 |
| `wasm` | `bts-wasi-1` | WASM 模块，例如 `module.wasm` | Rust 等语言编写的高性能逻辑、需要独立对象状态的模块。 |

`kind=bt` 表示扩展入口由 BT 源码提供，宿主会用纯 BT Runner 编译并调用其中的函数或类方法。`bts-bt-1` 是这个后端的 ABI 名称，表示 bindings 里的入口和对象方法会映射到同名 BT `fn` 与 `pub` 方法。

`kind=wasm` 表示扩展入口由 WASM/WASI 模块提供，宿主会用 WASM Runner 调用模块导出的 `bts_call` 分发函数。`bts-wasi-1` 是这个后端的 ABI 名称，表示参数和返回值通过 BtValueBinary 二进制格式在宿主和 WASM 线性内存之间传递。

安装扩展后的普通 BT 项目通常是这样：

```text
project/
├── main.bt
└── extensions/
    └── calc/
        └── calc-1.0.0.bts
```

扩展开发目录通常是这样：

```text
calc/
├── manifest.json
├── bindings.json
└── src/
    └── lib.bt
```

WASM 扩展开发目录通常是这样：

```text
calc_sdk/
├── manifest.json
├── bindings.json
├── Cargo.toml
├── module.wasm
└── src/
    └── lib.rs
```

## 参数

扩展入口和对象方法的参数由 `bindings.json` 声明。脚本调用时不需要关心扩展后端是纯 BT 还是 WASM，只需要按 bindings 暴露出的入口名、方法名和参数顺序调用。

## 返回值

扩展入口可以返回普通 BT 值，也可以返回扩展对象。扩展对象的方法继续通过点号链式调用；如果对象持有长期状态，应提供释放方法。

## 代码示例

项目脚本只关心 bindings 暴露出的入口名。扩展包安装为 `project/extensions/calc/calc-1.0.0.bts` 后，可以直接调用：

```bt
value = calc(10).add(5).value()

// 输出：15
print value
```

扩展入口注入到用户全局环境，但不是系统函数：

```bt
result = [has_env('calc'), has_envs('calc')]

// 输出：[true,false]
print result
```

## 注意事项

- 扩展入口名必须避免和系统函数、系统常量以及其他扩展入口冲突。
- 官方扩展库页面位于 `/ext`，可查看可安装扩展、源码地址、版本、权限和安装命令。
- 官方扩展库可通过 `bt install <name> [version]` 安装到 `extensions/<name>/<name>-<version>.bts`。
- `.bts` 包会校验条目路径、文件大小、manifest、bindings 和后端入口，不能把任意 zip 改名后直接当作扩展使用。
- 纯 BT 扩展适合零依赖脚本逻辑；WASM 扩展适合需要 Rust 生态、对象状态表或更强隔离边界的场景。
- 扩展对象如果长期持有外部资源，应提供 `close()` 或 `dispose()` 方法，并在 `bindings.json` 中声明 `lifecycle: "dispose"`。
