agent-messenger 1.0.0 → 1.1.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 (330) hide show
  1. package/.claude/commands/release.md +1 -1
  2. package/.claude-plugin/plugin.json +1 -1
  3. package/.github/workflows/ci.yml +1 -1
  4. package/.github/workflows/e2e.yml.disabled +69 -0
  5. package/README.md +16 -14
  6. package/biome.json +33 -1
  7. package/bun.lock +63 -0
  8. package/dist/package.json +8 -4
  9. package/dist/src/cli.d.ts.map +1 -1
  10. package/dist/src/cli.js +4 -1
  11. package/dist/src/cli.js.map +1 -1
  12. package/dist/src/platforms/discord/cli.js +1 -1
  13. package/dist/src/platforms/discord/client.d.ts.map +1 -1
  14. package/dist/src/platforms/discord/client.js +3 -3
  15. package/dist/src/platforms/discord/client.js.map +1 -1
  16. package/dist/src/platforms/discord/commands/user.d.ts.map +1 -1
  17. package/dist/src/platforms/discord/commands/user.js +10 -1
  18. package/dist/src/platforms/discord/commands/user.js.map +1 -1
  19. package/dist/src/platforms/discord/credential-manager.d.ts.map +1 -1
  20. package/dist/src/platforms/discord/credential-manager.js +18 -12
  21. package/dist/src/platforms/discord/credential-manager.js.map +1 -1
  22. package/dist/src/platforms/slack/cli.js +1 -1
  23. package/dist/src/platforms/slack/credential-manager.d.ts.map +1 -1
  24. package/dist/src/platforms/slack/credential-manager.js +20 -6
  25. package/dist/src/platforms/slack/credential-manager.js.map +1 -1
  26. package/dist/src/platforms/slack/token-extractor.d.ts.map +1 -1
  27. package/dist/src/platforms/slack/token-extractor.js +34 -9
  28. package/dist/src/platforms/slack/token-extractor.js.map +1 -1
  29. package/dist/src/platforms/teams/cli.d.ts.map +1 -0
  30. package/dist/{cli.js → src/platforms/teams/cli.js} +11 -10
  31. package/dist/src/platforms/teams/cli.js.map +1 -0
  32. package/dist/src/platforms/teams/client.d.ts +32 -0
  33. package/dist/src/platforms/teams/client.d.ts.map +1 -0
  34. package/dist/src/platforms/teams/client.js +202 -0
  35. package/dist/src/platforms/teams/client.js.map +1 -0
  36. package/dist/src/platforms/teams/commands/auth.d.ts +14 -0
  37. package/dist/src/platforms/teams/commands/auth.d.ts.map +1 -0
  38. package/dist/src/platforms/teams/commands/auth.js +176 -0
  39. package/dist/src/platforms/teams/commands/auth.js.map +1 -0
  40. package/dist/src/platforms/teams/commands/channel.d.ts +13 -0
  41. package/dist/src/platforms/teams/commands/channel.d.ts.map +1 -0
  42. package/dist/src/platforms/teams/commands/channel.js +97 -0
  43. package/dist/src/platforms/teams/commands/channel.js.map +1 -0
  44. package/dist/src/platforms/teams/commands/file.d.ts +12 -0
  45. package/dist/src/platforms/teams/commands/file.d.ts.map +1 -0
  46. package/dist/src/platforms/teams/commands/file.js +104 -0
  47. package/dist/src/platforms/teams/commands/file.js.map +1 -0
  48. package/dist/{commands → src/platforms/teams/commands}/index.d.ts +5 -2
  49. package/dist/src/platforms/teams/commands/index.d.ts.map +1 -0
  50. package/dist/{commands → src/platforms/teams/commands}/index.js +5 -2
  51. package/dist/src/platforms/teams/commands/index.js.map +1 -0
  52. package/dist/src/platforms/teams/commands/message.d.ts +17 -0
  53. package/dist/src/platforms/teams/commands/message.d.ts.map +1 -0
  54. package/dist/src/platforms/teams/commands/message.js +133 -0
  55. package/dist/src/platforms/teams/commands/message.js.map +1 -0
  56. package/dist/src/platforms/teams/commands/reaction.d.ts +9 -0
  57. package/dist/src/platforms/teams/commands/reaction.d.ts.map +1 -0
  58. package/dist/src/platforms/teams/commands/reaction.js +68 -0
  59. package/dist/src/platforms/teams/commands/reaction.js.map +1 -0
  60. package/dist/src/platforms/teams/commands/snapshot.d.ts +10 -0
  61. package/dist/src/platforms/teams/commands/snapshot.d.ts.map +1 -0
  62. package/dist/src/platforms/teams/commands/snapshot.js +85 -0
  63. package/dist/src/platforms/teams/commands/snapshot.js.map +1 -0
  64. package/dist/src/platforms/teams/commands/team.d.ts +18 -0
  65. package/dist/src/platforms/teams/commands/team.d.ts.map +1 -0
  66. package/dist/src/platforms/teams/commands/team.js +130 -0
  67. package/dist/src/platforms/teams/commands/team.js.map +1 -0
  68. package/dist/src/platforms/teams/commands/user.d.ts.map +1 -0
  69. package/dist/src/platforms/teams/commands/user.js +88 -0
  70. package/dist/src/platforms/teams/commands/user.js.map +1 -0
  71. package/dist/src/platforms/teams/credential-manager.d.ts +18 -0
  72. package/dist/src/platforms/teams/credential-manager.d.ts.map +1 -0
  73. package/dist/src/platforms/teams/credential-manager.js +81 -0
  74. package/dist/src/platforms/teams/credential-manager.js.map +1 -0
  75. package/dist/src/platforms/teams/index.d.ts +4 -0
  76. package/dist/src/platforms/teams/index.d.ts.map +1 -0
  77. package/dist/src/platforms/teams/index.js +6 -0
  78. package/dist/src/platforms/teams/index.js.map +1 -0
  79. package/dist/src/platforms/teams/token-extractor.d.ts +36 -0
  80. package/dist/src/platforms/teams/token-extractor.d.ts.map +1 -0
  81. package/dist/src/platforms/teams/token-extractor.js +335 -0
  82. package/dist/src/platforms/teams/token-extractor.js.map +1 -0
  83. package/dist/src/platforms/teams/types.d.ts +209 -0
  84. package/dist/src/platforms/teams/types.d.ts.map +1 -0
  85. package/dist/src/platforms/teams/types.js +65 -0
  86. package/dist/src/platforms/teams/types.js.map +1 -0
  87. package/docs/teams.md +321 -0
  88. package/e2e/README.md +256 -0
  89. package/e2e/config.ts +45 -0
  90. package/e2e/discord.e2e.test.ts +252 -0
  91. package/e2e/helpers.ts +107 -0
  92. package/e2e/slack.e2e.test.ts +309 -0
  93. package/package.json +8 -4
  94. package/scripts/postbuild.ts +15 -0
  95. package/skills/agent-teams/SKILL.md +292 -0
  96. package/skills/agent-teams/references/authentication.md +375 -0
  97. package/skills/agent-teams/references/common-patterns.md +596 -0
  98. package/skills/agent-teams/templates/monitor-channel.sh +239 -0
  99. package/skills/agent-teams/templates/post-message.sh +224 -0
  100. package/skills/agent-teams/templates/team-summary.sh +210 -0
  101. package/src/cli.ts +4 -0
  102. package/src/platforms/discord/client.ts +3 -3
  103. package/src/platforms/discord/commands/auth.test.ts +48 -32
  104. package/src/platforms/discord/commands/channel.test.ts +54 -42
  105. package/src/platforms/discord/commands/file.test.ts +40 -53
  106. package/src/platforms/discord/commands/guild.test.ts +47 -27
  107. package/src/platforms/discord/commands/message.test.ts +54 -51
  108. package/src/platforms/discord/commands/reaction.test.ts +54 -42
  109. package/src/platforms/discord/commands/user.ts +12 -1
  110. package/src/platforms/discord/credential-manager.test.ts +137 -136
  111. package/src/platforms/discord/credential-manager.ts +20 -13
  112. package/src/platforms/discord/token-extractor.test.ts +133 -383
  113. package/{tests → src/platforms/slack}/cli.test.ts +3 -3
  114. package/{tests/slack-client.test.ts → src/platforms/slack/client.test.ts} +1 -1
  115. package/{tests → src/platforms/slack}/commands/auth.test.ts +25 -13
  116. package/{tests → src/platforms/slack}/commands/channel.test.ts +2 -2
  117. package/{tests → src/platforms/slack}/commands/file.test.ts +2 -2
  118. package/{tests → src/platforms/slack}/commands/message.test.ts +2 -2
  119. package/{tests → src/platforms/slack}/commands/reaction.test.ts +1 -1
  120. package/{tests → src/platforms/slack}/commands/snapshot.test.ts +117 -105
  121. package/{tests → src/platforms/slack}/commands/user.test.ts +3 -3
  122. package/{tests → src/platforms/slack}/commands/workspace.test.ts +44 -95
  123. package/{tests → src/platforms/slack}/credential-manager.test.ts +2 -2
  124. package/src/platforms/slack/credential-manager.ts +22 -7
  125. package/src/platforms/slack/token-extractor-node-test.ts +40 -0
  126. package/src/platforms/slack/token-extractor-node.test.ts +10 -0
  127. package/src/platforms/slack/token-extractor.ts +36 -10
  128. package/{tests → src/platforms/slack}/types.test.ts +1 -1
  129. package/src/platforms/teams/cli.ts +36 -0
  130. package/src/platforms/teams/client.test.ts +500 -0
  131. package/src/platforms/teams/client.ts +365 -0
  132. package/src/platforms/teams/commands/auth.test.ts +99 -0
  133. package/src/platforms/teams/commands/auth.ts +232 -0
  134. package/src/platforms/teams/commands/channel.test.ts +147 -0
  135. package/src/platforms/teams/commands/channel.ts +129 -0
  136. package/src/platforms/teams/commands/file.test.ts +88 -0
  137. package/src/platforms/teams/commands/file.ts +144 -0
  138. package/src/platforms/teams/commands/index.ts +12 -0
  139. package/src/platforms/teams/commands/message.test.ts +110 -0
  140. package/src/platforms/teams/commands/message.ts +188 -0
  141. package/src/platforms/teams/commands/reaction.test.ts +87 -0
  142. package/src/platforms/teams/commands/reaction.ts +104 -0
  143. package/src/platforms/teams/commands/snapshot.test.ts +35 -0
  144. package/src/platforms/teams/commands/snapshot.ts +115 -0
  145. package/src/platforms/teams/commands/team.test.ts +157 -0
  146. package/src/platforms/teams/commands/team.ts +164 -0
  147. package/src/platforms/teams/commands/user.test.ts +83 -0
  148. package/src/platforms/teams/commands/user.ts +112 -0
  149. package/src/platforms/teams/credential-manager.test.ts +178 -0
  150. package/src/platforms/teams/credential-manager.ts +92 -0
  151. package/src/platforms/teams/index.ts +5 -0
  152. package/src/platforms/teams/token-extractor.test.ts +429 -0
  153. package/src/platforms/teams/token-extractor.ts +462 -0
  154. package/src/platforms/teams/types.test.ts +226 -0
  155. package/src/platforms/teams/types.ts +140 -0
  156. package/tsconfig.json +1 -1
  157. package/dist/cli.d.ts.map +0 -1
  158. package/dist/cli.js.map +0 -1
  159. package/dist/commands/auth.d.ts +0 -3
  160. package/dist/commands/auth.d.ts.map +0 -1
  161. package/dist/commands/auth.js +0 -140
  162. package/dist/commands/auth.js.map +0 -1
  163. package/dist/commands/channel.d.ts +0 -3
  164. package/dist/commands/channel.d.ts.map +0 -1
  165. package/dist/commands/channel.js +0 -118
  166. package/dist/commands/channel.js.map +0 -1
  167. package/dist/commands/file.d.ts +0 -3
  168. package/dist/commands/file.d.ts.map +0 -1
  169. package/dist/commands/file.js +0 -113
  170. package/dist/commands/file.js.map +0 -1
  171. package/dist/commands/index.d.ts.map +0 -1
  172. package/dist/commands/index.js.map +0 -1
  173. package/dist/commands/message.d.ts +0 -3
  174. package/dist/commands/message.d.ts.map +0 -1
  175. package/dist/commands/message.js +0 -214
  176. package/dist/commands/message.js.map +0 -1
  177. package/dist/commands/reaction.d.ts +0 -3
  178. package/dist/commands/reaction.d.ts.map +0 -1
  179. package/dist/commands/reaction.js +0 -100
  180. package/dist/commands/reaction.js.map +0 -1
  181. package/dist/commands/snapshot.d.ts +0 -3
  182. package/dist/commands/snapshot.d.ts.map +0 -1
  183. package/dist/commands/snapshot.js +0 -88
  184. package/dist/commands/snapshot.js.map +0 -1
  185. package/dist/commands/user.d.ts.map +0 -1
  186. package/dist/commands/user.js +0 -96
  187. package/dist/commands/user.js.map +0 -1
  188. package/dist/commands/workspace.d.ts +0 -3
  189. package/dist/commands/workspace.d.ts.map +0 -1
  190. package/dist/commands/workspace.js +0 -89
  191. package/dist/commands/workspace.js.map +0 -1
  192. package/dist/lib/credential-manager.d.ts +0 -13
  193. package/dist/lib/credential-manager.d.ts.map +0 -1
  194. package/dist/lib/credential-manager.js +0 -58
  195. package/dist/lib/credential-manager.js.map +0 -1
  196. package/dist/lib/index.d.ts +0 -3
  197. package/dist/lib/index.d.ts.map +0 -1
  198. package/dist/lib/index.js +0 -3
  199. package/dist/lib/index.js.map +0 -1
  200. package/dist/lib/ref-manager.d.ts +0 -26
  201. package/dist/lib/ref-manager.d.ts.map +0 -1
  202. package/dist/lib/ref-manager.js +0 -92
  203. package/dist/lib/ref-manager.js.map +0 -1
  204. package/dist/lib/slack-client.d.ts +0 -37
  205. package/dist/lib/slack-client.d.ts.map +0 -1
  206. package/dist/lib/slack-client.js +0 -379
  207. package/dist/lib/slack-client.js.map +0 -1
  208. package/dist/lib/token-extractor.d.ts +0 -28
  209. package/dist/lib/token-extractor.d.ts.map +0 -1
  210. package/dist/lib/token-extractor.js +0 -401
  211. package/dist/lib/token-extractor.js.map +0 -1
  212. package/dist/src/platforms/discord/client.test.d.ts +0 -2
  213. package/dist/src/platforms/discord/client.test.d.ts.map +0 -1
  214. package/dist/src/platforms/discord/client.test.js +0 -367
  215. package/dist/src/platforms/discord/client.test.js.map +0 -1
  216. package/dist/src/platforms/discord/commands/auth.test.d.ts +0 -2
  217. package/dist/src/platforms/discord/commands/auth.test.d.ts.map +0 -1
  218. package/dist/src/platforms/discord/commands/auth.test.js +0 -65
  219. package/dist/src/platforms/discord/commands/auth.test.js.map +0 -1
  220. package/dist/src/platforms/discord/commands/channel.test.d.ts +0 -2
  221. package/dist/src/platforms/discord/commands/channel.test.d.ts.map +0 -1
  222. package/dist/src/platforms/discord/commands/channel.test.js +0 -136
  223. package/dist/src/platforms/discord/commands/channel.test.js.map +0 -1
  224. package/dist/src/platforms/discord/commands/file.test.d.ts +0 -2
  225. package/dist/src/platforms/discord/commands/file.test.d.ts.map +0 -1
  226. package/dist/src/platforms/discord/commands/file.test.js +0 -83
  227. package/dist/src/platforms/discord/commands/file.test.js.map +0 -1
  228. package/dist/src/platforms/discord/commands/guild.test.d.ts +0 -2
  229. package/dist/src/platforms/discord/commands/guild.test.d.ts.map +0 -1
  230. package/dist/src/platforms/discord/commands/guild.test.js +0 -100
  231. package/dist/src/platforms/discord/commands/guild.test.js.map +0 -1
  232. package/dist/src/platforms/discord/commands/message.test.d.ts +0 -2
  233. package/dist/src/platforms/discord/commands/message.test.d.ts.map +0 -1
  234. package/dist/src/platforms/discord/commands/message.test.js +0 -91
  235. package/dist/src/platforms/discord/commands/message.test.js.map +0 -1
  236. package/dist/src/platforms/discord/commands/reaction.test.d.ts +0 -2
  237. package/dist/src/platforms/discord/commands/reaction.test.d.ts.map +0 -1
  238. package/dist/src/platforms/discord/commands/reaction.test.js +0 -115
  239. package/dist/src/platforms/discord/commands/reaction.test.js.map +0 -1
  240. package/dist/src/platforms/discord/commands/snapshot.test.d.ts +0 -2
  241. package/dist/src/platforms/discord/commands/snapshot.test.d.ts.map +0 -1
  242. package/dist/src/platforms/discord/commands/snapshot.test.js +0 -25
  243. package/dist/src/platforms/discord/commands/snapshot.test.js.map +0 -1
  244. package/dist/src/platforms/discord/commands/user.test.d.ts +0 -2
  245. package/dist/src/platforms/discord/commands/user.test.d.ts.map +0 -1
  246. package/dist/src/platforms/discord/commands/user.test.js +0 -103
  247. package/dist/src/platforms/discord/commands/user.test.js.map +0 -1
  248. package/dist/src/platforms/discord/credential-manager.test.d.ts +0 -2
  249. package/dist/src/platforms/discord/credential-manager.test.d.ts.map +0 -1
  250. package/dist/src/platforms/discord/credential-manager.test.js +0 -136
  251. package/dist/src/platforms/discord/credential-manager.test.js.map +0 -1
  252. package/dist/src/platforms/discord/token-extractor.test.d.ts +0 -2
  253. package/dist/src/platforms/discord/token-extractor.test.d.ts.map +0 -1
  254. package/dist/src/platforms/discord/token-extractor.test.js +0 -789
  255. package/dist/src/platforms/discord/token-extractor.test.js.map +0 -1
  256. package/dist/src/platforms/discord/types.test.d.ts +0 -2
  257. package/dist/src/platforms/discord/types.test.d.ts.map +0 -1
  258. package/dist/src/platforms/discord/types.test.js +0 -211
  259. package/dist/src/platforms/discord/types.test.js.map +0 -1
  260. package/dist/src/shared/utils/concurrency.test.d.ts +0 -2
  261. package/dist/src/shared/utils/concurrency.test.d.ts.map +0 -1
  262. package/dist/src/shared/utils/concurrency.test.js +0 -39
  263. package/dist/src/shared/utils/concurrency.test.js.map +0 -1
  264. package/dist/tests/cli.test.d.ts +0 -2
  265. package/dist/tests/cli.test.d.ts.map +0 -1
  266. package/dist/tests/cli.test.js +0 -83
  267. package/dist/tests/cli.test.js.map +0 -1
  268. package/dist/tests/commands/.test-slack-data/Local Storage/leveldb/CURRENT +0 -1
  269. package/dist/tests/commands/.test-slack-data/Local Storage/leveldb/LOCK +0 -0
  270. package/dist/tests/commands/.test-slack-data/Local Storage/leveldb/LOG +0 -3
  271. package/dist/tests/commands/.test-slack-data/Local Storage/leveldb/LOG.old +0 -1
  272. package/dist/tests/commands/.test-slack-data/Local Storage/leveldb/MANIFEST-000004 +0 -0
  273. package/dist/tests/commands/auth.test.d.ts +0 -2
  274. package/dist/tests/commands/auth.test.d.ts.map +0 -1
  275. package/dist/tests/commands/auth.test.js +0 -304
  276. package/dist/tests/commands/auth.test.js.map +0 -1
  277. package/dist/tests/commands/channel.test.d.ts +0 -2
  278. package/dist/tests/commands/channel.test.d.ts.map +0 -1
  279. package/dist/tests/commands/channel.test.js +0 -166
  280. package/dist/tests/commands/channel.test.js.map +0 -1
  281. package/dist/tests/commands/file.test.d.ts +0 -2
  282. package/dist/tests/commands/file.test.d.ts.map +0 -1
  283. package/dist/tests/commands/file.test.js +0 -175
  284. package/dist/tests/commands/file.test.js.map +0 -1
  285. package/dist/tests/commands/message.test.d.ts +0 -2
  286. package/dist/tests/commands/message.test.d.ts.map +0 -1
  287. package/dist/tests/commands/message.test.js +0 -293
  288. package/dist/tests/commands/message.test.js.map +0 -1
  289. package/dist/tests/commands/reaction.test.d.ts +0 -2
  290. package/dist/tests/commands/reaction.test.d.ts.map +0 -1
  291. package/dist/tests/commands/reaction.test.js +0 -84
  292. package/dist/tests/commands/reaction.test.js.map +0 -1
  293. package/dist/tests/commands/snapshot.test.d.ts +0 -2
  294. package/dist/tests/commands/snapshot.test.d.ts.map +0 -1
  295. package/dist/tests/commands/snapshot.test.js +0 -280
  296. package/dist/tests/commands/snapshot.test.js.map +0 -1
  297. package/dist/tests/commands/user.test.d.ts +0 -2
  298. package/dist/tests/commands/user.test.d.ts.map +0 -1
  299. package/dist/tests/commands/user.test.js +0 -117
  300. package/dist/tests/commands/user.test.js.map +0 -1
  301. package/dist/tests/commands/workspace.test.d.ts +0 -2
  302. package/dist/tests/commands/workspace.test.d.ts.map +0 -1
  303. package/dist/tests/commands/workspace.test.js +0 -453
  304. package/dist/tests/commands/workspace.test.js.map +0 -1
  305. package/dist/tests/credential-manager.test.d.ts +0 -2
  306. package/dist/tests/credential-manager.test.d.ts.map +0 -1
  307. package/dist/tests/credential-manager.test.js +0 -199
  308. package/dist/tests/credential-manager.test.js.map +0 -1
  309. package/dist/tests/slack-client.test.d.ts +0 -2
  310. package/dist/tests/slack-client.test.d.ts.map +0 -1
  311. package/dist/tests/slack-client.test.js +0 -741
  312. package/dist/tests/slack-client.test.js.map +0 -1
  313. package/dist/tests/types.test.d.ts +0 -2
  314. package/dist/tests/types.test.d.ts.map +0 -1
  315. package/dist/tests/types.test.js +0 -215
  316. package/dist/tests/types.test.js.map +0 -1
  317. package/dist/types/index.d.ts +0 -369
  318. package/dist/types/index.d.ts.map +0 -1
  319. package/dist/types/index.js +0 -92
  320. package/dist/types/index.js.map +0 -1
  321. package/dist/utils/error-handler.d.ts +0 -2
  322. package/dist/utils/error-handler.d.ts.map +0 -1
  323. package/dist/utils/error-handler.js +0 -5
  324. package/dist/utils/error-handler.js.map +0 -1
  325. package/dist/utils/output.d.ts +0 -2
  326. package/dist/utils/output.d.ts.map +0 -1
  327. package/dist/utils/output.js +0 -4
  328. package/dist/utils/output.js.map +0 -1
  329. /package/dist/{cli.d.ts → src/platforms/teams/cli.d.ts} +0 -0
  330. /package/dist/{commands → src/platforms/teams/commands}/user.d.ts +0 -0
