@xbongbong/xbbcli 2.1.1 → 2.4.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 (263) hide show
  1. package/README.md +97 -6
  2. package/auth-login.js +306 -0
  3. package/auth-logout.js +175 -0
  4. package/auth-status.js +105 -0
  5. package/bin/xbbcli.js +15 -2
  6. package/buyer-inquiry-detail.js +2 -14
  7. package/buyer-inquiry-list.js +2 -14
  8. package/clue-add-couser.js +2 -14
  9. package/clue-add.js +2 -14
  10. package/clue-back.js +2 -14
  11. package/clue-del.js +2 -14
  12. package/clue-delete-couser.js +2 -14
  13. package/clue-delete-mainuser.js +2 -14
  14. package/clue-detail.js +2 -14
  15. package/clue-distribution.js +2 -14
  16. package/clue-edit.js +2 -14
  17. package/clue-handover.js +3 -15
  18. package/clue-list.js +2 -14
  19. package/clue-thorough-delete.js +2 -14
  20. package/communicate-add.js +2 -14
  21. package/communicate-del.js +2 -14
  22. package/communicate-detail.js +2 -14
  23. package/communicate-edit.js +2 -14
  24. package/communicate-list.js +2 -14
  25. package/communicate-plan-add.js +2 -14
  26. package/communicate-plan-cancel.js +2 -14
  27. package/communicate-plan-del.js +2 -14
  28. package/communicate-plan-detail.js +2 -14
  29. package/communicate-plan-list.js +2 -14
  30. package/communicate-plan-single-operate.js +2 -14
  31. package/contact-add-couser.js +2 -14
  32. package/contact-add-mainuser.js +2 -14
  33. package/contact-add.js +2 -14
  34. package/contact-del.js +2 -14
  35. package/contact-delete-couser.js +2 -14
  36. package/contact-delete-mainuser.js +2 -14
  37. package/contact-detail.js +2 -14
  38. package/contact-edit.js +2 -14
  39. package/contact-handover.js +2 -14
  40. package/contact-list.js +2 -14
  41. package/contract-add-couser.js +2 -14
  42. package/contract-add-mainuser.js +2 -14
  43. package/contract-add.js +2 -14
  44. package/contract-del.js +2 -14
  45. package/contract-delete-couser.js +2 -14
  46. package/contract-delete-mainuser.js +2 -14
  47. package/contract-detail.js +2 -14
  48. package/contract-edit.js +2 -14
  49. package/contract-handover.js +2 -14
  50. package/contract-list.js +2 -14
  51. package/contract-outstock-add.js +2 -14
  52. package/contract-outstock-del.js +2 -14
  53. package/contract-outstock-detail.js +2 -14
  54. package/contract-outstock-edit.js +2 -14
  55. package/contract-outstock-list.js +2 -14
  56. package/customer-add-couser.js +2 -14
  57. package/customer-add.js +2 -14
  58. package/customer-back.js +2 -14
  59. package/customer-del.js +2 -14
  60. package/customer-delete-couser.js +2 -14
  61. package/customer-delete-mainuser.js +2 -14
  62. package/customer-detail.js +2 -14
  63. package/customer-distribution.js +2 -14
  64. package/customer-edit.js +2 -14
  65. package/customer-handover.js +2 -14
  66. package/customer-invoice-address-add.js +2 -14
  67. package/customer-invoice-address-edit.js +2 -14
  68. package/customer-invoice-address.js +2 -14
  69. package/customer-invoice-info-add.js +2 -14
  70. package/customer-invoice-info-edit.js +2 -14
  71. package/customer-invoice-info.js +2 -14
  72. package/customer-list.js +2 -14
  73. package/department-add.js +2 -14
  74. package/department-del.js +2 -14
  75. package/department-edit.js +2 -14
  76. package/department-list.js +2 -14
  77. package/form-data-add-couser.js +2 -14
  78. package/form-data-add-mainuser.js +2 -14
  79. package/form-data-add.js +2 -14
  80. package/form-data-del.js +2 -14
  81. package/form-data-delete-couser.js +2 -14
  82. package/form-data-delete-mainuser.js +2 -14
  83. package/form-data-detail.js +2 -14
  84. package/form-data-edit.js +2 -14
  85. package/form-data-handover.js +2 -14
  86. package/form-data-list.js +2 -14
  87. package/form-get.js +2 -14
  88. package/form-list.js +2 -14
  89. package/{ai-call-add-task.js → hkh-call-add-task.js} +4 -16
  90. package/{ai-word-list.js → hkh-word-list.js} +4 -16
  91. package/invoice-add.js +3 -15
  92. package/invoice-cancel.js +3 -15
  93. package/invoice-del.js +3 -15
  94. package/invoice-detail.js +3 -15
  95. package/invoice-edit.js +3 -15
  96. package/invoice-get-amount-detail.js +3 -15
  97. package/invoice-list.js +3 -15
  98. package/invoice-red.js +3 -15
  99. package/label-add.js +3 -15
  100. package/label-all-list.js +3 -15
  101. package/label-batch-add.js +3 -15
  102. package/label-batch-remove.js +3 -15
  103. package/label-del-completely.js +3 -15
  104. package/label-del.js +3 -15
  105. package/label-edit.js +3 -15
  106. package/label-group-add.js +3 -15
  107. package/label-group-del.js +3 -15
  108. package/label-group-list.js +3 -15
  109. package/label-group-update.js +3 -15
  110. package/label-list.js +3 -15
  111. package/label-reduction.js +3 -15
  112. package/label-repeat.js +3 -15
  113. package/market-activity-add.js +2 -14
  114. package/market-activity-del.js +2 -14
  115. package/market-activity-detail.js +2 -14
  116. package/market-activity-edit.js +2 -14
  117. package/market-activity-handover.js +2 -14
  118. package/market-activity-list.js +2 -14
  119. package/opportunity-add-couser.js +2 -14
  120. package/opportunity-add-mainuser.js +2 -14
  121. package/opportunity-add.js +2 -14
  122. package/opportunity-del.js +2 -14
  123. package/opportunity-delete-couser.js +2 -14
  124. package/opportunity-delete-mainuser.js +2 -14
  125. package/opportunity-detail.js +2 -14
  126. package/opportunity-edit.js +2 -14
  127. package/opportunity-handover.js +2 -14
  128. package/opportunity-list.js +2 -14
  129. package/package.json +2 -2
  130. package/pay-plan-add-couser.js +2 -14
  131. package/pay-plan-add-mainuser.js +2 -14
  132. package/pay-plan-add.js +2 -14
  133. package/pay-plan-delete-couser.js +2 -14
  134. package/pay-plan-delete-mainuser.js +2 -14
  135. package/pay-plan-handover.js +2 -14
  136. package/pay-sheet-add-bad.js +2 -14
  137. package/pay-sheet-add-couser.js +2 -14
  138. package/pay-sheet-add-mainuser.js +2 -14
  139. package/pay-sheet-add-red.js +2 -14
  140. package/pay-sheet-add-write-off.js +2 -14
  141. package/pay-sheet-del.js +2 -14
  142. package/pay-sheet-delete-couser.js +2 -14
  143. package/pay-sheet-delete-mainuser.js +2 -14
  144. package/pay-sheet-detail.js +2 -14
  145. package/pay-sheet-edit-bad.js +2 -14
  146. package/pay-sheet-edit-red.js +2 -14
  147. package/pay-sheet-edit-write-off.js +2 -14
  148. package/pay-sheet-get-amount-detail.js +2 -14
  149. package/pay-sheet-list.js +2 -14
  150. package/payment-add-couser.js +2 -14
  151. package/payment-add-mainuser.js +2 -14
  152. package/payment-add.js +2 -14
  153. package/payment-del.js +2 -14
  154. package/payment-delete-couser.js +2 -14
  155. package/payment-delete-mainuser.js +2 -14
  156. package/payment-detail.js +2 -14
  157. package/payment-edit.js +2 -14
  158. package/payment-handover.js +2 -14
  159. package/payment-list.js +2 -14
  160. package/payment-sheet-add-bad-debt.js +2 -14
  161. package/payment-sheet-add-pre.js +2 -14
  162. package/payment-sheet-add-red.js +2 -14
  163. package/payment-sheet-add-write-off.js +2 -14
  164. package/payment-sheet-del.js +2 -14
  165. package/payment-sheet-detail.js +2 -14
  166. package/payment-sheet-edit-bad-debt.js +2 -14
  167. package/payment-sheet-edit-red.js +2 -14
  168. package/payment-sheet-edit-write-off.js +2 -14
  169. package/payment-sheet-get-amount-detail.js +2 -14
  170. package/payment-sheet-handover.js +2 -14
  171. package/payment-sheet-list.js +2 -14
  172. package/product-add.js +2 -14
  173. package/product-category-add.js +2 -14
  174. package/product-category-del.js +2 -14
  175. package/product-category-list.js +2 -14
  176. package/product-category-update.js +2 -14
  177. package/product-del.js +2 -14
  178. package/product-detail.js +2 -14
  179. package/product-edit.js +2 -14
  180. package/product-list.js +2 -14
  181. package/product-online.js +2 -14
  182. package/quotation-add-couser.js +3 -15
  183. package/quotation-add-mainuser.js +3 -15
  184. package/quotation-add.js +3 -15
  185. package/quotation-del.js +3 -15
  186. package/quotation-delete-couser.js +3 -15
  187. package/quotation-delete-mainuser.js +3 -15
  188. package/quotation-detail.js +3 -15
  189. package/quotation-edit.js +3 -15
  190. package/quotation-handover.js +2 -14
  191. package/quotation-list.js +3 -15
  192. package/refund-add.js +2 -14
  193. package/refund-del.js +2 -14
  194. package/refund-detail.js +2 -14
  195. package/refund-edit.js +2 -14
  196. package/refund-list.js +2 -14
  197. package/role-list.js +2 -14
  198. package/sign-in-list.js +2 -14
  199. package/stage-get.js +2 -14
  200. package/stage-jump.js +2 -14
  201. package/supplier-add.js +2 -14
  202. package/token-del.js +5 -0
  203. package/token-generate.js +2 -14
  204. package/token-list.js +20 -2
  205. package/token-set.js +6 -374
  206. package/token-use.js +5 -0
  207. package/user-add.js +2 -14
  208. package/user-del.js +2 -14
  209. package/user-edit.js +2 -14
  210. package/user-handover.js +2 -14
  211. package/user-list.js +2 -14
  212. package/work-order-add.js +2 -14
  213. package/work-order-asset-add-couser.js +3 -15
  214. package/work-order-asset-add-mainuser.js +3 -15
  215. package/work-order-asset-add.js +3 -15
  216. package/work-order-asset-del-couser.js +3 -15
  217. package/work-order-asset-del-mainuser.js +3 -15
  218. package/work-order-asset-del.js +3 -15
  219. package/work-order-asset-detail.js +3 -15
  220. package/work-order-asset-edit.js +3 -15
  221. package/work-order-asset-handover.js +3 -15
  222. package/work-order-asset-list.js +3 -15
  223. package/work-order-del.js +2 -14
  224. package/work-order-detail.js +2 -14
  225. package/work-order-dynamic-list.js +2 -14
  226. package/work-order-edit.js +2 -14
  227. package/work-order-list.js +2 -14
  228. package/work-order-operate.js +2 -14
  229. package/work-order-template-detail.js +2 -14
  230. package/work-order-template-list.js +2 -14
  231. package/work-report-daily-add.js +2 -14
  232. package/work-report-daily-del.js +2 -14
  233. package/work-report-daily-detail.js +2 -14
  234. package/work-report-daily-edit.js +2 -14
  235. package/work-report-daily-get-work-plan.js +2 -14
  236. package/work-report-daily-list.js +2 -14
  237. package/work-report-monthly-add.js +2 -14
  238. package/work-report-monthly-del.js +2 -14
  239. package/work-report-monthly-detail.js +2 -14
  240. package/work-report-monthly-edit.js +2 -14
  241. package/work-report-monthly-list.js +2 -14
  242. package/work-report-weekly-add.js +2 -14
  243. package/work-report-weekly-del.js +2 -14
  244. package/work-report-weekly-detail.js +2 -14
  245. package/work-report-weekly-edit.js +2 -14
  246. package/work-report-weekly-list.js +2 -14
  247. package/work-task-add-couser.js +2 -14
  248. package/work-task-add.js +2 -14
  249. package/work-task-delete-couser.js +2 -14
  250. package/work-task-detail.js +2 -14
  251. package/work-task-edit.js +2 -14
  252. package/work-task-handover.js +2 -14
  253. package/workorder-add-couser.js +2 -14
  254. package/workorder-delete-couser.js +2 -14
  255. package/workorder-handover.js +2 -14
  256. package/workorderlist.js +2 -14
  257. package/workorderproductlist.js +2 -14
  258. package/worktimerecorddetail.js +2 -14
  259. package/worktimerecordlist.js +2 -14
  260. package/xbb-browser.js +330 -0
  261. package/xbb-config.js +146 -0
  262. package/xbb-token-store.js +389 -0
  263. package/version.js +0 -18
