-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathpreviewServer.js
148 lines (127 loc) · 3.97 KB
/
previewServer.js
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
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
'use strict'
'use babel'
const path = require('path')
const childProcess = require('child_process')
const fs = require('fs')
const EventEmitter = require('events')
const agentName = 'dumplings'
const serverStartedFlag = 'egg started'
const consoleCommandName = 'server:log'
module.exports = class PreviewServer extends EventEmitter {
boot (fouseStart = false) {
return new Promise((resolve, reject) => {
let that = this
this.stop(() => {
that._boot(resolve, reject)
})
})
}
deactivate () {
this.dumplingProcess.kill('SIGINT')
}
_boot (resolve, reject) {
const agentPath = atom.packages.resolvePackagePath(agentName) ||
path.join(atom.config.resourcePath, 'node_modules', 'dumplings')
console.log(`dumplings path ${agentPath}`)
// todo @shiji: egg Node.js >= 6.0.0 required.
const nodePath = this.getCommandPath('node')
let environment = process.env
environment.PORT = atom.config.get('weex-run.dumplingPort')
let child = childProcess.spawn(
nodePath,
[path.join(agentPath, 'index.js')],
{cwd: atom.config.resourcePath, env: environment})
this.dumplingProcess = child
// fetch logs
child.stdout.on('data', (data) => {
if (data.toString().includes(serverStartedFlag)) {
this.emit('start')
resolve()
}
console.log(data.toString())
atom.commands.dispatch(atom.views.getView(atom.workspace),
consoleCommandName,
{first: () => data.toString(), last: () => 'INFO'})
})
child.stderr.on('data', (data) => {
console.error(data.toString())
})
child.on('close', (code, signal) => {
this.dumplingProcess = null
this.emit('close')
console.log(`dumplings terminated due to receipt of signal ${signal}`)
})
child.on('exist', () => {
console.log('child exist')
})
}
stop (callback) {
let that = this
this.findSurvivalAgent((pids) => {
that.killProcess(pids || [], callback)
})
}
// find survival pids by `ps` names
findSurvivalAgent (callback) {
childProcess.exec(
`ps -ef | grep ${agentName}`,
(error, stdout) => {
if (error) {
console.warn('find survival agent process failed', error)
}
const survivals = stdout.split('\n')
.filter(e => !e.includes(' grep ') && e.includes(agentName))
.map(v => v.split(' ').filter(e => e.length !== 0))
.reduce(
(previousValue, currentValue) => {
let pid = currentValue[1]
previousValue.push(pid)
return previousValue
}, [])
console.log('survivals: ' + survivals)
callback(survivals)
})
}
// kill all processes in pid list, callback after all set.
killProcess (pids, callback) {
let ps = []
pids.forEach((pid) => {
ps.push(new Promise((resolve, reject) => {
childProcess.exec(
`kill -9 ${pid}`,
(error, stdout) => {
if (error) {
console.warn(`kill survival ${pid} process failed` + error.message)
// reject()
} else {
console.log(`dumpling survival ${pid} killed`)
}
resolve()
})
}))
})
Promise.all(ps).then(callback)
}
// get command by name. eg. `npm` `apm` `node`
getCommandPath (commandName) {
if (process.platform === 'win32') {
return 'node'
}
let apmRoot = path.join(process.resourcesPath, 'app', 'apm')
let commandPath = path.join(apmRoot, 'bin', commandName)
try {
if (!fs.statSync(commandPath)) {
commandPath = path.join(apmRoot, 'node_modules', 'atom-package-manager', 'bin', commandName)
}
} catch (e) {
// apmPath not exist
if (e.code === 'ENOENT') {
commandPath = path.join(apmRoot, 'node_modules', 'atom-package-manager', 'bin', commandName)
}
}
return commandPath
}
getDumplingProcess () {
return this.dumplingProcess
}
}