# @zenweb/result

Zenweb 结果处理模块，统一控制器返回结果，默认 JSON 格式输出。

## 安装

```bash
npm install @zenweb/result
```

## 快速开始

```typescript
import { Core } from '@zenweb/core';
import modInject from '@zenweb/inject';
import modResult from '@zenweb/result';

const app = new Core();
app.setup(modInject());
app.setup(modResult());
```

## 功能说明

### 成功结果

控制器返回值自动包装为 JSON：

```typescript
@Controller()
class UserController {
  @Get('/user')
  getUser() {
    return { name: '张三', age: 25 };
    // 输出: { "data": { "name": "张三", "age": 25 } }
  }
}
```

### 业务错误

使用 `fail()` 抛出**预知的业务错误**（参数校验失败、权限不足等），立即终止执行：

```typescript
import { fail } from '@zenweb/result';

@Controller()
class UserController {
  @Get('/user/:id')
  getUser(ctx: Context) {
    const id = Number(ctx.params.id);
    if (!id || id <= 0) {
      fail(400, '用户ID无效');
    }
    return { name: '张三' };
  }
}
```

`fail()` 调用后代码立即终止，后续代码不会执行。

### 意外错误

代码异常（如数据库连接失败、空指针）直接抛出 Error，框架自动处理：

```typescript
@Controller()
class UserController {
  @Get('/user/:id')
  async getUser(ctx: Context) {
    const user = await db.query('SELECT * FROM users WHERE id = ?', [ctx.params.id]);
    if (!user) {
      throw new Error('数据库查询失败');  // 意外错误，框架统一处理
    }
    return user;
  }
}
```

## 配置选项

| 配置项 | 默认值 | 说明 |
|-------|-------|------|
| `failCode` | - | 默认失败代码 |
| `failCodeHeader` | `true` (`'X-Fail-Code'`) | 失败代码输出到响应头 |
| `failMessage` | `'request fail'` | 默认失败消息 |
| `failStatus` | `422` | 默认失败 HTTP 状态码 |
| `successWrap` | `(ctx, data) => ({ data })` | 成功结果包装函数 |
| `failWrap` | `(ctx, err) => ({ code, data, message, ...extra })` | 错误结果包装函数 |
| `exposeUnexpected` | 开发环境自动开启 | 暴露意外错误详情 |
| `unexpectedStatus` | `500` | 意外错误 HTTP 状态码 |
| `unexpectedCode` | `500` | 意外错误代码 |
| `renders` | - | 自定义渲染器类列表 |

### 自定义输出格式

```typescript
app.setup(modResult({
  successWrap: (ctx, data) => ({ success: true, data }),
  failWrap: (ctx, err) => ({ success: false, error: { code: err.code, message: err.message } }),
}));
```

输出效果：
```json
// 成功
{ "success": true, "data": { "name": "张三" } }

// 失败
{ "success": false, "error": { "code": 400, "message": "用户ID无效" } }
```

## API

### `fail()` - 业务错误

```typescript
fail('错误消息');
fail(400, '参数错误');
fail(400, '参数错误', { field: 'email' });  // 附加数据
fail({ code: 123, message: '自定义', status: 200, data: { id: 1 } });
```

### `ctx.success()` - 手动输出

```typescript
@Controller()
class UserController {
  @Get('/export')
  async export(ctx: Context) {
    const data = await generateReport();
    await ctx.success(data);  // 等待输出完成
    await sendNotification();  // 输出后继续执行
  }
}
```

## 自定义渲染器

支持根据请求类型自动选择输出格式：

```typescript
import { Injectable } from '@zenweb/inject';
import { Context } from '@zenweb/core';
import { ResultRender } from '@zenweb/result';

@Injectable('singleton')
class XMLRender implements ResultRender {
  enwrap = false;  // 不包装，直接输出
  type = 'xml';
  match(ctx: Context) {
    return ctx.accepts('xml') === 'xml';
  }
  render(ctx: Context, data: unknown) {
    return toXML(data);
  }
}

app.setup(modResult({ renders: [XMLRender] }));
```

## 依赖

- `@zenweb/core`
- `@zenweb/inject`