aaden-cli 1.6.108 → 1.6.109-rc.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.
package/dist/index.js CHANGED
@@ -99,7 +99,7 @@ const {hillo} = __nccwpck_require__(6365)
99
99
  const version = (__nccwpck_require__(4147)/* .version */ .i8)
100
100
  const colors = __nccwpck_require__(3045)
101
101
  const defaultData = {
102
- frontendVersion: '', cliVersion: '', diskUsage: '', upTime: '', ngrokIsNew: false, hostInfo: {}
102
+ frontendVersion: '', cliVersion: '', diskUsage: '', upTime: '', ngrokIsNew: false, hostInfo: {}, tseInfo: {}
103
103
  }
104
104
 
105
105
  async function deviceEcho(data) {
@@ -110,7 +110,7 @@ async function deviceEcho(data) {
110
110
  Object.entries(data).forEach(en => {
111
111
  console.log(...en)
112
112
  })
113
- const {frontendVersion, cliVersion, diskUsage, upTime, ngrokIsNew, hostInfo} = Object.assign({}, defaultData, data)
113
+ const {frontendVersion, cliVersion, diskUsage, upTime, ngrokIsNew, hostInfo, tseInfo} = Object.assign({}, defaultData, data)
114
114
  if (parseInt(myDeviceId) === -1) {
115
115
  return
116
116
  }
@@ -132,7 +132,8 @@ async function deviceEcho(data) {
132
132
  lastUptime: upTime,
133
133
  ngrokOk: ngrokIsNew,
134
134
  deviceName: `${name}\n${adress1}\n${postCode} ${city} ${state}`,
135
- ...hostInfo
135
+ ...hostInfo,
136
+ ...tseInfo
136
137
  })
137
138
  console.log('report to remote server complete')
138
139
  } catch (e) {
@@ -249,6 +250,157 @@ function collectHostInfo() {
249
250
  module.exports = {collectHostInfo}
250
251
 
251
252
 
253
+ /***/ }),
254
+
255
+ /***/ 6677:
256
+ /***/ ((module, __unused_webpack_exports, __nccwpck_require__) => {
257
+
258
+ const fs = __nccwpck_require__(7147)
259
+ const os = __nccwpck_require__(2037)
260
+ const http = __nccwpck_require__(3685)
261
+ const https = __nccwpck_require__(5687)
262
+
263
+ // do-log 顺带上报的 TSE 适配服务(TseHost)信息,用来在云端看车队的 TSE 版本和服务状态。
264
+ // WSL 门店的 TseHost 跑在 Windows 侧,网站目录里的 jar 不一定是实际在跑的那个,
265
+ // 所以和 PHP 一样按 config.ini 的 [TSE] TseHost 去访问服务,jar 也按服务配置去找。
266
+ // 每一项单独兜底:探测失败就报 null,不能让 do-log 本身挂掉。
267
+
268
+ const CONFIG_INI = '/var/www/html/Resource/config/config.ini'
269
+ const DEFAULT_TSE_HOST = 'http://localhost:8014'
270
+ // Linux:aaden-tse.service 执行 tseServing.sh,里面 java -jar 的那个 jar
271
+ const LINUX_SERVING_SCRIPT = '/var/www/html/TseHost/tseServing.sh'
272
+ const LINUX_DEFAULT_JAR = '/var/www/html/TseHost/tse-0.0.2.jar'
273
+ // Windows(WSL 门店):WinSW 服务目录,jar 名写在 AadenTseServiceRegister.xml 里
274
+ const WINDOWS_USERS_DIR = '/mnt/c/Users'
275
+ const WINDOWS_TSE_DIR = 'Desktop/AadenTseOnWindows'
276
+ const WINDOWS_DEFAULT_JAR = 'tse-0.0.3.jar'
277
+ // 和 PHP 的 Api.php 一样给 3 秒
278
+ const PROBE_TIMEOUT_MS = 3000
279
+
280
+ async function safe(fn, fallback = null) {
281
+ try {
282
+ const value = await fn()
283
+ return value === undefined ? fallback : value
284
+ } catch (e) {
285
+ return fallback
286
+ }
287
+ }
288
+
289
+ function readTseSection() {
290
+ const section = {}
291
+ let inTse = false
292
+ for (const raw of fs.readFileSync(CONFIG_INI, 'utf-8').split(/\r?\n/)) {
293
+ const line = raw.trim()
294
+ if (!line || line.startsWith(';') || line.startsWith('#')) continue
295
+ const header = line.match(/^\[(.+)]$/)
296
+ if (header) {
297
+ inTse = header[1].trim() === 'TSE'
298
+ continue
299
+ }
300
+ if (!inTse) continue
301
+ const eq = line.indexOf('=')
302
+ if (eq < 0) continue
303
+ section[line.slice(0, eq).trim()] = line.slice(eq + 1).trim().replace(/^"(.*)"$/, '$1')
304
+ }
305
+ return section
306
+ }
307
+
308
+ // 与 PHP 的 INI_SCANNER_TYPED 一致:true/on/yes 为真,数字按非 0 为真
309
+ function parseEnabled(value) {
310
+ if (value === undefined) return false
311
+ const v = String(value).trim().toLowerCase()
312
+ if (['true', 'on', 'yes'].includes(v)) return true
313
+ if (/^-?\d+$/.test(v)) return parseInt(v, 10) !== 0
314
+ return false
315
+ }
316
+
317
+ // 连不上(服务没起、Windows 侧没开、超时)统一当作 status 0
318
+ function httpGet(url) {
319
+ return new Promise(resolve => {
320
+ // 兜底:响应中途断掉时 end 不会触发,不能让 do-log 卡在这里
321
+ const timer = setTimeout(() => resolve({status: 0, body: ''}), PROBE_TIMEOUT_MS + 1000)
322
+ const done = result => {
323
+ clearTimeout(timer)
324
+ resolve(result)
325
+ }
326
+ try {
327
+ const client = url.startsWith('https:') ? https : http
328
+ const req = client.get(url, {timeout: PROBE_TIMEOUT_MS}, res => {
329
+ let body = ''
330
+ res.setEncoding('utf-8')
331
+ res.on('data', chunk => {
332
+ if (body.length < 4096) body += chunk
333
+ })
334
+ res.on('end', () => done({status: res.statusCode, body}))
335
+ res.on('error', () => done({status: 0, body: ''}))
336
+ })
337
+ req.on('timeout', () => req.destroy(new Error('timeout')))
338
+ req.on('error', () => done({status: 0, body: ''}))
339
+ } catch (e) {
340
+ done({status: 0, body: ''})
341
+ }
342
+ })
343
+ }
344
+
345
+ function servingJarPath() {
346
+ if (/microsoft|wsl/i.test(os.release()) && fs.existsSync(WINDOWS_USERS_DIR)) {
347
+ for (const user of fs.readdirSync(WINDOWS_USERS_DIR)) {
348
+ const dir = `${WINDOWS_USERS_DIR}/${user}/${WINDOWS_TSE_DIR}`
349
+ const xml = `${dir}/AadenTseServiceRegister.xml`
350
+ if (!fs.existsSync(xml)) continue
351
+ const match = fs.readFileSync(xml, 'utf-8').match(/-jar\s+"?%BASE%\\([^"\s]+\.jar)/i)
352
+ return `${dir}/${match ? match[1] : WINDOWS_DEFAULT_JAR}`
353
+ }
354
+ // 没找到 Windows 侧的服务目录:按 Linux 的装法找
355
+ }
356
+ if (!fs.existsSync(LINUX_SERVING_SCRIPT)) return LINUX_DEFAULT_JAR
357
+ const match = fs.readFileSync(LINUX_SERVING_SCRIPT, 'utf-8').match(/-jar\s+(\S+\.jar)/)
358
+ return match ? match[1] : LINUX_DEFAULT_JAR
359
+ }
360
+
361
+ async function probeTse() {
362
+ const section = await safe(readTseSection, {})
363
+ const tseEnabled = parseEnabled(section.TseEnabled)
364
+ const tseHost = (section.TseHost || DEFAULT_TSE_HOST).replace(/\/+$/, '')
365
+ // 不同版本的 jar 大小不同,没有 /adapterVersion 的老版本只能靠它区分
366
+ const tseJarSize = await safe(() => {
367
+ const jar = servingJarPath()
368
+ return jar && fs.existsSync(jar) ? fs.statSync(jar).size : null
369
+ })
370
+
371
+ if (!tseEnabled) {
372
+ return {tseEnabled, tseHost, tseStatus: 'disabled', tseAdapterVersion: null, tseJarSize}
373
+ }
374
+
375
+ // ok:TSE 正常;error:服务在但 TSE 在自检 / 没初始化 / 硬件报错;down:服务连不上
376
+ const ping = await httpGet(`${tseHost}/ping`)
377
+ const tseStatus = ping.status === 0 ? 'down' : (ping.status === 200 ? 'ok' : 'error')
378
+
379
+ // 连不上时报 null,云端保留上次的版本;服务在但没有这个接口(2024-09 之前的构建)报空串
380
+ let tseAdapterVersion = null
381
+ if (ping.status !== 0) {
382
+ const res = await httpGet(`${tseHost}/adapterVersion`)
383
+ if (res.status === 200) {
384
+ tseAdapterVersion = await safe(() => {
385
+ const major = JSON.parse(res.body).major
386
+ return major === undefined || major === null ? null : String(major)
387
+ })
388
+ } else if (res.status === 404) {
389
+ tseAdapterVersion = ''
390
+ }
391
+ }
392
+
393
+ return {tseEnabled, tseHost, tseStatus, tseAdapterVersion, tseJarSize}
394
+ }
395
+
396
+ // 整体出错就什么都不报,云端保留上次的值
397
+ async function collectTseInfo() {
398
+ return safe(probeTse, {})
399
+ }
400
+
401
+ module.exports = {collectTseInfo}
402
+
403
+
252
404
  /***/ }),
