Completed
Push — master ( 854a25...f9c943 )
by Thomas
32s
created

module.exports.startChildProcess   C

Complexity

Conditions 11
Paths 12

Size

Total Lines 26

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 11
c 0
b 0
f 0
nc 12
nop 1
dl 0
loc 26
rs 5.2653

How to fix   Complexity   

Complexity

Complex classes like module.exports.startChildProcess often do a lot of different things. To break such a class down, we need to identify a cohesive component within that class. A common approach to find such a component is to look for fields/methods that share the same prefixes, or suffixes.

Once you have determined the fields that belong together, you can apply the Extract Class refactoring. If the component makes sense as a sub-class, Extract Subclass is also a candidate, and is often faster.

1
'use strict'
2
3
const output = require('./output')
4
const Container = require('./containers/Container')
5
const fs = require('fs')
6
const io = require('socket.io-client')
7
const tmp = require('tmp')
8
const pkg = require('../package.json')
9
const path = require('path')
10
const chalk = require('chalk')
11
const moment = require('moment')
12
const request = require('./util').request
13
const child = require('./util/ChildProcess')
14
const Module = require('./containers/Module')
15
const archiver = require('archiver')
16
const filesize = require('file-size')
17
18
module.exports = {
19
  uploadFile: function (containerToken, event, path, cb, spinner) {
20
    var r = request(containerToken + '/fs', {
21
      'action': event,
22
      'name': path
23
    }, {
24
      'Content-Type': 'multipart/form-data'
25
    })
26
27
    if (event === 'add' || event === 'change' || event === 'zipBall') {
28
      r = r.attach('file', path)
29
    }
30
31
    var self = this
32
    return r.end(function (response) {
33
      if (response.body && response.body === 'Error: invalid container') {
34
        Container.clean()
35
        var func = spinner || output.err
36
        func('Container ' + containerToken + ' does not exist anymore. We cleaned your local environment, so that you can start with a clean container.')
37
        process.exit()
38
      }
39
      if (cb) {
40
        cb(response.body || '')
41
        return
42
      }
43
      if (response.body) {
44
        if (response.body.indexOf('Error:') === 0) {
45
          output.err(response.body)
46
        } else {
47
          self.logSyncMessage(response.body)
48
        }
49
      }
50
    })
51
  },
52
53
  logMessage: function (data, ret) {
54
    var message =
55
      chalk.bold(chalk[data.color](data.component)) + ' ' +
56
      data.message
57
58
    if ('time' in data) {
59
      if (data.time === 'now') {
60
        data.time = (new Date()).getTime() / 1000
61
      }
62
      message += ' ' + chalk.dim(moment(data.time * 1000).format('hh:mm:ss'))
63
    }
64
65
    if (ret) {
66
      return message
67
    }
68
69
    return output.log(message)
70
  },
71
72
  logSyncMessage: function (message, ret) {
73
    return this.logMessage({
74
      component: 'Sync',
75
      color: 'green',
76
      message: message,
77
      time: 'now'
78
    }, !!ret)
79
  },
80
81
  createInitialZip: function (dir, containerToken, envr, cb) {
82
    if (fs.existsSync(path.join(dir, 'vendor'))) {
83
      output.warn('Ignoring directory \'vendor\'')
84
    }
85
    if (fs.existsSync(path.join(dir, 'node_modules'))) {
86
      output.warn('Ignoring directory \'node_modules\'')
87
    }
88
    if (fs.existsSync(path.join(dir, 'web/node_modules'))) {
89
      output.warn('Ignoring directory \'web/node_modules\'')
90
    }
91
92
    var zipName = tmp.tmpNameSync({})
93
    var spinner = output.wait(this.logSyncMessage('Creating initial zipball', true))
94
    var zipFile = fs.createWriteStream(zipName)
95
    var self = this
96
97
    zipFile.on('close', function () {
98
      // Upload file to api.sadev.io
99
      fs.stat(zipName, function (err, stat) {
100
        if (err) {
101
          spinner('Error creating zipball')
102
          process.exit()
103
        }
104
105
        spinner()
106
107
        var size = filesize(stat.size).human('si')
108
        var stopSpinner = output.wait(self.logSyncMessage('Uploading initial zipball (' + size + ')', true))
109
110
        try {
111
          self.uploadFile(containerToken, 'zipBall', zipName, function (responseBody) {
112
            fs.unlink(zipName, function () {})
113
            if (responseBody.indexOf('OK') !== 0) {
114
              stopSpinner(responseBody || 'Could not connect to server (empty response)')
115
              process.exit()
116
            }
117
            stopSpinner(true)
118
            cb()
119
          }, spinner)
120
        } catch (e) {
121
          stopSpinner(e.message)
122
        }
123
      })
124
    })
125
126
    var archive = archiver('zip', {
127
      store: true
128
    })
129
    archive.on('error', function (err) {
130
      output.err(err)
131
    })
132
    archive.pipe(zipFile)
133
    archive.glob(path.join(dir, '**'), {
134
      ignore: ['.inc/**', '.git/**', 'node_modules', 'web/node_modules', 'node_modules/**', 'web/node_modules/**', 'vendor/**', '.gitignore', '.jshintrc']
135
    })
136
    archive.finalize()
137
  },
138
139
  startChildProcess: function (type, callback, basePath) {
140
    Module.getManifest(function (manifest) {
141
      if (!('scripts' in manifest) || typeof manifest.scripts !== 'object' || !(type in manifest.scripts)) {
142
        return callback ? callback(0) : false
143
      }
144
145
      // Cast to array if script is string
146
      if(typeof manifest.scripts[type] === 'string'){
147
        manifest.scripts[type] = [manifest.scripts[type]]
148
      }
149
150
      if (!(type in manifest.scripts) || !('length' in manifest.scripts[type])) {
151
        return callback ? callback(0) : false
152
      }
153
154
      var count = 0
155
      for (var x in manifest.scripts[type]) {
156
        if (!manifest.scripts[type].hasOwnProperty(x)) {
157
          continue
158
        }
159
        var script = manifest.scripts[type][x]
160
        child.run(script, callback, basePath)
161
        count++
162
      }
163
164
      return !!count
165
    }, basePath)
166
  },
167
168
  startWebSocket: function (containerToken) {
169
    var socket = io('http://ws.sadev.io/')
170
    var self = this
171
172
    socket.on('connect', function () {
173
      socket.emit('room', 'SADEV:' + containerToken)
174
      socket.emit('room', 'BROADCAST')
175
      socket.emit('room', pkg.name + '/' + pkg.version)
176
      socket.emit('clientInfo', pkg)
177
    })
178
179
    socket.on('log', function (data) {
180
      if (!('color' in data)) {
181
        if (data.component === 'Logger') {
182
          data.color = 'yellow'
183
        } else {
184
          data.color = 'blue'
185
        }
186
      }
187
      self.logMessage(data)
188
    })
189
190
    socket.on('disconnect', function () {
191
      socket.close()
192
      setTimeout(function () {
193
        self.startWebSocket(containerToken)
194
      }, 200)
195
    })
196
197
    socket.open()
198
  }
199
200
}
201