Serverless Framework・Lambda・TypeScriptプロジェクトの環境構築の一例

### プロジェクト作成
```
$ serverless create --template aws-nodejs-typescript --path serverless-sample-project
```
AWS - Create
https://www.serverless.com/framework/docs/providers/aws/cli-reference/create/
・オプションの省略
serverless → sls
--template → -t
--path → -p

### npm
```
$ npm init --yes
→package.json作成、--yesオプションは-yでもOK(なしでもOK)
$ npm install
→package.jsonに記載されたパッケージを一括でインストール
```

### serverless.ts
```region``` を```ap-northeast-1``` に設定

```ts:serverless.ts
const serverlessConfiguration: AWS = {
  provider: {
    region: "ap-northeast-1"
  }
}
```

### 試しにデプロイ
```
$ serverless deploy --stage 環境名(デフォルトでdev) --aws-profile my_profile(プロファイル名、デフォルトでdefault)
```
・オプションの省略
--stage → -s

AWS - deploy
https://www.serverless.com/framework/docs/providers/aws/cli-reference/deploy/

Serverless Frameworkの```stage```という概念についてはこちら。
>the Serverless Framework has had the concept of stages; the ability to create different stacks of the same service. 
[Managing Stages and Environments](https://www.serverless.com/blog/stages-and-environments)

具体的にはLambda関数名やエンドポイント に```--stage``` オプションで設定した値(設定しなければ```dev``` )が入ったり、その値に応じて環境変数を切り替えたりすることができます。

```
// デプロイ成功後に下記表示
functions:
  hello: serverless-sample-project-dev-hello
```

そもそも、AWS CLIの設定についてはこちら。
AWS-CLIの初期設定のメモ
https://qiita.com/reflet/items/e4225435fe692663b705
Access Keyなどを```aws configure --profile``` で設定してそれを```deploy``` 時に指定することで、デプロイ先を切り替えます。

### git, GitHub
```
$ git init
からadd, commit, GitHub上でリポジトリ作成, remote add origin, pushなど
```

### ESLint
```
$ npm install --save-dev eslint
$ ./node_modules/.bin/eslint --init

✔ How would you like to use ESLint? · problems
✔ What type of modules does your project use? · commonjs
✔ Which framework does your project use? · none
✔ Does your project use TypeScript? · No / Yes
✔ Where does your code run? · node
✔ What format do you want your config file to be in? · JavaScript
@typescript-eslint/eslint-plugin@latest @typescript-eslint/parser@latest ?
Would you like to install them now with npm? ・ Yes
```

nodeを選択する時、```l```を押さないと選択項目が切り替わらないので注意(なぜここだけ)

```--save-dev``` は```-D```でもOK
(ちなみに```--save```はつけなくても```npm install``` がデフォルトで ```--save``` になっている)


スクリプトを設定

```json:package.json
{
  scripts: {
    "lint": "eslint",
    "lint:fix": "eslint --fix"
  }
}
```

いろいろ怒られるので```ignore```に追加

```:.eslintignore
webpack.config.js
```

ESLintの設定ファイルに下記追加

```js:.eslintrc.js
module.exports = {
  "env": {
    "jest": true
  },
  rules: {
    "@typescript-eslint/no-var-requires": 0
  }
}
```

>Specifying Environments
An environment defines global variables that are predefined. The available environments are:
jest - Jest global variables.
>
[Configuring ESLint](https://eslint.org/docs/user-guide/configuring#specifying-environments)

```"env"``` に```"jest": true``` を設定しておかないと、Jest関係のメソッドでこんな感じで怒られる。

```
error  'describe' is not defined   no-undef
error  'beforeAll' is not defined  no-undef
error  'it' is not defined         no-undef
error  'expect' is not defined     no-undef
```



また、```require``` を使うと怒られるので```no-var-requires``` を無効にする。
Rule: no-var-requires
https://palantir.github.io/tslint/rules/no-var-requires/


ESlintを試す 

```
$ npm run lint .
```


### Jest
```
$ npm install --save-dev jest ts-jest @types/jest serverless-jest-plugin
```

```ts:serverless.ts
const serverlessConfiguration: AWS = {
  plugins: ["serverless-webpack", "serverless-jest-plugin" // ←追加],
}
```
Serverless Jest Plugin
https://www.npmjs.com/package/serverless-jest-plugin
→こちらはあんまりメジャーではなさそうですが、lambdaに通したことにしてテストを行ってくれる```Lambda Wrapper```などを内包し、テストをコマンドで作れるようになるnpmモジュール。

Jestの設定ファイルを作成。TypeScriptに対応させる。

```
$ touch jest.config.js
```

```js:jest.config.js
module.exports = {
  roots: ["<rootDir>"],
  testMatch: [
    "**/__tests__/**/*.+(ts|tsx|js)",
    "**/?(*.)+(spec|test).+(ts|tsx|js)",
  ],
  transform: {
    "^.+\\.(ts|tsx)$": "ts-jest",
  },
};
```
Jest
https://typescript-jp.gitbook.io/deep-dive/intro-1/jest


hello関数のテストの作成

```
$ serverless create test -f hello (serverless-jest-pluginのコマンド)
→__tests_/hello.test.js作成
$ mv __tests__/hello.test.js __tests__/hello.test.ts
```

```json:package.json
{
  scripts: {
    "test": "jest",
    "ts-node": "ts-node"
  }
}
```
```jest``` コマンドのついでに```.ts``` ファイルをコンパイルして実行してくれる```ts-node``` も一緒に設定。

### ESLintとJestを試す
```
$ npm run lint .
$ npm run test
```

### 他
・ 環境変数の設定
Serverless Frameworkで環境変数を外部ファイルから読み込み、環境毎に自動で切り替えてみる
https://dev.classmethod.jp/articles/serverless-framework-conf-change/

Serverless Frameworkにおける環境変数の外部ファイル化の一例
https://qiita.com/momonoki1990/items/68c95a81bbfe1e9c17d4

・Loggerの設定(winstonなど)
Winstonでログを出力する
https://qiita.com/momonoki1990/items/32b345b3d60b60104769

・最後にデプロイを試す

```
$ serverless deploy --stage dev --aws-profile my_profile
```