agent-messenger 2.3.0 → 2.5.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 (438) hide show
  1. package/.claude-plugin/README.md +16 -16
  2. package/.claude-plugin/marketplace.json +29 -29
  3. package/.claude-plugin/plugin.json +5 -5
  4. package/.github/workflows/release.yml +0 -12
  5. package/CONTRIBUTING.md +1 -1
  6. package/README.md +11 -8
  7. package/bun.lock +70 -110
  8. package/bunfig.toml +3 -0
  9. package/dist/package.json +11 -3
  10. package/dist/src/platforms/channeltalk/cli.d.ts.map +1 -1
  11. package/dist/src/platforms/channeltalk/cli.js +2 -1
  12. package/dist/src/platforms/channeltalk/cli.js.map +1 -1
  13. package/dist/src/platforms/channeltalk/commands/index.d.ts +1 -0
  14. package/dist/src/platforms/channeltalk/commands/index.d.ts.map +1 -1
  15. package/dist/src/platforms/channeltalk/commands/index.js +1 -0
  16. package/dist/src/platforms/channeltalk/commands/index.js.map +1 -1
  17. package/dist/src/platforms/channeltalk/commands/whoami.d.ts +22 -0
  18. package/dist/src/platforms/channeltalk/commands/whoami.d.ts.map +1 -0
  19. package/dist/src/platforms/channeltalk/commands/whoami.js +40 -0
  20. package/dist/src/platforms/channeltalk/commands/whoami.js.map +1 -0
  21. package/dist/src/platforms/channeltalkbot/cli.d.ts.map +1 -1
  22. package/dist/src/platforms/channeltalkbot/cli.js +2 -1
  23. package/dist/src/platforms/channeltalkbot/cli.js.map +1 -1
  24. package/dist/src/platforms/channeltalkbot/commands/index.d.ts +1 -0
  25. package/dist/src/platforms/channeltalkbot/commands/index.d.ts.map +1 -1
  26. package/dist/src/platforms/channeltalkbot/commands/index.js +1 -0
  27. package/dist/src/platforms/channeltalkbot/commands/index.js.map +1 -1
  28. package/dist/src/platforms/channeltalkbot/commands/whoami.d.ts +13 -0
  29. package/dist/src/platforms/channeltalkbot/commands/whoami.d.ts.map +1 -0
  30. package/dist/src/platforms/channeltalkbot/commands/whoami.js +31 -0
  31. package/dist/src/platforms/channeltalkbot/commands/whoami.js.map +1 -0
  32. package/dist/src/platforms/discord/cli.d.ts.map +1 -1
  33. package/dist/src/platforms/discord/cli.js +2 -1
  34. package/dist/src/platforms/discord/cli.js.map +1 -1
  35. package/dist/src/platforms/discord/commands/index.d.ts +1 -0
  36. package/dist/src/platforms/discord/commands/index.d.ts.map +1 -1
  37. package/dist/src/platforms/discord/commands/index.js +1 -0
  38. package/dist/src/platforms/discord/commands/index.js.map +1 -1
  39. package/dist/src/platforms/discord/commands/whoami.d.ts +6 -0
  40. package/dist/src/platforms/discord/commands/whoami.d.ts.map +1 -0
  41. package/dist/src/platforms/discord/commands/whoami.js +33 -0
  42. package/dist/src/platforms/discord/commands/whoami.js.map +1 -0
  43. package/dist/src/platforms/discordbot/cli.d.ts.map +1 -1
  44. package/dist/src/platforms/discordbot/cli.js +2 -1
  45. package/dist/src/platforms/discordbot/cli.js.map +1 -1
  46. package/dist/src/platforms/discordbot/client.js +2 -2
  47. package/dist/src/platforms/discordbot/client.js.map +1 -1
  48. package/dist/src/platforms/discordbot/commands/index.d.ts +1 -0
  49. package/dist/src/platforms/discordbot/commands/index.d.ts.map +1 -1
  50. package/dist/src/platforms/discordbot/commands/index.js +1 -0
  51. package/dist/src/platforms/discordbot/commands/index.js.map +1 -1
  52. package/dist/src/platforms/discordbot/commands/whoami.d.ts +14 -0
  53. package/dist/src/platforms/discordbot/commands/whoami.d.ts.map +1 -0
  54. package/dist/src/platforms/discordbot/commands/whoami.js +32 -0
  55. package/dist/src/platforms/discordbot/commands/whoami.js.map +1 -0
  56. package/dist/src/platforms/instagram/cli.d.ts.map +1 -1
  57. package/dist/src/platforms/instagram/cli.js +2 -1
  58. package/dist/src/platforms/instagram/cli.js.map +1 -1
  59. package/dist/src/platforms/instagram/client.d.ts +6 -0
  60. package/dist/src/platforms/instagram/client.d.ts.map +1 -1
  61. package/dist/src/platforms/instagram/client.js +12 -0
  62. package/dist/src/platforms/instagram/client.js.map +1 -1
  63. package/dist/src/platforms/instagram/commands/index.d.ts +1 -0
  64. package/dist/src/platforms/instagram/commands/index.d.ts.map +1 -1
  65. package/dist/src/platforms/instagram/commands/index.js +1 -0
  66. package/dist/src/platforms/instagram/commands/index.js.map +1 -1
  67. package/dist/src/platforms/instagram/commands/whoami.d.ts +7 -0
  68. package/dist/src/platforms/instagram/commands/whoami.d.ts.map +1 -0
  69. package/dist/src/platforms/instagram/commands/whoami.js +19 -0
  70. package/dist/src/platforms/instagram/commands/whoami.js.map +1 -0
  71. package/dist/src/platforms/kakaotalk/cli.d.ts.map +1 -1
  72. package/dist/src/platforms/kakaotalk/cli.js +2 -1
  73. package/dist/src/platforms/kakaotalk/cli.js.map +1 -1
  74. package/dist/src/platforms/kakaotalk/client.d.ts +2 -1
  75. package/dist/src/platforms/kakaotalk/client.d.ts.map +1 -1
  76. package/dist/src/platforms/kakaotalk/client.js +225 -23
  77. package/dist/src/platforms/kakaotalk/client.js.map +1 -1
  78. package/dist/src/platforms/kakaotalk/commands/index.d.ts +1 -0
  79. package/dist/src/platforms/kakaotalk/commands/index.d.ts.map +1 -1
  80. package/dist/src/platforms/kakaotalk/commands/index.js +1 -0
  81. package/dist/src/platforms/kakaotalk/commands/index.js.map +1 -1
  82. package/dist/src/platforms/kakaotalk/commands/whoami.d.ts +3 -0
  83. package/dist/src/platforms/kakaotalk/commands/whoami.d.ts.map +1 -0
  84. package/dist/src/platforms/kakaotalk/commands/whoami.js +19 -0
  85. package/dist/src/platforms/kakaotalk/commands/whoami.js.map +1 -0
  86. package/dist/src/platforms/kakaotalk/index.d.ts +2 -2
  87. package/dist/src/platforms/kakaotalk/index.d.ts.map +1 -1
  88. package/dist/src/platforms/kakaotalk/index.js +1 -1
  89. package/dist/src/platforms/kakaotalk/index.js.map +1 -1
  90. package/dist/src/platforms/kakaotalk/protocol/session.d.ts +4 -2
  91. package/dist/src/platforms/kakaotalk/protocol/session.d.ts.map +1 -1
  92. package/dist/src/platforms/kakaotalk/protocol/session.js +27 -7
  93. package/dist/src/platforms/kakaotalk/protocol/session.js.map +1 -1
  94. package/dist/src/platforms/kakaotalk/protocol/types.d.ts +17 -0
  95. package/dist/src/platforms/kakaotalk/protocol/types.d.ts.map +1 -1
  96. package/dist/src/platforms/kakaotalk/protocol/types.js.map +1 -1
  97. package/dist/src/platforms/kakaotalk/types.d.ts +28 -0
  98. package/dist/src/platforms/kakaotalk/types.d.ts.map +1 -1
  99. package/dist/src/platforms/kakaotalk/types.js +14 -0
  100. package/dist/src/platforms/kakaotalk/types.js.map +1 -1
  101. package/dist/src/platforms/line/cli.js +2 -2
  102. package/dist/src/platforms/line/cli.js.map +1 -1
  103. package/dist/src/platforms/line/client.d.ts.map +1 -1
  104. package/dist/src/platforms/line/client.js +9 -36
  105. package/dist/src/platforms/line/client.js.map +1 -1
  106. package/dist/src/platforms/line/commands/auth.d.ts.map +1 -1
  107. package/dist/src/platforms/line/commands/auth.js +9 -47
  108. package/dist/src/platforms/line/commands/auth.js.map +1 -1
  109. package/dist/src/platforms/line/commands/index.d.ts +1 -1
  110. package/dist/src/platforms/line/commands/index.d.ts.map +1 -1
  111. package/dist/src/platforms/line/commands/index.js +1 -1
  112. package/dist/src/platforms/line/commands/index.js.map +1 -1
  113. package/dist/src/platforms/line/commands/whoami.d.ts +3 -0
  114. package/dist/src/platforms/line/commands/whoami.d.ts.map +1 -0
  115. package/dist/src/platforms/line/commands/{profile.js → whoami.js} +5 -5
  116. package/dist/src/platforms/line/commands/whoami.js.map +1 -0
  117. package/dist/src/platforms/slack/cli.d.ts.map +1 -1
  118. package/dist/src/platforms/slack/cli.js +2 -1
  119. package/dist/src/platforms/slack/cli.js.map +1 -1
  120. package/dist/src/platforms/slack/commands/index.d.ts +1 -0
  121. package/dist/src/platforms/slack/commands/index.d.ts.map +1 -1
  122. package/dist/src/platforms/slack/commands/index.js +1 -0
  123. package/dist/src/platforms/slack/commands/index.js.map +1 -1
  124. package/dist/src/platforms/slack/commands/whoami.d.ts +6 -0
  125. package/dist/src/platforms/slack/commands/whoami.d.ts.map +1 -0
  126. package/dist/src/platforms/slack/commands/whoami.js +39 -0
  127. package/dist/src/platforms/slack/commands/whoami.js.map +1 -0
  128. package/dist/src/platforms/slackbot/cli.d.ts.map +1 -1
  129. package/dist/src/platforms/slackbot/cli.js +2 -1
  130. package/dist/src/platforms/slackbot/cli.js.map +1 -1
  131. package/dist/src/platforms/slackbot/commands/index.d.ts +1 -0
  132. package/dist/src/platforms/slackbot/commands/index.d.ts.map +1 -1
  133. package/dist/src/platforms/slackbot/commands/index.js +1 -0
  134. package/dist/src/platforms/slackbot/commands/index.js.map +1 -1
  135. package/dist/src/platforms/slackbot/commands/whoami.d.ts +14 -0
  136. package/dist/src/platforms/slackbot/commands/whoami.d.ts.map +1 -0
  137. package/dist/src/platforms/slackbot/commands/whoami.js +32 -0
  138. package/dist/src/platforms/slackbot/commands/whoami.js.map +1 -0
  139. package/dist/src/platforms/teams/cli.d.ts.map +1 -1
  140. package/dist/src/platforms/teams/cli.js +2 -1
  141. package/dist/src/platforms/teams/cli.js.map +1 -1
  142. package/dist/src/platforms/teams/commands/index.d.ts +1 -0
  143. package/dist/src/platforms/teams/commands/index.d.ts.map +1 -1
  144. package/dist/src/platforms/teams/commands/index.js +1 -0
  145. package/dist/src/platforms/teams/commands/index.js.map +1 -1
  146. package/dist/src/platforms/teams/commands/reaction.d.ts.map +1 -1
  147. package/dist/src/platforms/teams/commands/reaction.js +2 -0
  148. package/dist/src/platforms/teams/commands/reaction.js.map +1 -1
  149. package/dist/src/platforms/teams/commands/whoami.d.ts +6 -0
  150. package/dist/src/platforms/teams/commands/whoami.d.ts.map +1 -0
  151. package/dist/src/platforms/teams/commands/whoami.js +30 -0
  152. package/dist/src/platforms/teams/commands/whoami.js.map +1 -0
  153. package/dist/src/platforms/telegram/cli.d.ts.map +1 -1
  154. package/dist/src/platforms/telegram/cli.js +2 -1
  155. package/dist/src/platforms/telegram/cli.js.map +1 -1
  156. package/dist/src/platforms/telegram/commands/index.d.ts +1 -0
  157. package/dist/src/platforms/telegram/commands/index.d.ts.map +1 -1
  158. package/dist/src/platforms/telegram/commands/index.js +1 -0
  159. package/dist/src/platforms/telegram/commands/index.js.map +1 -1
  160. package/dist/src/platforms/telegram/commands/whoami.d.ts +7 -0
  161. package/dist/src/platforms/telegram/commands/whoami.d.ts.map +1 -0
  162. package/dist/src/platforms/telegram/commands/whoami.js +27 -0
  163. package/dist/src/platforms/telegram/commands/whoami.js.map +1 -0
  164. package/dist/src/platforms/webex/cli.d.ts.map +1 -1
  165. package/dist/src/platforms/webex/cli.js +2 -1
  166. package/dist/src/platforms/webex/cli.js.map +1 -1
  167. package/dist/src/platforms/webex/commands/index.d.ts +1 -0
  168. package/dist/src/platforms/webex/commands/index.d.ts.map +1 -1
  169. package/dist/src/platforms/webex/commands/index.js +1 -0
  170. package/dist/src/platforms/webex/commands/index.js.map +1 -1
  171. package/dist/src/platforms/webex/commands/message.js +1 -1
  172. package/dist/src/platforms/webex/commands/message.js.map +1 -1
  173. package/dist/src/platforms/webex/commands/whoami.d.ts +6 -0
  174. package/dist/src/platforms/webex/commands/whoami.d.ts.map +1 -0
  175. package/dist/src/platforms/webex/commands/whoami.js +30 -0
  176. package/dist/src/platforms/webex/commands/whoami.js.map +1 -0
  177. package/dist/src/platforms/wechatbot/cli.d.ts +5 -0
  178. package/dist/src/platforms/wechatbot/cli.d.ts.map +1 -0
  179. package/dist/src/platforms/wechatbot/cli.js +19 -0
  180. package/dist/src/platforms/wechatbot/cli.js.map +1 -0
  181. package/dist/src/platforms/wechatbot/client.d.ts +36 -0
  182. package/dist/src/platforms/wechatbot/client.d.ts.map +1 -0
  183. package/dist/src/platforms/wechatbot/client.js +208 -0
  184. package/dist/src/platforms/wechatbot/client.js.map +1 -0
  185. package/dist/src/platforms/wechatbot/commands/auth.d.ts +28 -0
  186. package/dist/src/platforms/wechatbot/commands/auth.d.ts.map +1 -0
  187. package/dist/src/platforms/wechatbot/commands/auth.js +164 -0
  188. package/dist/src/platforms/wechatbot/commands/auth.js.map +1 -0
  189. package/dist/src/platforms/wechatbot/commands/index.d.ts +6 -0
  190. package/dist/src/platforms/wechatbot/commands/index.d.ts.map +1 -0
  191. package/dist/src/platforms/wechatbot/commands/index.js +6 -0
  192. package/dist/src/platforms/wechatbot/commands/index.js.map +1 -0
  193. package/dist/src/platforms/wechatbot/commands/message.d.ts +18 -0
  194. package/dist/src/platforms/wechatbot/commands/message.d.ts.map +1 -0
  195. package/dist/src/platforms/wechatbot/commands/message.js +80 -0
  196. package/dist/src/platforms/wechatbot/commands/message.js.map +1 -0
  197. package/dist/src/platforms/wechatbot/commands/shared.d.ts +9 -0
  198. package/dist/src/platforms/wechatbot/commands/shared.d.ts.map +1 -0
  199. package/dist/src/platforms/wechatbot/commands/shared.js +13 -0
  200. package/dist/src/platforms/wechatbot/commands/shared.js.map +1 -0
  201. package/dist/src/platforms/wechatbot/commands/template.d.ts +19 -0
  202. package/dist/src/platforms/wechatbot/commands/template.d.ts.map +1 -0
  203. package/dist/src/platforms/wechatbot/commands/template.js +76 -0
  204. package/dist/src/platforms/wechatbot/commands/template.js.map +1 -0
  205. package/dist/src/platforms/wechatbot/commands/user.d.ts +20 -0
  206. package/dist/src/platforms/wechatbot/commands/user.d.ts.map +1 -0
  207. package/dist/src/platforms/wechatbot/commands/user.js +53 -0
  208. package/dist/src/platforms/wechatbot/commands/user.js.map +1 -0
  209. package/dist/src/platforms/wechatbot/commands/whoami.d.ts +12 -0
  210. package/dist/src/platforms/wechatbot/commands/whoami.d.ts.map +1 -0
  211. package/dist/src/platforms/wechatbot/commands/whoami.js +33 -0
  212. package/dist/src/platforms/wechatbot/commands/whoami.js.map +1 -0
  213. package/dist/src/platforms/wechatbot/credential-manager.d.ts +17 -0
  214. package/dist/src/platforms/wechatbot/credential-manager.d.ts.map +1 -0
  215. package/dist/src/platforms/wechatbot/credential-manager.js +121 -0
  216. package/dist/src/platforms/wechatbot/credential-manager.js.map +1 -0
  217. package/dist/src/platforms/wechatbot/index.d.ts +5 -0
  218. package/dist/src/platforms/wechatbot/index.d.ts.map +1 -0
  219. package/dist/src/platforms/wechatbot/index.js +4 -0
  220. package/dist/src/platforms/wechatbot/index.js.map +1 -0
  221. package/dist/src/platforms/wechatbot/types.d.ts +94 -0
  222. package/dist/src/platforms/wechatbot/types.d.ts.map +1 -0
  223. package/dist/src/platforms/wechatbot/types.js +54 -0
  224. package/dist/src/platforms/wechatbot/types.js.map +1 -0
  225. package/dist/src/platforms/whatsapp/cli.d.ts.map +1 -1
  226. package/dist/src/platforms/whatsapp/cli.js +2 -1
  227. package/dist/src/platforms/whatsapp/cli.js.map +1 -1
  228. package/dist/src/platforms/whatsapp/client.d.ts +9 -0
  229. package/dist/src/platforms/whatsapp/client.d.ts.map +1 -1
  230. package/dist/src/platforms/whatsapp/client.js +143 -21
  231. package/dist/src/platforms/whatsapp/client.js.map +1 -1
  232. package/dist/src/platforms/whatsapp/commands/auth.d.ts.map +1 -1
  233. package/dist/src/platforms/whatsapp/commands/auth.js +133 -60
  234. package/dist/src/platforms/whatsapp/commands/auth.js.map +1 -1
  235. package/dist/src/platforms/whatsapp/commands/index.d.ts +1 -0
  236. package/dist/src/platforms/whatsapp/commands/index.d.ts.map +1 -1
  237. package/dist/src/platforms/whatsapp/commands/index.js +1 -0
  238. package/dist/src/platforms/whatsapp/commands/index.js.map +1 -1
  239. package/dist/src/platforms/whatsapp/commands/shared.js +2 -2
  240. package/dist/src/platforms/whatsapp/commands/shared.js.map +1 -1
  241. package/dist/src/platforms/whatsapp/commands/whoami.d.ts +7 -0
  242. package/dist/src/platforms/whatsapp/commands/whoami.d.ts.map +1 -0
  243. package/dist/src/platforms/whatsapp/commands/whoami.js +19 -0
  244. package/dist/src/platforms/whatsapp/commands/whoami.js.map +1 -0
  245. package/dist/src/platforms/whatsapp/credential-manager.d.ts.map +1 -1
  246. package/dist/src/platforms/whatsapp/credential-manager.js +14 -8
  247. package/dist/src/platforms/whatsapp/credential-manager.js.map +1 -1
  248. package/dist/src/platforms/whatsapp/ensure-auth.js +2 -2
  249. package/dist/src/platforms/whatsapp/ensure-auth.js.map +1 -1
  250. package/dist/src/platforms/whatsappbot/cli.d.ts.map +1 -1
  251. package/dist/src/platforms/whatsappbot/cli.js +2 -1
  252. package/dist/src/platforms/whatsappbot/cli.js.map +1 -1
  253. package/dist/src/platforms/whatsappbot/commands/index.d.ts +1 -0
  254. package/dist/src/platforms/whatsappbot/commands/index.d.ts.map +1 -1
  255. package/dist/src/platforms/whatsappbot/commands/index.js +1 -0
  256. package/dist/src/platforms/whatsappbot/commands/index.js.map +1 -1
  257. package/dist/src/platforms/whatsappbot/commands/whoami.d.ts +17 -0
  258. package/dist/src/platforms/whatsappbot/commands/whoami.d.ts.map +1 -0
  259. package/dist/src/platforms/whatsappbot/commands/whoami.js +39 -0
  260. package/dist/src/platforms/whatsappbot/commands/whoami.js.map +1 -0
  261. package/dist/src/shared/utils/qr.d.ts +15 -0
  262. package/dist/src/shared/utils/qr.d.ts.map +1 -0
  263. package/dist/src/shared/utils/qr.js +74 -0
  264. package/dist/src/shared/utils/qr.js.map +1 -0
  265. package/dist/src/tui/adapters/whatsapp-adapter.d.ts.map +1 -1
  266. package/dist/src/tui/adapters/whatsapp-adapter.js +20 -15
  267. package/dist/src/tui/adapters/whatsapp-adapter.js.map +1 -1
  268. package/docs/content/docs/agent-skills.mdx +4 -4
  269. package/docs/content/docs/cli/channeltalk.mdx +12 -1
  270. package/docs/content/docs/cli/channeltalkbot.mdx +10 -1
  271. package/docs/content/docs/cli/discord.mdx +11 -1
  272. package/docs/content/docs/cli/discordbot.mdx +10 -1
  273. package/docs/content/docs/cli/instagram.mdx +12 -1
  274. package/docs/content/docs/cli/kakaotalk.mdx +25 -1
  275. package/docs/content/docs/cli/line.mdx +5 -5
  276. package/docs/content/docs/cli/meta.json +1 -0
  277. package/docs/content/docs/cli/slack.mdx +11 -1
  278. package/docs/content/docs/cli/slackbot.mdx +10 -1
  279. package/docs/content/docs/cli/teams.mdx +11 -1
  280. package/docs/content/docs/cli/telegram.mdx +11 -0
  281. package/docs/content/docs/cli/webex.mdx +11 -1
  282. package/docs/content/docs/cli/wechatbot.mdx +188 -0
  283. package/docs/content/docs/cli/whatsapp.mdx +37 -8
  284. package/docs/content/docs/cli/whatsappbot.mdx +10 -1
  285. package/docs/content/docs/sdk/meta.json +1 -1
  286. package/docs/content/docs/sdk/wechatbot.mdx +282 -0
  287. package/docs/content/docs/tui.mdx +1 -1
  288. package/docs/src/app/page.tsx +5 -5
  289. package/package.json +11 -3
  290. package/skills/agent-channeltalk/SKILL.md +12 -1
  291. package/skills/agent-channeltalkbot/SKILL.md +10 -1
  292. package/skills/agent-discord/SKILL.md +11 -1
  293. package/skills/agent-discordbot/SKILL.md +10 -1
  294. package/skills/agent-instagram/SKILL.md +12 -1
  295. package/skills/agent-kakaotalk/SKILL.md +30 -1
  296. package/skills/agent-kakaotalk/references/common-patterns.md +1 -1
  297. package/skills/agent-line/SKILL.md +11 -15
  298. package/skills/agent-line/references/authentication.md +13 -4
  299. package/skills/agent-slack/SKILL.md +11 -1
  300. package/skills/agent-slackbot/SKILL.md +10 -1
  301. package/skills/agent-teams/SKILL.md +11 -1
  302. package/skills/agent-telegram/SKILL.md +6 -1
  303. package/skills/agent-webex/SKILL.md +11 -1
  304. package/skills/agent-wechatbot/SKILL.md +394 -0
  305. package/skills/agent-whatsapp/SKILL.md +63 -15
  306. package/skills/agent-whatsapp/references/authentication.md +36 -6
  307. package/skills/agent-whatsappbot/SKILL.md +10 -1
  308. package/src/platforms/channeltalk/cli.ts +2 -0
  309. package/src/platforms/channeltalk/commands/index.ts +1 -0
  310. package/src/platforms/channeltalk/commands/whoami.test.ts +64 -0
  311. package/src/platforms/channeltalk/commands/whoami.ts +62 -0
  312. package/src/platforms/channeltalkbot/cli.ts +2 -0
  313. package/src/platforms/channeltalkbot/commands/index.ts +1 -0
  314. package/src/platforms/channeltalkbot/commands/whoami.test.ts +104 -0
  315. package/src/platforms/channeltalkbot/commands/whoami.ts +42 -0
  316. package/src/platforms/discord/cli.ts +2 -0
  317. package/src/platforms/discord/commands/index.ts +1 -0
  318. package/src/platforms/discord/commands/whoami.test.ts +91 -0
  319. package/src/platforms/discord/commands/whoami.ts +36 -0
  320. package/src/platforms/discord/credential-manager.test.ts +18 -1
  321. package/src/platforms/discordbot/cli.ts +2 -0
  322. package/src/platforms/discordbot/client.ts +2 -2
  323. package/src/platforms/discordbot/commands/index.ts +1 -0
  324. package/src/platforms/discordbot/commands/whoami.test.ts +96 -0
  325. package/src/platforms/discordbot/commands/whoami.ts +44 -0
  326. package/src/platforms/instagram/cli.ts +2 -1
  327. package/src/platforms/instagram/client.ts +13 -0
  328. package/src/platforms/instagram/commands/auth.test.ts +216 -0
  329. package/src/platforms/instagram/commands/chat.test.ts +123 -0
  330. package/src/platforms/instagram/commands/index.ts +1 -0
  331. package/src/platforms/instagram/commands/message.test.ts +174 -0
  332. package/src/platforms/instagram/commands/whoami.test.ts +60 -0
  333. package/src/platforms/instagram/commands/whoami.ts +21 -0
  334. package/src/platforms/kakaotalk/cli.ts +2 -1
  335. package/src/platforms/kakaotalk/client.test.ts +182 -14
  336. package/src/platforms/kakaotalk/client.ts +261 -27
  337. package/src/platforms/kakaotalk/commands/auth.test.ts +299 -0
  338. package/src/platforms/kakaotalk/commands/chat.test.ts +97 -0
  339. package/src/platforms/kakaotalk/commands/index.ts +1 -0
  340. package/src/platforms/kakaotalk/commands/message.test.ts +113 -0
  341. package/src/platforms/kakaotalk/commands/whoami.test.ts +116 -0
  342. package/src/platforms/kakaotalk/commands/whoami.ts +21 -0
  343. package/src/platforms/kakaotalk/index.test.ts +5 -0
  344. package/src/platforms/kakaotalk/index.ts +2 -0
  345. package/src/platforms/kakaotalk/protocol/session.ts +29 -7
  346. package/src/platforms/kakaotalk/protocol/types.ts +9 -0
  347. package/src/platforms/kakaotalk/types.ts +30 -0
  348. package/src/platforms/line/cli.ts +2 -2
  349. package/src/platforms/line/client.ts +14 -39
  350. package/src/platforms/line/commands/auth.test.ts +141 -0
  351. package/src/platforms/line/commands/auth.ts +37 -61
  352. package/src/platforms/line/commands/chat.test.ts +110 -0
  353. package/src/platforms/line/commands/friend.test.ts +98 -0
  354. package/src/platforms/line/commands/index.ts +1 -1
  355. package/src/platforms/line/commands/message.test.ts +119 -0
  356. package/src/platforms/line/commands/whoami.test.ts +85 -0
  357. package/src/platforms/line/commands/{profile.ts → whoami.ts} +4 -4
  358. package/src/platforms/slack/cli.ts +2 -0
  359. package/src/platforms/slack/commands/index.ts +1 -0
  360. package/src/platforms/slack/commands/whoami.test.ts +126 -0
  361. package/src/platforms/slack/commands/whoami.ts +40 -0
  362. package/src/platforms/slackbot/cli.ts +2 -1
  363. package/src/platforms/slackbot/commands/channel.test.ts +139 -0
  364. package/src/platforms/slackbot/commands/index.ts +1 -0
  365. package/src/platforms/slackbot/commands/message.test.ts +226 -0
  366. package/src/platforms/slackbot/commands/reaction.test.ts +90 -0
  367. package/src/platforms/slackbot/commands/user.test.ts +143 -0
  368. package/src/platforms/slackbot/commands/whoami.test.ts +102 -0
  369. package/src/platforms/slackbot/commands/whoami.ts +44 -0
  370. package/src/platforms/teams/cli.ts +2 -0
  371. package/src/platforms/teams/commands/index.ts +1 -0
  372. package/src/platforms/teams/commands/reaction.test.ts +45 -61
  373. package/src/platforms/teams/commands/reaction.ts +2 -0
  374. package/src/platforms/teams/commands/whoami.test.ts +83 -0
  375. package/src/platforms/teams/commands/whoami.ts +33 -0
  376. package/src/platforms/telegram/cli.ts +2 -1
  377. package/src/platforms/telegram/commands/chat.test.ts +125 -0
  378. package/src/platforms/telegram/commands/index.ts +1 -0
  379. package/src/platforms/telegram/commands/message.test.ts +92 -0
  380. package/src/platforms/telegram/commands/whoami.test.ts +75 -0
  381. package/src/platforms/telegram/commands/whoami.ts +29 -0
  382. package/src/platforms/webex/cli.ts +2 -1
  383. package/src/platforms/webex/commands/auth.test.ts +58 -46
  384. package/src/platforms/webex/commands/index.ts +1 -0
  385. package/src/platforms/webex/commands/member.test.ts +60 -57
  386. package/src/platforms/webex/commands/message.test.ts +74 -121
  387. package/src/platforms/webex/commands/message.ts +1 -1
  388. package/src/platforms/webex/commands/snapshot.test.ts +54 -45
  389. package/src/platforms/webex/commands/space.test.ts +46 -49
  390. package/src/platforms/webex/commands/whoami.test.ts +113 -0
  391. package/src/platforms/webex/commands/whoami.ts +31 -0
  392. package/src/platforms/webex/credential-manager.test.ts +0 -1
  393. package/src/platforms/wechatbot/cli.ts +25 -0
  394. package/src/platforms/wechatbot/client.test.ts +497 -0
  395. package/src/platforms/wechatbot/client.ts +268 -0
  396. package/src/platforms/wechatbot/commands/auth.test.ts +211 -0
  397. package/src/platforms/wechatbot/commands/auth.ts +203 -0
  398. package/src/platforms/wechatbot/commands/index.ts +5 -0
  399. package/src/platforms/wechatbot/commands/message.test.ts +155 -0
  400. package/src/platforms/wechatbot/commands/message.ts +104 -0
  401. package/src/platforms/wechatbot/commands/shared.ts +22 -0
  402. package/src/platforms/wechatbot/commands/template.test.ts +199 -0
  403. package/src/platforms/wechatbot/commands/template.ts +102 -0
  404. package/src/platforms/wechatbot/commands/user.test.ts +165 -0
  405. package/src/platforms/wechatbot/commands/user.ts +75 -0
  406. package/src/platforms/wechatbot/commands/whoami.test.ts +109 -0
  407. package/src/platforms/wechatbot/commands/whoami.ts +43 -0
  408. package/src/platforms/wechatbot/credential-manager.test.ts +255 -0
  409. package/src/platforms/wechatbot/credential-manager.ts +148 -0
  410. package/src/platforms/wechatbot/index.test.ts +49 -0
  411. package/src/platforms/wechatbot/index.ts +19 -0
  412. package/src/platforms/wechatbot/types.test.ts +223 -0
  413. package/src/platforms/wechatbot/types.ts +107 -0
  414. package/src/platforms/whatsapp/cli.ts +2 -1
  415. package/src/platforms/whatsapp/client.ts +180 -37
  416. package/src/platforms/whatsapp/commands/auth.test.ts +311 -0
  417. package/src/platforms/whatsapp/commands/auth.ts +194 -84
  418. package/src/platforms/whatsapp/commands/chat.test.ts +198 -0
  419. package/src/platforms/whatsapp/commands/index.ts +1 -0
  420. package/src/platforms/whatsapp/commands/message.test.ts +231 -0
  421. package/src/platforms/whatsapp/commands/shared.ts +2 -2
  422. package/src/platforms/whatsapp/commands/whoami.test.ts +59 -0
  423. package/src/platforms/whatsapp/commands/whoami.ts +21 -0
  424. package/src/platforms/whatsapp/credential-manager.test.ts +20 -0
  425. package/src/platforms/whatsapp/credential-manager.ts +17 -8
  426. package/src/platforms/whatsapp/ensure-auth.ts +2 -2
  427. package/src/platforms/whatsappbot/cli.ts +2 -1
  428. package/src/platforms/whatsappbot/commands/auth.test.ts +217 -0
  429. package/src/platforms/whatsappbot/commands/index.ts +1 -0
  430. package/src/platforms/whatsappbot/commands/message.test.ts +198 -0
  431. package/src/platforms/whatsappbot/commands/template.test.ts +112 -0
  432. package/src/platforms/whatsappbot/commands/whoami.test.ts +100 -0
  433. package/src/platforms/whatsappbot/commands/whoami.ts +57 -0
  434. package/src/shared/utils/qr.ts +92 -0
  435. package/src/tui/adapters/whatsapp-adapter.ts +19 -16
  436. package/dist/src/platforms/line/commands/profile.d.ts +0 -3
  437. package/dist/src/platforms/line/commands/profile.d.ts.map +0 -1
  438. package/dist/src/platforms/line/commands/profile.js.map +0 -1