253
405
 
254
406
  /***/ 6545:
@@ -18577,7 +18729,7 @@ module.exports = JSON.parse('{"name":"axios","version":"0.19.2","description":"P
18577
18729
  /***/ ((module) => {
18578
18730
 
18579
18731
  "use strict";
18580
- module.exports = {"i8":"1.6.108"};
18732
+ module.exports = JSON.parse('{"i8":"1.6.109-rc.0"}');
18581
18733
 
18582
18734
  /***/ })
18583
18735
 
@@ -18664,6 +18816,7 @@ const InnerKenTimeStampFormat = 'YYYYMMDDHHmmss'
18664
18816
  const prompts = __nccwpck_require__(9646)
18665
18817
  const {deviceEcho, logAction, getCurrentDeviceId} = __nccwpck_require__(7415)
18666
18818
  const {collectHostInfo} = __nccwpck_require__(3727)
18819
+ const {collectTseInfo} = __nccwpck_require__(6677)
18667
18820
  const GlobalDeviceId = 'notset'
18668
18821
 
18669
18822
  const {program} = __nccwpck_require__(1904)
@@ -19540,7 +19693,8 @@ async function doLog() {
19540
19693
  diskUsage: diskUsage[diskUsage.length - 1].replace('\n', ''),
19541
19694
  upTime: getUpTime(),
19542
19695
  ngrokIsNew: ngrokNewestVersion(),
19543
- hostInfo: collectHostInfo()
19696
+ hostInfo: collectHostInfo(),
19697
+ tseInfo: await collectTseInfo()
19544
19698
  }
19545
19699
  )