package/refund-list.js CHANGED
@@ -3,6 +3,7 @@ import fs from 'node:fs';
3
3
  import os from 'node:os';
4
4
  import path from 'node:path';
5
5
  import { cli, Strategy } from './xbb-registry.js';
6
+ import { readActiveConfig } from './xbb-config.js';
6
7
 
7
8
  const CONFIG_FILE = path.join(os.homedir(), '.xbbcli', 'config.env');
8
9
  const REFUND_LIST_API_URL = 'https://proapi.xbongbong.com/pro/v2/api/refund/list';
@@ -11,20 +12,7 @@ const MISSING_TOKEN_MESSAGE = '缺少 token;请先执行 xbbcli token-set --co
11
12
  let lastPagination = null;
12
13
 
13
14
  function readConfig() {
14
- try {
15
- const parsed = JSON.parse(fs.readFileSync(CONFIG_FILE, 'utf8'));
16
- const companies = Array.isArray(parsed)
17
- ? parsed
18
- : Array.isArray(parsed?.companies)
19
- ? parsed.companies
20
- : null;
21
- if (companies) {
22
- return companies.find((item) => item && item.enable) || {};
23
- }
24
- return parsed || {};
25
- } catch {
26
- return {};
27
- }
15
+ return readActiveConfig();
28
16
  }
