File size: 2,882 Bytes
330c0d5
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
import template from 'express-art-template'
import { resolve } from 'node:path'
import util from 'node:util'
import url from 'node:url'
import lodash from 'lodash'

class applicationHandle {
  constructor () {
    this._events = {}
    this.handlers = ['WebSocketMethod', 'setViewEngine']
  }

  Handle (app) {
    this.handlers.forEach(handler => this[handler](app))
    return this
  }

  WebSocketMethod (app) {
    app.ws = (route, ...middlewares) => {
      let path = route
      if (typeof route == 'function') {
        path = '/'
        middlewares = [route, ...middlewares]
      }
      if (middlewares.length == 1 && util.isArray(middlewares[0])) {
        middlewares = middlewares[0]
      }
      middlewares.forEach((middleware, idx) => {
        let fn = (socket, request, next) => {
          if (request.ws) {
            let urlObj = url.parse(request.url, true)
            request.query = urlObj.query
            request.wsHandled = true
            try {
              middleware(socket, request, next)
            } catch (err) {
              next(err)
            }
          } else {
            next()
          }
        }
        /** 不走app.handle */
        this.add(this.WebSocketUrl(path), fn, idx)
      })
      return app
    }
  }

  setViewEngine (app) {
    app.engine('html', template)
    app.set('views', resolve('public'))
    app.set('view engine', 'html')
    app.set('x-powered-by', false)
  }

  WebSocketUrl (url) {
    if (url?.includes('?')) {
      let [baseUrl, query] = url.split('?')
      return `${baseUrl.replace(/\/$/, '')}.websocket?${query}`
    }
    return `${url.replace(/\/$/, '')}.websocket`
  }

  add (event, fn, id = 0) {
    if (!event || !fn) {
      return false
    }
    this.del(event, id)
    this._events[event] = this._events[event] || []
    this._events[event].push({ fn, id })
    return true
  }

  del (event, id = 0) {
    if (!this._events[event]) {
      return false
    } else if (id == 'all') {
      delete this._events[event]
      return true
    } else {
      let idx = this._events[event].findIndex(v => v.id == id)
      if (idx) {
        this._events[event].splice(idx, 1)
        return true
      }
    }
  }

  async call (key, args, callback) {
    if (!this._events[key]) {
      callback(false)
      return false
    }
    let ret
    for (let event of this._events[key]) {
      let fn = event.fn
      let done = true
      let reject = (msg = '') => {
        if (msg) {
          logger.error(new Error(msg))
          return
        }
        done = false
      }
      ret = fn(...args, reject)
      if (util.types.isPromise(ret)) {
        ret = await ret
      }
      if (done) {
        callback(ret)
        return ret
      }
    }
    callback(ret)
    return ret
  }

  has (key) {
    return !!this._events[key]
  }
}

export default new applicationHandle()