Json-server に関して

## Json-serverの立ち上がり
### json-serverインストール
* Step1 インストール
```
npm install json-server
```

* Step2 jsonファイルを用意(DBのようなもの)

```
package.json同じ階層の下に、mockと言うフォルダーを作成して、mockフォルダーの下にjsonファイルを作成
// mock/db.json
{
  "menu": [
    { "id": 1, "name": "menuA" },
    { "id": 2, "name": "menuB" },
     { "id": 3, "name": "menuC" }
  ]
}
```

* Step3 jsonファイルとポートを指定して実行
```
npx json-server --watch mock/db.json --port 30001
\{^_^}/ hi!

  Loading mock/db.json
  Loading mock/route.json
  Done

  Resources
  http://localhost:3001/menu
```
http://localhost:3001/menu でデータ取得ことが確認できる

* Step４　mockフォルダーの下にルーティングファイルを用意（Optional）
```
// mock/routes.json
{
  "/api/menu": "/menu"
}
```

* Step５　モックサーバー起動コマンドをpackage.jsonのscripts下へ追加
```
"scripts": {
"json-server": "json-server --watch mock/data.json --port 3001 --routes mock/routes.json"
}
```

* Step6　package.jsonで追加されたモックサーバーの起動コマンドを実行
```
npm run json-server
\{^_^}/ hi!

  Loading mock/db.json
  Loading mock/route.json
  Done

  Resources
  http://localhost:3001/menu

  Other routes
  /api/menu -> /menu

  Home
  http://localhost:3001

  Type s + enter at any time to create a snapshot of the database
  Watching...
```
http://localhost:3001/menu あるいはhttp://localhost:3001/api/menu で同じデータを取得ことが確認できる


### 上記よりモックサーバーが立ち上げたら、CRUDをテスト
* Getでデータを取得する
```
// 全件取得する
curl localhost:3001/menu
[
  {
    "id": 1,
    "name": "menuA"
  },
  {
    "id": 2,
    "name": "menuB"
  },
  {
    "id": 3,
    "name": "menuC"
  }
]  

//  Id指定で取得する
curl localhost:3001/menu/1   
{
  "id": 1,
  "name": "menuA"
}%   

```

* Postでレコードを追加する
```
curl -X POST localhost:3001/menu -d name=menuD
{
  "name": "menuD",
  "id": 4
}% 

// 確認する
curl localhost:3001/menu 
[
  {
    "id": 1,
    "name": "menuA"
  },
  {
    "id": 2,
    "name": "menuB"
  },
  {
    "id": 3,
    "name": "menuC"
  },
  {
    "name": "menuD",
    "id": 4
  }
]%                                                              
```
その時、mock/db.jsonの下にもmenuDが追加されました。

* PUTでレコードを更新する
```
curl -X PUT localhost:3001/menu/4 -d name=menuD-newName
{
  "name": "menuD-newName",
  "id": 4
}%                                                                  

//確認する
curl localhost:3001/menu
[
  {
    "id": 1,
    "name": "menuA"
  },
  {
    "id": 2,
    "name": "menuB"
  },
  {
    "id": 3,
    "name": "menuC"
  },
  {
    "name": "menuD-newName",
    "id": 4
  }
]%                                                                   
```
* Deleteでレコードを削除する
```
curl -X DELETE localhost:3001/menu/4
{}%  

// 確認する
curl localhost:3001/menu           
[
  {
    "id": 1,
    "name": "menuA"
  },
  {
    "id": 2,
    "name": "menuB"
  },
  {
    "id": 3,
    "name": "menuC"
  }
]%                                                               
```


