# 打包与安装

在本地开发阶段，通过飞块的“加载开发文件夹”可以非常方便地热更新调试。但当你准备把精心打造的插件分享给团队、朋友或提交至飞块拓展商店时，需要将其打包为标准的 **`.flyext`** 文件。

`.flyext` 本质是遵循规范的 ZIP 归档包，解压后根目录下直接包含 `manifest.json` 及运行时所需文件。飞块提供了全自动的打包工具，帮助你省心生成轻量、可靠且无冗余的发布包。

---

## 1. 推荐方式：使用官方 CLI 一键自动打包

官方推荐使用全局的 `flyon` 命令行工具进行打包。它会在独立的临时沙箱目录中完成构建、生产依赖拉取、原生模块编译与剔除无用文件，**绝不会修改或污染你的源码目录与现有的 `node_modules`**。

在项目根目录下直接运行：

```sh
# 基础打包：自动生成到 releases/ 目录下
flyon pack

# 指定输出目录
flyon pack --out-dir /path/to/releases

# 包含原生平台代码（如 .node 模块）时，在对应系统和架构的 CI 或机器上打包：
flyon pack --target macos-arm64 --electron /path/to/electron --out-dir /path/to/releases
```

> 💡 **命令提示**：
> - 详细的 CLI 安装及准备指南请参阅[使用插件开发工具包](../guides/toolkit.md)。
> - 纯 JavaScript / TypeScript 插件构建无需提供 Electron 可执行文件。
> - 若涉及 C/C++ 等原生模块编译，需通过 `--electron` 指定与目标飞块版本一致的公开 Electron 可执行文件，或设置环境变量 `FLYONDECK_ELECTRON_PATH`。

### 自动化构建器执行的步骤
1. **纯净安装依赖**：读取并校验 `package-lock.json`（带有 npm 依赖的插件必须提交锁文件），执行安全的 `npm ci`；
2. **原生模块重编译**：针对生产原生依赖运行固定版本的 `@electron/rebuild`，确保原生二进制与飞块运行环境 ABI 严丝合缝；
3. **剔除开发冗余**：自动移除 `devDependencies`、测试用例与 `.bin` 软链；
4. **生成通用或专用包**：纯 JS 插件默认生成 `插件ID-版本-universal.flyext`。`universal` 标识表示此包未硬编码特定 CPU 架构，具有最广泛的普适性。

---

## 2. 跨平台与原生运行时声明

如果你的插件包含原生二进制（如 `.node` 模块或可执行工具），需要在 `manifest.json` 中明确声明目标系统与架构约束：

```json
{
  "hostPlatforms": ["macos"],
  "target": {
    "platform": "macos",
    "arch": "arm64"
  },
  "runtime": {
    "node": ">=18",
    "napi": 8
  },
  "nativeModules": [
    "native/addon.node"
  ]
}
```

**关键属性说明：**
- **`target`**：支持 `windows`、`macos`、`linux`、`harmonyos`；架构支持 `x64`、`arm64`、`ia32`、`arm`。对于 Linux 还可细化指定 `libc: "glibc"` 或 `"musl"`。
- **`runtime`**：声明 Node.js / Electron 的 SemVer 版本范围，或声明最低支持的 Node-API（N-API）版本。使用 N-API 能显著降低对特定 Electron 内核版本的绑定。
- **`nativeModules`**：包内所有包含的原生模块相对路径白名单。普通纯 Web/JS 插件无需填写上述字段。

> 🛡️ **安全与安装校验**：  
> 飞块安装器在用户确认安装后，会在独立子进程中进行原生模块的兼容性试加载。若模块因依赖缺失或架构冲突导致加载失败，安装器会自动回滚并中止升级，完整保留旧版插件的正常运行状态。

---

## 3. 手动准备与底层打包（高级方式）

如果你没有安装全局 `flyon-cli`，也可以直接通过工具包的底层打包脚本对已构建完毕的产物目录进行归档。在工具包的 `packages` 目录执行：

```sh
npm exec -- flyondeck-plugin pack /path/to/hello /tmp/hello-1.0.0.flyext
```

- 第一个参数为已编译好的插件目录；
- 第二个参数为输出目标路径（请指定在源码目录之外）。

> ⚠️ **手动打包踩坑注意**：  
> 如果使用系统自带的压缩工具手动生成 ZIP，请务必**在插件文件夹内部全选文件后压缩**，切勿把外层文件夹一起打入。解压后的根目录必须直接看到 `manifest.json`。

---

## 4. 本地验证与安装体验

在分发给外部用户前，强烈建议在本地执行一次完整的端到端验证：

1. 打开飞块桌面客户端，进入“**拓展管理**”；
2. 点击右上角“**安装插件包**”，选择生成的 `.flyext` 文件；
3. 飞块会弹窗解析并展示插件的名称、版本、作者及所申请的系统权限，点击确认安装；
4. 启动插件，验证按键动作、超级块页面以及流程连通性。

> 💡 **为什么必须本地测试安装包？**  
> 直接加载开发文件夹时，很多依赖可能直接引用了全局或父级目录中的文件。通过安装纯净的 `.flyext`，可以第一时间发现那些“在本地开发时正常、打包后却漏掉的静态资源或依赖”。

---

## 5. 版本更新策略

当后续为插件修复缺陷或发布新功能时：
1. 保持 `manifest.json` 中的插件 ID 不变；
2. 按照 SemVer 语义化规范递增 `version`（例如从 `1.0.0` 升级为 `1.0.1`）；
3. 重新执行打包生成新版本的 `.flyext`。

如果更新涉及动作参数或状态来源的调整，请务必阅读[更新与迁移指南](../migrations/compatibility.md)，确保用户的已有配置平滑过渡。准备上架拓展商店时，请继续阅读[发布插件](./marketplace.md)。
