@iobroker/js-controller-cli 4.0.0-alpha.9-20211115-5dac659e → 4.0.3
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 +1 -1
- package/README.md +1 -1
- package/index.js +10 -10
- package/lib/cli/cliCert.js +13 -7
- package/lib/cli/cliCompact.js +22 -8
- package/lib/cli/cliDebug.js +35 -9
- package/lib/cli/cliHost.js +17 -25
- package/lib/cli/cliLogs.js +5 -14
- package/lib/cli/cliMessage.js +3 -11
- package/lib/cli/cliObjects.js +162 -28
- package/lib/cli/cliPlugin.js +120 -175
- package/lib/cli/cliProcess.js +22 -14
- package/lib/cli/cliStates.js +179 -45
- package/lib/cli/cliTools.js +3 -4
- package/lib/cli/messages.js +55 -64
- package/lib/setup/setupList.js +309 -199
- package/package.json +8 -7
package/lib/cli/cliProcess.js
CHANGED
|
@@ -8,14 +8,13 @@ const dbTools = require('@iobroker/js-controller-common-db').tools;
|
|
|
8
8
|
const deepClone = require('deep-clone');
|
|
9
9
|
const { EXIT_CODES } = require('@iobroker/js-controller-common');
|
|
10
10
|
|
|
11
|
-
const { getObjectFrom, getInstanceName, normalizeAdapterName, enumInstances} = require('./cliTools.js');
|
|
11
|
+
const { getObjectFrom, getInstanceName, normalizeAdapterName, enumInstances } = require('./cliTools.js');
|
|
12
12
|
|
|
13
13
|
// The root of this project. Change this when moving code to another directory
|
|
14
14
|
const rootDir = tools.getControllerDir();
|
|
15
15
|
const killAllScriptPath = path.join(rootDir, 'killall.sh');
|
|
16
16
|
|
|
17
17
|
module.exports = class CLIProcess extends CLICommand {
|
|
18
|
-
|
|
19
18
|
/** @param {import('./cliCommand').CLICommandOptions} options */
|
|
20
19
|
constructor(options) {
|
|
21
20
|
super(options);
|
|
@@ -62,7 +61,7 @@ module.exports = class CLIProcess extends CLICommand {
|
|
|
62
61
|
*/
|
|
63
62
|
stop(args) {
|
|
64
63
|
const adapterName = normalizeAdapterName(args[0]);
|
|
65
|
-
if (adapterName === undefined
|
|
64
|
+
if (adapterName === undefined) {
|
|
66
65
|
this.stopJSController();
|
|
67
66
|
} else if (adapterName === 'all') {
|
|
68
67
|
this.setAllAdaptersEnabled(false);
|
|
@@ -99,7 +98,7 @@ module.exports = class CLIProcess extends CLICommand {
|
|
|
99
98
|
* @param {boolean} [restartIfRunning=false] Whether running instances should be restarted
|
|
100
99
|
*/
|
|
101
100
|
setAdapterEnabled(adapter, enabled, restartIfRunning) {
|
|
102
|
-
const {callback, dbConnect} = this.options;
|
|
101
|
+
const { callback, dbConnect } = this.options;
|
|
103
102
|
dbConnect(async objects => {
|
|
104
103
|
// Due to the many return locations we cannot simply chain the promises here
|
|
105
104
|
// Use the pre-Node8 async/await pattern
|
|
@@ -108,7 +107,10 @@ module.exports = class CLIProcess extends CLICommand {
|
|
|
108
107
|
const adapterInstances = await enumInstances(objects, adapter);
|
|
109
108
|
// If there are multiple instances for this adapter, ask the user to specify which one
|
|
110
109
|
if (adapterInstances.length > 1) {
|
|
111
|
-
CLI.error.specifyInstance(
|
|
110
|
+
CLI.error.specifyInstance(
|
|
111
|
+
adapter,
|
|
112
|
+
adapterInstances.map(obj => obj._id.substring('system.adapter.'.length))
|
|
113
|
+
);
|
|
112
114
|
return void callback(EXIT_CODES.INVALID_ADAPTER_ID);
|
|
113
115
|
} else if (adapterInstances.length === 0) {
|
|
114
116
|
CLI.error.noInstancesFound(adapter);
|
|
@@ -162,14 +164,14 @@ module.exports = class CLIProcess extends CLICommand {
|
|
|
162
164
|
const daemon = setupDaemonize();
|
|
163
165
|
// On non-Windows OSes start KILLALL script
|
|
164
166
|
// to make sure nothing keeps running
|
|
165
|
-
if (!require('os').platform().
|
|
167
|
+
if (!require('os').platform().startsWith('win')) {
|
|
166
168
|
daemon.on('stopped', () => {
|
|
167
169
|
let data = '';
|
|
168
170
|
if (fs.existsSync(killAllScriptPath)) {
|
|
169
171
|
fs.chmodSync(killAllScriptPath, '777');
|
|
170
172
|
const child = require('child_process').spawn(killAllScriptPath, [], { windowsHide: true });
|
|
171
|
-
child.stdout.on('data', _data => data += _data.toString().replace(/\n/g, ''));
|
|
172
|
-
child.stderr.on('data', _data => data += _data.toString().replace(/\n/g, ''));
|
|
173
|
+
child.stdout.on('data', _data => (data += _data.toString().replace(/\n/g, '')));
|
|
174
|
+
child.stderr.on('data', _data => (data += _data.toString().replace(/\n/g, '')));
|
|
173
175
|
child.on('exit', exitCode => {
|
|
174
176
|
console.log('Exit code for "killall.sh": ' + exitCode);
|
|
175
177
|
return void callback();
|
|
@@ -185,9 +187,7 @@ module.exports = class CLIProcess extends CLICommand {
|
|
|
185
187
|
/** Restarts the JS controller */
|
|
186
188
|
restartJSController() {
|
|
187
189
|
const daemon = setupDaemonize();
|
|
188
|
-
daemon
|
|
189
|
-
.on('stopped', () => daemon.start())
|
|
190
|
-
.on('notrunning', () => daemon.start());
|
|
190
|
+
daemon.on('stopped', () => daemon.start()).on('notrunning', () => daemon.start());
|
|
191
191
|
daemon.stop();
|
|
192
192
|
}
|
|
193
193
|
|
|
@@ -207,7 +207,10 @@ module.exports = class CLIProcess extends CLICommand {
|
|
|
207
207
|
const alive = hostAlive ? hostAlive.val : false;
|
|
208
208
|
CLI.success.controllerStatus(alive);
|
|
209
209
|
console.log();
|
|
210
|
-
if (
|
|
210
|
+
if (
|
|
211
|
+
!dbTools.isLocalStatesDbServer(config.states.type, config.states.host) &&
|
|
212
|
+
!dbTools.isLocalObjectsDbServer(config.objects.type, config.objects.host)
|
|
213
|
+
) {
|
|
211
214
|
CLI.success.systemStatus(!isOffline);
|
|
212
215
|
}
|
|
213
216
|
|
|
@@ -232,7 +235,10 @@ module.exports = class CLIProcess extends CLICommand {
|
|
|
232
235
|
const adapterInstances = await enumInstances(_objects, adapterName);
|
|
233
236
|
// If there are multiple instances of this adapter, ask the user to specify which one
|
|
234
237
|
if (adapterInstances.length > 1) {
|
|
235
|
-
CLI.error.specifyInstance(
|
|
238
|
+
CLI.error.specifyInstance(
|
|
239
|
+
adapterName,
|
|
240
|
+
adapterInstances.map(obj => obj._id.substring('system.adapter.'.length))
|
|
241
|
+
);
|
|
236
242
|
return void callback(EXIT_CODES.INVALID_ADAPTER_ID);
|
|
237
243
|
} else if (adapterInstances.length === 0) {
|
|
238
244
|
CLI.error.noInstancesFound(adapterName);
|
|
@@ -341,7 +347,9 @@ function setupDaemonize() {
|
|
|
341
347
|
}
|
|
342
348
|
} catch {
|
|
343
349
|
console.warn('Cannot read memoryLimitMB');
|
|
344
|
-
console.warn(
|
|
350
|
+
console.warn(
|
|
351
|
+
`May be config file does not exist.\nPlease call "${tools.appName} setup first" to initialize the settings.`
|
|
352
|
+
);
|
|
345
353
|
}
|
|
346
354
|
const startObj = {
|
|
347
355
|
main: path.join(rootDir, 'controller.js'),
|
package/lib/cli/cliStates.js
CHANGED
|
@@ -1,14 +1,13 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
const { tools } = require('@iobroker/js-controller-common');
|
|
3
|
-
const CLI
|
|
4
|
-
const CLICommand
|
|
5
|
-
const {formatValue}
|
|
3
|
+
const CLI = require('./messages.js');
|
|
4
|
+
const CLICommand = require('./cliCommand.js');
|
|
5
|
+
const { formatValue } = require('./cliTools');
|
|
6
6
|
const ALIAS_STARTS_WITH = 'alias.';
|
|
7
7
|
|
|
8
8
|
/** Command iobroker state ... */
|
|
9
9
|
module.exports = class CLIStates extends CLICommand {
|
|
10
|
-
|
|
11
|
-
/** @param {import('./cliCommand').CLICommandOptions} options */
|
|
10
|
+
/** @param {CLICommandOptions} options */
|
|
12
11
|
constructor(options) {
|
|
13
12
|
super(options);
|
|
14
13
|
}
|
|
@@ -33,19 +32,16 @@ module.exports = class CLIStates extends CLICommand {
|
|
|
33
32
|
return 'null';
|
|
34
33
|
}
|
|
35
34
|
|
|
36
|
-
return [
|
|
37
|
-
obj.val,
|
|
38
|
-
obj.ack,
|
|
39
|
-
obj.from,
|
|
40
|
-
obj.ts,
|
|
41
|
-
obj.lc
|
|
42
|
-
].map(line => formatValue(line)).join('\n');
|
|
35
|
+
return [obj.val, obj.ack, obj.from, obj.ts, obj.lc].map(line => formatValue(line)).join('\n');
|
|
43
36
|
};
|
|
44
37
|
return this.get_(args, resultTransform);
|
|
45
38
|
case 'getValue':
|
|
46
39
|
case 'getvalue':
|
|
47
|
-
resultTransform = obj => obj ? formatValue(obj.val, pretty) : 'null';
|
|
40
|
+
resultTransform = obj => (obj ? formatValue(obj.val, pretty) : 'null');
|
|
48
41
|
return this.get_(args, resultTransform);
|
|
42
|
+
case 'getBinary':
|
|
43
|
+
case 'getbinary':
|
|
44
|
+
return this._getBinary(args);
|
|
49
45
|
case 'set':
|
|
50
46
|
return this.set_(args);
|
|
51
47
|
case 'chmod':
|
|
@@ -55,6 +51,10 @@ module.exports = class CLIStates extends CLICommand {
|
|
|
55
51
|
case 'delete':
|
|
56
52
|
case 'del':
|
|
57
53
|
return this.delete(args);
|
|
54
|
+
case 'getDBVersion':
|
|
55
|
+
return this.getDBVersion(args);
|
|
56
|
+
case 'setDBVersion':
|
|
57
|
+
return this.setDBVersion();
|
|
58
58
|
default:
|
|
59
59
|
CLI.error.unknownCommand('state', command);
|
|
60
60
|
showHelp();
|
|
@@ -62,32 +62,133 @@ module.exports = class CLIStates extends CLICommand {
|
|
|
62
62
|
}
|
|
63
63
|
}
|
|
64
64
|
|
|
65
|
+
/**
|
|
66
|
+
* Get the protocol version
|
|
67
|
+
*/
|
|
68
|
+
getDBVersion() {
|
|
69
|
+
const { callback, dbConnect } = this.options;
|
|
70
|
+
dbConnect(async (objects, states) => {
|
|
71
|
+
const version = await states.getProtocolVersion();
|
|
72
|
+
console.log(`Current States DB protocol version: ${version}`);
|
|
73
|
+
return void callback();
|
|
74
|
+
});
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
/**
|
|
78
|
+
* Set protocol version
|
|
79
|
+
*/
|
|
80
|
+
setDBVersion() {
|
|
81
|
+
const { callback, dbConnect } = this.options;
|
|
82
|
+
dbConnect(async (objects, states) => {
|
|
83
|
+
const rl = require('readline-sync');
|
|
84
|
+
|
|
85
|
+
let answer = rl.question('Changing the protocol version will restart all hosts! Continue? [N/y]', {
|
|
86
|
+
limit: /^(yes|y|n|no)$/i,
|
|
87
|
+
defaultInput: 'no'
|
|
88
|
+
});
|
|
89
|
+
|
|
90
|
+
answer = answer.toLowerCase();
|
|
91
|
+
|
|
92
|
+
if (answer !== 'y' && answer !== 'yes') {
|
|
93
|
+
console.log('Protocol version has not been changed!');
|
|
94
|
+
return void callback();
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
try {
|
|
98
|
+
await states.setProtocolVersion(this.options.version);
|
|
99
|
+
} catch (e) {
|
|
100
|
+
console.error(`Cannot update protocol version: ${e.message}`);
|
|
101
|
+
return void callback(1);
|
|
102
|
+
}
|
|
103
|
+
console.log(`States DB protocol updated to version ${this.options.version}`);
|
|
104
|
+
return void callback();
|
|
105
|
+
});
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
/**
|
|
109
|
+
* Checks if state is a binary state
|
|
110
|
+
* @param {string} id id of the state
|
|
111
|
+
* @param {object} objects the objects db
|
|
112
|
+
* @param {ioBroker.OtherObject?} obj cached object
|
|
113
|
+
* @return {Promise<boolean>}
|
|
114
|
+
* @private
|
|
115
|
+
*/
|
|
116
|
+
async _isBinary(id, objects, obj) {
|
|
117
|
+
obj = obj || (await objects.getObjectAsync(id));
|
|
118
|
+
|
|
119
|
+
return !!(obj && (obj.binary || (obj.common && obj.common.type === 'file')));
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
/**
|
|
123
|
+
* Get and show binary state
|
|
124
|
+
*
|
|
125
|
+
* @param {any[]} args
|
|
126
|
+
* @private
|
|
127
|
+
*/
|
|
128
|
+
_getBinary(args) {
|
|
129
|
+
const { callback, dbConnect } = this.options;
|
|
130
|
+
const id = args[1];
|
|
131
|
+
dbConnect(async (objects, states) => {
|
|
132
|
+
try {
|
|
133
|
+
/** @type Buffer | null */
|
|
134
|
+
const state = await states.getBinaryState(id);
|
|
135
|
+
|
|
136
|
+
if (!state) {
|
|
137
|
+
CLI.error.stateNotFound(id);
|
|
138
|
+
return void callback(1);
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
if (Buffer.isBuffer(state)) {
|
|
142
|
+
console.log(state.toString(this.options.encoding));
|
|
143
|
+
return void callback();
|
|
144
|
+
} else {
|
|
145
|
+
CLI.error.stateNotBinary(id);
|
|
146
|
+
return void callback(1);
|
|
147
|
+
}
|
|
148
|
+
} catch (e) {
|
|
149
|
+
CLI.error.unknown(e);
|
|
150
|
+
return void callback(1);
|
|
151
|
+
}
|
|
152
|
+
});
|
|
153
|
+
}
|
|
154
|
+
|
|
65
155
|
/**
|
|
66
156
|
* Returns the value of a state
|
|
67
157
|
* @param {any[]} args
|
|
68
158
|
* @param {(input: any) => any} resultTransform
|
|
69
159
|
*/
|
|
70
160
|
get_(args, resultTransform) {
|
|
71
|
-
const {callback, dbConnect} = this.options;
|
|
161
|
+
const { callback, dbConnect } = this.options;
|
|
72
162
|
const id = args[1];
|
|
73
163
|
|
|
74
|
-
dbConnect((objects, states) => {
|
|
164
|
+
dbConnect(async (objects, states) => {
|
|
75
165
|
if (id.startsWith(ALIAS_STARTS_WITH)) {
|
|
76
166
|
objects.getObject(id, (err, targetObj) => {
|
|
77
167
|
// alias
|
|
78
168
|
if (targetObj && targetObj.common && targetObj.common.alias && targetObj.common.alias.id) {
|
|
79
|
-
const aliasId =
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
169
|
+
const aliasId =
|
|
170
|
+
typeof targetObj.common.alias.id.read === 'string'
|
|
171
|
+
? targetObj.common.alias.id.read
|
|
172
|
+
: targetObj.common.alias.id;
|
|
173
|
+
objects.getObject(aliasId, async (err, sourceObj) => {
|
|
174
|
+
// read target
|
|
175
|
+
try {
|
|
176
|
+
if (await this._isBinary(aliasId, objects, targetObj)) {
|
|
177
|
+
CLI.error.stateBinaryGetUnsupported(aliasId);
|
|
178
|
+
return void callback(1);
|
|
179
|
+
}
|
|
180
|
+
|
|
181
|
+
const state = await states.getStateAsync(aliasId);
|
|
182
|
+
if (!state) {
|
|
183
|
+
CLI.error.stateNotFound(id);
|
|
85
184
|
} else {
|
|
86
185
|
tools.formatAliasValue(sourceObj.common, targetObj.common, state, console, '');
|
|
87
186
|
console.log(resultTransform(state));
|
|
88
187
|
}
|
|
89
|
-
|
|
90
|
-
|
|
188
|
+
} catch (e) {
|
|
189
|
+
CLI.error.unknown(e);
|
|
190
|
+
}
|
|
191
|
+
return void callback();
|
|
91
192
|
});
|
|
92
193
|
} else {
|
|
93
194
|
CLI.error.unknown(err || `Alias ${id} has no target`);
|
|
@@ -95,14 +196,21 @@ module.exports = class CLIStates extends CLICommand {
|
|
|
95
196
|
}
|
|
96
197
|
});
|
|
97
198
|
} else {
|
|
98
|
-
|
|
99
|
-
if (
|
|
100
|
-
CLI.error.
|
|
199
|
+
try {
|
|
200
|
+
if (await this._isBinary(id, objects)) {
|
|
201
|
+
CLI.error.stateBinaryGetUnsupported(id);
|
|
202
|
+
return void callback(1);
|
|
203
|
+
}
|
|
204
|
+
const state = await states.getStateAsync(id);
|
|
205
|
+
if (!state) {
|
|
206
|
+
CLI.error.stateNotFound(id);
|
|
101
207
|
} else {
|
|
102
208
|
console.log(resultTransform(state));
|
|
103
209
|
}
|
|
104
|
-
|
|
105
|
-
|
|
210
|
+
} catch (e) {
|
|
211
|
+
CLI.error.unknown(e);
|
|
212
|
+
}
|
|
213
|
+
return void callback();
|
|
106
214
|
}
|
|
107
215
|
});
|
|
108
216
|
}
|
|
@@ -111,7 +219,7 @@ module.exports = class CLIStates extends CLICommand {
|
|
|
111
219
|
* @param {any[]} args
|
|
112
220
|
*/
|
|
113
221
|
set_(args) {
|
|
114
|
-
const {callback, dbConnect, showHelp} = this.options;
|
|
222
|
+
const { callback, dbConnect, showHelp } = this.options;
|
|
115
223
|
// eslint-disable-next-line prefer-const
|
|
116
224
|
let [id, val, ack] = /** @type {[string, any, any]} */ (args.slice(1));
|
|
117
225
|
const force = args.includes('--force') || args.includes('-f');
|
|
@@ -127,13 +235,20 @@ module.exports = class CLIStates extends CLICommand {
|
|
|
127
235
|
}
|
|
128
236
|
|
|
129
237
|
dbConnect((objects, states) => {
|
|
130
|
-
const newVal = ack === undefined ?
|
|
238
|
+
const newVal = ack === undefined ? { val, ack: false } : { val, ack: !!ack };
|
|
131
239
|
|
|
132
240
|
if (id.startsWith(ALIAS_STARTS_WITH)) {
|
|
133
|
-
objects.getObject(id, (err, obj) => {
|
|
241
|
+
objects.getObject(id, async (err, obj) => {
|
|
242
|
+
if (await this._isBinary(id, objects, obj)) {
|
|
243
|
+
CLI.error.stateBinarySetUnsupported(id);
|
|
244
|
+
return void callback(1);
|
|
245
|
+
}
|
|
134
246
|
// alias
|
|
135
247
|
if (obj && obj.common && obj.common.alias && obj.common.alias.id) {
|
|
136
|
-
const aliasId =
|
|
248
|
+
const aliasId =
|
|
249
|
+
typeof obj.common.alias.id.write === 'string'
|
|
250
|
+
? obj.common.alias.id.write
|
|
251
|
+
: obj.common.alias.id;
|
|
137
252
|
|
|
138
253
|
objects.getObject(aliasId, (err, targetObj) => {
|
|
139
254
|
if (err) {
|
|
@@ -152,20 +267,28 @@ module.exports = class CLIStates extends CLICommand {
|
|
|
152
267
|
newVal.val = parseFloat(newVal.val);
|
|
153
268
|
} else if (obj.common.type === 'boolean') {
|
|
154
269
|
newVal.val = newVal.val.toString();
|
|
155
|
-
newVal.val =
|
|
270
|
+
newVal.val =
|
|
271
|
+
newVal.val === 'true' ||
|
|
272
|
+
newVal.val === '1' ||
|
|
273
|
+
newVal.val === 'ON' ||
|
|
274
|
+
newVal.val === 'on';
|
|
156
275
|
}
|
|
157
276
|
}
|
|
158
277
|
|
|
159
278
|
// write target
|
|
160
|
-
states.setState(
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
279
|
+
states.setState(
|
|
280
|
+
aliasId,
|
|
281
|
+
tools.formatAliasValue(obj.common, targetObj.common, newVal, console, ''),
|
|
282
|
+
err => {
|
|
283
|
+
if (err) {
|
|
284
|
+
CLI.error.unknown(err);
|
|
285
|
+
return void callback(1); // ?
|
|
286
|
+
} else {
|
|
287
|
+
CLI.success.stateUpdated(id, val, !!ack);
|
|
288
|
+
return void callback();
|
|
289
|
+
}
|
|
167
290
|
}
|
|
168
|
-
|
|
291
|
+
);
|
|
169
292
|
});
|
|
170
293
|
} else {
|
|
171
294
|
CLI.error.unknown(`Alias ${id} has no target`);
|
|
@@ -173,11 +296,17 @@ module.exports = class CLIStates extends CLICommand {
|
|
|
173
296
|
}
|
|
174
297
|
});
|
|
175
298
|
} else {
|
|
176
|
-
objects.getObject(id, (err, obj) => {
|
|
299
|
+
objects.getObject(id, async (err, obj) => {
|
|
177
300
|
if (err) {
|
|
178
301
|
CLI.error.unknown(err);
|
|
179
302
|
return void callback(1); // access error
|
|
180
303
|
}
|
|
304
|
+
|
|
305
|
+
if (await this._isBinary(id, objects, obj)) {
|
|
306
|
+
CLI.error.stateBinarySetUnsupported(id);
|
|
307
|
+
return void callback(1);
|
|
308
|
+
}
|
|
309
|
+
|
|
181
310
|
if (!obj && !force) {
|
|
182
311
|
CLI.error.objectNotFound(id, 'null');
|
|
183
312
|
return void callback(1); // object not exists
|
|
@@ -190,7 +319,11 @@ module.exports = class CLIStates extends CLICommand {
|
|
|
190
319
|
newVal.val = parseFloat(newVal.val);
|
|
191
320
|
} else if (obj.common.type === 'boolean') {
|
|
192
321
|
newVal.val = newVal.val.toString();
|
|
193
|
-
newVal.val =
|
|
322
|
+
newVal.val =
|
|
323
|
+
newVal.val === 'true' ||
|
|
324
|
+
newVal.val === '1' ||
|
|
325
|
+
newVal.val === 'ON' ||
|
|
326
|
+
newVal.val === 'on';
|
|
194
327
|
}
|
|
195
328
|
}
|
|
196
329
|
|
|
@@ -213,7 +346,7 @@ module.exports = class CLIStates extends CLICommand {
|
|
|
213
346
|
* @param {any[]} args
|
|
214
347
|
*/
|
|
215
348
|
delete(args) {
|
|
216
|
-
const {callback, dbConnect} = this.options;
|
|
349
|
+
const { callback, dbConnect } = this.options;
|
|
217
350
|
/** @type {string} */
|
|
218
351
|
const id = args[1];
|
|
219
352
|
if (!id) {
|
|
@@ -230,6 +363,7 @@ module.exports = class CLIStates extends CLICommand {
|
|
|
230
363
|
CLI.success.stateDeleted(id);
|
|
231
364
|
return void callback();
|
|
232
365
|
}
|
|
233
|
-
})
|
|
366
|
+
})
|
|
367
|
+
);
|
|
234
368
|
}
|
|
235
369
|
};
|
package/lib/cli/cliTools.js
CHANGED
|
@@ -9,9 +9,7 @@ const { tools } = require('@iobroker/js-controller-common');
|
|
|
9
9
|
function formatValue(val, pretty) {
|
|
10
10
|
// Only use JSON.stringify if we need it (for objects and arrays)
|
|
11
11
|
const needsStringify = tools.isObject(val) || tools.isArray(val);
|
|
12
|
-
const output = !needsStringify ? val
|
|
13
|
-
: pretty ? JSON.stringify(val, null, 2)
|
|
14
|
-
: JSON.stringify(val);
|
|
12
|
+
const output = !needsStringify ? val : pretty ? JSON.stringify(val, null, 2) : JSON.stringify(val);
|
|
15
13
|
return output;
|
|
16
14
|
}
|
|
17
15
|
|
|
@@ -53,6 +51,7 @@ function validateAdapterOrInstanceIdentifier(name) {
|
|
|
53
51
|
* Ensures that the given string contains a valid identifier for
|
|
54
52
|
* an adapter (without instance number) or instance (with instance number)
|
|
55
53
|
* @param {string} name
|
|
54
|
+
* @return {{name: string, instance:string|null, version: string|null, nameWithVersion:string}|null}
|
|
56
55
|
*/
|
|
57
56
|
function splitAdapterOrInstanceIdentifierWithVersion(name) {
|
|
58
57
|
const res = name.match(/^([a-z0-9\-_]+)\.?(\d+)?@?([a-z0-9\-_.]*)?$/);
|
|
@@ -108,7 +107,7 @@ function enumHosts(objects) {
|
|
|
108
107
|
function enumObjects(objects, type, startkey) {
|
|
109
108
|
return new Promise((resolve, reject) => {
|
|
110
109
|
const endkey = startkey + '\u9999';
|
|
111
|
-
objects.getObjectView('system', type, {startkey, endkey}, null, (err, res) => {
|
|
110
|
+
objects.getObjectView('system', type, { startkey, endkey }, null, (err, res) => {
|
|
112
111
|
if (err) {
|
|
113
112
|
return reject(err);
|
|
114
113
|
}
|
package/lib/cli/messages.js
CHANGED
|
@@ -2,49 +2,39 @@
|
|
|
2
2
|
const { tools } = require('@iobroker/js-controller-common');
|
|
3
3
|
|
|
4
4
|
const errorMessages = Object.freeze({
|
|
5
|
-
stateNotFound: (
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
) => `The object ${objectID} could not be deleted from enums!` + (error ? ` Reason: ${error}` : ''),
|
|
25
|
-
cannotChangeObject: (
|
|
26
|
-
/** @type {string} */ objectID,
|
|
27
|
-
/** @type {string?} */ error
|
|
28
|
-
) => `The object ${objectID} cannot be changed!` + (error ? ` Reason: ${error}` : ''),
|
|
29
|
-
objectPropertyNotFound: (
|
|
30
|
-
/** @type {string} */ objectID,
|
|
31
|
-
/** @type {string} */ propPath
|
|
32
|
-
) => `The requested property "${propPath}" or one of its parents was not found in the object "${objectID}"!`,
|
|
5
|
+
stateNotFound: (/** @type {string} */ stateID, /** @type {string?} */ error) =>
|
|
6
|
+
`The state ${stateID} was not found!` + (error ? ` Reason: ${error}` : ''),
|
|
7
|
+
stateNotBinary: (/** @type {string} */ stateId) => `State "${stateId}" is not binary.`,
|
|
8
|
+
stateBinaryGetUnsupported: (/** @type {string} */ stateId) =>
|
|
9
|
+
`State "${stateId}" is a binary state, please use getBinary.`,
|
|
10
|
+
stateBinarySetUnsupported: (/** @type {string} */ stateId) =>
|
|
11
|
+
`State "${stateId}" is a binary state and cannot be set via cli.`,
|
|
12
|
+
objectNotFound: (/** @type {string} */ objectID, /** @type {string?} */ error) =>
|
|
13
|
+
`The object ${objectID} was not found!` + (error ? ` Reason: ${error}` : ''),
|
|
14
|
+
cannotUpdateObject: (/** @type {string} */ objectID, /** @type {string?} */ error) =>
|
|
15
|
+
`The object ${objectID} could not be updated!` + (error ? ` Reason: ${error}` : ''),
|
|
16
|
+
cannotDeleteObject: (/** @type {string} */ objectID, /** @type {string?} */ error) =>
|
|
17
|
+
`The object ${objectID} cannot be deleted!` + (error ? ` Reason: ${error}` : ''),
|
|
18
|
+
cannotDeleteObjectFromEnums: (/** @type {string} */ objectID, /** @type {string?} */ error) =>
|
|
19
|
+
`The object ${objectID} could not be deleted from enums!` + (error ? ` Reason: ${error}` : ''),
|
|
20
|
+
cannotChangeObject: (/** @type {string} */ objectID, /** @type {string?} */ error) =>
|
|
21
|
+
`The object ${objectID} cannot be changed!` + (error ? ` Reason: ${error}` : ''),
|
|
22
|
+
objectPropertyNotFound: (/** @type {string} */ objectID, /** @type {string} */ propPath) =>
|
|
23
|
+
`The requested property "${propPath}" or one of its parents was not found in the object "${objectID}"!`,
|
|
33
24
|
invalidPropertyOrValue: () => `The property path or value is not valid. Please make sure the value is valid JSON.`,
|
|
34
25
|
invalidJSONValue: () => `The given value is not valid JSON.`,
|
|
35
26
|
|
|
36
|
-
unknownCommand: (
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
requiredArgumentMissing: (
|
|
41
|
-
/** @type {string} */ argName,
|
|
42
|
-
/** @type {string?} */ exampleCommand
|
|
43
|
-
) => `The required argument "${argName}" is missing!` + (exampleCommand ? ` Example: "${exampleCommand}"` : ''),
|
|
27
|
+
unknownCommand: (/** @type {string} */ prefix, /** @type {string} */ command) =>
|
|
28
|
+
`Unknown command "${prefix} ${command}"!`,
|
|
29
|
+
requiredArgumentMissing: (/** @type {string} */ argName, /** @type {string?} */ exampleCommand) =>
|
|
30
|
+
`The required argument "${argName}" is missing!` + (exampleCommand ? ` Example: "${exampleCommand}"` : ''),
|
|
44
31
|
|
|
45
32
|
noInstancesFound: adapter => `Cannot find any instances of "${adapter}"!`,
|
|
46
33
|
invalidInstance: instance => `The instance "${instance}" does not exist!`,
|
|
47
|
-
specifyInstance: (/** @type {string} */ adapter, /** @type {Array<string>?} */adapterInstances) =>
|
|
34
|
+
specifyInstance: (/** @type {string} */ adapter, /** @type {Array<string>?} */ adapterInstances) =>
|
|
35
|
+
`The adapter "${adapter}" has multiple instances! Please specify which one should be started: "${adapterInstances.join(
|
|
36
|
+
'", "'
|
|
37
|
+
)}".`,
|
|
48
38
|
adapterDirNotFound: adapter => `Cannot find the installation dir for adapter "${adapter}"!`,
|
|
49
39
|
mainFileNotFound: adapter => `Cannot find the main file for adapter "${adapter}"!`,
|
|
50
40
|
cannotLoadIoPackage: adapter => `Cannot load the io-package.json file for adapter "${adapter}"!`,
|
|
@@ -53,8 +43,10 @@ const errorMessages = Object.freeze({
|
|
|
53
43
|
/** @type {string} */ wrongPrefix,
|
|
54
44
|
/** @type {string} */ command,
|
|
55
45
|
/** @type {string?} */ correctPrefix
|
|
56
|
-
) =>
|
|
57
|
-
|
|
46
|
+
) =>
|
|
47
|
+
`The command ${command} is not intended to be used with ${wrongPrefix}!` + correctPrefix
|
|
48
|
+
? `Please use "${correctPrefix} ${command}" instead.`
|
|
49
|
+
: '',
|
|
58
50
|
unknown: err => `An unknown error occurred: ${err}`,
|
|
59
51
|
|
|
60
52
|
cannotChangeRunningSystem: () => `Cannot execute changes on running system. Stop ${tools.appName} first.`,
|
|
@@ -63,47 +55,46 @@ const errorMessages = Object.freeze({
|
|
|
63
55
|
hostDoesNotExist: hostname => `The host "${hostname}" does not exist!`,
|
|
64
56
|
dontRemoveCurrentHost: hostname => `Cannot remove host "${hostname}" from itself!`,
|
|
65
57
|
|
|
66
|
-
pluginNotDefined: (pluginName, host, instance) =>
|
|
58
|
+
pluginNotDefined: (pluginName, host, instance) =>
|
|
59
|
+
`The plugin "${pluginName}" does not exist for ${host ? `host "${host}"` : `instance "${instance}"`}!`,
|
|
67
60
|
|
|
68
|
-
cert: certName => `Certificate "${certName}" not found or error parsing certificate information
|
|
61
|
+
cert: certName => `Certificate "${certName}" not found or error parsing certificate information.`,
|
|
62
|
+
instanceAlreadyRunning: instance => `The instance "${instance}" is already running, please stop instance first.`
|
|
69
63
|
});
|
|
70
64
|
|
|
71
65
|
const successMessages = Object.freeze({
|
|
72
66
|
objectUpdated: objectID => `The object "${objectID}" was updated successfully.`,
|
|
73
67
|
objectDeleted: objectID => `The object "${objectID}" was deleted.`,
|
|
74
|
-
stateUpdated: (
|
|
75
|
-
|
|
76
|
-
/** @type {any} */ value,
|
|
77
|
-
/** @type {boolean | undefined} */ ack
|
|
78
|
-
) => `The state "${stateID}" was set to "${value}"${ack === undefined ? '' : ` with flag ack=${ack}`}`,
|
|
68
|
+
stateUpdated: (/** @type {string} */ stateID, /** @type {any} */ value, /** @type {boolean | undefined} */ ack) =>
|
|
69
|
+
`The state "${stateID}" was set to "${value}"${ack === undefined ? '' : ` with flag ack=${ack}`}`,
|
|
79
70
|
stateDeleted: stateID => `The state "${stateID}" was deleted.`,
|
|
80
71
|
adapterStarted: adapter => `The adapter "${adapter}" was started.`,
|
|
81
72
|
adapterStopped: adapter => `The adapter "${adapter}" was stopped.`,
|
|
82
73
|
adapterRestarted: adapter => `The adapter "${adapter}" was restarted.`,
|
|
83
|
-
systemStatus: isRunning =>
|
|
74
|
+
systemStatus: isRunning =>
|
|
75
|
+
isRunning ? `At least one ${tools.appName} host is running.` : `No ${tools.appName} host is running.`,
|
|
84
76
|
controllerStatus: isRunning => `${tools.appName} is ${isRunning ? '' : 'not '}running on this host.`,
|
|
85
|
-
messageSent: (
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
/** @type {string} */ from,
|
|
92
|
-
/** @type {string} */ to
|
|
93
|
-
) => `Host "${from}" successfully renamed to "${to}".`,
|
|
94
|
-
instanceHostChanged: (
|
|
95
|
-
/** @type {string} */ instance,
|
|
96
|
-
/** @type {string} */ from,
|
|
97
|
-
/** @type {string} */ to
|
|
98
|
-
) => `The host for instance "${instance}" was changed from "${from}" to "${to}".`,
|
|
77
|
+
messageSent: (/** @type {string} */ adapter, /** @type {string} */ command, /** @type {any} */ message) =>
|
|
78
|
+
`The command "${command}" was sent to "${adapter}" with the message "${message}".`,
|
|
79
|
+
hostRenamed: (/** @type {string} */ from, /** @type {string} */ to) =>
|
|
80
|
+
`Host "${from}" successfully renamed to "${to}".`,
|
|
81
|
+
instanceHostChanged: (/** @type {string} */ instance, /** @type {string} */ from, /** @type {string} */ to) =>
|
|
82
|
+
`The host for instance "${instance}" was changed from "${from}" to "${to}".`,
|
|
99
83
|
hostDeleted: hostname => `The host "${hostname}" was deleted.`,
|
|
100
84
|
|
|
101
|
-
pluginEnabledOrDisabled: (pluginName, host, instance, status) =>
|
|
102
|
-
|
|
85
|
+
pluginEnabledOrDisabled: (pluginName, host, instance, status) =>
|
|
86
|
+
`The plugin "${pluginName}" was successfully ${status ? 'enabled' : 'disabled'} for ${
|
|
87
|
+
host ? `host "${host}"` : `instance "${instance}"`
|
|
88
|
+
}.`,
|
|
89
|
+
pluginStatus: (pluginName, host, instance, status) =>
|
|
90
|
+
`The plugin "${pluginName}" is ${status ? 'enabled' : 'disabled'} for ${
|
|
91
|
+
host ? `host "${host}"` : `instance "${instance}"`
|
|
92
|
+
}.`
|
|
103
93
|
});
|
|
104
94
|
|
|
105
95
|
const warnings = Object.freeze({
|
|
106
|
-
noInstancesFoundOnHost: hostname =>
|
|
96
|
+
noInstancesFoundOnHost: hostname =>
|
|
97
|
+
hostname ? `No instances found for host "${hostname}"!` : `No instances found!`
|
|
107
98
|
});
|
|
108
99
|
|
|
109
100
|
// Capsule success messages in console.log
|