19546
19700
  console.log('finish')
package/index.js CHANGED
@@ -13,6 +13,7 @@ const InnerKenTimeStampFormat = 'YYYYMMDDHHmmss'
13
13
  const prompts = require('prompts')
14
14
  const {deviceEcho, logAction, getCurrentDeviceId} = require('./modules/firebase')
15
15
  const {collectHostInfo} = require('./modules/host-info')
16
+ const {collectTseInfo} = require('./modules/tse-info')
16
17
  const GlobalDeviceId = 'notset'
17
18
 
18
19
  const {program} = require('commander')
@@ -889,7 +890,8 @@ async function doLog() {
889
890
  diskUsage: diskUsage[diskUsage.length - 1].replace('\n', ''),
890
891
  upTime: getUpTime(),
891
892
  ngrokIsNew: ngrokNewestVersion(),
892
- hostInfo: collectHostInfo()
893
+ hostInfo: collectHostInfo(),
894
+ tseInfo: await collectTseInfo()
893
895
  }
894
896
  )
895
897
  console.log('finish')
@@ -3,7 +3,7 @@ const {hillo} = require('hillo')
3
3
  const version = require('./../package.json').version
4
4
  const colors = require('colors')
5
5
  const defaultData = {
6
- frontendVersion: '', cliVersion: '', diskUsage: '', upTime: '', ngrokIsNew: false, hostInfo: {}
6
+ frontendVersion: '', cliVersion: '', diskUsage: '', upTime: '', ngrokIsNew: false, hostInfo: {}, tseInfo: {}
7
7
  }
8
8
 