29
17
 
30
18
  function getRuntimeConfig() {
package/role-list.js CHANGED
@@ -3,6 +3,7 @@ import fs from 'node:fs';
3
3
  import os from 'node:os';
4
4
  import path from 'node:path';
5
5
  import { cli, Strategy } from './xbb-registry.js';
6
+ import { readActiveConfig } from './xbb-config.js';
6
7
 
7
8
  const CONFIG_FILE = path.join(os.homedir(), '.xbbcli', 'config.env');
8
9
  const API_URL = 'https://proapi.xbongbong.com/pro/v2/api/role/list';
@@ -11,20 +12,7 @@ const MISSING_TOKEN_MESSAGE = '缺少 token;请先执行 xbbcli token-set --co
11
12
  let lastPagination = null;
12
13
 
13
14
  function readConfig() {
14
- try {
15
- const parsed = JSON.parse(fs.readFileSync(CONFIG_FILE, 'utf8'));
16
- const companies = Array.isArray(parsed)
17
- ? parsed
18
- : Array.isArray(parsed?.companies)
19
- ? parsed.companies
20
- : null;
21
- if (companies) {
22
- return companies.find((item) => item && item.enable) || {};
23
- }
24
- return parsed || {};
25
- } catch {
26
- return {};
27
- }
15
+ return readActiveConfig();
28
16
  }
29
17
 
30
18
  function getRuntimeConfig() {
package/sign-in-list.js CHANGED
@@ -3,6 +3,7 @@ import fs from 'node:fs';
3
3
  import os from 'node:os';
4
4
  import path from 'node:path';
5
5
  import { cli, Strategy } from './xbb-registry.js';
6
+ import { readActiveConfig } from './xbb-config.js';
6
7
 
7
8
  const CONFIG_FILE = path.join(os.homedir(), '.xbbcli', 'config.env');
8
9
  const API_URL = 'https://proapi.xbongbong.com/pro/v2/api/signIn/list';
@@ -11,20 +12,7 @@ const MISSING_TOKEN_MESSAGE = '缺少 token;请先执行 xbbcli token-set --co
11
12
  let lastPagination = null;
12
13
 
13
14
  function readConfig() {
14
- try {
15
- const parsed = JSON.parse(fs.readFileSync(CONFIG_FILE, 'utf8'));
16
- const companies = Array.isArray(parsed)
17
- ? parsed
18
- : Array.isArray(parsed?.companies)
19
- ? parsed.companies
20
- : null;
21
- if (companies) {
22
- return companies.find((item) => item && item.enable) || {};
23
- }
24
- return parsed || {};
25
- } catch {
26
- return {};
27
- }
15
+ return readActiveConfig();
28
16
  }
29
17
 
30
18
  function getRuntimeConfig() {
package/stage-get.js CHANGED
@@ -3,6 +3,7 @@ import fs from 'node:fs';
3
3
  import os from 'node:os';
4
4
  import path from 'node:path';
5
5
  import { cli, Strategy } from './xbb-registry.js';
6
+ import { readActiveConfig } from './xbb-config.js';
6
7
 
7
8
  const CONFIG_FILE = path.join(os.homedir(), '.xbbcli', 'config.env');
8
9
  const API_URL = 'https://proapi.xbongbong.com/pro/v2/api/stage/get';
@@ -10,20 +11,7 @@ const DEFAULT_BASE_URL = 'https://proapi.xbongbong.com';
10
11
  const MISSING_TOKEN_MESSAGE = '缺少 token;请先执行 xbbcli token-set --corpid <CORPID> --token <TOKEN> --userId <USERID>';
11
12
 
12
13
  function readConfig() {
13
- try {
14
- const parsed = JSON.parse(fs.readFileSync(CONFIG_FILE, 'utf8'));
15
- const companies = Array.isArray(parsed)
16
- ? parsed
17
- : Array.isArray(parsed?.companies)
18
- ? parsed.companies
19
- : null;
20
- if (companies) {
21
- return companies.find((item) => item && item.enable) || {};
22
- }
23
- return parsed || {};
24
- } catch {
25
- return {};
26
- }
14
+ return readActiveConfig();
27
15
  }
28
16
 
29
17
  function getRuntimeConfig() {
package/stage-jump.js CHANGED
@@ -3,6 +3,7 @@ import fs from 'node:fs';
3
3
  import os from 'node:os';
4
4
  import path from 'node:path';
5
5
  import { cli, Strategy } from './xbb-registry.js';
6
+ import { readActiveConfig } from './xbb-config.js';
6
7
 
7
8
  const CONFIG_FILE = path.join(os.homedir(), '.xbbcli', 'config.env');
8
9
  const API_URL = 'https://proapi.xbongbong.com/pro/v2/api/stage/jump';
@@ -10,20 +11,7 @@ const DEFAULT_BASE_URL = 'https://proapi.xbongbong.com';
10
11
  const MISSING_TOKEN_MESSAGE = '缺少 token;请先执行 xbbcli token-set --corpid <CORPID> --token <TOKEN> --userId <USERID>';
11
12
 
12
13
  function readConfig() {
13
- try {
14
- const parsed = JSON.parse(fs.readFileSync(CONFIG_FILE, 'utf8'));
15
- const companies = Array.isArray(parsed)
16
- ? parsed
17
- : Array.isArray(parsed?.companies)
18
- ? parsed.companies
19
- : null;
20
- if (companies) {
21
- return companies.find((item) => item && item.enable) || {};
22
- }
23
- return parsed || {};
24
- } catch {
25
- return {};
26
- }
14
+ return readActiveConfig();
27
15
  }
28
16
 
29
17
  function getRuntimeConfig() {
package/supplier-add.js CHANGED
@@ -3,6 +3,7 @@ import os from 'node:os';
3
3
  import path from 'node:path';
4
4
  import crypto from 'node:crypto';
5
5
  import { cli, Strategy } from './xbb-registry.js';
6
+ import { readActiveConfig } from './xbb-config.js';
6
7
 
7
8
  const CONFIG_DIR = path.join(os.homedir(), '.xbbcli');
8
9
  const CONFIG_FILE = path.join(CONFIG_DIR, 'config.env');
@@ -10,20 +11,7 @@ const API_URL = 'https://proapi.xbongbong.com/pro/v2/api/supplier/add';
10
11
  const DEFAULT_BASE_URL = 'https://proapi.xbongbong.com';
11
12
 
12
13
  function readConfig() {
13
- try {
14
- const parsed = JSON.parse(fs.readFileSync(CONFIG_FILE, 'utf8'));
15
- const companies = Array.isArray(parsed)
16
- ? parsed
17
- : Array.isArray(parsed?.companies)
18
- ? parsed.companies
19
- : null;
20
- if (companies) {
21
- return companies.find((item) => item && item.enable) || {};
22
- }
23
- return parsed || {};
24
- } catch {
25
- return {};
26
- }
14
+ return readActiveConfig();
27
15
  }
28
16
 
29
17
  function getRuntimeConfig() {
package/token-del.js CHANGED
@@ -2,6 +2,7 @@ import fs from 'node:fs';
2
2
  import os from 'node:os';
3
3
  import path from 'node:path';
4
4
  import { cli, Strategy } from './xbb-registry.js';
5
+ import { isEnvActive, isEnvOnly, getEnvVarNames } from './xbb-config.js';
5
6
 
6
7
  const CONFIG_DIR = path.join(os.homedir(), '.xbbcli');
7
8
  const CONFIG_FILE = path.join(CONFIG_DIR, 'config.env');
@@ -66,6 +67,10 @@ async function delCompany(kwargs) {
66
67
  return createResult('error', '缺少 --corpid', '', '', '');
67
68
  }
68
69
 
70
+ if (isEnvOnly() || isEnvActive()) {
71
+ return createResult('error', `当前为环境变量模式(${getEnvVarNames().join(', ')}),不支持删除公司配置;如需多公司请改用 config.env`, corpid, '', '');
72
+ }
73
+
69
74
  const companies = readCompanies();
70
75
  if (!companies.length) {
71
76
  return createResult('error', '缺少本地配置;请先执行 xbbcli token-set --corpid <CORPID> --token <TOKEN> --userId <USERID>', corpid, '', 0);
package/token-generate.js CHANGED
@@ -3,6 +3,7 @@ import fs from 'node:fs';
3
3
  import os from 'node:os';
4
4
  import path from 'node:path';
5
5
  import { cli, Strategy } from './xbb-registry.js';
6
+ import { readActiveConfig } from './xbb-config.js';
6
7
 
7
8
  const CONFIG_FILE = path.join(os.homedir(), '.xbbcli', 'config.env');
8
9
  const API_URL = 'https://proapi.xbongbong.com/pro/v2/api/user/generateToken';
@@ -10,20 +11,7 @@ const DEFAULT_BASE_URL = 'https://proapi.xbongbong.com';
10
11
  const MISSING_TOKEN_MESSAGE = '缺少 token;请先执行 xbbcli token-set --corpid <CORPID> --token <TOKEN> --userId <USERID>';
11
12
 
12
13
  function readConfig() {
13
- try {
14
- const parsed = JSON.parse(fs.readFileSync(CONFIG_FILE, 'utf8'));
15
- const companies = Array.isArray(parsed)
16
- ? parsed
17
- : Array.isArray(parsed?.companies)
18
- ? parsed.companies
19
- : null;
20
- if (companies) {
21
- return companies.find((item) => item && item.enable) || {};
22
- }
23
- return parsed || {};
24
- } catch {
25
- return {};
26
- }
14
+ return readActiveConfig();
27
15
  }
28
16
 
29
17
  function resolveBaseUrl(corpid) {
package/token-list.js CHANGED
@@ -2,6 +2,7 @@ import fs from 'node:fs';
2
2
  import os from 'node:os';
3
3
  import path from 'node:path';
4
4
  import { cli, Strategy } from './xbb-registry.js';
5
+ import { readEnvConfig, hasEnvConfig, isEnvOnly } from './xbb-config.js';
5
6
 
6
7
  const CONFIG_DIR = path.join(os.homedir(), '.xbbcli');
7
8
  const CONFIG_FILE = path.join(CONFIG_DIR, 'config.env');
@@ -50,7 +51,7 @@ function maskToken(token) {
50
51
  return `${value.slice(0, 8)}****${value.slice(-4)}`;
51
52
  }
52
53
  function makeErrorRow(code, msg) {
53
- return [{ enable: '', corpid: '', corpName: '', userName: '', userId: '', baseurl: '', token: '', code, msg }];
54
+ return [{ enable: '', corpid: '', corpName: '', userName: '', userId: '', baseurl: '', token: '', code, msg, source: '' }];
54
55
  }
55
56
 
56
57
  cli({
@@ -64,9 +65,24 @@ cli({
64
65
  args: [
65
66
  { name: 'showToken', type: 'bool', default: false, help: '显示完整 token;默认只显示脱敏预览' },
66
67
  ],
67
- columns: ['enable', 'corpid', 'userId', 'baseurl', 'token', 'corpName', 'userName', 'code', 'msg'],
68
+ columns: ['enable', 'corpid', 'userId', 'baseurl', 'token', 'corpName', 'userName', 'code', 'msg', 'source'],
68
69
  func: async (kwargs) => {
69
70
  const companies = readCompanies();
71
+ const envConfig = readEnvConfig();
72
+ if (isEnvOnly() || (!companies.some((item) => item && item.enable === true) && hasEnvConfig(envConfig))) {
73
+ return [{
74
+ enable: 'true',
75
+ corpid: String(envConfig.corpid || ''),
76
+ userId: String(envConfig.userId || ''),
77
+ baseurl: String(envConfig.baseurl || ''),
78
+ token: Boolean(kwargs.showToken) ? String(envConfig.token || '') : maskToken(envConfig.token),
79
+ corpName: String(envConfig.corpName || ''),
80
+ userName: String(envConfig.userName || ''),
81
+ code: '',
82
+ msg: '来源为环境变量 XBB_*(环境变量模式不支持多公司切换)',
83
+ source: 'env',
84
+ }];
85
+ }
70
86
  if (!companies.length) {
71
87
  return makeErrorRow('NO_CONFIG', '缺少本地配置;请先执行 xbbcli token-set --corpid <CORPID> --token <TOKEN> --userId <USERID>');
72
88
  }
@@ -82,6 +98,7 @@ cli({
82
98
  userName: String(item.userName || ''),
83
99
  code: '',
84
100
  msg: '',
101
+ source: 'config',
85
102
  }));
86
103
  if (enabledCount !== 1) {
87
104
  rows.push({
@@ -92,6 +109,7 @@ cli({
92
109
  token: '',
93
110
  corpName: '',
94
111
  userName: '',
112
+ source: 'config',
95
113
  code: 'INVALID_ENABLE',
96
114
  msg: `配置中启用(enable=true)的公司数量为 ${enabledCount},请用 xbbcli token-use --corpid <CORPID> 修正`,
97
115
  });
package/token-set.js CHANGED
@@ -1,374 +1,5 @@
1
- import fs from 'node:fs';
2
- import os from 'node:os';
3
- import path from 'node:path';
4
- import { cli, Strategy, getRegistry } from './xbb-registry.js';
5
-
6
- const CONFIG_DIR = path.join(os.homedir(), '.xbbcli');
7
- const CONFIG_FILE = path.join(CONFIG_DIR, 'config.env');
8
- const FORMLIST_FILE_SUFFIX = '.formlist.json';
9
- const COMMAND_MAP_FILE_SUFFIX = '.command-map.md';
10
- const DEPARTMENT_USER_FILE_SUFFIX = '.department-user.json';
11
- const READ_ALL_PAGE_SIZE = 200;
12
- const READ_ALL_MAX_PAGES = 1000;
13
-
14
- function resolveBaseUrl(corpid) {
15
- if (corpid.startsWith('ding') || corpid.includes('$$ding')) {
16
- return 'https://proapi.xbongbong.com';
17
- }
18
- return 'https://appapi.xbongbong.com';
19
- }
20
-
21
- function normalizeArg(value) {
22
- return String(value || '').trim();
23
- }
24
-
25
- function getFormlistFile(corpid) {
26
- return path.join(CONFIG_DIR, `${corpid}${FORMLIST_FILE_SUFFIX}`);
27
- }
28
-
29
- function getCommandMapFile(corpid) {
30
- return path.join(CONFIG_DIR, `${corpid}${COMMAND_MAP_FILE_SUFFIX}`);
31
- }
32
-
33
- async function runCommandJson(name, kwargs) {
34
- const command = getRegistry().get(`xbb/${name}`);
35
- if (!command) throw new Error(`找不到命令:${name}`);
36
- const rows = await command.func(kwargs);
37
- if (!Array.isArray(rows)) throw new Error(`${name} 返回结果不是数组`);
38
- return rows;
39
- }
40
-
41
- async function getFormlistRows(corpid, saasMark) {
42
- const rows = await runCommandJson('form-list', { saasMark: String(saasMark) });
43
-
44
- if (!Array.isArray(rows)) {
45
- throw new Error(`form-list 返回结果不是数组:saasMark=${saasMark}`);
46
- }
47
-
48
- const errorRow = rows.find((item) => item && item.code);
49
- if (errorRow) {
50
- throw new Error(`form-list 获取失败(saasMark=${saasMark}):${errorRow.code} ${errorRow.msg || ''}`.trim());
51
- }
52
-
53
- return rows;
54
- }
55
-
56
- async function requestPersonalToken(corpid, token, userId, resetToken) {
57
- const rows = await runCommandJson('token-generate', {
58
- checkUserId: userId,
59
- resetToken: String(resetToken),
60
- token,
61
- corpid,
62
- });
63
-
64
- if (!Array.isArray(rows)) {
65
- throw new Error('token-generate 返回结果不是数组');
66
- }
67
-
68
- const errorRow = rows.find((item) => item && String(item.code ?? '') !== '' && Number(item.code) !== 1);
69
- if (errorRow) {
70
- throw new Error(`token-generate 获取个人 token 失败:${errorRow.code} ${errorRow.msg || ''}`.trim());
71
- }
72
-
73
- return String(rows[0]?.token || '').trim();
74
- }
75
-
76
- async function getPersonalToken(corpid, token, userId) {
77
- const existingToken = await requestPersonalToken(corpid, token, userId, 0);
78
-
79
- if (existingToken) {
80
- if (!existingToken.startsWith('user_')) {
81
- throw new Error('token-generate 未返回有效的个人 token');
82
- }
83
- return existingToken;
84
- }
85
-
86
- const personalToken = await requestPersonalToken(corpid, token, userId, 1);
87
- if (!personalToken.startsWith('user_')) {
88
- throw new Error('token-generate 未返回有效的个人 token');
89
- }
90
-
91
- return personalToken;
92
- }
93
-
94
- async function writeFormlistFile(corpid) {
95
- const customForms = await getFormlistRows(corpid, 2);
96
- const systemForms = await getFormlistRows(corpid, 1);
97
- const formlistFile = getFormlistFile(corpid);
98
- const mergedRows = [...customForms, ...systemForms];
99
-
100
- fs.writeFileSync(formlistFile, JSON.stringify(mergedRows, null, 2) + '\n', 'utf8');
101
- return formlistFile;
102
- }
103
-
104
- function getDepartmentUserFile(corpid) {
105
- return path.join(CONFIG_DIR, `${corpid}${DEPARTMENT_USER_FILE_SUFFIX}`);
106
- }
107
-
108
- async function fetchAllRows(name, pageSize) {
109
- const rows = [];
110
- for (let page = 1; page <= READ_ALL_MAX_PAGES; page += 1) {
111
- const pageRows = await runCommandJson(name, { page: String(page), pageSize: String(pageSize) });
112
- const errorRow = pageRows.find((item) => item && String(item.code ?? '') !== '');
113
- if (errorRow) {
114
- if (String(errorRow.code) === 'NO_DATA') {
115
- return rows;
116
- }
117
- throw new Error(`${name} 获取失败(page=${page}):${errorRow.code} ${errorRow.msg || ''}`.trim());
118
- }
119
- rows.push(...pageRows);
120
- }
121
- throw new Error(`${name} 分页超过 ${READ_ALL_MAX_PAGES} 页,未获取到完整数据`);
122
- }
123
-
124
- function parseDepartmentListField(value) {
125
- if (Array.isArray(value)) {
126
- return value;
127
- }
128
- const text = String(value ?? '').trim();
129
- if (!text) {
130
- return [];
131
- }
132
- try {
133
- const parsed = JSON.parse(text);
134
- return Array.isArray(parsed) ? parsed : text;
135
- } catch {
136
- return text;
137
- }
138
- }
139
-
140
- function toDepartmentEntry(row) {
141
- return {
142
- id: row.id ?? '',
143
- name: row.name ?? '',
144
- parentId: row.parentId ?? '',
145
- depIdRouter: row.depIdRouter ?? '',
146
- };
147
- }
148
-
149
- function toUserEntry(row) {
150
- return {
151
- userId: row.userId ?? '',
152
- name: row.name ?? '',
153
- position: row.position ?? '',
154
- jobnumber: row.jobnumber ?? '',
155
- departmentList: parseDepartmentListField(row.departmentList),
156
- };
157
- }
158
-
159
- async function writeDepartmentUserFile(corpid, userId) {
160
- const departmentRows = await fetchAllRows('department-list', READ_ALL_PAGE_SIZE);
161
- const userRows = await fetchAllRows('user-list', READ_ALL_PAGE_SIZE);
162
- const payload = {
163
- corpid,
164
- updatedAt: new Date().toISOString(),
165
- pageSize: READ_ALL_PAGE_SIZE,
166
- departmentCount: departmentRows.length,
167
- userCount: userRows.length,
168
- departments: departmentRows.map(toDepartmentEntry),
169
- users: userRows.map(toUserEntry),
170
- };
171
- const file = getDepartmentUserFile(corpid);
172
- fs.mkdirSync(CONFIG_DIR, { recursive: true });
173
- fs.writeFileSync(file, JSON.stringify(payload, null, 2) + '\n', 'utf8');
174
- return { file, corpName: getCorpName(departmentRows), userName: getUserName(userRows, userId) };
175
- }
176
-
177
- function getCorpName(departmentRows) {
178
- const root = departmentRows.find((row) => Number(row.id) === 1);
179
- return root ? String(root.name || '').trim() : '';
180
- }
181
-
182
- function getUserName(userRows, userId) {
183
- const target = String(userId || '').trim();
184
- if (!target) {
185
- return '';
186
- }
187
- const exact = userRows.find((row) => String(row.userId || '').trim() === target);
188
- const matched = exact || userRows.find((row) => String(row.userId || '').trim().toLowerCase() === target.toLowerCase());
189
- return matched ? String(matched.name || '').trim() : '';
190
- }
191
-
192
- function writeCompanyProfile(corpid, profile) {
193
- const fields = Object.entries(profile).filter(([, value]) => String(value || '').trim() !== '');
194
- if (!fields.length) {
195
- return;
196
- }
197
- const patch = Object.fromEntries(fields);
198
- const companies = readCompanies().map((item) => (
199
- String(item.corpid || '').trim() === corpid ? { ...item, ...patch } : item
200
- ));
201
- fs.writeFileSync(CONFIG_FILE, JSON.stringify(companies, null, 2) + '\n', 'utf8');
202
- }
203
-
204
- function normalizeBusinessType(value) {
205
- return String(value).trim().replace(/[))\]】,,;;::。!?!?]+$/g, '');
206
- }
207
-
208
- function getCommandBusinessType(command) {
209
- if (command.businessType !== undefined && command.businessType !== null) {
210
- return normalizeBusinessType(command.businessType);
211
- }
212
- const description = String(command.description || '');
213
- const match = description.match(/businessType\s*:\s*(\d+)/i);
214
- return match ? normalizeBusinessType(match[1]) : '';
215
- }
216
-
217
- function escapeCell(value) {
218
- return String(value ?? '').replace(/\|/g, '\\|').replace(/\r?\n/g, ' ');
219
- }
220
-
221
- function optionDescription(option) {
222
- return `--${option.name}: ${option.help || ''}`;
223
- }
224
-
225
- function writeCommandMap(corpid) {
226
- const formFile = getFormlistFile(corpid);
227
- if (!fs.existsSync(formFile)) {
228
- throw new Error(`Form cache not found: ${formFile}`);
229
- }
230
- const raw = fs.readFileSync(formFile, 'utf8').replace(/^\uFEFF/, '');
231
- const data = JSON.parse(raw);
232
- const forms = Array.isArray(data) ? data : data.data || [];
233
-
234
- const commands = [...getRegistry().values()]
235
- .filter((command) => command.site === 'xbb')
236
- .map((command) => ({
237
- ...command,
238
- command_options: command.args || [],
239
- }));
240
-
241
- const lines = [
242
- '# XBB 命令映射',
243
- '',
244
- `来源:xbb --help;表单缓存:${path.basename(formFile)}`,
245
- '',
246
- '| 命令 | 命令名称 | formId | businessType | 字段说明 |',
247
- '| --- | --- | --- | --- | --- |',
248
- ];
249
-
250
- for (const command of commands) {
251
- const commandBusinessType = getCommandBusinessType(command);
252
- const matchedForms = forms.filter((form) => String(form.businessType ?? '').trim() === commandBusinessType);
253
- const formIds = [...new Set(matchedForms.map((form) => form.formId).filter(Boolean))];
254
- const businessTypes = [...new Set(matchedForms.map((form) => form.businessType).filter(Boolean))];
255
- const options = (command.command_options || []).map(optionDescription).join('<br>');
256
- lines.push(
257
- `| ${escapeCell(command.name)} | ${escapeCell(command.description)} | ${escapeCell(formIds.join(', '))} | ${escapeCell(businessTypes.join(', ') || commandBusinessType)} | ${escapeCell(options)} |`,
258
- );
259
- }
260
-
261
- const commandMapFile = getCommandMapFile(corpid);
262
- fs.mkdirSync(CONFIG_DIR, { recursive: true });
263
- fs.writeFileSync(commandMapFile, `${lines.join('\n')}\n`, 'utf8');
264
- return commandMapFile;
265
- }
266
-
267
- function createResult(status, message, corpid, baseurl, userId, formlistFile = '', commandMapFile = '', enable = '', companyCount = '', departmentUserFile = '', corpName = '', userName = '') {
268
- return [{
269
- status,
270
- message,
271
- configFile: CONFIG_FILE,
272
- corpid,
273
- baseurl,
274
- userId,
275
- enable,
276
- companyCount,
277
- formlistFile,
278
- commandMapFile,
279
- departmentUserFile,
280
- corpName,
281
- userName,
282
- }];
283
- }
284
-
285
- function readCompanies() {
286
- try {
287
- const parsed = JSON.parse(fs.readFileSync(CONFIG_FILE, 'utf8'));
288
- return normalizeCompanies(parsed);
289
- } catch {
290
- return [];
291
- }
292
- }
293
-
294
- function normalizeCompanies(parsed) {
295
- if (Array.isArray(parsed)) {
296
- return parsed.filter((item) => item && typeof item === 'object');
297
- }
298
- if (parsed && Array.isArray(parsed.companies)) {
299
- return parsed.companies.filter((item) => item && typeof item === 'object');
300
- }
301
- if (parsed && parsed.corpid) {
302
- const { corpid, token, baseurl, userId } = parsed;
303
- return [{ corpid, token, baseurl, userId, enable: true }];
304
- }
305
- return [];
306
- }
307
-
308
- function upsertCompany(companies, entry) {
309
- const index = companies.findIndex((item) => String(item.corpid || '').trim() === entry.corpid);
310
- const next = companies.map((item) => ({ ...item, enable: false }));
311
- if (index === -1) {
312
- next.push({ ...entry, enable: true });
313
- } else {
314
- next[index] = { ...next[index], ...entry, enable: true };
315
- }
316
- return next;
317
- }
318
-
319
- async function setToken(kwargs) {
320
- const corpid = normalizeArg(kwargs.corpid);
321
- const token = normalizeArg(kwargs.token);
322
- const userId = normalizeArg(kwargs.userId);
323
-
324
- if (!corpid) {
325
- return createResult('error', '缺少 --corpid', '', '', '');
326
- }
327
-
328
- if (!token) {
329
- return createResult('error', '缺少 --token', corpid, '', '');
330
- }
331
-
332
- if (!userId) {
333
- return createResult('error', '缺少 --userId', corpid, '', '');
334
- }
335
-
336
- let personalToken = token;
337
- if (!token.startsWith('user_')) {
338
- try {
339
- personalToken = await getPersonalToken(corpid, token, userId);
340
- } catch (error) {
341
- return createResult('error', `生成个人 token 失败:${error.message}`, corpid, '', userId);
342
- }
343
- }
344
-
345
- const baseurl = resolveBaseUrl(corpid);
346
- const companies = upsertCompany(readCompanies(), { corpid, token: personalToken, baseurl, userId });
347
-
348
- fs.mkdirSync(CONFIG_DIR, { recursive: true });
349
- fs.writeFileSync(CONFIG_FILE, JSON.stringify(companies, null, 2) + '\n', 'utf8');
350
-
351
- try {
352
- const formlistFile = await writeFormlistFile(corpid);
353
- const commandMapFile = writeCommandMap(corpid);
354
- const { file: departmentUserFile, corpName, userName } = await writeDepartmentUserFile(corpid, userId);
355
- writeCompanyProfile(corpid, { corpName, userName });
356
- return createResult('ok', '已保存 corpid、token、baseurl、userId,并同步表单模板缓存、命令映射文件与部门/员工缓存', corpid, baseurl, userId, formlistFile, commandMapFile, true, companies.length, departmentUserFile, corpName, userName);
357
- } catch (error) {
358
- return createResult(
359
- 'partial',
360
- `已保存 corpid、token、baseurl、userId,但同步缓存失败:${error.message}`,
361
- corpid,
362
- baseurl,
363
- userId,
364
- getFormlistFile(corpid),
365
- '',
366
- true,
367
- companies.length,
368
- '',
369
- );
370
- }
371
- }
1
+ import { cli, Strategy } from './xbb-registry.js';
2
+ import { saveCompanyCredentials } from './xbb-token-store.js';
372
3
 
373
4
  cli({
374
5
  site: 'xbb',
@@ -381,7 +12,8 @@ cli({
381
12
  { name: 'corpid', type: 'str', help: '公司id(必填)' },
382
13
  { name: 'token', type: 'str', help: '要保存的 API token' },
383
14
  { name: 'userId', type: 'str', help: '操作人id(必填)' },
15
+ { name: 'noEnv', type: 'bool', default: false, help: '不写入环境变量,仅保存到 config.env' },
384
16
  ],
385
- columns: ['status', 'message', 'configFile', 'corpid', 'baseurl', 'userId', 'enable', 'companyCount', 'formlistFile', 'commandMapFile', 'departmentUserFile', 'corpName', 'userName'],
386
- func: setToken,
387
- });
17
+ columns: ['status', 'message', 'configFile', 'corpid', 'baseurl', 'userId', 'enable', 'companyCount', 'formlistFile', 'commandMapFile', 'departmentUserFile', 'corpName', 'userName', 'envStored', 'envFile'],
18
+ func: saveCompanyCredentials,
19
+ });