@@ -1,35 +1,36 @@
1
- import { afterAll, beforeEach, describe, expect, test } from 'bun:test'
1
+ import { afterAll, describe, expect, test } from 'bun:test'
2
2
  import { rmSync } from 'node:fs'
3
3
  import { join } from 'node:path'
4
- import { CredentialManager } from '../../src/platforms/slack/credential-manager'
5
- import type { WorkspaceCredentials } from '../../src/platforms/slack/types'
6
-
7
- const testConfigDir = join(import.meta.dir, '.test-workspace-config')
4
+ import { CredentialManager } from '@/platforms/slack/credential-manager'
5
+ import type { WorkspaceCredentials } from '@/platforms/slack/types'
6
+
7
+ const testDirs: string[] = []
8
+
9
+ function setup(): CredentialManager {
10
+ const testConfigDir = join(
11
+ import.meta.dir,
12
+ `.test-workspace-config-${Date.now()}-${Math.random().toString(36).slice(2)}`
13
+ )
14
+ testDirs.push(testConfigDir)
15
+ return new CredentialManager(testConfigDir)
16
+ }
17
+
18
+ afterAll(() => {
19
+ for (const dir of testDirs) {
20
+ rmSync(dir, { recursive: true, force: true })
21
+ }
22
+ })
8
23
 
