@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
package/lib/daemonInstance.js
CHANGED
|
@@ -1,225 +1,225 @@
|
|
|
1
|
-
'use strict'
|
|
2
|
-
|
|
3
|
-
const fs = require('fs')
|
|
4
|
-
const HttpsServer = require('https').Server
|
|
5
|
-
const ipAddress = require('ip-address')
|
|
6
|
-
const nssocket = require('nssocket')
|
|
7
|
-
const
|
|
8
|
-
const
|
|
9
|
-
const
|
|
10
|
-
|
|
11
|
-
const PID = process.pid
|
|
12
|
-
|
|
13
|
-
let socketServer
|
|
14
|
-
|
|
15
|
-
function start (customInstance, socketFile) {
|
|
16
|
-
const socketToMaster = new nssocket.NsSocket()
|
|
17
|
-
let parentSocketFile
|
|
18
|
-
let processInfo
|
|
19
|
-
let reporterInstance
|
|
20
|
-
|
|
21
|
-
console.log('PID of daemon instance:', PID)
|
|
22
|
-
|
|
23
|
-
if (socketFile) {
|
|
24
|
-
parentSocketFile = socketFile
|
|
25
|
-
} else {
|
|
26
|
-
parentSocketFile = process.argv[2]
|
|
27
|
-
}
|
|
28
|
-
|
|
29
|
-
// connect to parent socket for parent-child communication
|
|
30
|
-
socketToMaster.connect(parentSocketFile, (err) => {
|
|
31
|
-
// in case of connection error exit the process immediately
|
|
32
|
-
// to notify parent
|
|
33
|
-
if (err) {
|
|
34
|
-
return process.exit(1)
|
|
35
|
-
}
|
|
36
|
-
|
|
37
|
-
// parent process will pass options in the "init" event
|
|
38
|
-
socketToMaster.dataOnce(['init'], (options) => {
|
|
39
|
-
const sockPath = options.sockPath
|
|
40
|
-
const cwd = options.cwd
|
|
41
|
-
const verbose = options.verbose
|
|
42
|
-
let getInstanceAsync
|
|
43
|
-
|
|
44
|
-
if (customInstance) {
|
|
45
|
-
getInstanceAsync = Promise.resolve({
|
|
46
|
-
instance: typeof customInstance === 'function' ? customInstance() : customInstance
|
|
47
|
-
})
|
|
48
|
-
} else {
|
|
49
|
-
getInstanceAsync = instanceHandler.find(cwd)
|
|
50
|
-
}
|
|
51
|
-
|
|
52
|
-
// find and initialize a jsreport instance
|
|
53
|
-
getInstanceAsync
|
|
54
|
-
.then((instanceInfo) => {
|
|
55
|
-
return instanceHandler.initialize(instanceInfo.instance, verbose)
|
|
56
|
-
})
|
|
57
|
-
.then((instance) => {
|
|
58
|
-
let adminAuthentication
|
|
59
|
-
let jsreportServer
|
|
60
|
-
let address
|
|
61
|
-
let hostname
|
|
62
|
-
let protocol
|
|
63
|
-
let appPath
|
|
64
|
-
|
|
65
|
-
reporterInstance = instance
|
|
66
|
-
|
|
67
|
-
if (
|
|
68
|
-
instance.options.extensions &&
|
|
69
|
-
instance.options.extensions.authentication &&
|
|
70
|
-
instance.options.extensions.authentication.admin
|
|
71
|
-
) {
|
|
72
|
-
adminAuthentication = instance.options.extensions.authentication.admin
|
|
73
|
-
}
|
|
74
|
-
|
|
75
|
-
if (instance.express && instance.express.server) {
|
|
76
|
-
jsreportServer = instance.express.server
|
|
77
|
-
address = jsreportServer.address()
|
|
78
|
-
} else {
|
|
79
|
-
throw new Error(
|
|
80
|
-
'jsreport instance detected does not have jsreport-express extension enabled, ' +
|
|
81
|
-
'either install or enable it first to use keepAlive option'
|
|
82
|
-
)
|
|
83
|
-
}
|
|
84
|
-
|
|
85
|
-
appPath = instance.options.appPath || ''
|
|
86
|
-
|
|
87
|
-
if (appPath === '/') {
|
|
88
|
-
appPath = ''
|
|
89
|
-
}
|
|
90
|
-
|
|
91
|
-
// normalizing ipv6 to ipv4
|
|
92
|
-
if (address.family === 'IPv6') {
|
|
93
|
-
hostname = new ipAddress.Address6(address.address).to4()
|
|
94
|
-
|
|
95
|
-
if (typeof hostname !== 'string') {
|
|
96
|
-
hostname = hostname.address
|
|
97
|
-
}
|
|
98
|
-
} else {
|
|
99
|
-
hostname = address.address
|
|
100
|
-
}
|
|
101
|
-
|
|
102
|
-
// normalizing host, on windows connecting to "0.0.0.0" doesn't work
|
|
103
|
-
if (hostname === '0.0.0.0') {
|
|
104
|
-
hostname = 'localhost'
|
|
105
|
-
}
|
|
106
|
-
|
|
107
|
-
if (jsreportServer instanceof HttpsServer) {
|
|
108
|
-
protocol = 'https'
|
|
109
|
-
} else {
|
|
110
|
-
protocol = 'http'
|
|
111
|
-
}
|
|
112
|
-
|
|
113
|
-
const urlToServer = `${protocol}://${hostname}:${address.port}/${appPath}`
|
|
114
|
-
|
|
115
|
-
// starting a server in a new socket to allow the monitoring
|
|
116
|
-
// and query of this process from the CLI
|
|
117
|
-
socketServer = startSocketServer({
|
|
118
|
-
socketPath: sockPath,
|
|
119
|
-
socketPrefix: 'm',
|
|
120
|
-
// Create 'symbolic' file on the system, so it can be later
|
|
121
|
-
// found, since the `\\.pipe\\*` "files" can't
|
|
122
|
-
// be enumerated because ... Windows.
|
|
123
|
-
createSymbolicForSocket: process.platform === 'win32',
|
|
124
|
-
protocol: monitorProtocol
|
|
125
|
-
}, (socketInitErr, serverInfo) => {
|
|
126
|
-
if (socketInitErr) {
|
|
127
|
-
return socketToMaster.send(['init'], {
|
|
128
|
-
error: socketInitErr.message,
|
|
129
|
-
stacks:
|
|
130
|
-
})
|
|
131
|
-
}
|
|
132
|
-
|
|
133
|
-
// collecting all the information about this process
|
|
134
|
-
// for later queries
|
|
135
|
-
processInfo = {
|
|
136
|
-
uid: serverInfo.uid,
|
|
137
|
-
pid: PID,
|
|
138
|
-
cwd: cwd,
|
|
139
|
-
version: instance.version,
|
|
140
|
-
socketFile: serverInfo.socketFile,
|
|
141
|
-
normalizedSocketFile: serverInfo.normalizedSocketFile,
|
|
142
|
-
url: urlToServer,
|
|
143
|
-
adminAuthentication: adminAuthentication
|
|
144
|
-
}
|
|
145
|
-
|
|
146
|
-
socketToMaster.send(['init'], Object.assign({}, processInfo, { error: null }))
|
|
147
|
-
})
|
|
148
|
-
})
|
|
149
|
-
.catch((err) => {
|
|
150
|
-
const meta = {}
|
|
151
|
-
|
|
152
|
-
if (err.code != null) {
|
|
153
|
-
meta.code = err.code
|
|
154
|
-
}
|
|
155
|
-
|
|
156
|
-
socketToMaster.send(['init'], {
|
|
157
|
-
error: err.message,
|
|
158
|
-
stacks:
|
|
159
|
-
meta: Object.keys(meta).length > 0 ? meta : undefined
|
|
160
|
-
})
|
|
161
|
-
|
|
162
|
-
setImmediate(() => {
|
|
163
|
-
process.exit(1)
|
|
164
|
-
})
|
|
165
|
-
})
|
|
166
|
-
})
|
|
167
|
-
|
|
168
|
-
socketToMaster.send(['alive'])
|
|
169
|
-
})
|
|
170
|
-
|
|
171
|
-
socketToMaster.on('error', (err) => {
|
|
172
|
-
if (err.code === 'ECONNREFUSED') {
|
|
173
|
-
try {
|
|
174
|
-
fs.unlinkSync(parentSocketFile)
|
|
175
|
-
} catch (e) {}
|
|
176
|
-
}
|
|
177
|
-
|
|
178
|
-
process.exit(1)
|
|
179
|
-
})
|
|
180
|
-
|
|
181
|
-
function monitorProtocol (socket) {
|
|
182
|
-
socket.on('error', (err) => {
|
|
183
|
-
console.error('socket error:', err)
|
|
184
|
-
socket.destroy()
|
|
185
|
-
})
|
|
186
|
-
|
|
187
|
-
socket.data(['info'], () => {
|
|
188
|
-
socket.send(['info'], processInfo)
|
|
189
|
-
})
|
|
190
|
-
|
|
191
|
-
socket.data(['kill'], () => {
|
|
192
|
-
if (process.platform === 'win32') {
|
|
193
|
-
//
|
|
194
|
-
// On Windows, delete the 'symbolic' sock file. This
|
|
195
|
-
// file is used for exploration as a mapping to the
|
|
196
|
-
// `\\.pipe\\*` "files" that can't
|
|
197
|
-
// be enumerated because ... Windows.
|
|
198
|
-
//
|
|
199
|
-
try {
|
|
200
|
-
fs.unlinkSync(processInfo.socketFile)
|
|
201
|
-
} catch (e) {}
|
|
202
|
-
}
|
|
203
|
-
|
|
204
|
-
// close the server to prevent accepting new connections,
|
|
205
|
-
// such situation can happen when doing concurrent calls to kill the server
|
|
206
|
-
if (socketServer) {
|
|
207
|
-
socketServer.close()
|
|
208
|
-
}
|
|
209
|
-
|
|
210
|
-
const exit = () => process.exit()
|
|
211
|
-
|
|
212
|
-
if (reporterInstance) {
|
|
213
|
-
reporterInstance.close().then(exit, exit)
|
|
214
|
-
} else {
|
|
215
|
-
exit()
|
|
216
|
-
}
|
|
217
|
-
})
|
|
218
|
-
}
|
|
219
|
-
}
|
|
220
|
-
|
|
221
|
-
if (require.main === module) {
|
|
222
|
-
start()
|
|
223
|
-
} else {
|
|
224
|
-
module.exports = start
|
|
225
|
-
}
|
|
1
|
+
'use strict'
|
|
2
|
+
|
|
3
|
+
const fs = require('fs')
|
|
4
|
+
const HttpsServer = require('https').Server
|
|
5
|
+
const ipAddress = require('ip-address')
|
|
6
|
+
const nssocket = require('nssocket')
|
|
7
|
+
const instanceHandler = require('./instanceHandler')
|
|
8
|
+
const startSocketServer = require('./utils/startSocketServer')
|
|
9
|
+
const { getErrors } = require('./utils/error')
|
|
10
|
+
|
|
11
|
+
const PID = process.pid
|
|
12
|
+
|
|
13
|
+
let socketServer
|
|
14
|
+
|
|
15
|
+
function start (customInstance, socketFile) {
|
|
16
|
+
const socketToMaster = new nssocket.NsSocket()
|
|
17
|
+
let parentSocketFile
|
|
18
|
+
let processInfo
|
|
19
|
+
let reporterInstance
|
|
20
|
+
|
|
21
|
+
console.log('PID of daemon instance:', PID)
|
|
22
|
+
|
|
23
|
+
if (socketFile) {
|
|
24
|
+
parentSocketFile = socketFile
|
|
25
|
+
} else {
|
|
26
|
+
parentSocketFile = process.argv[2]
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
// connect to parent socket for parent-child communication
|
|
30
|
+
socketToMaster.connect(parentSocketFile, (err) => {
|
|
31
|
+
// in case of connection error exit the process immediately
|
|
32
|
+
// to notify parent
|
|
33
|
+
if (err) {
|
|
34
|
+
return process.exit(1)
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
// parent process will pass options in the "init" event
|
|
38
|
+
socketToMaster.dataOnce(['init'], (options) => {
|
|
39
|
+
const sockPath = options.sockPath
|
|
40
|
+
const cwd = options.cwd
|
|
41
|
+
const verbose = options.verbose
|
|
42
|
+
let getInstanceAsync
|
|
43
|
+
|
|
44
|
+
if (customInstance) {
|
|
45
|
+
getInstanceAsync = Promise.resolve({
|
|
46
|
+
instance: typeof customInstance === 'function' ? customInstance() : customInstance
|
|
47
|
+
})
|
|
48
|
+
} else {
|
|
49
|
+
getInstanceAsync = instanceHandler.find(cwd)
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
// find and initialize a jsreport instance
|
|
53
|
+
getInstanceAsync
|
|
54
|
+
.then((instanceInfo) => {
|
|
55
|
+
return instanceHandler.initialize(instanceInfo.instance, verbose)
|
|
56
|
+
})
|
|
57
|
+
.then((instance) => {
|
|
58
|
+
let adminAuthentication
|
|
59
|
+
let jsreportServer
|
|
60
|
+
let address
|
|
61
|
+
let hostname
|
|
62
|
+
let protocol
|
|
63
|
+
let appPath
|
|
64
|
+
|
|
65
|
+
reporterInstance = instance
|
|
66
|
+
|
|
67
|
+
if (
|
|
68
|
+
instance.options.extensions &&
|
|
69
|
+
instance.options.extensions.authentication &&
|
|
70
|
+
instance.options.extensions.authentication.admin
|
|
71
|
+
) {
|
|
72
|
+
adminAuthentication = instance.options.extensions.authentication.admin
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
if (instance.express && instance.express.server) {
|
|
76
|
+
jsreportServer = instance.express.server
|
|
77
|
+
address = jsreportServer.address()
|
|
78
|
+
} else {
|
|
79
|
+
throw new Error(
|
|
80
|
+
'jsreport instance detected does not have jsreport-express extension enabled, ' +
|
|
81
|
+
'either install or enable it first to use keepAlive option'
|
|
82
|
+
)
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
appPath = instance.options.appPath || ''
|
|
86
|
+
|
|
87
|
+
if (appPath === '/') {
|
|
88
|
+
appPath = ''
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
// normalizing ipv6 to ipv4
|
|
92
|
+
if (address.family === 'IPv6') {
|
|
93
|
+
hostname = new ipAddress.Address6(address.address).to4()
|
|
94
|
+
|
|
95
|
+
if (typeof hostname !== 'string') {
|
|
96
|
+
hostname = hostname.address
|
|
97
|
+
}
|
|
98
|
+
} else {
|
|
99
|
+
hostname = address.address
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
// normalizing host, on windows connecting to "0.0.0.0" doesn't work
|
|
103
|
+
if (hostname === '0.0.0.0') {
|
|
104
|
+
hostname = 'localhost'
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
if (jsreportServer instanceof HttpsServer) {
|
|
108
|
+
protocol = 'https'
|
|
109
|
+
} else {
|
|
110
|
+
protocol = 'http'
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
const urlToServer = `${protocol}://${hostname}:${address.port}/${appPath}`
|
|
114
|
+
|
|
115
|
+
// starting a server in a new socket to allow the monitoring
|
|
116
|
+
// and query of this process from the CLI
|
|
117
|
+
socketServer = startSocketServer({
|
|
118
|
+
socketPath: sockPath,
|
|
119
|
+
socketPrefix: 'm',
|
|
120
|
+
// Create 'symbolic' file on the system, so it can be later
|
|
121
|
+
// found, since the `\\.pipe\\*` "files" can't
|
|
122
|
+
// be enumerated because ... Windows.
|
|
123
|
+
createSymbolicForSocket: process.platform === 'win32',
|
|
124
|
+
protocol: monitorProtocol
|
|
125
|
+
}, (socketInitErr, serverInfo) => {
|
|
126
|
+
if (socketInitErr) {
|
|
127
|
+
return socketToMaster.send(['init'], {
|
|
128
|
+
error: socketInitErr.message,
|
|
129
|
+
stacks: getErrors(socketInitErr).map(e => e.stack)
|
|
130
|
+
})
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
// collecting all the information about this process
|
|
134
|
+
// for later queries
|
|
135
|
+
processInfo = {
|
|
136
|
+
uid: serverInfo.uid,
|
|
137
|
+
pid: PID,
|
|
138
|
+
cwd: cwd,
|
|
139
|
+
version: instance.version,
|
|
140
|
+
socketFile: serverInfo.socketFile,
|
|
141
|
+
normalizedSocketFile: serverInfo.normalizedSocketFile,
|
|
142
|
+
url: urlToServer,
|
|
143
|
+
adminAuthentication: adminAuthentication
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
socketToMaster.send(['init'], Object.assign({}, processInfo, { error: null }))
|
|
147
|
+
})
|
|
148
|
+
})
|
|
149
|
+
.catch((err) => {
|
|
150
|
+
const meta = {}
|
|
151
|
+
|
|
152
|
+
if (err.code != null) {
|
|
153
|
+
meta.code = err.code
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
socketToMaster.send(['init'], {
|
|
157
|
+
error: err.message,
|
|
158
|
+
stacks: getErrors(err).map(e => e.stack),
|
|
159
|
+
meta: Object.keys(meta).length > 0 ? meta : undefined
|
|
160
|
+
})
|
|
161
|
+
|
|
162
|
+
setImmediate(() => {
|
|
163
|
+
process.exit(1)
|
|
164
|
+
})
|
|
165
|
+
})
|
|
166
|
+
})
|
|
167
|
+
|
|
168
|
+
socketToMaster.send(['alive'])
|
|
169
|
+
})
|
|
170
|
+
|
|
171
|
+
socketToMaster.on('error', (err) => {
|
|
172
|
+
if (err.code === 'ECONNREFUSED') {
|
|
173
|
+
try {
|
|
174
|
+
fs.unlinkSync(parentSocketFile)
|
|
175
|
+
} catch (e) {}
|
|
176
|
+
}
|
|
177
|
+
|
|
178
|
+
process.exit(1)
|
|
179
|
+
})
|
|
180
|
+
|
|
181
|
+
function monitorProtocol (socket) {
|
|
182
|
+
socket.on('error', (err) => {
|
|
183
|
+
console.error('socket error:', err)
|
|
184
|
+
socket.destroy()
|
|
185
|
+
})
|
|
186
|
+
|
|
187
|
+
socket.data(['info'], () => {
|
|
188
|
+
socket.send(['info'], processInfo)
|
|
189
|
+
})
|
|
190
|
+
|
|
191
|
+
socket.data(['kill'], () => {
|
|
192
|
+
if (process.platform === 'win32') {
|
|
193
|
+
//
|
|
194
|
+
// On Windows, delete the 'symbolic' sock file. This
|
|
195
|
+
// file is used for exploration as a mapping to the
|
|
196
|
+
// `\\.pipe\\*` "files" that can't
|
|
197
|
+
// be enumerated because ... Windows.
|
|
198
|
+
//
|
|
199
|
+
try {
|
|
200
|
+
fs.unlinkSync(processInfo.socketFile)
|
|
201
|
+
} catch (e) {}
|
|
202
|
+
}
|
|
203
|
+
|
|
204
|
+
// close the server to prevent accepting new connections,
|
|
205
|
+
// such situation can happen when doing concurrent calls to kill the server
|
|
206
|
+
if (socketServer) {
|
|
207
|
+
socketServer.close()
|
|
208
|
+
}
|
|
209
|
+
|
|
210
|
+
const exit = () => process.exit()
|
|
211
|
+
|
|
212
|
+
if (reporterInstance) {
|
|
213
|
+
reporterInstance.close().then(exit, exit)
|
|
214
|
+
} else {
|
|
215
|
+
exit()
|
|
216
|
+
}
|
|
217
|
+
})
|
|
218
|
+
}
|
|
219
|
+
}
|
|
220
|
+
|
|
221
|
+
if (require.main === module) {
|
|
222
|
+
start()
|
|
223
|
+
} else {
|
|
224
|
+
module.exports = start
|
|
225
|
+
}
|
|
@@ -1,74 +1,74 @@
|
|
|
1
|
-
'use strict'
|
|
2
|
-
|
|
3
|
-
const util = require('util')
|
|
4
|
-
const path = require('path')
|
|
5
|
-
const fs = require('fs')
|
|
6
|
-
const { addStack } = require('./
|
|
7
|
-
const accessAsync = util.promisify(fs.access)
|
|
8
|
-
|
|
9
|
-
module.exports = async (extensions, commander) => {
|
|
10
|
-
const results = []
|
|
11
|
-
|
|
12
|
-
await Promise.all(extensions.map(async (ext) => {
|
|
13
|
-
try {
|
|
14
|
-
const extCliPath = path.join(ext.directory, 'cli/main.js')
|
|
15
|
-
let extCliExport
|
|
16
|
-
|
|
17
|
-
if (ext.cliModule === false) {
|
|
18
|
-
return
|
|
19
|
-
}
|
|
20
|
-
|
|
21
|
-
if (ext.cliModule) {
|
|
22
|
-
extCliExport = ext.cliModule
|
|
23
|
-
} else {
|
|
24
|
-
let hasCli = false
|
|
25
|
-
|
|
26
|
-
try {
|
|
27
|
-
await accessAsync(extCliPath)
|
|
28
|
-
hasCli = true
|
|
29
|
-
} catch (e) {}
|
|
30
|
-
|
|
31
|
-
if (!hasCli) {
|
|
32
|
-
return
|
|
33
|
-
}
|
|
34
|
-
|
|
35
|
-
extCliExport = require(extCliPath)
|
|
36
|
-
}
|
|
37
|
-
|
|
38
|
-
if (!extCliExport) {
|
|
39
|
-
return
|
|
40
|
-
}
|
|
41
|
-
|
|
42
|
-
if (Array.isArray(extCliExport)) {
|
|
43
|
-
results.push({
|
|
44
|
-
extension: ext.name,
|
|
45
|
-
cliModulePath: extCliPath,
|
|
46
|
-
commands: extCliExport
|
|
47
|
-
})
|
|
48
|
-
|
|
49
|
-
extCliExport.forEach((commandModule) => commander.registerCommand(commandModule))
|
|
50
|
-
} else {
|
|
51
|
-
results.push({
|
|
52
|
-
extension: ext.name,
|
|
53
|
-
cliModulePath: extCliPath,
|
|
54
|
-
commands: [extCliExport]
|
|
55
|
-
})
|
|
56
|
-
|
|
57
|
-
commander.registerCommand(extCliExport)
|
|
58
|
-
}
|
|
59
|
-
} catch (e) {
|
|
60
|
-
const err = new Error(e.message)
|
|
61
|
-
|
|
62
|
-
addStack(err, e.stack, {
|
|
63
|
-
stackPrefix: 'Register Command Error stack: ',
|
|
64
|
-
stripMessage: true
|
|
65
|
-
})
|
|
66
|
-
|
|
67
|
-
err.message = `Error while trying to register cli command in extension "${ext.name}". reason: ${err.message}`
|
|
68
|
-
|
|
69
|
-
throw err
|
|
70
|
-
}
|
|
71
|
-
}))
|
|
72
|
-
|
|
73
|
-
return results
|
|
74
|
-
}
|
|
1
|
+
'use strict'
|
|
2
|
+
|
|
3
|
+
const util = require('util')
|
|
4
|
+
const path = require('path')
|
|
5
|
+
const fs = require('fs')
|
|
6
|
+
const { addStack } = require('./utils/error')
|
|
7
|
+
const accessAsync = util.promisify(fs.access)
|
|
8
|
+
|
|
9
|
+
module.exports = async (extensions, commander) => {
|
|
10
|
+
const results = []
|
|
11
|
+
|
|
12
|
+
await Promise.all(extensions.map(async (ext) => {
|
|
13
|
+
try {
|
|
14
|
+
const extCliPath = path.join(ext.directory, 'cli/main.js')
|
|
15
|
+
let extCliExport
|
|
16
|
+
|
|
17
|
+
if (ext.cliModule === false) {
|
|
18
|
+
return
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
if (ext.cliModule) {
|
|
22
|
+
extCliExport = ext.cliModule
|
|
23
|
+
} else {
|
|
24
|
+
let hasCli = false
|
|
25
|
+
|
|
26
|
+
try {
|
|
27
|
+
await accessAsync(extCliPath)
|
|
28
|
+
hasCli = true
|
|
29
|
+
} catch (e) {}
|
|
30
|
+
|
|
31
|
+
if (!hasCli) {
|
|
32
|
+
return
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
extCliExport = require(extCliPath)
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
if (!extCliExport) {
|
|
39
|
+
return
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
if (Array.isArray(extCliExport)) {
|
|
43
|
+
results.push({
|
|
44
|
+
extension: ext.name,
|
|
45
|
+
cliModulePath: extCliPath,
|
|
46
|
+
commands: extCliExport
|
|
47
|
+
})
|
|
48
|
+
|
|
49
|
+
extCliExport.forEach((commandModule) => commander.registerCommand(commandModule))
|
|
50
|
+
} else {
|
|
51
|
+
results.push({
|
|
52
|
+
extension: ext.name,
|
|
53
|
+
cliModulePath: extCliPath,
|
|
54
|
+
commands: [extCliExport]
|
|
55
|
+
})
|
|
56
|
+
|
|
57
|
+
commander.registerCommand(extCliExport)
|
|
58
|
+
}
|
|
59
|
+
} catch (e) {
|
|
60
|
+
const err = new Error(e.message)
|
|
61
|
+
|
|
62
|
+
addStack(err, e.stack, {
|
|
63
|
+
stackPrefix: 'Register Command Error stack: ',
|
|
64
|
+
stripMessage: true
|
|
65
|
+
})
|
|
66
|
+
|
|
67
|
+
err.message = `Error while trying to register cli command in extension "${ext.name}". reason: ${err.message}`
|
|
68
|
+
|
|
69
|
+
throw err
|
|
70
|
+
}
|
|
71
|
+
}))
|
|
72
|
+
|
|
73
|
+
return results
|
|
74
|
+
}
|