## エンドポイントごとにJsonファイルを分ける
json-serverの仕様上、サーバーが起動する時、データのjsonファイルは一つしか読み込めないため、開発を進めるうちに、モック用のデータjsonファイルも大きくなり過ぎてしまう。
下記のはエンドポイント毎にjsonファイルを分ける方法を紹介する。
### エンドポイントごとにJsonファイルを分ける
例：今のdb.jsonファイルは下記のようになっている。
```
// mock/db.json
{
  "menu": [
    {
      "id": 1,
      "name": "menuA"
    },
    {
      "id": 2,
      "name": "menuB"
    },
    {
      "id": 3,
      "name": "menuC"
    }
  ],
  "customers": [
    {
      "id": 1,
      "name": "Jack"
    },
    {
      "id": 2,
      "name": "Jim"
    },
    {
      "id": 3,
      "name": "Jhon"
    }
  ],
  "cards": [
    {
      "id": 1300157001,
      "ctsId": 1,
      "leval": "A"
    },
    {
      "id": 1300157002,
      "ctsId": 2,
      "leval": "A"
    },
    {
      "id": 1300157003,
      "ctsId": 3,
      "leval": "B"
    }
  ]
}


```

* Step1 エンドポイント毎にjsonファイルを分ける
```
//mockフォルダーの下にdataフォルダーを作成し、エンドポイント毎にjsonファイルを作成
.
└── mock
    └── data
        ├── menu.json
        └── customers.json
        └── cards.json
```
* Step2 mockフォルダーの下にdataフォルダーしたのjsonファイルを一つのdb.jsonへまとめるスクリプトファイルmergeDataToDb.cjsを作成する
```
// mock/mergeDataToDb.cjs
const fs = require('fs')
const path = require('path')
const outputFileName = 'db.json'

const root = path.resolve('./', 'mock')
const fixturesPath = root + '/data'
const json = {}

try {
  fs.unlinkSync(root + '/' + outputFileName)
} catch (error) {
  console.log('db.jsonファイル存在したいため、これから作成する')
}

fs.readdirSync(fixturesPath).reduce((api, file) => {
  if (api === undefined) api = {}

  if (path.extname(file) == '.json') {
    const endpoint = path.basename(file, path.extname(file))
    if (api[endpoint] === undefined) api[endpoint] = {}
    json[endpoint] = JSON.parse(
      fs.readFileSync(fixturesPath + '/' + file, 'utf-8')
    )
  }
}, {})

fs.writeFile(root + '/' + outputFileName, JSON.stringify(json), function (err) {
  if (err) throw err
  console.log('=== Create ' + outputFileName)
})

```

* 起動コマンドを修正
 package.jsonと同じ階層でjson-server.jsonファイルを作成し、ポート番号、ルーティングなどを設定する
```
// json-server.json
{
  "watch": true,
  "routes": "mock/routes.json",
  "port": 3001
}

```
 mockフォルダーの下にjsonーserverの起動に関して起動スクリプトファイルindex.cjsを追加する
```
// mock/index.cjx
const jsonServer = require('json-server')
const server = jsonServer.create()
const router = jsonServer.router('mock/db.json')
const middlewares = jsonServer.defaults()
const apiURL = require('./routes.json')

server.use(middlewares)

server.use(jsonServer.rewriter(apiURL))

server.use(router)
server.listen(3001, () => {
  console.log('JSON Server is running')
})

```
 package.jsonでのjsonーserver起動コマンドを修正する
```
// json-server.json
"scripts": {
"json-server":{
  "json-server": "node mock/merge_data_to_db.cjs && node mock/index.cjs"
}
```
以上でエンドポイント毎にjsonファイルを分けました。

## PostをGetとして扱う
開発段階で、モックAPIを使う時、リクエストはPOSTで、レスポンスはデータを取得する、つまりモックAPIはGetとして動作させる。その時、起動スクリプトファイルindex.cjsでmiddlewaresの下に下記の内容を追加すれば良い。
```
// mock/index.cjs

server.use(jsonServer.bodyParser)
server.use((req, res, next) => {
  if (req.method === 'POST') {
    req.method = 'GET'
  }
  next()
})

```