@webos-tools/cli 3.0.0

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.
Files changed (177) hide show
  1. package/.eslintignore +1 -0
  2. package/.eslintrc.js +52 -0
  3. package/APIs.js +79 -0
  4. package/CHANGELOG.md +110 -0
  5. package/LICENSE +201 -0
  6. package/README.md +218 -0
  7. package/bin/ares-config.js +199 -0
  8. package/bin/ares-device-info.js +30 -0
  9. package/bin/ares-device.js +219 -0
  10. package/bin/ares-generate.js +270 -0
  11. package/bin/ares-inspect.js +179 -0
  12. package/bin/ares-install.js +223 -0
  13. package/bin/ares-launch.js +318 -0
  14. package/bin/ares-log.js +255 -0
  15. package/bin/ares-novacom.js +223 -0
  16. package/bin/ares-package.js +336 -0
  17. package/bin/ares-pull.js +156 -0
  18. package/bin/ares-push.js +155 -0
  19. package/bin/ares-server.js +174 -0
  20. package/bin/ares-setup-device.js +520 -0
  21. package/bin/ares-shell.js +132 -0
  22. package/bin/ares.js +166 -0
  23. package/files/conf/ares.json +49 -0
  24. package/files/conf/command-service.json +73 -0
  25. package/files/conf/config.json +22 -0
  26. package/files/conf/ipk.json +30 -0
  27. package/files/conf/novacom-devices.json +35 -0
  28. package/files/conf/query/query-app.json +14 -0
  29. package/files/conf/query/query-hosted.json +18 -0
  30. package/files/conf/query/query-package.json +10 -0
  31. package/files/conf/query/query-service.json +6 -0
  32. package/files/conf/sdk.json +8 -0
  33. package/files/conf/template.json +57 -0
  34. package/files/conf/webos_emul +27 -0
  35. package/files/conf-base/env/sdk-ose.json +8 -0
  36. package/files/conf-base/env/sdk-tv.json +8 -0
  37. package/files/conf-base/profile/config-ose.json +21 -0
  38. package/files/conf-base/profile/config-tv.json +22 -0
  39. package/files/conf-base/query/query-app.json +14 -0
  40. package/files/conf-base/query/query-hosted.json +18 -0
  41. package/files/conf-base/query/query-package.json +10 -0
  42. package/files/conf-base/query/query-service.json +6 -0
  43. package/files/conf-base/template-conf/ose-templates.json +67 -0
  44. package/files/conf-base/template-conf/tv-sdk-templates.json +57 -0
  45. package/files/help/ares-config.help +43 -0
  46. package/files/help/ares-device.help +94 -0
  47. package/files/help/ares-generate.help +65 -0
  48. package/files/help/ares-inspect.help +70 -0
  49. package/files/help/ares-install.help +90 -0
  50. package/files/help/ares-launch.help +100 -0
  51. package/files/help/ares-log-pmlogd.help +84 -0
  52. package/files/help/ares-log.help +101 -0
  53. package/files/help/ares-novacom.help +68 -0
  54. package/files/help/ares-package.help +101 -0
  55. package/files/help/ares-pull.help +38 -0
  56. package/files/help/ares-push.help +38 -0
  57. package/files/help/ares-server.help +39 -0
  58. package/files/help/ares-setup-device.help +75 -0
  59. package/files/help/ares-shell.help +42 -0
  60. package/files/help/ares.help +47 -0
  61. package/files/help/readme.help +23 -0
  62. package/files/schema/ApplicationDescription.schema +319 -0
  63. package/files/schema/NovacomDevices.schema +61 -0
  64. package/files/templates/ose-sdk-templates/appinfo/appinfo.json +10 -0
  65. package/files/templates/ose-sdk-templates/bootplate-web/index.html +88 -0
  66. package/files/templates/ose-sdk-templates/hosted-webapp/index.html +14 -0
  67. package/files/templates/ose-sdk-templates/icon/icon.png +0 -0
  68. package/files/templates/ose-sdk-templates/js-service/helloclient.js +31 -0
  69. package/files/templates/ose-sdk-templates/js-service/helloworld_webos_service.js +188 -0
  70. package/files/templates/ose-sdk-templates/qml-app/main.qml +68 -0
  71. package/files/templates/ose-sdk-templates/qmlappinfo/appinfo.json +10 -0
  72. package/files/templates/ose-sdk-templates/serviceinfo/package.json +11 -0
  73. package/files/templates/ose-sdk-templates/serviceinfo/services.json +8 -0
  74. package/files/templates/tv-sdk-templates/appinfo/appinfo.json +10 -0
  75. package/files/templates/tv-sdk-templates/bootplate-web/index.html +58 -0
  76. package/files/templates/tv-sdk-templates/bootplate-web/webOSTVjs-1.2.4/LICENSE-2.0.txt +202 -0
  77. package/files/templates/tv-sdk-templates/bootplate-web/webOSTVjs-1.2.4/webOSTV-dev.js +1 -0
  78. package/files/templates/tv-sdk-templates/bootplate-web/webOSTVjs-1.2.4/webOSTV.js +1 -0
  79. package/files/templates/tv-sdk-templates/hosted-webapp/index.html +14 -0
  80. package/files/templates/tv-sdk-templates/js-service/helloworld_service.js +37 -0
  81. package/files/templates/tv-sdk-templates/packageinfo/packageinfo.json +4 -0
  82. package/files/templates/tv-sdk-templates/serviceinfo/package.json +11 -0
  83. package/files/templates/tv-sdk-templates/serviceinfo/services.json +8 -0
  84. package/files/templates/tv-sdk-templates/webicon/icon.png +0 -0
  85. package/files/templates/tv-sdk-templates/webicon/largeIcon.png +0 -0
  86. package/lib/base/ares.html +40 -0
  87. package/lib/base/cli-appdata.js +289 -0
  88. package/lib/base/cli-control.js +44 -0
  89. package/lib/base/common-tools.js +29 -0
  90. package/lib/base/error-handler.js +265 -0
  91. package/lib/base/file-watcher.js +155 -0
  92. package/lib/base/help-format.js +147 -0
  93. package/lib/base/luna.js +178 -0
  94. package/lib/base/novacom.js +1191 -0
  95. package/lib/base/sdkenv.js +59 -0
  96. package/lib/base/server.js +137 -0
  97. package/lib/base/setup-device.js +324 -0
  98. package/lib/base/version-tools.js +79 -0
  99. package/lib/com.sdk.ares.hostedapp.ipk +0 -0
  100. package/lib/device.js +1419 -0
  101. package/lib/generator.js +377 -0
  102. package/lib/inspect.js +494 -0
  103. package/lib/install.js +463 -0
  104. package/lib/launch.js +605 -0
  105. package/lib/log.js +584 -0
  106. package/lib/package.js +2129 -0
  107. package/lib/pull.js +231 -0
  108. package/lib/pusher.js +210 -0
  109. package/lib/session.js +74 -0
  110. package/lib/shell.js +193 -0
  111. package/lib/tar-filter-pack.js +62 -0
  112. package/lib/util/copy.js +31 -0
  113. package/lib/util/createFileName.js +40 -0
  114. package/lib/util/eof.js +30 -0
  115. package/lib/util/json.js +63 -0
  116. package/lib/util/merge.js +14 -0
  117. package/lib/util/objclone.js +40 -0
  118. package/lib/util/spinner.js +37 -0
  119. package/npm-shrinkwrap.json +85 -0
  120. package/package.json +98 -0
  121. package/spec/helpers/reporter.js +65 -0
  122. package/spec/jsSpecs/apiTest/generator.spec.js +372 -0
  123. package/spec/jsSpecs/apiTest/inspector.spec.js +89 -0
  124. package/spec/jsSpecs/apiTest/installer.spec.js +67 -0
  125. package/spec/jsSpecs/apiTest/launcher.spec.js +150 -0
  126. package/spec/jsSpecs/apiTest/packager.spec.js +194 -0
  127. package/spec/jsSpecs/apiTest/puller.spec.js +101 -0
  128. package/spec/jsSpecs/apiTest/pusher.spec.js +103 -0
  129. package/spec/jsSpecs/apiTest/server.spec.js +115 -0
  130. package/spec/jsSpecs/apiTest/setupDevice.spec.js +93 -0
  131. package/spec/jsSpecs/apiTest/shell.spec.js +49 -0
  132. package/spec/jsSpecs/ares-config.spec.js +78 -0
  133. package/spec/jsSpecs/ares-device.spec.js +443 -0
  134. package/spec/jsSpecs/ares-generate.spec.js +397 -0
  135. package/spec/jsSpecs/ares-inspect.spec.js +252 -0
  136. package/spec/jsSpecs/ares-install.spec.js +150 -0
  137. package/spec/jsSpecs/ares-launch.spec.js +301 -0
  138. package/spec/jsSpecs/ares-log.spec.js +824 -0
  139. package/spec/jsSpecs/ares-novacom.spec.js +149 -0
  140. package/spec/jsSpecs/ares-package.spec.js +1211 -0
  141. package/spec/jsSpecs/ares-pull.spec.js +157 -0
  142. package/spec/jsSpecs/ares-push.spec.js +146 -0
  143. package/spec/jsSpecs/ares-server.spec.js +160 -0
  144. package/spec/jsSpecs/ares-setup-device.spec.js +281 -0
  145. package/spec/jsSpecs/ares-shell.spec.js +220 -0
  146. package/spec/jsSpecs/ares.spec.js +83 -0
  147. package/spec/jsSpecs/common-spec.js +169 -0
  148. package/spec/support/jasmine.json +22 -0
  149. package/spec/tempFiles/com.jasmine.native.app_0.0.1_arm.ipk +0 -0
  150. package/spec/tempFiles/com.jasmine.native.app_0.0.1_x86.ipk +0 -0
  151. package/spec/tempFiles/com.jasmine.web.app_0.0.1_all.ipk +0 -0
  152. package/spec/tempFiles/com.logtest.web.app_1.0.0_all.ipk +0 -0
  153. package/spec/tempFiles/copyFiles/helloFile.txt +1 -0
  154. package/spec/tempFiles/copyFiles/testFile.txt +1 -0
  155. package/spec/tempFiles/ipks/com.sample.echo_0.0.1_all.ipk +0 -0
  156. package/spec/tempFiles/ipks/com.web.app_1.0.0_all.ipk +0 -0
  157. package/spec/tempFiles/nativeApp/auto/pkg_arm64/GLES2 +0 -0
  158. package/spec/tempFiles/nativeApp/auto/pkg_arm64/appinfo.json +9 -0
  159. package/spec/tempFiles/nativeApp/auto/pkg_arm64/icon.png +0 -0
  160. package/spec/tempFiles/nativeApp/auto/pkg_arm64/largeIcon.png +0 -0
  161. package/spec/tempFiles/nativeApp/ose/pkg_arm/Hello +0 -0
  162. package/spec/tempFiles/nativeApp/ose/pkg_arm/appinfo.json +9 -0
  163. package/spec/tempFiles/nativeApp/ose/pkg_arm/icon.png +0 -0
  164. package/spec/tempFiles/nativeApp/ose/pkg_arm/largeIcon.png +0 -0
  165. package/spec/tempFiles/nativeApp/ose/pkg_arm/package.properties +2 -0
  166. package/spec/tempFiles/nativeApp/oseEmul/pkg_x86/Hello +0 -0
  167. package/spec/tempFiles/nativeApp/oseEmul/pkg_x86/appinfo.json +9 -0
  168. package/spec/tempFiles/nativeApp/oseEmul/pkg_x86/icon.png +0 -0
  169. package/spec/tempFiles/nativeApp/oseEmul/pkg_x86/largeIcon.png +0 -0
  170. package/spec/tempFiles/nativeApp/rsi/pkg_x86/GLES2 +0 -0
  171. package/spec/tempFiles/nativeApp/rsi/pkg_x86/appinfo.json +9 -0
  172. package/spec/tempFiles/nativeApp/rsi/pkg_x86/icon.png +0 -0
  173. package/spec/tempFiles/nativeApp/rsi/pkg_x86/largeIcon.png +0 -0
  174. package/spec/tempFiles/sign/sign.crt +32 -0
  175. package/spec/tempFiles/sign/signPriv.key +52 -0
  176. package/spec/test_data/ares-generate.json +41 -0
  177. package/spec/test_data/ares.json +33 -0
