# Wasmeld CLI

`wasmeld-package` 提供 `wasmeld` 命令，用于：

- 开发、编译和打包 WebAssembly Component
- 监听源码并将开发版本自动部署到 Wasmeld Console
- 解析、锁定和替换 WIT Package 依赖
- 构建并发布版本化 WIT Package

Runtime 不接收 Rust 源码。CLI 会先将 Rust 编译为 WebAssembly Component，再生成
`.wasmpkg` 或上传到 Console。

## 运行

在项目工作区内可以直接运行：

```bash
cargo +stable run -p wasmeld-package --bin wasmeld -- <command>
```

Component 默认使用 Rust `1.90.0` 和 `wasm32-wasip2` 目标构建。可以通过
`WASMELD_COMPONENT_TOOLCHAIN` 指定其它已安装工具链。

## Component 项目

一个可打包的 Component 至少需要：

```text
component/
├── Cargo.toml
├── wasmeld.toml
├── wit.lock
├── src/lib.rs
└── wit/world.wit
```

`Cargo.toml` 必须提供 `cdylib` Target 和 Wasmeld 元数据：

```toml
[package]
name = "echo-component"
version = "0.1.0"

[package.metadata.wasmeld]
id = "echo"
world = "component:echo/echo-component@0.1.0"

[lib]
crate-type = ["cdylib"]
```

`version` 成为正式包的 Revision；`id` 是服务 ID；`world` 必须与 Component 实际导出的
WIT World 一致。

## 边写边预览

先启动 Console：

```bash
cargo +stable run -p wasmeld-console
```

再启动开发循环：

```bash
cargo +stable run -p wasmeld-package --bin wasmeld -- \
  dev components/echo/Cargo.toml
```

开发循环会监听 Rust、Cargo、WIT 清单以及本地 `replace` WIT 源，并执行：

```text
同步 WIT 依赖
→ Debug 编译
→ 生成 .wasmpkg
→ 注册开发 Revision
→ 启动并切换 Deployment
→ 注销上一开发 Revision
```

默认服务 ID 为 `<id>-dev`，Revision 为 `<version>-dev.h<component-hash>`。正式服务不会
被覆盖。构建、校验或启动失败时不会切换 Deployment，上一版本继续提供服务。
编译过程中再次保存源码会在当前构建结束后立即触发下一轮构建。若 Component 已构建
成功但 Console 暂时不可用，开发循环会保留该 `.wasmpkg` 并重试部署，不会等待新的
源码变化，也不会为每次重试重复编译。

管理面默认每 5 秒刷新一次，也可以直接调用开发服务：

```bash
curl http://127.0.0.1:8081/v1/services/echo-dev/invoke \
  -H 'Content-Type: application/octet-stream' \
  --data-binary 'hello'
```

开发选项：

| 选项 | 作用 |
| --- | --- |
| `--console <url>` | Console 管理 API，默认 `http://127.0.0.1:8080` |
| `--id <service-id>` | 覆盖默认的 `<id>-dev` 服务 ID |
| `--once` | 构建、部署一次后退出，适合脚本和 CI |
| `--release` | 使用 Release 而不是 Debug 构建 |
| `--locked` | 要求依赖与现有 `wit.lock` 完全一致 |
| `--poll-ms <n>` | 源码扫描间隔，最小 100 ms，默认 350 ms |

也可以通过 `WASMELD_CONSOLE` 设置管理 API 地址。退出 `wasmeld dev` 不会停止当前开发
Deployment；它会继续运行，直到手工停止、切换或注销。

只修改 Rust 源码且不允许契约变化时使用 `--locked`。需要同步修改本地 WIT `replace`
时不要使用该选项，CLI 会更新 `wit.lock`。

## 打包 Component

```bash
cargo +stable run -p wasmeld-package --bin wasmeld -- \
  pack components/echo/Cargo.toml --locked
```

默认执行 Release 构建并输出：

```text
dist/echo-0.1.0.wasmpkg
```

可用选项：

| 选项 | 作用 |
| --- | --- |
| `--output <path>`、`-o <path>` | 指定输出文件 |
| `--no-build` | 使用现有 Release Component 制品 |
| `--locked` | 禁止 WIT 依赖解析结果改变 |

`.wasmpkg` 是受约束的 ZIP，固定包含：

```text
package.toml
component.wasm
```

`package.toml` 记录服务 ID、Revision、World 和 Component SHA-256。运行时资源限制不由
组件声明，而是在 Console 注册时由平台策略注入。

## WIT 依赖

`wasmeld.toml` 使用精确版本：

```toml
schema_version = 1

[wit]
root = "wit"

[registry]
url = "http://127.0.0.1:8080"

[dependencies]
"wasmeld:service" = "0.1.0"
"wasmeld:kv" = "0.1.0"
"wasmeld:resident" = "0.1.0"

[replace."wasmeld:service"]
path = "../../wit/service"
```

依赖解析结果写入 `wit.lock`，源码开发时应提交该文件。解析出的 `wit/deps/` 是生成目录，
不应提交。

普通请求型 Component 只需要 `wasmeld:service`。需要接收 Host 定时器、网络流、UDP、
消息订阅或扩展 source 事件时，再依赖并导出 `wasmeld:resident/actor@0.1.0`；例如
`components/resident-probe`。`resident` 是独立版本化 package，不会把所有 Host 能力
合并到基础 service world。

同步依赖：

```bash
wasmeld wit fetch --manifest components/echo/wasmeld.toml
```

校验锁定结果且禁止变化：

```bash
wasmeld wit fetch --manifest components/echo/wasmeld.toml --locked
```

`wit tidy` 当前与 `wit fetch` 使用相同的确定性解析和物化流程。查看根依赖和有效来源：

```bash
wasmeld wit graph --manifest components/echo/wasmeld.toml
```

添加本地替换：

```bash
wasmeld wit replace wasmeld:service@0.1.0 \
  --path ../../wit/service \
  --manifest components/echo/wasmeld.toml
```

包级替换可以省略 `@version`。精确版本替换的优先级更高。移除替换：

```bash
wasmeld wit replace wasmeld:service@0.1.0 \
  --drop \
  --manifest components/echo/wasmeld.toml
```

## WIT Package

将 WIT 源目录构建为标准二进制 WIT Package：

```bash
wasmeld wit build wit/service \
  --output dist/wit/wasmeld-service-0.1.0.wasm
```

发布到 Console 的不可变 WIT Registry：

```bash
wasmeld wit publish wit/service \
  --registry http://127.0.0.1:8080
```

Registry 地址也可以通过 `WASMELD_REGISTRY` 设置。相同 Package 版本不可覆盖；协议变化
应发布新版本，并由 Component 在 `wasmeld.toml` 中显式选择。

## 环境变量

| 变量 | 作用 |
| --- | --- |
| `WASMELD_COMPONENT_TOOLCHAIN` | Component Rust 工具链，默认 `1.90.0` |
| `WASMELD_CONSOLE` | `wasmeld dev` 使用的 Console 管理 API |
| `WASMELD_REGISTRY` | `wit publish` 使用的 Registry 地址 |