9
9
  export async function deviceEcho(data) {
@@ -14,7 +14,7 @@ export async function deviceEcho(data) {
14
14
  Object.entries(data).forEach(en => {
15
15
  console.log(...en)
16
16
  })
17
- const {frontendVersion, cliVersion, diskUsage, upTime, ngrokIsNew, hostInfo} = Object.assign({}, defaultData, data)
17
+ const {frontendVersion, cliVersion, diskUsage, upTime, ngrokIsNew, hostInfo, tseInfo} = Object.assign({}, defaultData, data)
18
18
  if (parseInt(myDeviceId) === -1) {
19
19
  return
20
20
  }
@@ -36,7 +36,8 @@ export async function deviceEcho(data) {
36
36
  lastUptime: upTime,
37
37
  ngrokOk: ngrokIsNew,
38
38
  deviceName: `${name}\n${adress1}\n${postCode} ${city} ${state}`,
39
- ...hostInfo
39
+ ...hostInfo,
40
+ ...tseInfo
40
41
  })
41
42
  console.log('report to remote server complete')
42
43
  } catch (e) {
@@ -0,0 +1,144 @@
1
+ const fs = require('fs')
2
+ const os = require('os')
3
+ const http = require('http')
4
+ const https = require('https')
5
+
6
+ // do-log 顺带上报的 TSE 适配服务(TseHost)信息,用来在云端看车队的 TSE 版本和服务状态。
7
+ // WSL 门店的 TseHost 跑在 Windows 侧,网站目录里的 jar 不一定是实际在跑的那个,
8
+ // 所以和 PHP 一样按 config.ini 的 [TSE] TseHost 去访问服务,jar 也按服务配置去找。
9
+ // 每一项单独兜底:探测失败就报 null,不能让 do-log 本身挂掉。
10
+
11
+ const CONFIG_INI = '/var/www/html/Resource/config/config.ini'
12
+ const DEFAULT_TSE_HOST = 'http://localhost:8014'
13
+ // Linux:aaden-tse.service 执行 tseServing.sh,里面 java -jar 的那个 jar
14
+ const LINUX_SERVING_SCRIPT = '/var/www/html/TseHost/tseServing.sh'
15
+ const LINUX_DEFAULT_JAR = '/var/www/html/TseHost/tse-0.0.2.jar'
16
+ // Windows(WSL 门店):WinSW 服务目录,jar 名写在 AadenTseServiceRegister.xml 里
17
+ const WINDOWS_USERS_DIR = '/mnt/c/Users'
18
+ const WINDOWS_TSE_DIR = 'Desktop/AadenTseOnWindows'
19
+ const WINDOWS_DEFAULT_JAR = 'tse-0.0.3.jar'
20
+ // 和 PHP 的 Api.php 一样给 3 秒
21
+ const PROBE_TIMEOUT_MS = 3000
22
+
23
+ async function safe(fn, fallback = null) {
24
+ try {
25
+ const value = await fn()
26
+ return value === undefined ? fallback : value
27
+ } catch (e) {
28
+ return fallback
29
+ }
30
+ }
31
+
32
+ function readTseSection() {
33
+ const section = {}
34
+ let inTse = false
35
+ for (const raw of fs.readFileSync(CONFIG_INI, 'utf-8').split(/\r?\n/)) {
36
+ const line = raw.trim()
37
+ if (!line || line.startsWith(';') || line.startsWith('#')) continue
38
+ const header = line.match(/^\[(.+)]$/)
39
+ if (header) {
40
+ inTse = header[1].trim() === 'TSE'
41
+ continue
42
+ }
43
+ if (!inTse) continue
44
+ const eq = line.indexOf('=')
45
+ if (eq < 0) continue
46
+ section[line.slice(0, eq).trim()] = line.slice(eq + 1).trim().replace(/^"(.*)"$/, '$1')
47
+ }
48
+ return section
49
+ }
50
+
51
+ // 与 PHP 的 INI_SCANNER_TYPED 一致:true/on/yes 为真,数字按非 0 为真
52
+ function parseEnabled(value) {
53
+ if (value === undefined) return false
54
+ const v = String(value).trim().toLowerCase()
55
+ if (['true', 'on', 'yes'].includes(v)) return true
56
+ if (/^-?\d+$/.test(v)) return parseInt(v, 10) !== 0
57
+ return false
58
+ }
59
+
60
+ // 连不上(服务没起、Windows 侧没开、超时)统一当作 status 0
61
+ function httpGet(url) {
62
+ return new Promise(resolve => {
63
+ // 兜底:响应中途断掉时 end 不会触发,不能让 do-log 卡在这里
64
+ const timer = setTimeout(() => resolve({status: 0, body: ''}), PROBE_TIMEOUT_MS + 1000)
65
+ const done = result => {
66
+ clearTimeout(timer)
67
+ resolve(result)
68
+ }
69
+ try {
70
+ const client = url.startsWith('https:') ? https : http
71
+ const req = client.get(url, {timeout: PROBE_TIMEOUT_MS}, res => {
72
+ let body = ''
73
+ res.setEncoding('utf-8')
74
+ res.on('data', chunk => {
75
+ if (body.length < 4096) body += chunk
76
+ })
77
+ res.on('end', () => done({status: res.statusCode, body}))
78
+ res.on('error', () => done({status: 0, body: ''}))
79
+ })
80
+ req.on('timeout', () => req.destroy(new Error('timeout')))
81
+ req.on('error', () => done({status: 0, body: ''}))
82
+ } catch (e) {
83
+ done({status: 0, body: ''})
84
+ }
85
+ })
86
+ }
87
+
88
+ function servingJarPath() {
89
+ if (/microsoft|wsl/i.test(os.release()) && fs.existsSync(WINDOWS_USERS_DIR)) {
90
+ for (const user of fs.readdirSync(WINDOWS_USERS_DIR)) {
91
+ const dir = `${WINDOWS_USERS_DIR}/${user}/${WINDOWS_TSE_DIR}`
92
+ const xml = `${dir}/AadenTseServiceRegister.xml`
93
+ if (!fs.existsSync(xml)) continue
94
+ const match = fs.readFileSync(xml, 'utf-8').match(/-jar\s+"?%BASE%\\([^"\s]+\.jar)/i)
95
+ return `${dir}/${match ? match[1] : WINDOWS_DEFAULT_JAR}`
96
+ }
97
+ // 没找到 Windows 侧的服务目录:按 Linux 的装法找
98
+ }
99
+ if (!fs.existsSync(LINUX_SERVING_SCRIPT)) return LINUX_DEFAULT_JAR
100
+ const match = fs.readFileSync(LINUX_SERVING_SCRIPT, 'utf-8').match(/-jar\s+(\S+\.jar)/)
101
+ return match ? match[1] : LINUX_DEFAULT_JAR
102
+ }
103
+
104
+ async function probeTse() {
105
+ const section = await safe(readTseSection, {})
106
+ const tseEnabled = parseEnabled(section.TseEnabled)
107
+ const tseHost = (section.TseHost || DEFAULT_TSE_HOST).replace(/\/+$/, '')
108
+ // 不同版本的 jar 大小不同,没有 /adapterVersion 的老版本只能靠它区分
109
+ const tseJarSize = await safe(() => {
110
+ const jar = servingJarPath()
111
+ return jar && fs.existsSync(jar) ? fs.statSync(jar).size : null
112
+ })
113
+
114
+ if (!tseEnabled) {
115
+ return {tseEnabled, tseHost, tseStatus: 'disabled', tseAdapterVersion: null, tseJarSize}
116
+ }
117
+
118
+ // ok:TSE 正常;error:服务在但 TSE 在自检 / 没初始化 / 硬件报错;down:服务连不上
119
+ const ping = await httpGet(`${tseHost}/ping`)
120
+ const tseStatus = ping.status === 0 ? 'down' : (ping.status === 200 ? 'ok' : 'error')
121
+
122
+ // 连不上时报 null,云端保留上次的版本;服务在但没有这个接口(2024-09 之前的构建)报空串
123
+ let tseAdapterVersion = null
124
+ if (ping.status !== 0) {
125
+ const res = await httpGet(`${tseHost}/adapterVersion`)
126
+ if (res.status === 200) {
127
+ tseAdapterVersion = await safe(() => {
128
+ const major = JSON.parse(res.body).major
129
+ return major === undefined || major === null ? null : String(major)
130
+ })
131
+ } else if (res.status === 404) {
132
+ tseAdapterVersion = ''
133
+ }
134
+ }
135
+
136
+ return {tseEnabled, tseHost, tseStatus, tseAdapterVersion, tseJarSize}
137
+ }
138
+
139
+ // 整体出错就什么都不报,云端保留上次的值
140
+ async function collectTseInfo() {
141
+ return safe(probeTse, {})
142
+ }
143
+
144
+ module.exports = {collectTseInfo}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "aaden-cli",
3
- "version": "1.6.108",
3
+ "version": "1.6.109-rc.0",
4
4
  "description": "",
5
5
  "main": "dist/index.js",
6
6
  "scripts": {