# l-mock

### 说明

服务端接口Mock命令行工具，支持数据模拟/数据模型/接口代理/接口调试

### 依赖
```
nodejs >=12.0.0
```
### 安装
```
npm i -g l-mock

```

### 快速启动

1. 定位到项目目录

```
cd path/to/project
```

2. 初始化接口目录:

```
lmock init
```

> `init` 命令会在项目根目录下创建默认文件夹 mock，通过`--dir`参数可指定目录名

3.定位到 mock 目录并启动

```
cd mock && lmock start
```

### 启动参数

| 参数 | 说明 |
| ---- | ---- |
| `-p` | 可选，默认监听 3000 端口，可通过`-p`配置端口，支持多项目同时 mock |
| `-u` | 可选，同时启动 UI 编辑界面 |
| `-ws` | 可选，同时启动websocket服务器 |
| `-io` | 可选，同时启动Socket.io服务器 |
| `-sp` | 可选，websocket服务的端口，默认为 4000 |

访问`localhost:3000/a` 成功返回数据

访问`localhost:3000/ui` 调起 UI 界面

### 接口格式

| Params      | Value                 | Description                                                                                                                                                                                             |
| ----------- | --------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| url         | /xx                   | 请求 api, 支持正则的[匹配模式](https://expressjs.com/en/4x/api.html#path-examples)                                                                                                                      |
| method      | get/post/put/delete   | 请求方法                                                                                                                                                                                                |
| dataType    | jsonp                 | **可选** 当请求为 jsonp 时需配置该项，仅当 result 为 JSON 时生效，为 function 时要自己处理返回                                                                                                          |
| contentType | `application/x-www-form-urlencoded` | **可选** 当方法为`post`且请求类型为`application/x-www-form-urlencoded`时，需配置该参数                                                                                                                                |
| test        | http://test/api/1     | **可选** 将请求代理到测试地址，当配置 product 时，优先代理 product                                                                                                                                      |
| product     | http://prod/api/1     | **可选** 将请求代理到正式地址                                                                                                                                                                           |
| result      | JSON/Function         | **JSON** 直接配置静态/动态数据，动态数据的配置可参考 [Mockjs](http://mockjs.com/examples.html)<br>**Function** 支持返回一个方法，你可以读取请求参数进行一些判断, 并返回自定义内容，支持 Mock 和文件读取 |

### 接口例子

1. 返回 JSON 格式数据

```javascript
/*
  最简单也是最常用的返回json格式数据，变量语法可参考 http://mockjs.com/examples.html
 */

module.exports = {
  url: '/a',
  method: 'get',
  result: {
    'status|1': ["no_login", "OK", "error", "not_registered"],             'msg': '@csentence()',
    'data': {
      a: 2
    }
  }
}
```

2. 返回 JSONP 格式数据

```javascript
/*
  返回简单的json数据，变量语法可参考 http://mockjs.com/examples.html
 */

module.exports = {
  url: "/a",
  method: "get",
  dataType: "jsonp",
  result: {
    "status|1": [
      "no_login",
      "OK",
      "error",
      "not_registered",
      "account_reviewing",
    ],
    msg: "@csentence()",
    data: {
      a: 2,
    },
  },
};
```

3. 自定义函数

```javascript
/*
  用户可以自定义返回函数，采用express语法application/x-www-form-urlencoded，需设置contentType参数
 */

module.exports = {
  url: "/b",
  method: "post",
  contentType: "application/x-www-form-urlencoded",
  result: function (req, res) {
    // POST方法req.body获取请求信息
    if (req.body.name === "admin" && req.body.password === "admin") {
      res.send({
        msg: "登录成功！",
        code: 0,
        authorization: "fdjflsjflfds4f5df5s4f5d4f5s",
      });
    } else {
      res.send({ msg: "账号或者密码错误！", code: 1 });
    }
  },
};
```

4. 支持 Model 数据结构引用

```javascript
/*
  饮用model文件夹中的模型
*/

// model/user.js
module.exports = {
  avatar: "@image(100x100)",
  nickname: "@cname",
  user_type: 1,
  vip: 1,
};

// api/d.js
module.exports = {
  url: "/d",
  method: "get",
  result: function (req, res) {
    const Mock = res.Mock;
    const User = res.require("model/user");
    const json = {
      status: "ok",
      data: {
        user: User,
      },
    };
    res.send(Mock.mock(json));
  },
};
```

5. 动态 Mock 和文件读取

```javascript
/*
  通过(:value)动态设置url参数
  通过res.require引入模块文件
 */

module.exports = {
  url: "/c/:id",
  method: "get",
  result: function (req, res) {
    const Mock = res.Mock;
    const json = res.require("model/c");
    // url 参数通过req.params获取，?xxx=xx参数通过req.query获取
    if (req.params.id === "1") {
      // res.cookie('name', 'tobi', { domain: '.example.com', path: '/admin', secure: true });
      res.send({ msg: "获取用户" + req.params.id + "信息成功" });
    } else {
      res.send(Mock.mock(json));
    }
  },
};
```

6. 代理接口

```javascript
/*
  接口代理的使用，直接代理到正式/测试地址，可解决跨域问题
 */

module.exports = {
  url: "/a/v1/emoticons/list/public",
  method: "get",
  test: "https://removeserver.com",
  result: {}
};
```

### WebSocket调试

启动命令：`lmock start -u -ws` 或 `lmock start -u -io` （打开UI功能，选择原生websocket或socket.io）

websocket接口定义于`/socket`文件夹下，格式如同HTTP API。

| Params | Type | Description |
| ------ | ----- | ----------- |
| name   | String | 事件名称，客户端通过此名称监听事件 |
| interval | Number | **可选** 定时发送事件的间隔时间(毫秒) |
| timeout | Number | **可选** 延迟发送事件的时间(毫秒)，与interval互斥 |
| result | JSON | 事件数据，支持Mock.js语法动态生成数据 |

1.定时发送数据（ws连接建立后会自动发送数据）
```javascript
module.exports = {
  name: "acc_info",
  interval: 9000,
  // timeout: 5000,
  result: {
    'game_cnt': '@integer(100, 1000)',
    'game_cnt_rank': '@float(0.1, 1.0, 2)',
  }
};
```

2.手动触发数据
```javascript
module.exports = {
  name: "user_info",
  result: {
    status: 'ok',
    data: {
      name: '@cfirst()',
      age: '@integer(10, 100)',
      gender: '@pick(["男", "女"])',
      address: '@city()'
    }
  }
}
```
手动触发数据需要通过可视化的UI界面：

**操作步骤：** 选中mock文件 ——> 点击连接（选择连接方式）——> 点击发往客户端

#### 开发调试
UI工具中的WebSocket客户端仅做为连通性测试和数据查看，开发中请从业务代码中连接WebSocket Mock服务器，如：
```javascript
const socket = new WebSocket(`ws://192.168.0.1:4000`)
```

#### 测试服务端接口
可视化工具支持测试服务端websocket接口，一般用于校验websocket连通性，通过配置ws服务端地址和配置项进行连接，可自行尝试。



### 项目快速配置

工具也可以只安装在项目中作为开发依赖，不用全局安装

```
npm i l-lmock --save-dev
```

修改 package.json 中的 scripts

```
"scripts": {
  "mock": "cd mock && lmock start",
}
```

运行时执行 `npm run mock`

### API 用法

除了用命令行模式开启服务，还可通过与工程脚本配合，用代码启动服务

```javascript
const path = require("path");
const lmock = require("l-mock");
const mockDir = path.resolve("./mock/");
const port = 4000;

lmock.start(mockDir, port);
```

### Future features
1. 一键部署外链
...