9
24
  describe('Workspace Commands', () => {
10
- let credManager: CredentialManager
11
-
12
- beforeEach(() => {
13
- rmSync(testConfigDir, { recursive: true, force: true })
14
- credManager = new CredentialManager(testConfigDir)
15
- })
16
-
17
- afterAll(() => {
18
- rmSync(testConfigDir, { recursive: true, force: true })
19
- })
20
-
21
25
  describe('workspace list', () => {
22
26
  test('returns empty list when no workspaces exist', async () => {
23
- // Given: No workspaces configured
24
- // When: Loading config
27
+ const credManager = setup()
25
28
  const config = await credManager.load()
26
-
27
- // Then: Should have empty workspaces
28
29
  expect(Object.keys(config.workspaces)).toHaveLength(0)
29
30
  })
30
31
 
31
32
  test('lists all workspaces with current marker', async () => {
32
- // Given: Multiple workspaces with one as current
33
+ const credManager = setup()
33
34
  const ws1: WorkspaceCredentials = {
34
35
  workspace_id: 'T123',
35
36
  workspace_name: 'acme-corp',
@@ -47,11 +48,9 @@ describe('Workspace Commands', () => {
47
48
  await credManager.setWorkspace(ws2)
48
49
  await credManager.setCurrentWorkspace('T123')
49
50
 
50
- // When: Loading config
51
51
  const config = await credManager.load()
52
52
  const workspaces = Object.values(config.workspaces)
53
53
 
54
- // Then: Should list all workspaces
55
54
  expect(workspaces).toHaveLength(2)
56
55
  expect(workspaces.map((w) => w.workspace_id)).toContain('T123')
57
56
  expect(workspaces.map((w) => w.workspace_id)).toContain('T456')
@@ -59,7 +58,7 @@ describe('Workspace Commands', () => {
59
58
  })
60
59
 
61
60
  test('shows current marker for active workspace', async () => {
62
- // Given: Workspace set as current
61
+ const credManager = setup()
63
62
  const ws: WorkspaceCredentials = {
64
63
  workspace_id: 'T789',
65
64
  workspace_name: 'current-ws',
@@ -69,16 +68,14 @@ describe('Workspace Commands', () => {
69
68
  await credManager.setWorkspace(ws)
70
69
  await credManager.setCurrentWorkspace('T789')
71
70
 
72
- // When: Loading config
73
71
  const config = await credManager.load()
74
72
 
75
- // Then: Current workspace should match
76
73
  expect(config.current_workspace).toBe('T789')
77
74
  expect(config.workspaces.T789).toBeDefined()
78
75
  })
79
76
 
80
77
  test('handles list with no current workspace', async () => {
81
- // Given: Workspaces exist but none is current
78
+ const credManager = setup()
82
79
  const ws: WorkspaceCredentials = {
83
80
  workspace_id: 'T999',
84
81
  workspace_name: 'no-current',
@@ -87,10 +84,8 @@ describe('Workspace Commands', () => {
87
84
  }
88
85
  await credManager.setWorkspace(ws)
89
86
 
90
- // When: Loading config
91
87
  const config = await credManager.load()
92
88
 
93
- // Then: current_workspace should be null
94
89
  expect(config.current_workspace).toBeNull()
95
90
  expect(config.workspaces.T999).toBeDefined()
96
91
  })
@@ -98,7 +93,7 @@ describe('Workspace Commands', () => {
98
93
 
99
94
  describe('workspace switch', () => {
100
95
  test('switches to existing workspace', async () => {
101
- // Given: Multiple workspaces exist
96
+ const credManager = setup()
102
97
  const ws1: WorkspaceCredentials = {
103
98
  workspace_id: 'T111',
104
99
  workspace_name: 'first',
@@ -115,25 +110,20 @@ describe('Workspace Commands', () => {
115
110
  await credManager.setWorkspace(ws2)
116
111
  await credManager.setCurrentWorkspace('T111')
117
112
 
118
- // When: Switching to second workspace
119
113
  await credManager.setCurrentWorkspace('T222')
120
114
 
121
- // Then: Current should be updated
122
115
  const config = await credManager.load()
123
116
  expect(config.current_workspace).toBe('T222')
124
117
  })
125
118
 
126
119
  test('fails when workspace does not exist', async () => {
127
- // Given: Workspace does not exist
128
- // When: Trying to get non-existent workspace
120
+ const credManager = setup()
129
121
  const ws = await credManager.getWorkspace('nonexistent')
130
-
131
- // Then: Should return null
132
122
  expect(ws).toBeNull()
133
123
  })
134
124
 
135
125
  test('validates workspace exists before switching', async () => {
136
- // Given: Only one workspace exists
126
+ const credManager = setup()
137
127
  const ws: WorkspaceCredentials = {
138
128
  workspace_id: 'T333',
139
129
  workspace_name: 'only-one',
@@ -143,16 +133,14 @@ describe('Workspace Commands', () => {
143
133
  await credManager.setWorkspace(ws)
144
134
  await credManager.setCurrentWorkspace('T333')
145
135
 
146
- // When: Trying to switch to non-existent workspace
147
136
  const config = await credManager.load()
148
137
  const targetExists = 'T999' in config.workspaces
149
138
 
150
- // Then: Should not exist
151
139
  expect(targetExists).toBe(false)
152
140
  })
153
141
 
154
142
  test('preserves workspace credentials when switching', async () => {
155
- // Given: Multiple workspaces with different credentials
143
+ const credManager = setup()
156
144
  const ws1: WorkspaceCredentials = {
157
145
  workspace_id: 'T444',
158
146
  workspace_name: 'first',
@@ -168,7 +156,6 @@ describe('Workspace Commands', () => {
168
156
  await credManager.setWorkspace(ws1)
169
157
  await credManager.setWorkspace(ws2)
170
158
 
171
- // When: Switching between workspaces
172
159
  await credManager.setCurrentWorkspace('T444')
173
160
  let config = await credManager.load()
174
161
  expect(config.current_workspace).toBe('T444')
@@ -176,7 +163,6 @@ describe('Workspace Commands', () => {
176
163
  await credManager.setCurrentWorkspace('T555')
177
164
  config = await credManager.load()
178
165
 
179
- // Then: Both workspaces should still have their credentials
180
166
  expect(config.workspaces.T444.token).toBe('token-444')
181
167
  expect(config.workspaces.T555.token).toBe('token-555')
182
168
  expect(config.current_workspace).toBe('T555')
@@ -185,7 +171,7 @@ describe('Workspace Commands', () => {
185
171
 
186
172
  describe('workspace current', () => {
187
173
  test('returns current workspace details', async () => {
188
- // Given: A current workspace is set
174
+ const credManager = setup()
189
175
  const ws: WorkspaceCredentials = {
190
176
  workspace_id: 'T666',
191
177
  workspace_name: 'current-workspace',
@@ -195,10 +181,8 @@ describe('Workspace Commands', () => {
195
181
  await credManager.setWorkspace(ws)
196
182
  await credManager.setCurrentWorkspace('T666')
197
183
 
198
- // When: Getting current workspace
199
184
  const current = await credManager.getWorkspace()
200
185
 
201
- // Then: Should return workspace details
202
186
  expect(current).not.toBeNull()
203
187
  expect(current?.workspace_id).toBe('T666')
204
188
  expect(current?.workspace_name).toBe('current-workspace')
@@ -207,16 +191,13 @@ describe('Workspace Commands', () => {
207
191
  })
208
192
 
209
193
  test('returns null when no current workspace set', async () => {
210
- // Given: No current workspace
211
- // When: Getting current workspace
194
+ const credManager = setup()
212
195
  const current = await credManager.getWorkspace()
213
-
214
- // Then: Should return null
215
196
  expect(current).toBeNull()
216
197
  })
217
198
 
218
199
  test('returns null when current workspace is deleted', async () => {
219
- // Given: Current workspace is set
200
+ const credManager = setup()
220
201
  const ws: WorkspaceCredentials = {
221
202
  workspace_id: 'T777',
222
203
  workspace_name: 'to-delete',
@@ -226,16 +207,14 @@ describe('Workspace Commands', () => {
226
207
  await credManager.setWorkspace(ws)
227
208
  await credManager.setCurrentWorkspace('T777')
228
209
 
229
- // When: Workspace is removed
230
210
  await credManager.removeWorkspace('T777')
231
211
 
232
- // Then: Current should be null
233
212
  const current = await credManager.getWorkspace()
234
213
  expect(current).toBeNull()
235
214
  })
236
215
 
237
216
  test('shows correct workspace after switching', async () => {
238
- // Given: Multiple workspaces with one as current
217
+ const credManager = setup()
239
218
  const ws1: WorkspaceCredentials = {
240
219
  workspace_id: 'T888',
241
220
  workspace_name: 'first',
@@ -252,11 +231,9 @@ describe('Workspace Commands', () => {
252
231
  await credManager.setWorkspace(ws2)
253
232
  await credManager.setCurrentWorkspace('T888')
254
233
 
255
- // When: Switching to second workspace
256
234
  await credManager.setCurrentWorkspace('T999')
257
235
  const current = await credManager.getWorkspace()
258
236
 
259
- // Then: Should return second workspace
260
237
  expect(current?.workspace_id).toBe('T999')
261
238
  expect(current?.workspace_name).toBe('second')
262
239
  })
@@ -264,7 +241,7 @@ describe('Workspace Commands', () => {
264
241
 
265
242
  describe('workspace remove', () => {
266
243
  test('removes workspace by id', async () => {
267
- // Given: A workspace exists
244
+ const credManager = setup()
268
245
  const ws: WorkspaceCredentials = {
269
246
  workspace_id: 'T-remove',
270
247
  workspace_name: 'to-remove',
@@ -273,16 +250,14 @@ describe('Workspace Commands', () => {
273
250
  }
274
251
  await credManager.setWorkspace(ws)
275
252
 
276
- // When: Workspace is removed
277
253
  await credManager.removeWorkspace('T-remove')
278
254
 
279
- // Then: Workspace should not exist
280
255
  const retrieved = await credManager.getWorkspace('T-remove')
281
256
  expect(retrieved).toBeNull()
282
257
  })
283
258
 
284
259
  test('removes current workspace and clears current', async () => {
285
- // Given: Current workspace is set
260
+ const credManager = setup()
286
261
  const ws: WorkspaceCredentials = {
287
262
  workspace_id: 'T-current-remove',
288
263
  workspace_name: 'current-to-remove',
@@ -292,16 +267,14 @@ describe('Workspace Commands', () => {
292
267
  await credManager.setWorkspace(ws)
293
268
  await credManager.setCurrentWorkspace('T-current-remove')
294
269
 
295
- // When: Current workspace is removed
296
270
  await credManager.removeWorkspace('T-current-remove')
297
271
 
298
- // Then: Current should be null
299
272
  const config = await credManager.load()
300
273
  expect(config.current_workspace).toBeNull()
301
274
  })
302
275
 
303
276
  test('removes workspace without affecting others', async () => {
304
- // Given: Multiple workspaces exist
277
+ const credManager = setup()
305
278
  const ws1: WorkspaceCredentials = {
306
279
  workspace_id: 'T-keep',
307
280
  workspace_name: 'keep',
@@ -318,10 +291,8 @@ describe('Workspace Commands', () => {
318
291
  await credManager.setWorkspace(ws2)
319
292
  await credManager.setCurrentWorkspace('T-keep')
320
293
 
321
- // When: One workspace is removed
322
294
  await credManager.removeWorkspace('T-remove-one')
323
295
 
324
- // Then: Other workspace should remain
325
296
  const config = await credManager.load()
326
297
  expect(config.workspaces['T-keep']).toBeDefined()
327
298
  expect(config.workspaces['T-remove-one']).toBeUndefined()
@@ -329,17 +300,15 @@ describe('Workspace Commands', () => {
329
300
  })
330
301
 
331
302
  test('handles removing non-existent workspace gracefully', async () => {
332
- // Given: Workspace does not exist
333
- // When: Trying to remove non-existent workspace
303
+ const credManager = setup()
334
304
  await credManager.removeWorkspace('nonexistent')
335
305
 
336
- // Then: Should not throw error
337
306
  const config = await credManager.load()
338
307
  expect(config.workspaces).toEqual({})
339
308
  })
340
309
 
341
310
  test('clears current only if removed workspace was current', async () => {
342
- // Given: Multiple workspaces with one as current
311
+ const credManager = setup()
343
312
  const ws1: WorkspaceCredentials = {
344
313
  workspace_id: 'T-current-1',
345
314
  workspace_name: 'current-1',
@@ -356,10 +325,8 @@ describe('Workspace Commands', () => {
356
325
  await credManager.setWorkspace(ws2)
357
326
  await credManager.setCurrentWorkspace('T-current-1')
358
327
 
359
- // When: Non-current workspace is removed
360
328
  await credManager.removeWorkspace('T-other')
361
329
 
362
- // Then: Current should remain unchanged
363
330
  const config = await credManager.load()
364
331
  expect(config.current_workspace).toBe('T-current-1')
365
332
  })
@@ -367,7 +334,7 @@ describe('Workspace Commands', () => {
367
334
 
368
335
  describe('Output Formatting', () => {
369
336
  test('formats list output correctly', async () => {
370
- // Given: Multiple workspaces
337
+ const credManager = setup()
371
338
  const ws1: WorkspaceCredentials = {
372
339
  workspace_id: 'T-format-1',
373
340
  workspace_name: 'format-1',
@@ -384,7 +351,6 @@ describe('Workspace Commands', () => {
384
351
  await credManager.setWorkspace(ws2)
385
352
  await credManager.setCurrentWorkspace('T-format-1')
386
353
 
387
- // When: Creating list output
388
354
  const config = await credManager.load()
389
355
  const output = Object.values(config.workspaces).map((ws) => ({
390
356
  id: ws.workspace_id,
@@ -392,7 +358,6 @@ describe('Workspace Commands', () => {
392
358
  current: ws.workspace_id === config.current_workspace,
393
359
  }))
394
360
 
395
- // Then: Should be valid JSON
396
361
  const json = JSON.stringify(output)
397
362
  const parsed = JSON.parse(json)
398
363
  expect(parsed).toHaveLength(2)
@@ -401,7 +366,7 @@ describe('Workspace Commands', () => {
401
366
  })
402
367
 
403
368
  test('formats switch output correctly', async () => {
404
- // Given: Workspace to switch to
369
+ const credManager = setup()
405
370
  const ws: WorkspaceCredentials = {
406
371
  workspace_id: 'T-switch-format',
407
372
  workspace_name: 'switch-format',
@@ -411,17 +376,15 @@ describe('Workspace Commands', () => {
411
376
  await credManager.setWorkspace(ws)
412
377
  await credManager.setCurrentWorkspace('T-switch-format')
413
378
 
414
- // When: Creating switch output
415
379
  const output = { current: 'T-switch-format' }
416
380
 
417
- // Then: Should be valid JSON
418
381
  const json = JSON.stringify(output)
419
382
  const parsed = JSON.parse(json)
420
383
  expect(parsed.current).toBe('T-switch-format')
421
384
  })
422
385
 
423
386
  test('formats current output correctly', async () => {
424
- // Given: Current workspace
387
+ const credManager = setup()
425
388
  const ws: WorkspaceCredentials = {
426
389
  workspace_id: 'T-current-format',
427
390
  workspace_name: 'current-format',
@@ -431,14 +394,12 @@ describe('Workspace Commands', () => {
431
394
  await credManager.setWorkspace(ws)
432
395
  await credManager.setCurrentWorkspace('T-current-format')
433
396
 
434
- // When: Creating current output
435
397
  const current = await credManager.getWorkspace()
436
398
  const output = {
437
399
  workspace_id: current?.workspace_id,
438
400
  workspace_name: current?.workspace_name,
439
401
  }
440
402
 
441
- // Then: Should be valid JSON
442
403
  const json = JSON.stringify(output)
443
404
  const parsed = JSON.parse(json)
444
405
  expect(parsed.workspace_id).toBe('T-current-format')
@@ -446,7 +407,7 @@ describe('Workspace Commands', () => {
446
407
  })
447
408
 
448
409
  test('formats remove output correctly', async () => {
449
- // Given: Workspace to remove
410
+ const credManager = setup()
450
411
  const ws: WorkspaceCredentials = {
451
412
  workspace_id: 'T-remove-format',
452
413
  workspace_name: 'remove-format',
@@ -455,27 +416,22 @@ describe('Workspace Commands', () => {
455
416
  }
456
417
  await credManager.setWorkspace(ws)
457
418
 
458
- // When: Creating remove output
459
419
  const output = { removed: 'T-remove-format' }
460
420
 
461
- // Then: Should be valid JSON
462
421
  const json = JSON.stringify(output)
463
422
  const parsed = JSON.parse(json)
464
423
  expect(parsed.removed).toBe('T-remove-format')
465
424
  })
466
425
 
467
426
  test('pretty prints JSON correctly', async () => {
468
- // Given: Output data
469
427
  const output = {
470
428
  id: 'T123',
471
429
  name: 'test',
472
430
  current: true,
473
431
  }
474
432
 
475
- // When: Pretty printing
476
433
  const pretty = JSON.stringify(output, null, 2)
477
434
 
478
- // Then: Should contain newlines and indentation
479
435
  expect(pretty).toContain('\n')
480
436
  expect(pretty).toContain(' ')
481
437
  })
@@ -483,26 +439,21 @@ describe('Workspace Commands', () => {
483
439
 
484
440
  describe('Error Handling', () => {
485
441
  test('handles missing workspace gracefully', async () => {
486
- // Given: Workspace does not exist
487
- // When: Trying to get workspace
442
+ const credManager = setup()
488
443
  const ws = await credManager.getWorkspace('missing')
489
-
490
- // Then: Should return null
491
444
  expect(ws).toBeNull()
492
445
  })
493
446
 
494
447
  test('handles corrupted config gracefully', async () => {
495
- // Given: Config directory exists
496
- // When: Loading from empty directory
448
+ const credManager = setup()
497
449
  const config = await credManager.load()
498
450
 
499
- // Then: Should return default config
500
451
  expect(config.current_workspace).toBeNull()
501
452
  expect(config.workspaces).toEqual({})
502
453
  })
503
454
 
504
455
  test('handles concurrent operations', async () => {
505
- // Given: Multiple workspaces
456
+ const credManager = setup()
506
457
  const ws1: WorkspaceCredentials = {
507
458
  workspace_id: 'T-concurrent-1',
508
459
  workspace_name: 'concurrent-1',
@@ -516,11 +467,9 @@ describe('Workspace Commands', () => {
516
467
  cookie: 'cookie-2',
517
468
  }
518
469
 
519
- // When: Setting workspaces sequentially
520
470
  await credManager.setWorkspace(ws1)
521
471
  await credManager.setWorkspace(ws2)
522
472
 
523
- // Then: Both should be saved
524
473
  const config = await credManager.load()
525
474
  expect(Object.keys(config.workspaces)).toHaveLength(2)
526
475
  })
@@ -1,8 +1,8 @@
1
1
  import { afterAll, beforeEach, describe, expect, test } from 'bun:test'
2
2
  import { existsSync, rmSync } from 'node:fs'
3
3
  import { join } from 'node:path'
4
- import { CredentialManager } from '../src/platforms/slack/credential-manager'
5
- import type { Config, WorkspaceCredentials } from '../src/platforms/slack/types'
4
+ import { CredentialManager } from '@/platforms/slack/credential-manager'
5
+ import type { Config, WorkspaceCredentials } from '@/platforms/slack/types'
6
6
 
7
7
  const testConfigDir = join(import.meta.dir, '.test-config')
8
8
 
@@ -1,5 +1,5 @@
1
1
  import { existsSync } from 'node:fs'
2
- import { mkdir } from 'node:fs/promises'
2
+ import { chmod, mkdir, readFile, writeFile } from 'node:fs/promises'
3
3
  import { homedir } from 'node:os'
4
4
  import { join } from 'node:path'
5
5
  import type { Config, WorkspaceCredentials } from './types'
@@ -21,21 +21,36 @@ export class CredentialManager {
21
21
  }
22
22
  }
23
23
 
24
- const file = Bun.file(this.credentialsPath)
25
- const content = await file.text()
24
+ const content = await readFile(this.credentialsPath, 'utf-8')
26
25
  return JSON.parse(content) as Config
27
26
  }
28
27
 
29
28
  async save(config: Config): Promise<void> {
30
29
  await mkdir(this.configDir, { recursive: true })
31
30
 
32
- const file = Bun.file(this.credentialsPath)
33
- await Bun.write(file, JSON.stringify(config, null, 2))
34
-
35
- await Bun.spawn(['chmod', '0600', this.credentialsPath]).exited
31
+ await writeFile(this.credentialsPath, JSON.stringify(config, null, 2))
32
+ await chmod(this.credentialsPath, 0o600)
36
33
  }
37
34
 
38
35
  async getWorkspace(id?: string): Promise<WorkspaceCredentials | null> {
36
+ // Check env vars first (take precedence over file-based credentials)
37
+ // Only use env credentials if no specific id requested, or id matches env workspace
38
+ const envToken = process.env.E2E_SLACK_TOKEN
39
+ const envCookie = process.env.E2E_SLACK_COOKIE
40
+ const envWorkspaceId = process.env.E2E_SLACK_WORKSPACE_ID
41
+ const envWorkspaceName = process.env.E2E_SLACK_WORKSPACE_NAME
42
+
43
+ if (envToken && envCookie && envWorkspaceId && envWorkspaceName) {
44
+ if (!id || id === envWorkspaceId) {
45
+ return {
46
+ token: envToken,
47
+ cookie: envCookie,
48
+ workspace_id: envWorkspaceId,
49
+ workspace_name: envWorkspaceName,
50
+ }
51
+ }
52
+ }
53
+
39
54
  const config = await this.load()
40
55
 
41
56
  if (id) {
@@ -0,0 +1,40 @@
1
+ import { mkdirSync, mkdtempSync, rmSync } from 'node:fs'
2
+ import { tmpdir } from 'node:os'
3
+ import { join } from 'node:path'
4
+ import Database from 'better-sqlite3'
5
+ import { TokenExtractor } from './token-extractor'
6
+
7
+ const tempDir = mkdtempSync(join(tmpdir(), 'token-extractor-test-'))
8
+ const slackDir = join(tempDir, 'Slack')
9
+ mkdirSync(slackDir)
10
+
11
+ const dbPath = join(slackDir, 'Cookies')
12
+
13
+ try {
14
+ const db = new Database(dbPath)
15
+ db.exec(`
16
+ CREATE TABLE cookies (
17
+ name TEXT,
18
+ value TEXT,
19
+ encrypted_value BLOB,
20
+ host_key TEXT,
21
+ last_access_utc INTEGER
22
+ )
23
+ `)
24
+ db.prepare(
25
+ "INSERT INTO cookies (name, value, host_key, last_access_utc) VALUES ('d', 'xoxd-test-cookie', '.slack.com', 1000)"
26
+ ).run()
27
+ db.close()
28
+
29
+ const extractor = new TokenExtractor(process.platform, slackDir)
30
+ const result = (extractor as any).readCookieFromDB(dbPath)
31
+
32
+ if (result !== 'xoxd-test-cookie') {
33
+ console.error('Expected xoxd-test-cookie, got:', result)
34
+ process.exit(1)
35
+ }
36
+
37
+ console.log('ok')
38
+ } finally {
39
+ rmSync(tempDir, { recursive: true })
40
+ }
@@ -0,0 +1,10 @@
1
+ import { expect, test } from 'bun:test'
2
+ import { execSync } from 'node:child_process'
3
+
4
+ test('TokenExtractor works in Node.js', () => {
5
+ const result = execSync('bun tsx src/platforms/slack/token-extractor-node-test.ts', {
6
+ cwd: process.cwd(),
7
+ encoding: 'utf-8',
8
+ })
9
+ expect(result.trim()).toBe('ok')
10
+ })
@@ -1,11 +1,13 @@
1
- import { Database } from 'bun:sqlite'
2
1
  import { execSync } from 'node:child_process'
3
2
  import { createDecipheriv, pbkdf2Sync } from 'node:crypto'
4
- import { existsSync, readdirSync, readFileSync } from 'node:fs'
5
- import { homedir } from 'node:os'
3
+ import { copyFileSync, existsSync, readdirSync, readFileSync, rmSync } from 'node:fs'
4
+ import { createRequire } from 'node:module'
5
+ import { homedir, tmpdir } from 'node:os'
6
6
  import { join } from 'node:path'
7
7
  import { ClassicLevel } from 'classic-level'
8
8
 
9
+ const require = createRequire(import.meta.url)
10
+
9
11
  export interface ExtractedWorkspace {
10
12
  workspace_id: string
11
13
  workspace_name: string
@@ -395,20 +397,40 @@ export class TokenExtractor {
395
397
  }
396
398
 
397
399
  private readCookieFromDB(dbPath: string): string {
400
+ // Copy the database to a temp file to avoid SQLite lock contention
401
+ // when Slack is running and has a write lock on the Cookies database
402
+ const tempDbPath = join(
403
+ tmpdir(),
404
+ `slack-cookies-${Date.now()}-${Math.random().toString(36).slice(2)}.db`
405
+ )
406
+
398
407
  try {
399
- const db = new Database(dbPath, { readonly: true })
408
+ copyFileSync(dbPath, tempDbPath)
409
+ } catch {
410
+ return ''
411
+ }
400
412
 
401
- const row = db
402
- .query(
403
- `SELECT value, encrypted_value
413
+ try {
414
+ const sql = `SELECT value, encrypted_value
404
415
  FROM cookies
405
416
  WHERE name = 'd' AND host_key LIKE '%slack.com%'
406
417
  ORDER BY last_access_utc DESC
407
418
  LIMIT 1`
408
- )
409
- .get() as { value?: string; encrypted_value?: Uint8Array } | null
410
419
 
411
- db.close()
420
+ type CookieRow = { value?: string; encrypted_value?: Uint8Array | Buffer } | null
421
+
422
+ let row: CookieRow
423
+ if (typeof globalThis.Bun !== 'undefined') {
424
+ const { Database } = require('bun:sqlite')
425
+ const db = new Database(tempDbPath, { readonly: true })
426
+ row = db.query(sql).get() as CookieRow
427
+ db.close()
428
+ } else {
429
+ const Database = require('better-sqlite3')
430
+ const db = new Database(tempDbPath, { readonly: true })
431
+ row = db.prepare(sql).get() as CookieRow
432
+ db.close()
433
+ }
412
434
 
413
435
  if (!row) {
414
436
  return ''
@@ -428,6 +450,10 @@ export class TokenExtractor {
428
450
  return ''
429
451
  } catch {
430
452
  return ''
453
+ } finally {
454
+ try {
455
+ rmSync(tempDbPath, { force: true })
456
+ } catch {}
431
457
  }
432
458
  }
433
459
 
@@ -7,7 +7,7 @@ import {
7
7
  SlackReactionSchema,
8
8
  SlackUserSchema,
9
9
  WorkspaceCredentialsSchema,
10
- } from '../src/platforms/slack/types'
10
+ } from '@/platforms/slack/types'
11
11
 
12
12
  test('SlackChannelSchema validates correct data', () => {
13
13
  const validChannel = {