@@ -1,4 +1,4 @@
1
- import { afterEach, beforeEach, describe, expect, mock, spyOn, test } from 'bun:test'
1
+ import { afterEach, beforeEach, describe, expect, spyOn, test } from 'bun:test'
2
2
  import * as childProcess from 'node:child_process'
3
3
 
4
4
  import { WebexClient } from '../client'
@@ -7,7 +7,9 @@ import { loginAction, logoutAction, statusAction } from './auth'
7
7
 
8
8
  describe('auth commands', () => {
9
9
  let consoleSpy: ReturnType<typeof spyOn>
10
- let _consoleErrorSpy: ReturnType<typeof spyOn>
10
+ let consoleErrorSpy: ReturnType<typeof spyOn>
11
+ let execSpy: ReturnType<typeof spyOn>
12
+ const protoSpies: ReturnType<typeof spyOn>[] = []
11
13
  const mockPerson = {
12
14
  id: 'person-1',
13
15
  displayName: 'Test User',
@@ -17,21 +19,31 @@ describe('auth commands', () => {
17
19
  created: '2024-01-01T00:00:00.000Z',
18
20
  }
19
21
 
22
+ function protoSpy<T extends object>(target: T, method: keyof T) {
23
+ const s = spyOn(target, method as any)
24
+ protoSpies.push(s)
25
+ return s
26
+ }
27
+
20
28
  beforeEach(() => {
21
29
  consoleSpy = spyOn(console, 'log').mockImplementation(() => {})
22
- _consoleErrorSpy = spyOn(console, 'error').mockImplementation(() => {})
23
- spyOn(childProcess, 'exec').mockImplementation((() => {}) as any)
30
+ consoleErrorSpy = spyOn(console, 'error').mockImplementation(() => {})
31
+ execSpy = spyOn(childProcess, 'exec').mockImplementation((() => {}) as any)
24
32
  })
25
33
 
26
34
  afterEach(() => {
27
- mock.restore()
35
+ consoleSpy.mockRestore()
36
+ consoleErrorSpy.mockRestore()
37
+ execSpy.mockRestore()
38
+ for (const s of protoSpies) s.mockRestore()
39
+ protoSpies.length = 0
28
40
  })
29
41
 
30
42
  describe('loginAction with --token', () => {
31
43
  test('authenticates with provided token (bot token flow)', async () => {
32
- spyOn(WebexClient.prototype, 'login').mockResolvedValue(new WebexClient())
33
- spyOn(WebexClient.prototype, 'testAuth').mockResolvedValue(mockPerson)
34
- spyOn(WebexCredentialManager.prototype, 'saveConfig').mockResolvedValue(undefined)
44
+ protoSpy(WebexClient.prototype, 'login').mockResolvedValue(new WebexClient())
45
+ protoSpy(WebexClient.prototype, 'testAuth').mockResolvedValue(mockPerson)
46
+ protoSpy(WebexCredentialManager.prototype, 'saveConfig').mockResolvedValue(undefined)
35
47
 
36
48
  await loginAction({ token: 'bot-token-123', pretty: false })
37
49
 
@@ -43,9 +55,9 @@ describe('auth commands', () => {
43
55
  })
44
56
 
45
57
  test('saves tokenType as manual with expiresAt 0', async () => {
46
- spyOn(WebexClient.prototype, 'login').mockResolvedValue(new WebexClient())
47
- spyOn(WebexClient.prototype, 'testAuth').mockResolvedValue(mockPerson)
48
- const saveSpy = spyOn(WebexCredentialManager.prototype, 'saveConfig').mockResolvedValue(undefined)
58
+ protoSpy(WebexClient.prototype, 'login').mockResolvedValue(new WebexClient())
59
+ protoSpy(WebexClient.prototype, 'testAuth').mockResolvedValue(mockPerson)
60
+ const saveSpy = protoSpy(WebexCredentialManager.prototype, 'saveConfig').mockResolvedValue(undefined)
49
61
 
50
62
  await loginAction({ token: 'bot-token-123', pretty: false })
51
63
 
@@ -58,7 +70,7 @@ describe('auth commands', () => {
58
70
 
59
71
  describe('loginAction with --client-id and --client-secret', () => {
60
72
  test('uses provided credentials for Device Grant flow', async () => {
61
- spyOn(WebexCredentialManager.prototype, 'requestDeviceCode').mockResolvedValue({
73
+ protoSpy(WebexCredentialManager.prototype, 'requestDeviceCode').mockResolvedValue({
62
74
  deviceCode: 'd',
63
75
  userCode: 'u',
64
76
  verificationUri: 'https://v',
@@ -66,14 +78,14 @@ describe('auth commands', () => {
66
78
  expiresIn: 300,
67
79
  interval: 0.01,
68
80
  })
69
- spyOn(WebexCredentialManager.prototype, 'pollDeviceToken').mockResolvedValue({
81
+ protoSpy(WebexCredentialManager.prototype, 'pollDeviceToken').mockResolvedValue({
70
82
  accessToken: 'at',
71
83
  refreshToken: 'rt',
72
84
  expiresAt: Date.now() + 3600000,
73
85
  })
74
- spyOn(WebexCredentialManager.prototype, 'saveConfig').mockResolvedValue(undefined)
75
- spyOn(WebexClient.prototype, 'login').mockResolvedValue(new WebexClient())
76
- spyOn(WebexClient.prototype, 'testAuth').mockResolvedValue(mockPerson)
86
+ protoSpy(WebexCredentialManager.prototype, 'saveConfig').mockResolvedValue(undefined)
87
+ protoSpy(WebexClient.prototype, 'login').mockResolvedValue(new WebexClient())
88
+ protoSpy(WebexClient.prototype, 'testAuth').mockResolvedValue(mockPerson)
77
89
 
78
90
  await loginAction({ clientId: 'my-id', clientSecret: 'my-secret', pretty: false })
79
91
 
@@ -82,7 +94,7 @@ describe('auth commands', () => {
82
94
  })
83
95
 
84
96
  test('saves tokenType as oauth in config', async () => {
85
- spyOn(WebexCredentialManager.prototype, 'requestDeviceCode').mockResolvedValue({
97
+ protoSpy(WebexCredentialManager.prototype, 'requestDeviceCode').mockResolvedValue({
86
98
  deviceCode: 'd',
87
99
  userCode: 'u',
88
100
  verificationUri: 'https://v',
@@ -90,14 +102,14 @@ describe('auth commands', () => {
90
102
  expiresIn: 300,
91
103
  interval: 0.01,
92
104
  })
93
- spyOn(WebexCredentialManager.prototype, 'pollDeviceToken').mockResolvedValue({
105
+ protoSpy(WebexCredentialManager.prototype, 'pollDeviceToken').mockResolvedValue({
94
106
  accessToken: 'at',
95
107
  refreshToken: 'rt',
96
108
  expiresAt: Date.now() + 3600000,
97
109
  })
98
- const saveSpy = spyOn(WebexCredentialManager.prototype, 'saveConfig').mockResolvedValue(undefined)
99
- spyOn(WebexClient.prototype, 'login').mockResolvedValue(new WebexClient())
100
- spyOn(WebexClient.prototype, 'testAuth').mockResolvedValue(mockPerson)
110
+ const saveSpy = protoSpy(WebexCredentialManager.prototype, 'saveConfig').mockResolvedValue(undefined)
111
+ protoSpy(WebexClient.prototype, 'login').mockResolvedValue(new WebexClient())
112
+ protoSpy(WebexClient.prototype, 'testAuth').mockResolvedValue(mockPerson)
101
113
 
102
114
  await loginAction({ clientId: 'my-id', clientSecret: 'my-secret', pretty: false })
103
115
 
@@ -106,7 +118,7 @@ describe('auth commands', () => {
106
118
  })
107
119
 
108
120
  test('saves clientId and clientSecret in config', async () => {
109
- spyOn(WebexCredentialManager.prototype, 'requestDeviceCode').mockResolvedValue({
121
+ protoSpy(WebexCredentialManager.prototype, 'requestDeviceCode').mockResolvedValue({
110
122
  deviceCode: 'd',
111
123
  userCode: 'u',
112
124
  verificationUri: 'https://v',
@@ -114,18 +126,18 @@ describe('auth commands', () => {
114
126
  expiresIn: 300,
115
127
  interval: 0.01,
116
128
  })
117
- spyOn(WebexCredentialManager.prototype, 'pollDeviceToken').mockResolvedValue({
129
+ protoSpy(WebexCredentialManager.prototype, 'pollDeviceToken').mockResolvedValue({
118
130
  accessToken: 'at',
119
131
  refreshToken: 'rt',
120
132
  expiresAt: Date.now() + 3600000,
121
133
  })
122
- spyOn(WebexCredentialManager.prototype, 'saveConfig').mockResolvedValue(undefined)
123
- spyOn(WebexClient.prototype, 'login').mockResolvedValue(new WebexClient())
124
- spyOn(WebexClient.prototype, 'testAuth').mockResolvedValue(mockPerson)
134
+ const saveSpy = protoSpy(WebexCredentialManager.prototype, 'saveConfig').mockResolvedValue(undefined)
135
+ protoSpy(WebexClient.prototype, 'login').mockResolvedValue(new WebexClient())
136
+ protoSpy(WebexClient.prototype, 'testAuth').mockResolvedValue(mockPerson)
125
137
 
126
138
  await loginAction({ clientId: 'my-id', clientSecret: 'my-secret', pretty: false })
127
139
 
128
- const savedConfig = (WebexCredentialManager.prototype.saveConfig as ReturnType<typeof spyOn>).mock.calls[0][0] as { clientId: string; clientSecret: string }
140
+ const savedConfig = saveSpy.mock.calls[0][0] as { clientId: string; clientSecret: string }
129
141
  expect(savedConfig.clientId).toBe('my-id')
130
142
  expect(savedConfig.clientSecret).toBe('my-secret')
131
143
  })
@@ -133,10 +145,10 @@ describe('auth commands', () => {
133
145
 
134
146
  describe('statusAction', () => {
135
147
  test('shows authenticated status when token is valid', async () => {
136
- spyOn(WebexCredentialManager.prototype, 'loadConfig').mockResolvedValue(null)
137
- spyOn(WebexCredentialManager.prototype, 'getToken').mockResolvedValue('valid-token')
138
- spyOn(WebexClient.prototype, 'login').mockResolvedValue(new WebexClient())
139
- spyOn(WebexClient.prototype, 'testAuth').mockResolvedValue(mockPerson)
148
+ protoSpy(WebexCredentialManager.prototype, 'loadConfig').mockResolvedValue(null)
149
+ protoSpy(WebexCredentialManager.prototype, 'getToken').mockResolvedValue('valid-token')
150
+ protoSpy(WebexClient.prototype, 'login').mockResolvedValue(new WebexClient())
151
+ protoSpy(WebexClient.prototype, 'testAuth').mockResolvedValue(mockPerson)
140
152
 
141
153
  await statusAction({ pretty: false })
142
154
 
@@ -147,9 +159,9 @@ describe('auth commands', () => {
147
159
  })
148
160
 
149
161
  test('shows not authenticated when no token', async () => {
150
- spyOn(WebexCredentialManager.prototype, 'loadConfig').mockResolvedValue(null)
151
- spyOn(WebexCredentialManager.prototype, 'getToken').mockResolvedValue(null)
152
- const exitSpy = spyOn(process, 'exit').mockImplementation(() => undefined as never)
162
+ protoSpy(WebexCredentialManager.prototype, 'loadConfig').mockResolvedValue(null)
163
+ protoSpy(WebexCredentialManager.prototype, 'getToken').mockResolvedValue(null)
164
+ const exitSpy = protoSpy(process, 'exit').mockImplementation(() => undefined as never)
153
165
 
154
166
  await statusAction({ pretty: false })
155
167
 
@@ -160,10 +172,10 @@ describe('auth commands', () => {
160
172
  })
161
173
 
162
174
  test('shows not authenticated when token validation fails', async () => {
163
- spyOn(WebexCredentialManager.prototype, 'loadConfig').mockResolvedValue(null)
164
- spyOn(WebexCredentialManager.prototype, 'getToken').mockResolvedValue('invalid-token')
165
- spyOn(WebexClient.prototype, 'login').mockResolvedValue(new WebexClient())
166
- spyOn(WebexClient.prototype, 'testAuth').mockRejectedValue(new Error('401 Unauthorized'))
175
+ protoSpy(WebexCredentialManager.prototype, 'loadConfig').mockResolvedValue(null)
176
+ protoSpy(WebexCredentialManager.prototype, 'getToken').mockResolvedValue('invalid-token')
177
+ protoSpy(WebexClient.prototype, 'login').mockResolvedValue(new WebexClient())
178
+ protoSpy(WebexClient.prototype, 'testAuth').mockRejectedValue(new Error('401 Unauthorized'))
167
179
 
168
180
  await statusAction({ pretty: false })
169
181
 
@@ -173,16 +185,16 @@ describe('auth commands', () => {
173
185
  })
174
186
 
175
187
  test('loads config for stored client credentials', async () => {
176
- spyOn(WebexCredentialManager.prototype, 'loadConfig').mockResolvedValue({
188
+ protoSpy(WebexCredentialManager.prototype, 'loadConfig').mockResolvedValue({
177
189
  accessToken: 'at',
178
190
  refreshToken: 'rt',
179
191
  expiresAt: Date.now() + 3600000,
180
192
  clientId: 'stored-id',
181
193
  clientSecret: 'stored-secret',
182
194
  })
183
- spyOn(WebexCredentialManager.prototype, 'getToken').mockResolvedValue('valid-token')
184
- spyOn(WebexClient.prototype, 'login').mockResolvedValue(new WebexClient())
185
- spyOn(WebexClient.prototype, 'testAuth').mockResolvedValue(mockPerson)
195
+ protoSpy(WebexCredentialManager.prototype, 'getToken').mockResolvedValue('valid-token')
196
+ protoSpy(WebexClient.prototype, 'login').mockResolvedValue(new WebexClient())
197
+ protoSpy(WebexClient.prototype, 'testAuth').mockResolvedValue(mockPerson)
186
198
 
187
199
  await statusAction({ pretty: false })
188
200
 
@@ -192,12 +204,12 @@ describe('auth commands', () => {
192
204
 
193
205
  describe('logoutAction', () => {
194
206
  test('clears credentials when authenticated', async () => {
195
- spyOn(WebexCredentialManager.prototype, 'loadConfig').mockResolvedValue({
207
+ protoSpy(WebexCredentialManager.prototype, 'loadConfig').mockResolvedValue({
196
208
  accessToken: 'token',
197
209
  refreshToken: 'refresh',
198
210
  expiresAt: Date.now() + 3600000,
199
211
  })
200
- const clearSpy = spyOn(WebexCredentialManager.prototype, 'clearCredentials').mockResolvedValue(undefined)
212
+ const clearSpy = protoSpy(WebexCredentialManager.prototype, 'clearCredentials').mockResolvedValue(undefined)
201
213
 
202
214
  await logoutAction({ pretty: false })
203
215
 
@@ -208,8 +220,8 @@ describe('auth commands', () => {
208
220
  })
209
221
 
210
222
  test('shows error when not authenticated', async () => {
211
- spyOn(WebexCredentialManager.prototype, 'loadConfig').mockResolvedValue(null)
212
- const exitSpy = spyOn(process, 'exit').mockImplementation(() => undefined as never)
223
+ protoSpy(WebexCredentialManager.prototype, 'loadConfig').mockResolvedValue(null)
224
+ const exitSpy = protoSpy(process, 'exit').mockImplementation(() => undefined as never)
213
225
 
214
226
  await logoutAction({ pretty: false })
215
227
 
@@ -3,3 +3,4 @@ export { memberCommand } from './member'
3
3
  export { messageCommand } from './message'
4
4
  export { snapshotAction, snapshotCommand } from './snapshot'
5
5
  export { spaceCommand } from './space'
6
+ export { whoamiCommand } from './whoami'
@@ -1,65 +1,70 @@
1
1
  import { afterEach, beforeEach, describe, expect, mock, spyOn, test } from 'bun:test'
2
2
 
3
- import { WebexClient } from '../client'
4
3
  import { WebexError } from '../types'
4
+
5
+ const mockHandleError = mock((err: Error) => {
6
+ throw err
7
+ })
8
+
9
+ mock.module('@/shared/utils/error-handler', () => ({
10
+ handleError: mockHandleError,
11
+ }))
12
+
13
+ const mockMembers = [
14
+ {
15
+ id: 'mem-1',
16
+ roomId: 'room-1',
17
+ personId: 'person-1',
18
+ personEmail: 'alice@example.com',
19
+ personDisplayName: 'Alice',
20
+ isModerator: true,
21
+ created: '2024-01-01T00:00:00.000Z',
22
+ },
23
+ {
24
+ id: 'mem-2',
25
+ roomId: 'room-1',
26
+ personId: 'person-2',
27
+ personEmail: 'bob@example.com',
28
+ personDisplayName: 'Bob',
29
+ isModerator: false,
30
+ created: '2024-01-02T00:00:00.000Z',
31
+ },
32
+ ]
33
+
34
+ const mockListMemberships = mock(() => Promise.resolve(mockMembers))
35
+ const mockLogin = mock(() => Promise.resolve({ listMemberships: mockListMemberships }))
36
+
37
+ mock.module('../client', () => ({
38
+ WebexClient: class {
39
+ login = mockLogin
40
+ },
41
+ }))
42
+
5
43
  import { listAction } from './member'
6
44
 
7
45
  describe('member commands', () => {
8
46
  let consoleSpy: ReturnType<typeof spyOn>
9
- let consoleErrorSpy: ReturnType<typeof spyOn>
10
- let processExitSpy: ReturnType<typeof spyOn>
11
- let stderrOutput: string
12
- let origStderrWrite: typeof process.stderr.write
13
- const mockMembers = [
14
- {
15
- id: 'mem-1',
16
- roomId: 'room-1',
17
- personId: 'person-1',
18
- personEmail: 'alice@example.com',
19
- personDisplayName: 'Alice',
20
- isModerator: true,
21
- created: '2024-01-01T00:00:00.000Z',
22
- },
23
- {
24
- id: 'mem-2',
25
- roomId: 'room-1',
26
- personId: 'person-2',
27
- personEmail: 'bob@example.com',
28
- personDisplayName: 'Bob',
29
- isModerator: false,
30
- created: '2024-01-02T00:00:00.000Z',
31
- },
32
- ]
33
47
 
34
48
  beforeEach(() => {
35
- consoleSpy = spyOn(console, 'log').mockImplementation(() => {})
36
- consoleErrorSpy = spyOn(console, 'error').mockImplementation(() => {})
37
- processExitSpy = spyOn(process, 'exit').mockImplementation((_code?: number) => {
38
- throw new Error(`process.exit(${_code})`)
49
+ mockListMemberships.mockReset().mockImplementation(() => Promise.resolve(mockMembers))
50
+ mockLogin.mockReset().mockImplementation(() =>
51
+ Promise.resolve({ listMemberships: mockListMemberships }),
52
+ )
53
+ mockHandleError.mockReset().mockImplementation((err: Error) => {
54
+ throw err
39
55
  })
40
- stderrOutput = ''
41
- origStderrWrite = process.stderr.write
42
- process.stderr.write = ((chunk: string | Uint8Array) => {
43
- stderrOutput += typeof chunk === 'string' ? chunk : new TextDecoder().decode(chunk)
44
- return true
45
- }) as typeof process.stderr.write
46
- spyOn(WebexClient.prototype, 'login').mockResolvedValue(new WebexClient() as any)
47
- spyOn(WebexClient.prototype, 'listMemberships').mockResolvedValue(mockMembers)
56
+
57
+ consoleSpy = spyOn(console, 'log').mockImplementation(() => {})
48
58
  })
49
59
 
50
60
  afterEach(() => {
51
- process.stderr.write = origStderrWrite
52
- mock.restore()
61
+ consoleSpy.mockRestore()
53
62
  })
54
63
 
55
64
  test('listAction calls listMemberships with spaceId and outputs mapped members', async () => {
56
- const listMembershipsSpy = spyOn(WebexClient.prototype, 'listMemberships').mockResolvedValue(
57
- mockMembers,
58
- )
59
-
60
65
  await listAction('room-1', {})
61
66
 
62
- expect(listMembershipsSpy).toHaveBeenCalledWith('room-1', { max: undefined })
67
+ expect(mockListMemberships).toHaveBeenCalledWith('room-1', { max: undefined })
63
68
  expect(consoleSpy).toHaveBeenCalledWith(
64
69
  JSON.stringify([
65
70
  {
@@ -83,30 +88,28 @@ describe('member commands', () => {
83
88
  })
84
89
 
85
90
  test('listAction passes limit option to listMemberships', async () => {
86
- const listMembershipsSpy = spyOn(WebexClient.prototype, 'listMemberships').mockResolvedValue(
87
- mockMembers,
88
- )
89
-
90
91
  await listAction('room-1', { limit: 25 })
91
92
 
92
- expect(listMembershipsSpy).toHaveBeenCalledWith('room-1', { max: 25 })
93
+ expect(mockListMemberships).toHaveBeenCalledWith('room-1', { max: 25 })
93
94
  })
94
95
 
95
96
  test('listAction handles not-authenticated case', async () => {
96
- spyOn(WebexClient.prototype, 'login').mockRejectedValue(
97
- new WebexError('No Webex credentials found.', 'no_credentials'),
98
- )
97
+ mockLogin.mockImplementation(async () => {
98
+ throw new WebexError('No Webex credentials found.', 'no_credentials')
99
+ })
99
100
 
100
- await expect(listAction('room-1', {})).rejects.toThrow('process.exit(1)')
101
+ await expect(listAction('room-1', {})).rejects.toThrow('No Webex credentials found.')
101
102
 
102
- expect(stderrOutput).toContain('No Webex credentials found')
103
+ expect(mockHandleError).toHaveBeenCalledWith(expect.any(WebexError))
103
104
  })
104
105
 
105
106
  test('listAction handles API error', async () => {
106
- spyOn(WebexClient.prototype, 'listMemberships').mockRejectedValue(new Error('API failure'))
107
+ mockListMemberships.mockImplementation(async () => {
108
+ throw new Error('API failure')
109
+ })
107
110
 
108
- await expect(listAction('room-1', {})).rejects.toThrow('process.exit(1)')
111
+ await expect(listAction('room-1', {})).rejects.toThrow('API failure')
109
112
 
110
- expect(processExitSpy).toHaveBeenCalledWith(1)
113
+ expect(mockHandleError).toHaveBeenCalledWith(expect.any(Error))
111
114
  })
112
115
  })