# @soapi/app-server

<!-- description -->

`app-server`是快速的、简单、灵活的用于开发接口平台的`service`开发框架。

<!-- description -->

## Install

```shell
npm install @soapi/app-server
```

or use yarn

```shell
yarn add @soapi/app-server
```

## Usage

<!-- usage -->

接口平台的`service`主要分为 3 个部分，分别是：`service`基本信息、`interaction`界面插槽定义、`hooks`事件响应、`app`自定义 koa, 平台 api 调用。

### service 基本信息

service 基本信息主要是告诉平台 “我是谁”，可以直接通过对对应字段赋值设置。

```javascript
import { service, app } from '@soapi/app-server'

service.name = 'your service name'
service.version = 'your service version(must conform to the semver)'
service.changelog = ''
service.mode = 'http'
service.host = '0.0.0.0'
service.port = 8000

// NOTE: 将启动一个server，绑定到上面设定的0.0.0.0:8000端口
service.start()
```

`service.version`必须符合[Semantic Versioning](https://semver.org/)规范。
这样平台才可以判断`service`是否升级，从而可以进行相应的升级操作。

### 自定义 koa

通过增加`koa`中间件扩展`service`功能。

```javascript
import { service, app } from '@soapi/app-server'

/* 你可以自定义koa中间件，实现service的功能扩展 */
app.use(/* custom koa middleware here */)

service.start()
```

### 界面插槽定义

`service`可以为操作界面添加一些新的功能。可以添加一个按钮或者输入框，然后响应用户的操作请求（按钮点击或者输入内容）。
这方便服务为用户提供一些快捷操作方式。

```javascript
import { service, interaction } from '@soapi/app-server'

// ...省略基本信息配置...

const rules = {
  name: [{ required: true, message: 'Name 不能为空' }],
  url: [{ required: true, message: 'Url 不能为空' }],
}
/**
 * 插件的应用配置页面插槽
 * 配置页面的插槽没有callback
 * 配置信息将被存储到平台数据库
 * 当需要的使用的时候，可以通过平台的api接口获取相应的配置信息
 * 这保证简单的插件可以做到无状态
 *
 * 目前插槽只有`application`，其他插槽未开放。
 */
interaction.application = [
  {
    // 类型
    type: 'string',
    // 输入框的label
    label: 'label',
    // 通过api获取配置数据的数据key值(e.g. 通过config.default就能取得用户输入的stirng)
    name: 'default',
    /* 输入框组件的props */
    props: { rules: rules.url },
  },
]

service.start()
```

### 平台 api 调用

为了减少 request 的沉余数据，ctx 中只包含一些 id，需要更详细的信息要通过 api 接口调用才可以。

```javascript
import { service, hooks } from '@soapi/app-server'

// ...省略基本信息配置...

hooks.on('applicationUpdated', async ctx => {
  ctx.log.info('来源于平台：', ctx.origin)
  ctx.log.info(`Id为${ctx.appId}的应用更新啦`)

  const config = ctx.api.getConfig(ctx.serviceId)
  ctx.log.info(`项目的配置页面的配置信息为：${config}`)
})

service.start()
```

**`service.start()`以后，不可以再修改任何配置，否则将导致接口平台的升级检测失败。如果想要修改，请同时修改版本号，然后重启服务**

<!-- usage -->

<!-- supplement -->

### `hooks`事件响应

当用户/平台进行某些操作时，将触发一些事件，service 可以监听这些事件，并对此做出响应，我们将此称之为`hooks`。

```javascript
import { service, hooks } from '@soapi/app-server'

// ...省略基本信息配置...

hooks.on('applicationUpdated', async ctx => {
  ctx.log.info('来源于平台：', ctx.origin)
  ctx.log.info(`Id为${ctx.appId}的应用更新啦`)
})

service.start()
```

当在接口平台的应用中启动此插件后，每次应用更新后，都会触发记录一条日志。

需要注意的是，hooks 是异步执行的。既，平台通知到`service`后，request 请求就结束了。之后的操作相对于平台来说都是异步的。
框架会在 callback 执行完成后，调用`end`接口，自动通知平台，`service`的任务已经执行完成。

### Hooks List

#### `log`

接口平台记录 log 时会向插件通知 log 事件。

---

#### `createApp`

创建应用

#### `removeApp`

删除应用

#### `updateApp`

更新应用信息

---

#### `createSchema`

应用创建新`schema`

#### `updateSchema`

更新`schema`内容

#### `removeSchema`

删除`schema`

---

#### `createRoute`

应用创建新`route`

#### `updateRoute`

更新`route`信息

#### `removeRoute`

删除`route`

---

#### `publishAppRelease`

应用发布新版本

### API LIST

#### `ctx.api.getRoute`

获取应用的 route 信息

#### `ctx.api.getSchema`

获取应用的 schema 信息

#### `ctx.api.getAppConfig`

获取服务在应用中的配置信息

#### `ctx.api.getApplication`

获取应用的基本信息

## `ctx.throwError`

通过这个 api 报错，会将错误上报到 接口平台进行记录

## `ctx.logger`

提供`ctx.logger.info`, `ctx.logger.warn`, `ctx.logger.error`, `ctx.logger.success`四个等级，输出日志并将错误上报到 server。

<!-- supplement -->