package/lib/install.js ADDED
@@ -0,0 +1,463 @@
1
+ /*
2
+ * Copyright (c) 2020-2024 LG Electronics Inc.
3
+ *
4
+ * SPDX-License-Identifier: Apache-2.0
5
+ */
6
+
7
+ const async = require('async'),
8
+ crypto = require('crypto'),
9
+ fs = require('fs'),
10
+ npmlog = require('npmlog'),
11
+ path = require('path'),
12
+ streamBuffers = require('stream-buffers'),
13
+ util = require('util'),
14
+ sessionLib = require('./session'),
15
+ Appdata = require('./base/cli-appdata'),
16
+ errHndl = require('./base/error-handler'),
17
+ luna = require('./base/luna'),
18
+ novacom = require('./base/novacom'),
19
+ spinner = require('./util/spinner');
20
+
21
+ (function() {
22
+ const cliData = new Appdata(),
23
+ log = npmlog;
24
+
25
+ log.heading = 'installer';
26
+ log.level = 'warn';
27
+
28
+ const installer = {
29
+ /**
30
+ * @property {Object} log an npm log instance
31
+ */
32
+ log: log,
33
+
34
+ /**
35
+ * Install the given package on the given target device
36
+ * @param {Object} options installation options
37
+ * @options options {Object} device the device to install the package onto, or null to select the default device
38
+ * @param {String} hostPkgPath absolute path on the host of the package to be installed
39
+ * @param {Function} next common-js callback
40
+ */
41
+ install: function(options, hostPkgPath, next, middleCb) {
42
+ if (typeof next !== 'function') {
43
+ throw errHndl.getErrMsg("MISSING_CALLBACK", "next", util.inspect(next));
44
+ }
45
+
46
+ if (!hostPkgPath) {
47
+ return next(errHndl.getErrMsg("EMPTY_VALUE", "PACKAGE_FILE"));
48
+ }
49
+
50
+ const hostPkgName = path.basename(hostPkgPath),
51
+ configData = cliData.getConfig(true),
52
+ config = {
53
+ 'tempDirForIpk': '/media/developer/temp',
54
+ 'changeTempDir': true,
55
+ 'removeIpkAfterInst': true
56
+ };
57
+
58
+ if (configData.install) {
59
+ const conf = configData.install;
60
+ for (const prop in conf) {
61
+ if (Object.prototype.hasOwnProperty.call(config, prop)) {
62
+ config[prop] = conf[prop];
63
+ }
64
+ }
65
+ }
66
+
67
+ const appId = 'com.ares.defaultName',
68
+ devicePkgPath = path.join(config.tempDirForIpk, hostPkgName).replace(/\\/g,'/'),
69
+ os = new streamBuffers.WritableStreamBuffer();
70
+ let srcMd5, dstMd5, md5DataSize = 200;
71
+ options = options || {};
72
+
73
+ log.info('install#install()', 'installing ' + hostPkgPath);
74
+ async.waterfall([
75
+ function(next) {
76
+ options.nReplies = 0; // -i
77
+ makeSession(options, next);
78
+ },
79
+ function(session, next) {
80
+ if (options.opkg) {
81
+ // FIXME: Need more consideration whether this condition is necessary or not.
82
+ if (options.session.getDevice().username !== 'root') {
83
+ return setImmediate(next, errHndl.getErrMsg("NEED_ROOT_PERMISSION", "opkg install"));
84
+ }
85
+ }
86
+ let cmd = '/usr/bin/test -d ' + config.tempDirForIpk + ' || /bin/mkdir -p ' + config.tempDirForIpk;
87
+ if (options.session.getDevice().username === 'root') {
88
+ cmd += ' && /bin/chmod 777 ' + config.tempDirForIpk;
89
+ }
90
+ options.op = (options.session.target.files || 'stream') + 'Put';
91
+ options.session.run(cmd, null, null, null, next);
92
+ },
93
+ function(next) {
94
+ middleCb("Installing package " + hostPkgPath);
95
+ spinner.start();
96
+ options.session.put(hostPkgPath, devicePkgPath, next);
97
+ },
98
+ function(next) {
99
+ options.session.run("/bin/ls -l \"" + devicePkgPath + "\"", null, os, null, next);
100
+ },
101
+ function(next) {
102
+ log.verbose("install#install()", "ls -l:", os.getContents().toString());
103
+ next();
104
+ },
105
+ function(next) {
106
+ const md5 = crypto.createHash('md5'),
107
+ buffer = Buffer.alloc(md5DataSize);
108
+ let pos = 0;
109
+
110
+ async.waterfall([
111
+ fs.lstat.bind(fs, hostPkgPath),
112
+ function(stat, next) {
113
+ if (stat.size > md5DataSize) {
114
+ pos = stat.size-md5DataSize;
115
+ } else {
116
+ pos = 0;
117
+ md5DataSize = stat.size;
118
+ }
119
+ next();
120
+ },
121
+ fs.open.bind(fs, hostPkgPath, 'r'),
122
+ function(fd, next) {
123
+ fs.read(fd, buffer, 0, md5DataSize, pos, function() {
124
+ md5.update(buffer);
125
+ next();
126
+ });
127
+ },
128
+ function() {
129
+ srcMd5 = md5.digest('hex');
130
+ if (!srcMd5) {
131
+ log.warn("install#install()", "Failed to get md5sum from the ipk file");
132
+ }
133
+ log.silly("install#install()", "srcMd5:", srcMd5);
134
+ next();
135
+ }
136
+ ], function(err) {
137
+ next(err);
138
+ });
139
+ },
140
+ function(next) {
141
+ const cmd = "/usr/bin/tail -c " + md5DataSize + " \"" + devicePkgPath + "\" | /usr/bin/md5sum";
142
+ async.series([
143
+ function(next) {
144
+ options.session.run(cmd, null, _onData, null, next);
145
+ }
146
+ ], function(err) {
147
+ if (err) {
148
+ return next(err);
149
+ }
150
+ });
151
+
152
+ function _onData(data) {
153
+ let str;
154
+ if (Buffer.isBuffer(data)) {
155
+ str = data.toString().trim();
156
+ } else {
157
+ str = data.trim();
158
+ }
159
+ if (str) {
160
+ dstMd5 = str.split('-')[0].trim();
161
+ log.silly("install#install()", "dstMd5:", dstMd5);
162
+ }
163
+ if (!dstMd5) {
164
+ log.warn("install#install()", "Failed to get md5sum from the transmitted file");
165
+ }
166
+ next();
167
+ }
168
+ },
169
+ function(next) {
170
+ if (!srcMd5 || !dstMd5) {
171
+ log.warn("install#install()", "Cannot verify transmitted file");
172
+ } else {
173
+ log.verbose("install#install()", "srcMd5:", srcMd5, ", dstMd5:", dstMd5);
174
+ if (srcMd5 !== dstMd5) {
175
+ return next(errHndl.getErrMsg("FAILED_TRANSMIT_FILE"));
176
+ }
177
+ }
178
+ next();
179
+ },
180
+ function(next) {
181
+ const op = (options.opkg) ? _opkg : _appinstalld;
182
+ op(next);
183
+
184
+ function _opkg(next) {
185
+ let cmd = '/usr/bin/opkg install "' + devicePkgPath + '"';
186
+ cmd = cmd.concat((options.opkg_param) ? ' ' + options.opkg_param : '');
187
+
188
+ async.series([
189
+ options.session.run.bind(options.session, cmd, null, __data, __data),
190
+ options.session.run.bind(options.session, '/usr/sbin/ls-control scan-services ', null, null, __data)
191
+ ], function(err) {
192
+ if (err) {
193
+ return next(err);
194
+ }
195
+ next(null, null);
196
+ });
197
+
198
+ function __data(data) {
199
+ const str = (Buffer.isBuffer(data)) ? data.toString() : data;
200
+ middleCb(str.trim());
201
+ }
202
+ }
203
+
204
+ function _appinstalld(next) {
205
+ const target = options.session.getDevice(),
206
+ addr = target.lunaAddr.install,
207
+ returnValue = addr.returnValue.split('.'),
208
+ param = {
209
+ // luna param
210
+ id: appId,
211
+ ipkUrl: devicePkgPath,
212
+ subscribe: true
213
+ };
214
+ options.sessionCall = false;
215
+
216
+ luna.send(options, addr, param, function(lineObj, next) {
217
+ let resultValue = lineObj;
218
+
219
+ for (let index = 1; index < returnValue.length; index++) {
220
+ resultValue = resultValue[returnValue[index]];
221
+ }
222
+
223
+ if (resultValue.match(/FAILED/i)) {
224
+ // failure: stop
225
+ log.verbose("install#install()", "failure");
226
+ const errValue = ((lineObj.details && lineObj.details.reason) ? lineObj.details.reason :
227
+ (resultValue ? resultValue : ''));
228
+ next(errHndl.getErrMsg("FAILED_CALL_LUNA", errValue, null, addr.service));
229
+ } else if (resultValue.match(/installed|^SUCCESS/i)) {
230
+ // success: stop
231
+ log.verbose("install#install()", "success");
232
+ next(null, resultValue);
233
+ } else {
234
+ // no err & no status : continue
235
+ log.verbose("install#install()", "waiting");
236
+ next(null, null);
237
+ }
238
+ }, next);
239
+ }
240
+ },
241
+ function(status, next) {
242
+ if (typeof status === 'function') {
243
+ next = status;
244
+ }
245
+
246
+ if (config.removeIpkAfterInst) {
247
+ options.session.run('/bin/rm -f "' + devicePkgPath + '"', null, null, null, next);
248
+ } else {
249
+ next();
250
+ }
251
+ },
252
+ function(next) {
253
+ next(null, {msg: "Success"});
254
+ }
255
+ ], function(err, result) {
256
+ next(err, result);
257
+ });
258
+ },
259
+
260
+ remove: function(options, packageName, next, middleCb) {
261
+ if (typeof next !== 'function') {
262
+ throw errHndl.getErrMsg("MISSING_CALLBACK", "next", util.inspect(next));
263
+ }
264
+ options = options || {};
265
+ async.waterfall([
266
+ function(next) {
267
+ options.nReplies = 0; // -i
268
+ makeSession(options, next);
269
+ },
270
+ function(session, next) {
271
+ if (options.opkg) {
272
+ // FIXME: Need more consideration whether this condition is necessary or not.
273
+ if (options.session.getDevice().username !== 'root') {
274
+ return setImmediate(next, errHndl.getErrMsg("NEED_ROOT_PERMISSION","opkg remove"));
275
+ }
276
+ }
277
+ setImmediate(next);
278
+ },
279
+ function(next) {
280
+ const op = (options.opkg) ? _opkg : _appinstalld;
281
+ op(next);
282
+
283
+ function _opkg(next) {
284
+ let cmd = '/usr/bin/opkg remove ' + packageName;
285
+ cmd = cmd.concat((options.opkg_param) ? ' ' + options.opkg_param : '');
286
+
287
+ async.series([
288
+ options.session.run.bind(options.session, cmd, null, __data, __error),
289
+ options.session.run.bind(options.session, '/usr/sbin/ls-control scan-services ',null, null, __error)
290
+ ], function(err) {
291
+ if (err) {
292
+ return next(err);
293
+ }
294
+ next(null, {});
295
+ });
296
+
297
+ function __data(data) {
298
+ const str = (Buffer.isBuffer(data)) ? data.toString() : data;
299
+ if (str.match(/No packages installed or removed/g)) {
300
+ return next(errHndl.getErrMsg("FAILED_REMOVE_PACKAGE", packageName));
301
+ } else {
302
+ middleCb(str.trim());
303
+ }
304
+ }
305
+
306
+ function __error(data) {
307
+ const str = (Buffer.isBuffer(data)) ? data.toString() : data;
308
+ return next(new Error(str));
309
+ }
310
+ }
311
+
312
+ function _appinstalld(next) {
313
+ const target = options.session.getDevice(),
314
+ addr = target.lunaAddr.remove,
315
+ returnValue = addr.returnValue.split('.'),
316
+ param = {
317
+ // luna param
318
+ id: packageName,
319
+ subscribe: true
320
+ };
321
+ let exit = 0;
322
+ options.sessionCall = false;
323
+
324
+ luna.send(options, addr, param, function(lineObj, next) {
325
+ let resultValue = lineObj;
326
+
327
+ for (let index = 1; index < returnValue.length; index++) {
328
+ resultValue = resultValue[returnValue[index]];
329
+ }
330
+
331
+ if (resultValue.match(/FAILED/i)) {
332
+ // failure: stop
333
+ log.verbose("install#remove()", "failure");
334
+ if (!exit) {
335
+ exit++;
336
+ const errValue = ((lineObj.details && lineObj.details.reason) ? lineObj.details.reason :
337
+ (resultValue ? resultValue : ''));
338
+ next(errHndl.getErrMsg("FAILED_CALL_LUNA", errValue, null, addr.service));
339
+ }
340
+ } else if (resultValue.match(/removed|^SUCCESS/i)) {
341
+ log.verbose("install#remove()", "success");
342
+ // success: stop
343
+ next(null, {
344
+ status: resultValue
345
+ });
346
+ } else {
347
+ // no err & no status : continue
348
+ log.verbose("install#remove()", "waiting");
349
+ next();
350
+ }
351
+ }, next);
352
+ }
353
+ }
354
+ ], function(err, result) {
355
+ log.silly("install#remove()", "err:", err, ", result:", result);
356
+ if (!err) {
357
+ result.msg = 'Removed package ' + packageName;
358
+ }
359
+ next(err, result);
360
+ });
361
+ },
362
+
363
+ list: function(options, next, middleCb) {
364
+ if (typeof next !== 'function') {
365
+ throw errHndl.getErrMsg("MISSING_CALLBACK", "next", util.inspect(next));
366
+ }
367
+ options = options || {};
368
+ async.series([
369
+ function(next) {
370
+ options.nReplies = 1; // -n 1
371
+ makeSession(options, next);
372
+ },
373
+ function(next) {
374
+ if (options.opkg) {
375
+ // FIXME: Need more consideration whether this condition is necessary or not.
376
+ if (options.session.getDevice().username !== 'root') {
377
+ return setImmediate(next, errHndl.getErrMsg("NEED_ROOT_PERMISSION", "opkg list"));
378
+ }
379
+ }
380
+ setImmediate(next);
381
+ },
382
+ function(next) {
383
+ sessionLib.getSessionList(options, next);
384
+ },
385
+ function(next) {
386
+ const op = (options.opkg) ? _opkg : _appinstalld;
387
+ op(next);
388
+
389
+ function _opkg(next) {
390
+ let cmd = '/usr/bin/opkg list';
391
+ cmd = cmd.concat((options.opkg_param) ? ' ' + options.opkg_param : '');
392
+
393
+ async.series([
394
+ options.session.run.bind(options.session, cmd,
395
+ null, __data, __data)
396
+ ], function(err) {
397
+ if (err) {
398
+ return next(err);
399
+ }
400
+ next(null, {});
401
+ });
402
+
403
+ function __data(data) {
404
+ const str = (Buffer.isBuffer(data)) ? data.toString() : data;
405
+ middleCb(str.trim());
406
+ }
407
+ }
408
+
409
+ function _appinstalld(next) {
410
+ const addr = options.session.getDevice().lunaAddr.list,
411
+ returnValue = addr.returnValue.split('.'),
412
+ param = {
413
+ // luna param
414
+ subscribe: false
415
+ };
416
+
417
+ luna.send(options, addr, param, function(lineObj, next) {
418
+ let resultValue = lineObj;
419
+ for (let index = 1; index < returnValue.length; index++) {
420
+ resultValue = resultValue[returnValue[index]];
421
+ }
422
+
423
+ if (Array.isArray(resultValue)) {
424
+ // success: stop
425
+ for (let index = 0; index < resultValue.length; index++) {
426
+ if (!resultValue[index].visible) {
427
+ resultValue.splice(index, 1);
428
+ index--;
429
+ }
430
+ }
431
+ log.verbose("install#list()", "success");
432
+ next(null, resultValue);
433
+ } else {
434
+ // failure: stop
435
+ log.verbose("install#list()", "failure");
436
+ next(errHndl.getErrMsg("INVALID_OBJECT"));
437
+ }
438
+
439
+ }, next);
440
+ }
441
+ }
442
+ ], function(err, results) {
443
+ log.silly("install#list()", "err:", err, ", results:", results[3]);
444
+ next(err, results[3]);
445
+ });
446
+ }
447
+ };
448
+
449
+ function makeSession(options, next) {
450
+ if (!options.session) {
451
+ log.info("install#makeSession()", "need to make new session");
452
+ const printTarget = true;
453
+ options.session = new novacom.Session(options.device, printTarget, next);
454
+ } else {
455
+ log.info("install#makeSession()", "already exist session");
456
+ next(null, options.session);
457
+ }
458
+ }
459
+
460
+ if (typeof module !== 'undefined' && module.exports) {
461
+ module.exports = installer;
462
+ }
463
+ }());