iT邦幫忙

2019 iT 邦幫忙鐵人賽

DAY 4
0

Api Server 部分使用 apollographql + Mongo 設定方式檔案如下

比較要注意的部分是 config的部分 因為 server跟 client分開來所以要加上cros的設定 要注意 origin 的設定

const express = require('express')
const cors = require('cors')
const bodyParser = require('body-parser')
const cookieSession = require('cookie-session')

const config = require('./config')

const mongoose = require('./mongoose')
mongoose.connect(config.mongoURI)

require('./src/models')

const schema = require('./src')
const {
  apolloMiddleInterFace,
  apolloMiddle
} = require('./middleware/apolloMiddle')

require('./config/seed/index')

const port = process.env.PORT || 8080

const server = express()

server.use(cors({ credentials: true, origin: config.origin }))
server.use(bodyParser.json())
server.use(bodyParser.urlencoded({ extended: true }))
server.use(
  cookieSession({
    maxAge: 30 * 24 * 60 * 60 * 1000,
    keys: [config.cookieKey],
    secure: config.production
  })
)

apolloMiddle(server, schema)
apolloMiddleInterFace(server)

server.listen(port, err => {
  if (err) throw err
  // eslint-disable-next-line no-console
  console.log(`> ready on http://localhost:${port}`)
})

config檔案 這邊會再區分 上線版本與開發版本的config

module.exports = {
  production: false,
  origin: 'http://localhost:3000',
  mongoURI: 'mongodb://mongo:27017/erp-system',
  cookieKey: '',
  secret: ''
}


mongo 部分 先建立連線 並且把所有的model有引用進來


const mongoose = require('./mongoose')
mongoose.connect(config.mongoURI)

require('./src/models')

這邊的require('./src/models') 會把該目錄的都一次載入如下

var normalizedPath = require('path').join(__dirname)
require('fs')
  .readdirSync(normalizedPath)
  .forEach(function(file) {
    if (file !== 'fragment') {
      require('./' + file)
    }
  })

mongo 部分則是使用docker 比較快就可以開始開發

apollographql部分 建立


apolloMiddle(server, schema)
apolloMiddleInterFace(server)

兩個middleware 一個是處理 payload對應 與 schema的地方 另外一個用來做一些共同行為的處理

在對應部分設定 除了server.use( '/graphql',.... 這是對應graphql server的位置之外還會設定一個
server.use('/graphiql',.... 差別在一個小i 這個 graphiqlExpress apollographql提供的網頁介面查詢測試語法的介面

const { graphqlExpress, graphiqlExpress } = require('apollo-server-express')
const bodyParser = require('body-parser')

const mongoLog = require('../middleware/mongoLog')

const apolloMiddle = (server, schema) =>
  server.use(
    '/graphql',
    bodyParser.json(),
    graphqlExpress(req => ({
      schema,
      context: { req },
      async formatResponse(data) {
        if (!data.errors) await mongoLog(req)
        return data
      }
    }))
  )

const apolloMiddleInterFace = server => {
  server.use(
    '/graphiql',
    graphiqlExpress({
      endpointURL: '/graphql'
    })
  )
}

module.exports = { apolloMiddle, apolloMiddleInterFace }


另外一隻middleware 會用來做一些log紀錄 或是共用行為的處理

const { getUserId } = require('../src/utils')

const Log = require('../src/models/log')
const User = require('../src/models/user')

const mongoLog = async req => {
  if (req.originalUrl === '/graphql') {
    if (req.body.query.includes('mutation')) {
      if (req.body.operationName === 'login') {
        const user = await User.findOne({ account: req.body.variables.account })
        const log = new Log({
          operationName: req.body.operationName,
          body: JSON.stringify(req.body),
          createUserId: user._id
        })
        await log.save()
      } else {
        const userId = getUserId({ req }, false)
        const log = new Log({
          operationName: req.body.operationName,
          body: JSON.stringify(req.body),
          createUserId: userId
        })
        await log.save()
      }
    }
  }
}

module.exports = mongoLog

總結

server端的環境就是要注意的有 cros 跨區, 還有 apollograpqhl,mongo的連結設定


上一篇
起手式(Client)
下一篇
偏好設定
系列文
Next + Ant + Apollo Graphql + Mongo 後台系統 製作與發佈10

尚未有邦友留言

立即登入留言