@jsreport/jsreport-cli 3.0.0-beta.2 → 3.1.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -21
- package/README.md +16 -12
- package/cli.js +93 -93
- package/example.config.json +43 -43
- package/example.server.js +14 -14
- package/index.js +20 -22
- package/jsreport.config.js +8 -8
- package/lib/cliExtension.js +59 -59
- package/lib/{createCommandParser.js → commander/createCommandParser.js} +44 -45
- package/lib/commander/createCustomCommandBuilder.js +150 -0
- package/lib/commander/createLogger.js +51 -0
- package/lib/commander/executeCommand.js +37 -0
- package/lib/commander/getCommandEventName.js +4 -0
- package/lib/commander/index.js +279 -0
- package/lib/commander/jsreportInstance.js +98 -0
- package/lib/commander/registerCommand.js +91 -0
- package/lib/commander/startCommand.js +234 -0
- package/lib/commander/startProcessing.js +208 -0
- package/lib/commands/_initializeApp.js +206 -208
- package/lib/commands/configure.js +393 -395
- package/lib/commands/help.js +453 -454
- package/lib/commands/init.js +76 -77
- package/lib/commands/kill.js +85 -86
- package/lib/commands/render.js +490 -488
- package/lib/commands/repair.js +55 -56
- package/lib/commands/start.js +72 -74
- package/lib/commands/win-install.js +124 -126
- package/lib/commands/win-uninstall.js +100 -102
- package/lib/daemonHandler.js +164 -164
- package/lib/daemonInstance.js +225 -225
- package/lib/{registerExtensionsCommands.js → detectAndRegisterExtensionsCommands.js} +74 -74
- package/lib/instanceHandler.js +316 -316
- package/lib/keepAliveProcess.js +205 -205
- package/lib/{errorUtils.js → utils/error.js} +149 -127
- package/lib/{getTempPaths.js → utils/getTempPaths.js} +39 -39
- package/lib/{normalizePathOptionOrArg.js → utils/normalizePathOptionOrArg.js} +41 -41
- package/lib/{normalizeSocketPath.js → utils/normalizeSocketPath.js} +9 -9
- package/lib/{startSocketServer.js → utils/startSocketServer.js} +53 -53
- package/package.json +105 -106
- package/test/testUtils.js +197 -198
- package/lib/commander.js +0 -1108
|
@@ -1,102 +1,100 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
const
|
|
4
|
-
const
|
|
5
|
-
|
|
6
|
-
const
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
exports.
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
const
|
|
17
|
-
const
|
|
18
|
-
const
|
|
19
|
-
const
|
|
20
|
-
const
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
let
|
|
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
|
-
winser = Winser({ silent: !verbose, nssmPath: staticPaths.nssm
|
|
80
|
-
}
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
})
|
|
102
|
-
}
|
|
1
|
+
const path = require('path')
|
|
2
|
+
const fs = require('fs')
|
|
3
|
+
const platform = require('os').platform()
|
|
4
|
+
const Winser = require('winser-with-api').Winser
|
|
5
|
+
|
|
6
|
+
const description = 'WINDOWS ONLY - Stop and uninstall service'
|
|
7
|
+
const command = 'win-uninstall'
|
|
8
|
+
|
|
9
|
+
exports.command = command
|
|
10
|
+
exports.description = description
|
|
11
|
+
|
|
12
|
+
exports.handler = (argv) => {
|
|
13
|
+
return new Promise((resolve, reject) => {
|
|
14
|
+
const verbose = argv.verbose
|
|
15
|
+
const context = argv.context
|
|
16
|
+
const logger = context.logger
|
|
17
|
+
const cwd = context.cwd
|
|
18
|
+
const staticPaths = context.staticPaths || {}
|
|
19
|
+
const appInfo = context.appInfo
|
|
20
|
+
const existsPackageJson = fs.existsSync(path.join(cwd, './package.json'))
|
|
21
|
+
let pathToApp
|
|
22
|
+
let serviceName
|
|
23
|
+
let customError
|
|
24
|
+
|
|
25
|
+
logger.info('Platform is ' + platform)
|
|
26
|
+
|
|
27
|
+
if (platform !== 'win32') {
|
|
28
|
+
logger.info('Unstalling windows service for app only works on windows platforms..')
|
|
29
|
+
|
|
30
|
+
return resolve({
|
|
31
|
+
uninstalled: false,
|
|
32
|
+
serviceName: null
|
|
33
|
+
})
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
if (!existsPackageJson && !appInfo) {
|
|
37
|
+
customError = new Error('To uninstall windows service for app you need a package.json file')
|
|
38
|
+
customError.cleanState = true
|
|
39
|
+
return reject(customError)
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
if (appInfo) {
|
|
43
|
+
if (!appInfo.path) {
|
|
44
|
+
customError = new Error('To uninstall windows service for app you need to pass "path" in appInfo')
|
|
45
|
+
customError.cleanState = true
|
|
46
|
+
return reject(customError)
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
pathToApp = appInfo.path
|
|
50
|
+
|
|
51
|
+
if (!appInfo.name) {
|
|
52
|
+
customError = new Error('To uninstall windows service for app you need to pass "name" in appInfo')
|
|
53
|
+
customError.cleanState = true
|
|
54
|
+
return reject(customError)
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
serviceName = appInfo.name
|
|
58
|
+
} else {
|
|
59
|
+
pathToApp = cwd
|
|
60
|
+
|
|
61
|
+
const userPkg = require(path.join(pathToApp, './package.json'))
|
|
62
|
+
|
|
63
|
+
if (!userPkg.name) {
|
|
64
|
+
customError = new Error('To uninstall windows service for app you need a "name" field in package.json file')
|
|
65
|
+
customError.cleanState = true
|
|
66
|
+
return reject(customError)
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
serviceName = userPkg.name
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
logger.info('Uninstalling windows service "' + serviceName + '".')
|
|
73
|
+
|
|
74
|
+
let winser
|
|
75
|
+
|
|
76
|
+
if (appInfo) {
|
|
77
|
+
winser = Winser({ silent: !verbose, nssmPath: staticPaths.nssm, app: appInfo })
|
|
78
|
+
} else {
|
|
79
|
+
winser = Winser({ silent: !verbose, nssmPath: staticPaths.nssm })
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
winser.remove({
|
|
83
|
+
path: pathToApp,
|
|
84
|
+
stop: true
|
|
85
|
+
}, (err) => {
|
|
86
|
+
if (err) {
|
|
87
|
+
const error = 'Error while trying to uninstall windows service'
|
|
88
|
+
error.originalError = err
|
|
89
|
+
return reject(error)
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
logger.info('Windows service "' + serviceName + '" uninstalled')
|
|
93
|
+
|
|
94
|
+
resolve({
|
|
95
|
+
uninstalled: true,
|
|
96
|
+
serviceName: serviceName
|
|
97
|
+
})
|
|
98
|
+
})
|
|
99
|
+
})
|
|
100
|
+
}
|
package/lib/daemonHandler.js
CHANGED
|
@@ -1,164 +1,164 @@
|
|
|
1
|
-
'use strict'
|
|
2
|
-
|
|
3
|
-
const util = require('util')
|
|
4
|
-
const path = require('path')
|
|
5
|
-
const fs = require('fs')
|
|
6
|
-
const nssocket = require('nssocket')
|
|
7
|
-
const lockfile = require('lockfile')
|
|
8
|
-
const getTempPaths = require('./getTempPaths')
|
|
9
|
-
const normalizeSocketPath = require('./normalizeSocketPath')
|
|
10
|
-
|
|
11
|
-
const lock = util.promisify(lockfile.lock.bind(lockfile))
|
|
12
|
-
const unlock = util.promisify(lockfile.unlock.bind(lockfile))
|
|
13
|
-
|
|
14
|
-
exports.findProcessByCWD = findProcessByCWD
|
|
15
|
-
exports.findProcessByUidOrPid = findProcessByUidOrPid
|
|
16
|
-
exports.getAllProcesses = getAllProcesses
|
|
17
|
-
exports.getSockets = getSockets
|
|
18
|
-
exports.kill = kill
|
|
19
|
-
|
|
20
|
-
async function findProcessByCWD (sockPath, cwd) {
|
|
21
|
-
const processes = await getAllProcesses(sockPath)
|
|
22
|
-
|
|
23
|
-
const procs = processes.filter((p) => {
|
|
24
|
-
return p.cwd === cwd
|
|
25
|
-
})
|
|
26
|
-
|
|
27
|
-
if (procs.length === 0) {
|
|
28
|
-
return null
|
|
29
|
-
}
|
|
30
|
-
|
|
31
|
-
return procs[0]
|
|
32
|
-
}
|
|
33
|
-
|
|
34
|
-
async function findProcessByUidOrPid (sockPath, id) {
|
|
35
|
-
const processes = await getAllProcesses(sockPath)
|
|
36
|
-
|
|
37
|
-
const procs = search([(p) => {
|
|
38
|
-
return p.uid === id
|
|
39
|
-
}, (p) => {
|
|
40
|
-
return String(p.pid) === String(id)
|
|
41
|
-
}])
|
|
42
|
-
|
|
43
|
-
if (procs.length === 0) {
|
|
44
|
-
return null
|
|
45
|
-
}
|
|
46
|
-
|
|
47
|
-
return procs[0]
|
|
48
|
-
|
|
49
|
-
function search (filters) {
|
|
50
|
-
let result = []
|
|
51
|
-
|
|
52
|
-
filters.forEach((filter) => {
|
|
53
|
-
if (result.length > 0) {
|
|
54
|
-
return
|
|
55
|
-
}
|
|
56
|
-
|
|
57
|
-
result = processes.filter(filter)
|
|
58
|
-
})
|
|
59
|
-
|
|
60
|
-
return result
|
|
61
|
-
}
|
|
62
|
-
}
|
|
63
|
-
|
|
64
|
-
async function kill (proc) {
|
|
65
|
-
const socketFile = proc.normalizedSocketFile
|
|
66
|
-
const lockfilePath = path.join(getTempPaths().cliPath, 'jsreport-keepAlive-kill.lock')
|
|
67
|
-
|
|
68
|
-
await lock(lockfilePath, {
|
|
69
|
-
stale: 3500,
|
|
70
|
-
retries: 30,
|
|
71
|
-
retryWait: 100
|
|
72
|
-
})
|
|
73
|
-
|
|
74
|
-
try {
|
|
75
|
-
await new Promise((resolve, reject) => {
|
|
76
|
-
const socket = new nssocket.NsSocket()
|
|
77
|
-
|
|
78
|
-
socket.connect(socketFile, (err) => {
|
|
79
|
-
if (err) {
|
|
80
|
-
return reject(err)
|
|
81
|
-
}
|
|
82
|
-
|
|
83
|
-
socket.send(['kill'], (err) => {
|
|
84
|
-
if (err) {
|
|
85
|
-
return reject(err)
|
|
86
|
-
}
|
|
87
|
-
|
|
88
|
-
resolve()
|
|
89
|
-
socket.end()
|
|
90
|
-
})
|
|
91
|
-
})
|
|
92
|
-
|
|
93
|
-
socket.on('close', () => {
|
|
94
|
-
// we only care to reject on close when there was no other event fired
|
|
95
|
-
// that resolved the promise.
|
|
96
|
-
// this can happen when we are in the middle of sending data and the socket
|
|
97
|
-
// was detroyed for some reason (like daemon process exit)
|
|
98
|
-
reject(new Error(`connection to socket "${socketFile}" was closed unexpectedly`))
|
|
99
|
-
})
|
|
100
|
-
|
|
101
|
-
socket.on('error', (err) => {
|
|
102
|
-
reject(err)
|
|
103
|
-
})
|
|
104
|
-
})
|
|
105
|
-
} finally {
|
|
106
|
-
await unlock(lockfilePath)
|
|
107
|
-
}
|
|
108
|
-
}
|
|
109
|
-
|
|
110
|
-
async function getAllProcesses (sockPath) {
|
|
111
|
-
const sockets = await getSockets(sockPath)
|
|
112
|
-
|
|
113
|
-
const processes = await Promise.all(sockets.map(async function getProcess (name) {
|
|
114
|
-
let fullPath = path.join(sockPath, name)
|
|
115
|
-
const socket = new nssocket.NsSocket()
|
|
116
|
-
|
|
117
|
-
fullPath = normalizeSocketPath(fullPath)
|
|
118
|
-
|
|
119
|
-
return new Promise((resolve, reject) => {
|
|
120
|
-
socket.connect(fullPath, (connectErr) => {
|
|
121
|
-
if (connectErr) {
|
|
122
|
-
return reject(connectErr)
|
|
123
|
-
}
|
|
124
|
-
|
|
125
|
-
socket.dataOnce(['info'], (info) => {
|
|
126
|
-
resolve(info)
|
|
127
|
-
socket.end()
|
|
128
|
-
})
|
|
129
|
-
|
|
130
|
-
socket.send(['info'], (err) => {
|
|
131
|
-
if (err) {
|
|
132
|
-
return resolve()
|
|
133
|
-
}
|
|
134
|
-
})
|
|
135
|
-
})
|
|
136
|
-
|
|
137
|
-
socket.on('close', () => {
|
|
138
|
-
resolve()
|
|
139
|
-
})
|
|
140
|
-
|
|
141
|
-
socket.on('error', (err) => {
|
|
142
|
-
if (err.code === 'ECONNREFUSED') {
|
|
143
|
-
try {
|
|
144
|
-
fs.unlinkSync(fullPath)
|
|
145
|
-
} catch (e) {}
|
|
146
|
-
|
|
147
|
-
resolve()
|
|
148
|
-
} else {
|
|
149
|
-
resolve()
|
|
150
|
-
}
|
|
151
|
-
})
|
|
152
|
-
})
|
|
153
|
-
}))
|
|
154
|
-
|
|
155
|
-
return processes.filter(Boolean)
|
|
156
|
-
}
|
|
157
|
-
|
|
158
|
-
async function getSockets (sockPath) {
|
|
159
|
-
let sockets = []
|
|
160
|
-
|
|
161
|
-
sockets = fs.readdirSync(sockPath)
|
|
162
|
-
|
|
163
|
-
return sockets
|
|
164
|
-
}
|
|
1
|
+
'use strict'
|
|
2
|
+
|
|
3
|
+
const util = require('util')
|
|
4
|
+
const path = require('path')
|
|
5
|
+
const fs = require('fs')
|
|
6
|
+
const nssocket = require('nssocket')
|
|
7
|
+
const lockfile = require('lockfile')
|
|
8
|
+
const getTempPaths = require('./utils/getTempPaths')
|
|
9
|
+
const normalizeSocketPath = require('./utils/normalizeSocketPath')
|
|
10
|
+
|
|
11
|
+
const lock = util.promisify(lockfile.lock.bind(lockfile))
|
|
12
|
+
const unlock = util.promisify(lockfile.unlock.bind(lockfile))
|
|
13
|
+
|
|
14
|
+
exports.findProcessByCWD = findProcessByCWD
|
|
15
|
+
exports.findProcessByUidOrPid = findProcessByUidOrPid
|
|
16
|
+
exports.getAllProcesses = getAllProcesses
|
|
17
|
+
exports.getSockets = getSockets
|
|
18
|
+
exports.kill = kill
|
|
19
|
+
|
|
20
|
+
async function findProcessByCWD (sockPath, cwd) {
|
|
21
|
+
const processes = await getAllProcesses(sockPath)
|
|
22
|
+
|
|
23
|
+
const procs = processes.filter((p) => {
|
|
24
|
+
return p.cwd === cwd
|
|
25
|
+
})
|
|
26
|
+
|
|
27
|
+
if (procs.length === 0) {
|
|
28
|
+
return null
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
return procs[0]
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
async function findProcessByUidOrPid (sockPath, id) {
|
|
35
|
+
const processes = await getAllProcesses(sockPath)
|
|
36
|
+
|
|
37
|
+
const procs = search([(p) => {
|
|
38
|
+
return p.uid === id
|
|
39
|
+
}, (p) => {
|
|
40
|
+
return String(p.pid) === String(id)
|
|
41
|
+
}])
|
|
42
|
+
|
|
43
|
+
if (procs.length === 0) {
|
|
44
|
+
return null
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
return procs[0]
|
|
48
|
+
|
|
49
|
+
function search (filters) {
|
|
50
|
+
let result = []
|
|
51
|
+
|
|
52
|
+
filters.forEach((filter) => {
|
|
53
|
+
if (result.length > 0) {
|
|
54
|
+
return
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
result = processes.filter(filter)
|
|
58
|
+
})
|
|
59
|
+
|
|
60
|
+
return result
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
async function kill (proc) {
|
|
65
|
+
const socketFile = proc.normalizedSocketFile
|
|
66
|
+
const lockfilePath = path.join(getTempPaths().cliPath, 'jsreport-keepAlive-kill.lock')
|
|
67
|
+
|
|
68
|
+
await lock(lockfilePath, {
|
|
69
|
+
stale: 3500,
|
|
70
|
+
retries: 30,
|
|
71
|
+
retryWait: 100
|
|
72
|
+
})
|
|
73
|
+
|
|
74
|
+
try {
|
|
75
|
+
await new Promise((resolve, reject) => {
|
|
76
|
+
const socket = new nssocket.NsSocket()
|
|
77
|
+
|
|
78
|
+
socket.connect(socketFile, (err) => {
|
|
79
|
+
if (err) {
|
|
80
|
+
return reject(err)
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
socket.send(['kill'], (err) => {
|
|
84
|
+
if (err) {
|
|
85
|
+
return reject(err)
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
resolve()
|
|
89
|
+
socket.end()
|
|
90
|
+
})
|
|
91
|
+
})
|
|
92
|
+
|
|
93
|
+
socket.on('close', () => {
|
|
94
|
+
// we only care to reject on close when there was no other event fired
|
|
95
|
+
// that resolved the promise.
|
|
96
|
+
// this can happen when we are in the middle of sending data and the socket
|
|
97
|
+
// was detroyed for some reason (like daemon process exit)
|
|
98
|
+
reject(new Error(`connection to socket "${socketFile}" was closed unexpectedly`))
|
|
99
|
+
})
|
|
100
|
+
|
|
101
|
+
socket.on('error', (err) => {
|
|
102
|
+
reject(err)
|
|
103
|
+
})
|
|
104
|
+
})
|
|
105
|
+
} finally {
|
|
106
|
+
await unlock(lockfilePath)
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
async function getAllProcesses (sockPath) {
|
|
111
|
+
const sockets = await getSockets(sockPath)
|
|
112
|
+
|
|
113
|
+
const processes = await Promise.all(sockets.map(async function getProcess (name) {
|
|
114
|
+
let fullPath = path.join(sockPath, name)
|
|
115
|
+
const socket = new nssocket.NsSocket()
|
|
116
|
+
|
|
117
|
+
fullPath = normalizeSocketPath(fullPath)
|
|
118
|
+
|
|
119
|
+
return new Promise((resolve, reject) => {
|
|
120
|
+
socket.connect(fullPath, (connectErr) => {
|
|
121
|
+
if (connectErr) {
|
|
122
|
+
return reject(connectErr)
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
socket.dataOnce(['info'], (info) => {
|
|
126
|
+
resolve(info)
|
|
127
|
+
socket.end()
|
|
128
|
+
})
|
|
129
|
+
|
|
130
|
+
socket.send(['info'], (err) => {
|
|
131
|
+
if (err) {
|
|
132
|
+
return resolve()
|
|
133
|
+
}
|
|
134
|
+
})
|
|
135
|
+
})
|
|
136
|
+
|
|
137
|
+
socket.on('close', () => {
|
|
138
|
+
resolve()
|
|
139
|
+
})
|
|
140
|
+
|
|
141
|
+
socket.on('error', (err) => {
|
|
142
|
+
if (err.code === 'ECONNREFUSED') {
|
|
143
|
+
try {
|
|
144
|
+
fs.unlinkSync(fullPath)
|
|
145
|
+
} catch (e) {}
|
|
146
|
+
|
|
147
|
+
resolve()
|
|
148
|
+
} else {
|
|
149
|
+
resolve()
|
|
150
|
+
}
|
|
151
|
+
})
|
|
152
|
+
})
|
|
153
|
+
}))
|
|
154
|
+
|
|
155
|
+
return processes.filter(Boolean)
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
async function getSockets (sockPath) {
|
|
159
|
+
let sockets = []
|
|
160
|
+
|
|
161
|
+
sockets = fs.readdirSync(sockPath)
|
|
162
|
+
|
|
163
|
+
return sockets
|
|
164
|
+
}
|