> For the complete documentation index, see [llms.txt](https://packhouse-doc.metalsheep.com/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://packhouse-doc.metalsheep.com/application/api-service.md).

# API Service

### 在開始前必須了解...

* [AWS](https://aws.amazon.com/tw/)的基本知識
* [Serverless](https://serverless.com/)的架構與原理

## Install

{% hint style="info" %}
開始前你必須安裝[AWS-CLI](https://aws.amazon.com/tw/cli/)並擁有個人的Secret Access Key允許Serverless可以建立服務。
{% endhint %}

#### 安裝CLI工具集

```bash
npm install serverless packhouse-cli mocha -g
```

#### 建立服務檔案

```javascript
packhouse generate-api-service
```

{% hint style="danger" %}
你必須手動添加你的`IAM-ROLE`使你的Lambda有能力使用其他服務，可於`serverless.yml`中找到以下欄位：
{% endhint %}

```yaml
provider:
  name: aws
  runtime: nodejs12.x
  ### 這裡
  role: YOUR-IAM-ROLE
  ###
  stage: v1
  region: us-east-1
  timeout: 30
  memorySize: 256
```

#### 初始化及部署服務

{% hint style="info" %}
建立的服務預設Region在`us-east-1。`
{% endhint %}

```javascript
cd service
npm install
npm run deploy
```

## Architecture

這是我們建立Packhouse前使用的架構：

![參考自php laravel](/files/-LzjtpjB16EJqx3F9J6r)

由於是建立在Cloud Service的服務，因此Database的操作大多來自SDK，而不是SQL，所以讀寫資料庫的工作交由Repository：

![Packhouse的架構跟Model2相差不遠](/files/-Lzjv096DdPzaskiKmmH)

## Invoke

當你部屬好你的第一個服務後，就會看見以下這段Log：

```javascript
endpoints:
  GET - https://xxxxxx.execute-api.us-east-1.amazonaws.com/v1/hello
```

開啟你的瀏覽器並貼上這段網址：

```javascript
https://xxxxxx.execute-api.us-east-1.amazonaws.com/v1/hello?message=helloworld
```

即可看到你的第一個Response：

<div align="left"><img src="/files/-LzkMAS-HU406iB2rDHA" alt=""></div>

也可以在**Dynamodb**中看到你的Message Log：

<div align="left"><img src="/files/-LzkMLZy2E12MtMQiOCE" alt=""></div>

{% hint style="danger" %}
為了避免被收取額外費用，你可以使用`npm run remove`指令關閉整個服務。
{% endhint %}

## AWS Exception

AWS SDK的所有方法雖然都有提供`promise`接口，但它的`promise`有一個糟糕的問題，在有一定複雜的呼叫過程時如果有程式碼報錯，`promise`會捕捉到`error`卻不會觸發`catch()`。

```javascript
// 這是個糟糕的例子 😢
let AWS = require('aws-sdk')
let client = new AWS.DynamoDB.DocumentClient()
let group = {
    tools: {
        getUser: {
            handler(self, name) {
                let parmas = {
                    TableName: 'users',
                    Key: {
                        name
                    }
                }
                // 避免如下宣告
                client.get(params).promise().then(self.success).catch(self.error)
            }
        }
    }
}
```

```javascript
// 這是個優良案例 🤣
let AWS = require('aws-sdk')
let client = new AWS.DynamoDB.DocumentClient()
let group = {
    tools: {
        getUser: {
            handler(self, name) {
                let parmas = {
                    TableName: 'users',
                    Key: {
                        name
                    }
                }
                client.get(params, self.assess())
            }
        }
    }
}
```
