# 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())
            }
        }
    }
}
```


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://packhouse-doc.metalsheep.com/application/api-service.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
