@lhremote/core 0.6.0 → 0.8.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 (356) hide show
  1. package/README.md +39 -0
  2. package/dist/cdp/client.d.ts +5 -1
  3. package/dist/cdp/client.d.ts.map +1 -1
  4. package/dist/cdp/client.js +11 -3
  5. package/dist/cdp/client.js.map +1 -1
  6. package/dist/data/index.d.ts +1 -0
  7. package/dist/data/index.d.ts.map +1 -1
  8. package/dist/data/index.js +1 -0
  9. package/dist/data/index.js.map +1 -1
  10. package/dist/data/linkedin-reference.d.ts +44 -0
  11. package/dist/data/linkedin-reference.d.ts.map +1 -0
  12. package/dist/data/linkedin-reference.js +316 -0
  13. package/dist/data/linkedin-reference.js.map +1 -0
  14. package/dist/data/linkedin-reference.test.d.ts +2 -0
  15. package/dist/data/linkedin-reference.test.d.ts.map +1 -0
  16. package/dist/data/linkedin-reference.test.js +124 -0
  17. package/dist/data/linkedin-reference.test.js.map +1 -0
  18. package/dist/db/index.d.ts +1 -1
  19. package/dist/db/index.d.ts.map +1 -1
  20. package/dist/db/index.js +1 -1
  21. package/dist/db/index.js.map +1 -1
  22. package/dist/db/repositories/action-budget.d.ts +29 -0
  23. package/dist/db/repositories/action-budget.d.ts.map +1 -0
  24. package/dist/db/repositories/action-budget.js +100 -0
  25. package/dist/db/repositories/action-budget.js.map +1 -0
  26. package/dist/db/repositories/action-budget.test.d.ts +2 -0
  27. package/dist/db/repositories/action-budget.test.d.ts.map +1 -0
  28. package/dist/db/repositories/action-budget.test.js +181 -0
  29. package/dist/db/repositories/action-budget.test.js.map +1 -0
  30. package/dist/db/repositories/campaign-hard-delete.integration.test.d.ts +2 -0
  31. package/dist/db/repositories/campaign-hard-delete.integration.test.d.ts.map +1 -0
  32. package/dist/db/repositories/campaign-hard-delete.integration.test.js +78 -0
  33. package/dist/db/repositories/campaign-hard-delete.integration.test.js.map +1 -0
  34. package/dist/db/repositories/campaign.d.ts +14 -0
  35. package/dist/db/repositories/campaign.d.ts.map +1 -1
  36. package/dist/db/repositories/campaign.js +125 -0
  37. package/dist/db/repositories/campaign.js.map +1 -1
  38. package/dist/db/repositories/index.d.ts +1 -0
  39. package/dist/db/repositories/index.d.ts.map +1 -1
  40. package/dist/db/repositories/index.js +1 -0
  41. package/dist/db/repositories/index.js.map +1 -1
  42. package/dist/index.d.ts +6 -5
  43. package/dist/index.d.ts.map +1 -1
  44. package/dist/index.js +28 -6
  45. package/dist/index.js.map +1 -1
  46. package/dist/linkedin/__tests__/dom-automation.integration.test.d.ts +2 -0
  47. package/dist/linkedin/__tests__/dom-automation.integration.test.d.ts.map +1 -0
  48. package/dist/linkedin/__tests__/dom-automation.integration.test.js +160 -0
  49. package/dist/linkedin/__tests__/dom-automation.integration.test.js.map +1 -0
  50. package/dist/linkedin/__tests__/selectors.integration.test.d.ts +2 -0
  51. package/dist/linkedin/__tests__/selectors.integration.test.d.ts.map +1 -0
  52. package/dist/linkedin/__tests__/selectors.integration.test.js +258 -0
  53. package/dist/linkedin/__tests__/selectors.integration.test.js.map +1 -0
  54. package/dist/linkedin/dom-automation.d.ts +67 -0
  55. package/dist/linkedin/dom-automation.d.ts.map +1 -0
  56. package/dist/linkedin/dom-automation.js +139 -0
  57. package/dist/linkedin/dom-automation.js.map +1 -0
  58. package/dist/linkedin/index.d.ts +3 -0
  59. package/dist/linkedin/index.d.ts.map +1 -0
  60. package/dist/linkedin/index.js +5 -0
  61. package/dist/linkedin/index.js.map +1 -0
  62. package/dist/linkedin/selectors.d.ts +67 -0
  63. package/dist/linkedin/selectors.d.ts.map +1 -0
  64. package/dist/linkedin/selectors.js +74 -0
  65. package/dist/linkedin/selectors.js.map +1 -0
  66. package/dist/operations/build-linkedin-url.d.ts +39 -0
  67. package/dist/operations/build-linkedin-url.d.ts.map +1 -0
  68. package/dist/operations/build-linkedin-url.js +72 -0
  69. package/dist/operations/build-linkedin-url.js.map +1 -0
  70. package/dist/operations/campaign-delete.d.ts +6 -2
  71. package/dist/operations/campaign-delete.d.ts.map +1 -1
  72. package/dist/operations/campaign-delete.js +9 -2
  73. package/dist/operations/campaign-delete.js.map +1 -1
  74. package/dist/operations/campaign-delete.test.js +41 -1
  75. package/dist/operations/campaign-delete.test.js.map +1 -1
  76. package/dist/operations/campaign-erase.d.ts +19 -0
  77. package/dist/operations/campaign-erase.d.ts.map +1 -0
  78. package/dist/operations/campaign-erase.js +22 -0
  79. package/dist/operations/campaign-erase.js.map +1 -0
  80. package/dist/operations/campaign-erase.test.d.ts +2 -0
  81. package/dist/operations/campaign-erase.test.d.ts.map +1 -0
  82. package/dist/operations/campaign-erase.test.js +101 -0
  83. package/dist/operations/campaign-erase.test.js.map +1 -0
  84. package/dist/operations/comment-on-post.d.ts +34 -0
  85. package/dist/operations/comment-on-post.d.ts.map +1 -0
  86. package/dist/operations/comment-on-post.js +108 -0
  87. package/dist/operations/comment-on-post.js.map +1 -0
  88. package/dist/operations/comment-on-post.test.d.ts +2 -0
  89. package/dist/operations/comment-on-post.test.d.ts.map +1 -0
  90. package/dist/operations/comment-on-post.test.js +240 -0
  91. package/dist/operations/comment-on-post.test.js.map +1 -0
  92. package/dist/operations/dismiss-errors.d.ts +22 -0
  93. package/dist/operations/dismiss-errors.d.ts.map +1 -0
  94. package/dist/operations/dismiss-errors.js +55 -0
  95. package/dist/operations/dismiss-errors.js.map +1 -0
  96. package/dist/operations/dismiss-errors.test.d.ts +2 -0
  97. package/dist/operations/dismiss-errors.test.d.ts.map +1 -0
  98. package/dist/operations/dismiss-errors.test.js +136 -0
  99. package/dist/operations/dismiss-errors.test.js.map +1 -0
  100. package/dist/operations/endorse-skills.d.ts +10 -0
  101. package/dist/operations/endorse-skills.d.ts.map +1 -0
  102. package/dist/operations/endorse-skills.js +12 -0
  103. package/dist/operations/endorse-skills.js.map +1 -0
  104. package/dist/operations/enrich-profile.d.ts +18 -0
  105. package/dist/operations/enrich-profile.d.ts.map +1 -0
  106. package/dist/operations/enrich-profile.js +15 -0
  107. package/dist/operations/enrich-profile.js.map +1 -0
  108. package/dist/operations/ephemeral-action.d.ts +22 -0
  109. package/dist/operations/ephemeral-action.d.ts.map +1 -0
  110. package/dist/operations/ephemeral-action.js +31 -0
  111. package/dist/operations/ephemeral-action.js.map +1 -0
  112. package/dist/operations/follow-person.d.ts +9 -0
  113. package/dist/operations/follow-person.d.ts.map +1 -0
  114. package/dist/operations/follow-person.js +11 -0
  115. package/dist/operations/follow-person.js.map +1 -0
  116. package/dist/operations/get-action-budget.d.ts +6 -0
  117. package/dist/operations/get-action-budget.d.ts.map +1 -0
  118. package/dist/operations/get-action-budget.js +22 -0
  119. package/dist/operations/get-action-budget.js.map +1 -0
  120. package/dist/operations/get-action-budget.test.d.ts +2 -0
  121. package/dist/operations/get-action-budget.test.d.ts.map +1 -0
  122. package/dist/operations/get-action-budget.test.js +79 -0
  123. package/dist/operations/get-action-budget.test.js.map +1 -0
  124. package/dist/operations/get-errors.d.ts +9 -3
  125. package/dist/operations/get-errors.d.ts.map +1 -1
  126. package/dist/operations/get-errors.js +41 -4
  127. package/dist/operations/get-errors.js.map +1 -1
  128. package/dist/operations/get-errors.test.js +108 -42
  129. package/dist/operations/get-errors.test.js.map +1 -1
  130. package/dist/operations/get-feed.d.ts +33 -0
  131. package/dist/operations/get-feed.d.ts.map +1 -0
  132. package/dist/operations/get-feed.js +220 -0
  133. package/dist/operations/get-feed.js.map +1 -0
  134. package/dist/operations/get-feed.test.d.ts +2 -0
  135. package/dist/operations/get-feed.test.d.ts.map +1 -0
  136. package/dist/operations/get-feed.test.js +276 -0
  137. package/dist/operations/get-feed.test.js.map +1 -0
  138. package/dist/operations/get-post-engagers.d.ts +40 -0
  139. package/dist/operations/get-post-engagers.d.ts.map +1 -0
  140. package/dist/operations/get-post-engagers.js +128 -0
  141. package/dist/operations/get-post-engagers.js.map +1 -0
  142. package/dist/operations/get-post-engagers.test.d.ts +2 -0
  143. package/dist/operations/get-post-engagers.test.d.ts.map +1 -0
  144. package/dist/operations/get-post-engagers.test.js +19 -0
  145. package/dist/operations/get-post-engagers.test.js.map +1 -0
  146. package/dist/operations/get-post-stats.d.ts +38 -0
  147. package/dist/operations/get-post-stats.d.ts.map +1 -0
  148. package/dist/operations/get-post-stats.js +100 -0
  149. package/dist/operations/get-post-stats.js.map +1 -0
  150. package/dist/operations/get-post-stats.test.d.ts +2 -0
  151. package/dist/operations/get-post-stats.test.d.ts.map +1 -0
  152. package/dist/operations/get-post-stats.test.js +34 -0
  153. package/dist/operations/get-post-stats.test.js.map +1 -0
  154. package/dist/operations/get-post.d.ts +183 -0
  155. package/dist/operations/get-post.d.ts.map +1 -0
  156. package/dist/operations/get-post.js +270 -0
  157. package/dist/operations/get-post.js.map +1 -0
  158. package/dist/operations/get-post.test.d.ts +2 -0
  159. package/dist/operations/get-post.test.d.ts.map +1 -0
  160. package/dist/operations/get-post.test.js +449 -0
  161. package/dist/operations/get-post.test.js.map +1 -0
  162. package/dist/operations/get-profile-activity.d.ts +129 -0
  163. package/dist/operations/get-profile-activity.d.ts.map +1 -0
  164. package/dist/operations/get-profile-activity.js +181 -0
  165. package/dist/operations/get-profile-activity.js.map +1 -0
  166. package/dist/operations/get-profile-activity.test.d.ts +2 -0
  167. package/dist/operations/get-profile-activity.test.d.ts.map +1 -0
  168. package/dist/operations/get-profile-activity.test.js +205 -0
  169. package/dist/operations/get-profile-activity.test.js.map +1 -0
  170. package/dist/operations/get-throttle-status.d.ts +6 -0
  171. package/dist/operations/get-throttle-status.d.ts.map +1 -0
  172. package/dist/operations/get-throttle-status.js +30 -0
  173. package/dist/operations/get-throttle-status.js.map +1 -0
  174. package/dist/operations/get-throttle-status.test.d.ts +2 -0
  175. package/dist/operations/get-throttle-status.test.d.ts.map +1 -0
  176. package/dist/operations/get-throttle-status.test.js +62 -0
  177. package/dist/operations/get-throttle-status.test.js.map +1 -0
  178. package/dist/operations/index.d.ts +24 -0
  179. package/dist/operations/index.d.ts.map +1 -1
  180. package/dist/operations/index.js +35 -0
  181. package/dist/operations/index.js.map +1 -1
  182. package/dist/operations/like-person-posts.d.ts +14 -0
  183. package/dist/operations/like-person-posts.d.ts.map +1 -0
  184. package/dist/operations/like-person-posts.js +28 -0
  185. package/dist/operations/like-person-posts.js.map +1 -0
  186. package/dist/operations/message-person.d.ts +11 -0
  187. package/dist/operations/message-person.d.ts.map +1 -0
  188. package/dist/operations/message-person.js +19 -0
  189. package/dist/operations/message-person.js.map +1 -0
  190. package/dist/operations/react-to-post.d.ts +38 -0
  191. package/dist/operations/react-to-post.d.ts.map +1 -0
  192. package/dist/operations/react-to-post.js +82 -0
  193. package/dist/operations/react-to-post.js.map +1 -0
  194. package/dist/operations/react-to-post.test.d.ts +2 -0
  195. package/dist/operations/react-to-post.test.d.ts.map +1 -0
  196. package/dist/operations/react-to-post.test.js +154 -0
  197. package/dist/operations/react-to-post.test.js.map +1 -0
  198. package/dist/operations/remove-connection.d.ts +6 -0
  199. package/dist/operations/remove-connection.d.ts.map +1 -0
  200. package/dist/operations/remove-connection.js +7 -0
  201. package/dist/operations/remove-connection.js.map +1 -0
  202. package/dist/operations/resolve-linkedin-entity.d.ts +33 -0
  203. package/dist/operations/resolve-linkedin-entity.d.ts.map +1 -0
  204. package/dist/operations/resolve-linkedin-entity.js +198 -0
  205. package/dist/operations/resolve-linkedin-entity.js.map +1 -0
  206. package/dist/operations/search-posts.d.ts +143 -0
  207. package/dist/operations/search-posts.d.ts.map +1 -0
  208. package/dist/operations/search-posts.js +220 -0
  209. package/dist/operations/search-posts.js.map +1 -0
  210. package/dist/operations/search-posts.test.d.ts +2 -0
  211. package/dist/operations/search-posts.test.d.ts.map +1 -0
  212. package/dist/operations/search-posts.test.js +261 -0
  213. package/dist/operations/search-posts.test.js.map +1 -0
  214. package/dist/operations/send-inmail.d.ts +11 -0
  215. package/dist/operations/send-inmail.d.ts.map +1 -0
  216. package/dist/operations/send-inmail.js +19 -0
  217. package/dist/operations/send-inmail.js.map +1 -0
  218. package/dist/operations/send-invite.d.ts +9 -0
  219. package/dist/operations/send-invite.d.ts.map +1 -0
  220. package/dist/operations/send-invite.js +14 -0
  221. package/dist/operations/send-invite.js.map +1 -0
  222. package/dist/operations/visit-profile.d.ts +14 -0
  223. package/dist/operations/visit-profile.d.ts.map +1 -0
  224. package/dist/operations/visit-profile.js +49 -0
  225. package/dist/operations/visit-profile.js.map +1 -0
  226. package/dist/operations/visit-profile.test.d.ts +2 -0
  227. package/dist/operations/visit-profile.test.d.ts.map +1 -0
  228. package/dist/operations/visit-profile.test.js +193 -0
  229. package/dist/operations/visit-profile.test.js.map +1 -0
  230. package/dist/services/app.d.ts.map +1 -1
  231. package/dist/services/app.js +37 -12
  232. package/dist/services/app.js.map +1 -1
  233. package/dist/services/app.test.js +57 -0
  234. package/dist/services/app.test.js.map +1 -1
  235. package/dist/services/boolean-expression.d.ts +29 -0
  236. package/dist/services/boolean-expression.d.ts.map +1 -0
  237. package/dist/services/boolean-expression.js +79 -0
  238. package/dist/services/boolean-expression.js.map +1 -0
  239. package/dist/services/boolean-expression.test.d.ts +2 -0
  240. package/dist/services/boolean-expression.test.d.ts.map +1 -0
  241. package/dist/services/boolean-expression.test.js +64 -0
  242. package/dist/services/boolean-expression.test.js.map +1 -0
  243. package/dist/services/campaign.d.ts +10 -0
  244. package/dist/services/campaign.d.ts.map +1 -1
  245. package/dist/services/campaign.js +16 -0
  246. package/dist/services/campaign.js.map +1 -1
  247. package/dist/services/collection.d.ts +5 -2
  248. package/dist/services/collection.d.ts.map +1 -1
  249. package/dist/services/collection.js +33 -5
  250. package/dist/services/collection.js.map +1 -1
  251. package/dist/services/collection.test.js +64 -6
  252. package/dist/services/collection.test.js.map +1 -1
  253. package/dist/services/ephemeral-campaign.d.ts +64 -0
  254. package/dist/services/ephemeral-campaign.d.ts.map +1 -0
  255. package/dist/services/ephemeral-campaign.js +210 -0
  256. package/dist/services/ephemeral-campaign.js.map +1 -0
  257. package/dist/services/ephemeral-campaign.test.d.ts +2 -0
  258. package/dist/services/ephemeral-campaign.test.d.ts.map +1 -0
  259. package/dist/services/ephemeral-campaign.test.js +333 -0
  260. package/dist/services/ephemeral-campaign.test.js.map +1 -0
  261. package/dist/services/errors.d.ts +21 -0
  262. package/dist/services/errors.d.ts.map +1 -1
  263. package/dist/services/errors.js +35 -0
  264. package/dist/services/errors.js.map +1 -1
  265. package/dist/services/index.d.ts +7 -1
  266. package/dist/services/index.d.ts.map +1 -1
  267. package/dist/services/index.js +7 -1
  268. package/dist/services/index.js.map +1 -1
  269. package/dist/services/instance-context.d.ts.map +1 -1
  270. package/dist/services/instance-context.js +9 -1
  271. package/dist/services/instance-context.js.map +1 -1
  272. package/dist/services/instance-context.test.js +77 -1
  273. package/dist/services/instance-context.test.js.map +1 -1
  274. package/dist/services/instance.d.ts +43 -0
  275. package/dist/services/instance.d.ts.map +1 -1
  276. package/dist/services/instance.js +151 -0
  277. package/dist/services/instance.js.map +1 -1
  278. package/dist/services/instance.test.js +101 -0
  279. package/dist/services/instance.test.js.map +1 -1
  280. package/dist/services/launcher.d.ts +23 -0
  281. package/dist/services/launcher.d.ts.map +1 -1
  282. package/dist/services/launcher.js +81 -11
  283. package/dist/services/launcher.js.map +1 -1
  284. package/dist/services/launcher.test.js +109 -42
  285. package/dist/services/launcher.test.js.map +1 -1
  286. package/dist/services/sn-url-builder.d.ts +21 -0
  287. package/dist/services/sn-url-builder.d.ts.map +1 -0
  288. package/dist/services/sn-url-builder.js +132 -0
  289. package/dist/services/sn-url-builder.js.map +1 -0
  290. package/dist/services/sn-url-builder.test.d.ts +2 -0
  291. package/dist/services/sn-url-builder.test.d.ts.map +1 -0
  292. package/dist/services/sn-url-builder.test.js +130 -0
  293. package/dist/services/sn-url-builder.test.js.map +1 -0
  294. package/dist/services/url-builder.d.ts +12 -0
  295. package/dist/services/url-builder.d.ts.map +1 -0
  296. package/dist/services/url-builder.js +100 -0
  297. package/dist/services/url-builder.js.map +1 -0
  298. package/dist/services/url-builder.test.d.ts +2 -0
  299. package/dist/services/url-builder.test.d.ts.map +1 -0
  300. package/dist/services/url-builder.test.js +79 -0
  301. package/dist/services/url-builder.test.js.map +1 -0
  302. package/dist/services/url-templates.d.ts +41 -0
  303. package/dist/services/url-templates.d.ts.map +1 -0
  304. package/dist/services/url-templates.js +118 -0
  305. package/dist/services/url-templates.js.map +1 -0
  306. package/dist/services/url-templates.test.d.ts +2 -0
  307. package/dist/services/url-templates.test.d.ts.map +1 -0
  308. package/dist/services/url-templates.test.js +159 -0
  309. package/dist/services/url-templates.test.js.map +1 -0
  310. package/dist/types/action-budget.d.ts +52 -0
  311. package/dist/types/action-budget.d.ts.map +1 -0
  312. package/dist/types/action-budget.js +4 -0
  313. package/dist/types/action-budget.js.map +1 -0
  314. package/dist/types/campaign.d.ts +24 -0
  315. package/dist/types/campaign.d.ts.map +1 -1
  316. package/dist/types/feed.d.ts +32 -0
  317. package/dist/types/feed.d.ts.map +1 -0
  318. package/dist/types/feed.js +4 -0
  319. package/dist/types/feed.js.map +1 -0
  320. package/dist/types/index.d.ts +8 -2
  321. package/dist/types/index.d.ts.map +1 -1
  322. package/dist/types/linkedin-url.d.ts +109 -0
  323. package/dist/types/linkedin-url.d.ts.map +1 -0
  324. package/dist/types/linkedin-url.js +4 -0
  325. package/dist/types/linkedin-url.js.map +1 -0
  326. package/dist/types/post-analytics.d.ts +40 -0
  327. package/dist/types/post-analytics.d.ts.map +1 -0
  328. package/dist/types/post-analytics.js +4 -0
  329. package/dist/types/post-analytics.js.map +1 -0
  330. package/dist/types/post.d.ts +43 -0
  331. package/dist/types/post.d.ts.map +1 -0
  332. package/dist/types/post.js +4 -0
  333. package/dist/types/post.js.map +1 -0
  334. package/dist/types/search-posts.d.ts +22 -0
  335. package/dist/types/search-posts.d.ts.map +1 -0
  336. package/dist/types/search-posts.js +4 -0
  337. package/dist/types/search-posts.js.map +1 -0
  338. package/dist/types/ui-health.d.ts +16 -0
  339. package/dist/types/ui-health.d.ts.map +1 -1
  340. package/dist/voyager/index.d.ts +2 -0
  341. package/dist/voyager/index.d.ts.map +1 -0
  342. package/dist/voyager/index.js +4 -0
  343. package/dist/voyager/index.js.map +1 -0
  344. package/dist/voyager/interceptor.d.ts +100 -0
  345. package/dist/voyager/interceptor.d.ts.map +1 -0
  346. package/dist/voyager/interceptor.integration.test.d.ts +2 -0
  347. package/dist/voyager/interceptor.integration.test.d.ts.map +1 -0
  348. package/dist/voyager/interceptor.integration.test.js +89 -0
  349. package/dist/voyager/interceptor.integration.test.js.map +1 -0
  350. package/dist/voyager/interceptor.js +235 -0
  351. package/dist/voyager/interceptor.js.map +1 -0
  352. package/dist/voyager/interceptor.test.d.ts +2 -0
  353. package/dist/voyager/interceptor.test.d.ts.map +1 -0
  354. package/dist/voyager/interceptor.test.js +372 -0
  355. package/dist/voyager/interceptor.test.js.map +1 -0
  356. package/package.json +1 -1
@@ -0,0 +1,40 @@
1
+ /**
2
+ * Engagement statistics for a LinkedIn post.
3
+ */
4
+ export interface PostStats {
5
+ /** The resolved post URN (e.g. `urn:li:activity:1234567890`). */
6
+ readonly postUrn: string;
7
+ /** Total number of reactions. */
8
+ readonly reactionCount: number;
9
+ /** Reactions broken down by type. */
10
+ readonly reactionsByType: readonly ReactionCount[];
11
+ /** Total number of comments. */
12
+ readonly commentCount: number;
13
+ /** Total number of shares/reposts. */
14
+ readonly shareCount: number;
15
+ }
16
+ /**
17
+ * Reaction count for a specific reaction type.
18
+ */
19
+ export interface ReactionCount {
20
+ /** LinkedIn reaction type (e.g. `LIKE`, `PRAISE`, `EMPATHY`, `ENTERTAINMENT`, `INTEREST`, `APPRECIATION`). */
21
+ readonly type: string;
22
+ /** Number of reactions of this type. */
23
+ readonly count: number;
24
+ }
25
+ /**
26
+ * A person who engaged with a post (reacted, commented, etc.).
27
+ */
28
+ export interface PostEngager {
29
+ /** First name of the engager. */
30
+ readonly firstName: string;
31
+ /** Last name of the engager. */
32
+ readonly lastName: string;
33
+ /** LinkedIn public profile ID (vanity URL slug), if available. */
34
+ readonly publicId: string | null;
35
+ /** Professional headline. */
36
+ readonly headline: string | null;
37
+ /** Engagement type (e.g. `LIKE`, `PRAISE`, `EMPATHY`). */
38
+ readonly engagementType: string;
39
+ }
40
+ //# sourceMappingURL=post-analytics.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"post-analytics.d.ts","sourceRoot":"","sources":["../../src/types/post-analytics.ts"],"names":[],"mappings":"AAGA;;GAEG;AACH,MAAM,WAAW,SAAS;IACxB,iEAAiE;IACjE,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;IACzB,iCAAiC;IACjC,QAAQ,CAAC,aAAa,EAAE,MAAM,CAAC;IAC/B,qCAAqC;IACrC,QAAQ,CAAC,eAAe,EAAE,SAAS,aAAa,EAAE,CAAC;IACnD,gCAAgC;IAChC,QAAQ,CAAC,YAAY,EAAE,MAAM,CAAC;IAC9B,sCAAsC;IACtC,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAC;CAC7B;AAED;;GAEG;AACH,MAAM,WAAW,aAAa;IAC5B,8GAA8G;IAC9G,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,wCAAwC;IACxC,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;CACxB;AAED;;GAEG;AACH,MAAM,WAAW,WAAW;IAC1B,iCAAiC;IACjC,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;IAC3B,gCAAgC;IAChC,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;IAC1B,kEAAkE;IAClE,QAAQ,CAAC,QAAQ,EAAE,MAAM,GAAG,IAAI,CAAC;IACjC,6BAA6B;IAC7B,QAAQ,CAAC,QAAQ,EAAE,MAAM,GAAG,IAAI,CAAC;IACjC,0DAA0D;IAC1D,QAAQ,CAAC,cAAc,EAAE,MAAM,CAAC;CACjC"}
@@ -0,0 +1,4 @@
1
+ // SPDX-License-Identifier: AGPL-3.0-only
2
+ // Copyright (C) 2026 Oleksii PELYKH
3
+ export {};
4
+ //# sourceMappingURL=post-analytics.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"post-analytics.js","sourceRoot":"","sources":["../../src/types/post-analytics.ts"],"names":[],"mappings":"AAAA,yCAAyC;AACzC,oCAAoC"}
@@ -0,0 +1,43 @@
1
+ /**
2
+ * Detailed data for a single LinkedIn post.
3
+ */
4
+ export interface PostDetail {
5
+ /** The resolved post URN (e.g. `urn:li:activity:1234567890`). */
6
+ readonly postUrn: string;
7
+ /** Author display name. */
8
+ readonly authorName: string;
9
+ /** Author professional headline. */
10
+ readonly authorHeadline: string | null;
11
+ /** Author LinkedIn public profile ID (vanity URL slug), if available. */
12
+ readonly authorPublicId: string | null;
13
+ /** Post text content. */
14
+ readonly text: string;
15
+ /** Epoch milliseconds when the post was published, if available. */
16
+ readonly publishedAt: number | null;
17
+ /** Total number of reactions. */
18
+ readonly reactionCount: number;
19
+ /** Total number of comments. */
20
+ readonly commentCount: number;
21
+ /** Total number of shares/reposts. */
22
+ readonly shareCount: number;
23
+ }
24
+ /**
25
+ * A comment on a LinkedIn post.
26
+ */
27
+ export interface PostComment {
28
+ /** Comment URN identifier. */
29
+ readonly commentUrn: string | null;
30
+ /** Author display name. */
31
+ readonly authorName: string;
32
+ /** Author professional headline. */
33
+ readonly authorHeadline: string | null;
34
+ /** Author LinkedIn public profile ID (vanity URL slug), if available. */
35
+ readonly authorPublicId: string | null;
36
+ /** Comment text content. */
37
+ readonly text: string;
38
+ /** Epoch milliseconds when the comment was created, if available. */
39
+ readonly createdAt: number | null;
40
+ /** Number of reactions on this comment. */
41
+ readonly reactionCount: number;
42
+ }
43
+ //# sourceMappingURL=post.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"post.d.ts","sourceRoot":"","sources":["../../src/types/post.ts"],"names":[],"mappings":"AAGA;;GAEG;AACH,MAAM,WAAW,UAAU;IACzB,iEAAiE;IACjE,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;IACzB,2BAA2B;IAC3B,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAC;IAC5B,oCAAoC;IACpC,QAAQ,CAAC,cAAc,EAAE,MAAM,GAAG,IAAI,CAAC;IACvC,yEAAyE;IACzE,QAAQ,CAAC,cAAc,EAAE,MAAM,GAAG,IAAI,CAAC;IACvC,yBAAyB;IACzB,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,oEAAoE;IACpE,QAAQ,CAAC,WAAW,EAAE,MAAM,GAAG,IAAI,CAAC;IACpC,iCAAiC;IACjC,QAAQ,CAAC,aAAa,EAAE,MAAM,CAAC;IAC/B,gCAAgC;IAChC,QAAQ,CAAC,YAAY,EAAE,MAAM,CAAC;IAC9B,sCAAsC;IACtC,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAC;CAC7B;AAED;;GAEG;AACH,MAAM,WAAW,WAAW;IAC1B,8BAA8B;IAC9B,QAAQ,CAAC,UAAU,EAAE,MAAM,GAAG,IAAI,CAAC;IACnC,2BAA2B;IAC3B,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAC;IAC5B,oCAAoC;IACpC,QAAQ,CAAC,cAAc,EAAE,MAAM,GAAG,IAAI,CAAC;IACvC,yEAAyE;IACzE,QAAQ,CAAC,cAAc,EAAE,MAAM,GAAG,IAAI,CAAC;IACvC,4BAA4B;IAC5B,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,qEAAqE;IACrE,QAAQ,CAAC,SAAS,EAAE,MAAM,GAAG,IAAI,CAAC;IAClC,2CAA2C;IAC3C,QAAQ,CAAC,aAAa,EAAE,MAAM,CAAC;CAChC"}
@@ -0,0 +1,4 @@
1
+ // SPDX-License-Identifier: AGPL-3.0-only
2
+ // Copyright (C) 2026 Oleksii PELYKH
3
+ export {};
4
+ //# sourceMappingURL=post.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"post.js","sourceRoot":"","sources":["../../src/types/post.ts"],"names":[],"mappings":"AAAA,yCAAyC;AACzC,oCAAoC"}
@@ -0,0 +1,22 @@
1
+ /**
2
+ * A LinkedIn post returned from a content search.
3
+ */
4
+ export interface SearchPostResult {
5
+ /** Post URN (e.g. `urn:li:activity:1234567890`). */
6
+ readonly postUrn: string;
7
+ /** Post text content (may be truncated by API). */
8
+ readonly text: string | null;
9
+ /** Author first name. */
10
+ readonly authorFirstName: string | null;
11
+ /** Author last name. */
12
+ readonly authorLastName: string | null;
13
+ /** Author LinkedIn public ID (vanity URL slug). */
14
+ readonly authorPublicId: string | null;
15
+ /** Author professional headline. */
16
+ readonly authorHeadline: string | null;
17
+ /** Total number of reactions on the post. */
18
+ readonly reactionCount: number;
19
+ /** Total number of comments on the post. */
20
+ readonly commentCount: number;
21
+ }
22
+ //# sourceMappingURL=search-posts.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"search-posts.d.ts","sourceRoot":"","sources":["../../src/types/search-posts.ts"],"names":[],"mappings":"AAGA;;GAEG;AACH,MAAM,WAAW,gBAAgB;IAC/B,oDAAoD;IACpD,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;IACzB,mDAAmD;IACnD,QAAQ,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI,CAAC;IAC7B,yBAAyB;IACzB,QAAQ,CAAC,eAAe,EAAE,MAAM,GAAG,IAAI,CAAC;IACxC,wBAAwB;IACxB,QAAQ,CAAC,cAAc,EAAE,MAAM,GAAG,IAAI,CAAC;IACvC,mDAAmD;IACnD,QAAQ,CAAC,cAAc,EAAE,MAAM,GAAG,IAAI,CAAC;IACvC,oCAAoC;IACpC,QAAQ,CAAC,cAAc,EAAE,MAAM,GAAG,IAAI,CAAC;IACvC,6CAA6C;IAC7C,QAAQ,CAAC,aAAa,EAAE,MAAM,CAAC;IAC/B,4CAA4C;IAC5C,QAAQ,CAAC,YAAY,EAAE,MAAM,CAAC;CAC/B"}
@@ -0,0 +1,4 @@
1
+ // SPDX-License-Identifier: AGPL-3.0-only
2
+ // Copyright (C) 2026 Oleksii PELYKH
3
+ export {};
4
+ //# sourceMappingURL=search-posts.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"search-posts.js","sourceRoot":"","sources":["../../src/types/search-posts.ts"],"names":[],"mappings":"AAAA,yCAAyC;AACzC,oCAAoC"}
@@ -46,6 +46,20 @@ export interface PopupState {
46
46
  /** Whether the popup can be closed by the user. */
47
47
  readonly closable?: boolean;
48
48
  }
49
+ /**
50
+ * A popup detected in the LinkedHelper instance UI DOM.
51
+ *
52
+ * Instance popups render behind the LinkedIn webview and are invisible
53
+ * to the user. They can block operations without any visible indication.
54
+ */
55
+ export interface InstancePopup {
56
+ /** The popup title text (e.g., "Failed to initialize UI"). */
57
+ readonly title: string;
58
+ /** The popup body/description text, if available. */
59
+ readonly description?: string;
60
+ /** Whether the popup is dismissable (has actionable controls to close or dismiss it). */
61
+ readonly closable: boolean;
62
+ }
49
63
  /**
50
64
  * Aggregated UI health status for a LinkedHelper instance.
51
65
  */
@@ -56,5 +70,7 @@ export interface UIHealthStatus {
56
70
  readonly issues: readonly InstanceIssue[];
57
71
  /** Current popup overlay state, or `null` if no popup is present. */
58
72
  readonly popup: PopupState | null;
73
+ /** Popups detected in the instance UI DOM. */
74
+ readonly instancePopups: readonly InstancePopup[];
59
75
  }
60
76
  //# sourceMappingURL=ui-health.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"ui-health.d.ts","sourceRoot":"","sources":["../../src/types/ui-health.ts"],"names":[],"mappings":"AAGA;;GAEG;AACH,MAAM,WAAW,eAAe;IAC9B,QAAQ,CAAC,EAAE,EAAE,MAAM,CAAC;IACpB,QAAQ,CAAC,OAAO,EAAE;QAChB,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;QACzB,QAAQ,CAAC,QAAQ,EAAE,aAAa,CAAC;YAC/B,QAAQ,CAAC,EAAE,EAAE,MAAM,CAAC;YACpB,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;SACvB,CAAC,CAAC;KACJ,CAAC;CACH;AAED;;GAEG;AACH,MAAM,WAAW,sBAAsB;IACrC,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;CAC1B;AAED;;;;;GAKG;AACH,MAAM,MAAM,aAAa,GACrB;IAAE,QAAQ,CAAC,IAAI,EAAE,QAAQ,CAAC;IAAC,QAAQ,CAAC,EAAE,EAAE,MAAM,CAAC;IAAC,QAAQ,CAAC,IAAI,EAAE,eAAe,CAAA;CAAE,GAChF;IAAE,QAAQ,CAAC,IAAI,EAAE,gBAAgB,CAAC;IAAC,QAAQ,CAAC,EAAE,EAAE,MAAM,CAAC;IAAC,QAAQ,CAAC,IAAI,EAAE,sBAAsB,CAAA;CAAE,CAAC;AAEpG;;;;;GAKG;AACH,MAAM,WAAW,UAAU;IACzB,mDAAmD;IACnD,QAAQ,CAAC,OAAO,EAAE,OAAO,CAAC;IAC1B,4CAA4C;IAC5C,QAAQ,CAAC,OAAO,CAAC,EAAE,MAAM,CAAC;IAC1B,mDAAmD;IACnD,QAAQ,CAAC,QAAQ,CAAC,EAAE,OAAO,CAAC;CAC7B;AAED;;GAEG;AACH,MAAM,WAAW,cAAc;IAC7B,0DAA0D;IAC1D,QAAQ,CAAC,OAAO,EAAE,OAAO,CAAC;IAC1B,4DAA4D;IAC5D,QAAQ,CAAC,MAAM,EAAE,SAAS,aAAa,EAAE,CAAC;IAC1C,qEAAqE;IACrE,QAAQ,CAAC,KAAK,EAAE,UAAU,GAAG,IAAI,CAAC;CACnC"}
1
+ {"version":3,"file":"ui-health.d.ts","sourceRoot":"","sources":["../../src/types/ui-health.ts"],"names":[],"mappings":"AAGA;;GAEG;AACH,MAAM,WAAW,eAAe;IAC9B,QAAQ,CAAC,EAAE,EAAE,MAAM,CAAC;IACpB,QAAQ,CAAC,OAAO,EAAE;QAChB,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;QACzB,QAAQ,CAAC,QAAQ,EAAE,aAAa,CAAC;YAC/B,QAAQ,CAAC,EAAE,EAAE,MAAM,CAAC;YACpB,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;SACvB,CAAC,CAAC;KACJ,CAAC;CACH;AAED;;GAEG;AACH,MAAM,WAAW,sBAAsB;IACrC,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;CAC1B;AAED;;;;;GAKG;AACH,MAAM,MAAM,aAAa,GACrB;IAAE,QAAQ,CAAC,IAAI,EAAE,QAAQ,CAAC;IAAC,QAAQ,CAAC,EAAE,EAAE,MAAM,CAAC;IAAC,QAAQ,CAAC,IAAI,EAAE,eAAe,CAAA;CAAE,GAChF;IAAE,QAAQ,CAAC,IAAI,EAAE,gBAAgB,CAAC;IAAC,QAAQ,CAAC,EAAE,EAAE,MAAM,CAAC;IAAC,QAAQ,CAAC,IAAI,EAAE,sBAAsB,CAAA;CAAE,CAAC;AAEpG;;;;;GAKG;AACH,MAAM,WAAW,UAAU;IACzB,mDAAmD;IACnD,QAAQ,CAAC,OAAO,EAAE,OAAO,CAAC;IAC1B,4CAA4C;IAC5C,QAAQ,CAAC,OAAO,CAAC,EAAE,MAAM,CAAC;IAC1B,mDAAmD;IACnD,QAAQ,CAAC,QAAQ,CAAC,EAAE,OAAO,CAAC;CAC7B;AAED;;;;;GAKG;AACH,MAAM,WAAW,aAAa;IAC5B,8DAA8D;IAC9D,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IACvB,qDAAqD;IACrD,QAAQ,CAAC,WAAW,CAAC,EAAE,MAAM,CAAC;IAC9B,yFAAyF;IACzF,QAAQ,CAAC,QAAQ,EAAE,OAAO,CAAC;CAC5B;AAED;;GAEG;AACH,MAAM,WAAW,cAAc;IAC7B,0DAA0D;IAC1D,QAAQ,CAAC,OAAO,EAAE,OAAO,CAAC;IAC1B,4DAA4D;IAC5D,QAAQ,CAAC,MAAM,EAAE,SAAS,aAAa,EAAE,CAAC;IAC1C,qEAAqE;IACrE,QAAQ,CAAC,KAAK,EAAE,UAAU,GAAG,IAAI,CAAC;IAClC,8CAA8C;IAC9C,QAAQ,CAAC,cAAc,EAAE,SAAS,aAAa,EAAE,CAAC;CACnD"}
@@ -0,0 +1,2 @@
1
+ export { VoyagerInterceptor, VOYAGER_URL_PATTERN, type VoyagerFetchOptions, type VoyagerResponse, type VoyagerResponseHandler, } from "./interceptor.js";
2
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/voyager/index.ts"],"names":[],"mappings":"AAGA,OAAO,EACL,kBAAkB,EAClB,mBAAmB,EACnB,KAAK,mBAAmB,EACxB,KAAK,eAAe,EACpB,KAAK,sBAAsB,GAC5B,MAAM,kBAAkB,CAAC"}
@@ -0,0 +1,4 @@
1
+ // SPDX-License-Identifier: AGPL-3.0-only
2
+ // Copyright (C) 2026 Oleksii PELYKH
3
+ export { VoyagerInterceptor, VOYAGER_URL_PATTERN, } from "./interceptor.js";
4
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/voyager/index.ts"],"names":[],"mappings":"AAAA,yCAAyC;AACzC,oCAAoC;AAEpC,OAAO,EACL,kBAAkB,EAClB,mBAAmB,GAIpB,MAAM,kBAAkB,CAAC"}
@@ -0,0 +1,100 @@
1
+ import type { CDPClient } from "../cdp/client.js";
2
+ /** URL pattern matching LinkedIn Voyager API endpoints. */
3
+ export declare const VOYAGER_URL_PATTERN: RegExp;
4
+ /**
5
+ * A captured Voyager API response.
6
+ */
7
+ export interface VoyagerResponse {
8
+ /** The full request URL. */
9
+ readonly url: string;
10
+ /** HTTP status code. */
11
+ readonly status: number;
12
+ /** Parsed JSON response body, or raw string if JSON parsing failed. */
13
+ readonly body: unknown;
14
+ }
15
+ /**
16
+ * Callback for intercepted Voyager API responses.
17
+ */
18
+ export type VoyagerResponseHandler = (response: VoyagerResponse) => void;
19
+ /**
20
+ * Options for active Voyager API fetching.
21
+ */
22
+ export interface VoyagerFetchOptions {
23
+ /** Additional HTTP headers to include in the request. */
24
+ readonly headers?: Readonly<Record<string, string>>;
25
+ }
26
+ /**
27
+ * CDP Network domain listener for LinkedIn Voyager API responses.
28
+ *
29
+ * Intercepts HTTP responses matching the Voyager API URL pattern
30
+ * (`/voyager/api/`) via the Chrome DevTools Protocol Network domain.
31
+ *
32
+ * Two modes of operation:
33
+ * - **Passive**: Enable the interceptor and register handlers to capture
34
+ * Voyager responses triggered by page navigation, scrolling, or user
35
+ * interaction within the LinkedIn WebView.
36
+ * - **Active**: Use {@link fetch} to execute Voyager API requests directly
37
+ * in the page context (which has the LinkedIn session cookies).
38
+ *
39
+ * The interceptor is read-only — it does not modify requests or responses,
40
+ * so it coexists safely with LinkedHelper's mockttp proxy.
41
+ */
42
+ export declare class VoyagerInterceptor {
43
+ private readonly client;
44
+ private readonly handlers;
45
+ private readonly pendingRequests;
46
+ private interceptEnabled;
47
+ constructor(client: CDPClient);
48
+ /** Whether passive interception is currently enabled. */
49
+ get isEnabled(): boolean;
50
+ /**
51
+ * Enable the CDP Network domain and start intercepting Voyager responses.
52
+ *
53
+ * Subscribes to `Network.responseReceived`, `Network.loadingFinished`,
54
+ * and `Network.loadingFailed` events. Responses matching the Voyager
55
+ * URL pattern are captured and emitted to registered handlers.
56
+ */
57
+ enable(): Promise<void>;
58
+ /**
59
+ * Disable the CDP Network domain and stop intercepting.
60
+ *
61
+ * Cleans up event listeners and pending request state.
62
+ */
63
+ disable(): Promise<void>;
64
+ /**
65
+ * Register a handler for passively intercepted Voyager responses.
66
+ */
67
+ onResponse(handler: VoyagerResponseHandler): void;
68
+ /**
69
+ * Remove a previously registered response handler.
70
+ */
71
+ offResponse(handler: VoyagerResponseHandler): void;
72
+ /**
73
+ * Wait for the next Voyager response matching an optional URL filter.
74
+ *
75
+ * Requires the interceptor to be {@link enable}d.
76
+ *
77
+ * @param filter - Optional predicate applied to the response URL.
78
+ * @param timeout - Maximum wait time in ms (default: 30 000).
79
+ */
80
+ waitForResponse(filter?: (url: string) => boolean, timeout?: number): Promise<VoyagerResponse>;
81
+ /**
82
+ * Execute a Voyager API request in the LinkedIn page context.
83
+ *
84
+ * Runs `fetch()` inside the WebView where LinkedIn session cookies are
85
+ * available, automatically extracting the CSRF token from cookies.
86
+ *
87
+ * Does not require the interceptor to be {@link enable}d — works
88
+ * independently of the Network domain.
89
+ *
90
+ * @param path - Voyager API path (e.g. `/voyager/api/feed/dash/feedUpdates`).
91
+ * Full URLs starting with `https://` are also accepted.
92
+ * @param options - Optional fetch configuration.
93
+ */
94
+ fetch(path: string, options?: VoyagerFetchOptions): Promise<VoyagerResponse>;
95
+ private handleResponseReceived;
96
+ private handleLoadingFinished;
97
+ private handleLoadingFailed;
98
+ private fetchAndEmitBody;
99
+ }
100
+ //# sourceMappingURL=interceptor.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"interceptor.d.ts","sourceRoot":"","sources":["../../src/voyager/interceptor.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,kBAAkB,CAAC;AAGlD,2DAA2D;AAC3D,eAAO,MAAM,mBAAmB,QAAqB,CAAC;AAKtD;;GAEG;AACH,MAAM,WAAW,eAAe;IAC9B,4BAA4B;IAC5B,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAC;IACrB,wBAAwB;IACxB,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IACxB,uEAAuE;IACvE,QAAQ,CAAC,IAAI,EAAE,OAAO,CAAC;CACxB;AAED;;GAEG;AACH,MAAM,MAAM,sBAAsB,GAAG,CAAC,QAAQ,EAAE,eAAe,KAAK,IAAI,CAAC;AAEzE;;GAEG;AACH,MAAM,WAAW,mBAAmB;IAClC,yDAAyD;IACzD,QAAQ,CAAC,OAAO,CAAC,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,CAAC;CACrD;AAUD;;;;;;;;;;;;;;;GAeG;AACH,qBAAa,kBAAkB;IAC7B,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAY;IACnC,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAAqC;IAC9D,OAAO,CAAC,QAAQ,CAAC,eAAe,CAG5B;IACJ,OAAO,CAAC,gBAAgB,CAAS;gBAErB,MAAM,EAAE,SAAS;IAI7B,yDAAyD;IACzD,IAAI,SAAS,IAAI,OAAO,CAEvB;IAED;;;;;;OAMG;IACG,MAAM,IAAI,OAAO,CAAC,IAAI,CAAC;IAS7B;;;;OAIG;IACG,OAAO,IAAI,OAAO,CAAC,IAAI,CAAC;IAU9B;;OAEG;IACH,UAAU,CAAC,OAAO,EAAE,sBAAsB,GAAG,IAAI;IAIjD;;OAEG;IACH,WAAW,CAAC,OAAO,EAAE,sBAAsB,GAAG,IAAI;IAIlD;;;;;;;OAOG;IACG,eAAe,CACnB,MAAM,CAAC,EAAE,CAAC,GAAG,EAAE,MAAM,KAAK,OAAO,EACjC,OAAO,CAAC,EAAE,MAAM,GACf,OAAO,CAAC,eAAe,CAAC;IA2B3B;;;;;;;;;;;;OAYG;IACG,KAAK,CACT,IAAI,EAAE,MAAM,EACZ,OAAO,CAAC,EAAE,mBAAmB,GAC5B,OAAO,CAAC,eAAe,CAAC;IAyE3B,OAAO,CAAC,sBAAsB,CAY5B;IAEF,OAAO,CAAC,qBAAqB,CAO3B;IAEF,OAAO,CAAC,mBAAmB,CAGzB;YAEY,gBAAgB;CAqC/B"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=interceptor.integration.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"interceptor.integration.test.d.ts","sourceRoot":"","sources":["../../src/voyager/interceptor.integration.test.ts"],"names":[],"mappings":""}
@@ -0,0 +1,89 @@
1
+ // SPDX-License-Identifier: AGPL-3.0-only
2
+ // Copyright (C) 2026 Oleksii PELYKH
3
+ import { createServer } from "node:http";
4
+ import { afterAll, afterEach, beforeAll, describe, expect, it } from "vitest";
5
+ import { CDPClient } from "../cdp/client.js";
6
+ import { launchChromium, } from "../cdp/testing/launch-chromium.js";
7
+ import { VoyagerInterceptor } from "./interceptor.js";
8
+ describe("VoyagerInterceptor (integration)", () => {
9
+ let chromium;
10
+ let server;
11
+ let serverPort;
12
+ let client;
13
+ let interceptor;
14
+ beforeAll(async () => {
15
+ chromium = await launchChromium();
16
+ // Start a minimal local HTTP server to avoid external network dependency
17
+ // (http://example.com caused Windows CI timeouts)
18
+ server = createServer((_req, res) => {
19
+ res.writeHead(200, { "Content-Type": "text/html" });
20
+ res.end("<html></html>");
21
+ });
22
+ await new Promise((resolve) => server.listen(0, resolve));
23
+ serverPort = server.address().port;
24
+ }, 30_000);
25
+ afterAll(async () => {
26
+ await chromium.close();
27
+ server.close();
28
+ });
29
+ afterEach(async () => {
30
+ if (interceptor?.isEnabled) {
31
+ await interceptor.disable();
32
+ }
33
+ client?.disconnect();
34
+ });
35
+ describe("enable / disable", () => {
36
+ it("should enable and disable without error on a real browser", async () => {
37
+ client = new CDPClient(chromium.port);
38
+ await client.connect();
39
+ interceptor = new VoyagerInterceptor(client);
40
+ await interceptor.enable();
41
+ expect(interceptor.isEnabled).toBe(true);
42
+ await interceptor.disable();
43
+ expect(interceptor.isEnabled).toBe(false);
44
+ });
45
+ });
46
+ describe("passive interception", () => {
47
+ it("should capture responses matching Voyager URL pattern", async () => {
48
+ client = new CDPClient(chromium.port);
49
+ await client.connect();
50
+ interceptor = new VoyagerInterceptor(client);
51
+ // Navigate to the local HTTP server so we have an origin for fetch
52
+ await client.send("Page.enable");
53
+ const loadPromise = client.waitForEvent("Page.loadEventFired");
54
+ await client.navigate(`http://localhost:${serverPort.toString()}`);
55
+ await loadPromise;
56
+ await client.send("Page.disable").catch(() => { });
57
+ await interceptor.enable();
58
+ // Use waitForResponse for deterministic waiting instead of setTimeout
59
+ const responsePromise = interceptor.waitForResponse(undefined, 5000);
60
+ // Trigger a fetch from within the page to a URL containing /voyager/api/
61
+ // The local server responds with 200 to any path
62
+ await client.evaluate(`fetch("/voyager/api/test-endpoint").catch(() => {})`, true);
63
+ const captured = await responsePromise;
64
+ expect(captured.url).toContain("/voyager/api/");
65
+ });
66
+ });
67
+ describe("waitForResponse", () => {
68
+ it("should resolve when a matching response arrives", async () => {
69
+ client = new CDPClient(chromium.port);
70
+ await client.connect();
71
+ interceptor = new VoyagerInterceptor(client);
72
+ // Navigate to the local HTTP server so we have an origin for fetch
73
+ await client.send("Page.enable");
74
+ const loadPromise = client.waitForEvent("Page.loadEventFired");
75
+ await client.navigate(`http://localhost:${serverPort.toString()}`);
76
+ await loadPromise;
77
+ await client.send("Page.disable").catch(() => { });
78
+ await interceptor.enable();
79
+ // Start waiting before triggering the fetch
80
+ const responsePromise = interceptor.waitForResponse(undefined, 5000);
81
+ // Trigger a fetch matching the voyager pattern
82
+ await client.evaluate(`fetch("/voyager/api/integration-test").catch(() => {})`, true);
83
+ const response = await responsePromise;
84
+ expect(response.url).toContain("/voyager/api/");
85
+ expect(response.status).toEqual(expect.any(Number));
86
+ });
87
+ });
88
+ });
89
+ //# sourceMappingURL=interceptor.integration.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"interceptor.integration.test.js","sourceRoot":"","sources":["../../src/voyager/interceptor.integration.test.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,235 @@
1
+ // SPDX-License-Identifier: AGPL-3.0-only
2
+ // Copyright (C) 2026 Oleksii PELYKH
3
+ import { CDPEvaluationError, CDPTimeoutError } from "../cdp/errors.js";
4
+ /** URL pattern matching LinkedIn Voyager API endpoints. */
5
+ export const VOYAGER_URL_PATTERN = /\/voyager\/api\//;
6
+ /** Default timeout for response wait operations (ms). */
7
+ const DEFAULT_TIMEOUT = 30_000;
8
+ /**
9
+ * CDP Network domain listener for LinkedIn Voyager API responses.
10
+ *
11
+ * Intercepts HTTP responses matching the Voyager API URL pattern
12
+ * (`/voyager/api/`) via the Chrome DevTools Protocol Network domain.
13
+ *
14
+ * Two modes of operation:
15
+ * - **Passive**: Enable the interceptor and register handlers to capture
16
+ * Voyager responses triggered by page navigation, scrolling, or user
17
+ * interaction within the LinkedIn WebView.
18
+ * - **Active**: Use {@link fetch} to execute Voyager API requests directly
19
+ * in the page context (which has the LinkedIn session cookies).
20
+ *
21
+ * The interceptor is read-only — it does not modify requests or responses,
22
+ * so it coexists safely with LinkedHelper's mockttp proxy.
23
+ */
24
+ export class VoyagerInterceptor {
25
+ client;
26
+ handlers = new Set();
27
+ pendingRequests = new Map();
28
+ interceptEnabled = false;
29
+ constructor(client) {
30
+ this.client = client;
31
+ }
32
+ /** Whether passive interception is currently enabled. */
33
+ get isEnabled() {
34
+ return this.interceptEnabled;
35
+ }
36
+ /**
37
+ * Enable the CDP Network domain and start intercepting Voyager responses.
38
+ *
39
+ * Subscribes to `Network.responseReceived`, `Network.loadingFinished`,
40
+ * and `Network.loadingFailed` events. Responses matching the Voyager
41
+ * URL pattern are captured and emitted to registered handlers.
42
+ */
43
+ async enable() {
44
+ if (this.interceptEnabled)
45
+ return;
46
+ await this.client.send("Network.enable");
47
+ this.client.on("Network.responseReceived", this.handleResponseReceived);
48
+ this.client.on("Network.loadingFinished", this.handleLoadingFinished);
49
+ this.client.on("Network.loadingFailed", this.handleLoadingFailed);
50
+ this.interceptEnabled = true;
51
+ }
52
+ /**
53
+ * Disable the CDP Network domain and stop intercepting.
54
+ *
55
+ * Cleans up event listeners and pending request state.
56
+ */
57
+ async disable() {
58
+ if (!this.interceptEnabled)
59
+ return;
60
+ this.interceptEnabled = false;
61
+ this.client.off("Network.responseReceived", this.handleResponseReceived);
62
+ this.client.off("Network.loadingFinished", this.handleLoadingFinished);
63
+ this.client.off("Network.loadingFailed", this.handleLoadingFailed);
64
+ this.pendingRequests.clear();
65
+ await this.client.send("Network.disable").catch(() => { });
66
+ }
67
+ /**
68
+ * Register a handler for passively intercepted Voyager responses.
69
+ */
70
+ onResponse(handler) {
71
+ this.handlers.add(handler);
72
+ }
73
+ /**
74
+ * Remove a previously registered response handler.
75
+ */
76
+ offResponse(handler) {
77
+ this.handlers.delete(handler);
78
+ }
79
+ /**
80
+ * Wait for the next Voyager response matching an optional URL filter.
81
+ *
82
+ * Requires the interceptor to be {@link enable}d.
83
+ *
84
+ * @param filter - Optional predicate applied to the response URL.
85
+ * @param timeout - Maximum wait time in ms (default: 30 000).
86
+ */
87
+ async waitForResponse(filter, timeout) {
88
+ if (!this.interceptEnabled) {
89
+ throw new Error("VoyagerInterceptor is not enabled — call enable() before waitForResponse()");
90
+ }
91
+ const ms = timeout ?? DEFAULT_TIMEOUT;
92
+ return new Promise((resolve, reject) => {
93
+ const timer = setTimeout(() => {
94
+ this.offResponse(handler);
95
+ reject(new CDPTimeoutError("Timed out waiting for Voyager response"));
96
+ }, ms);
97
+ const handler = (response) => {
98
+ if (!filter || filter(response.url)) {
99
+ clearTimeout(timer);
100
+ this.offResponse(handler);
101
+ resolve(response);
102
+ }
103
+ };
104
+ this.onResponse(handler);
105
+ });
106
+ }
107
+ /**
108
+ * Execute a Voyager API request in the LinkedIn page context.
109
+ *
110
+ * Runs `fetch()` inside the WebView where LinkedIn session cookies are
111
+ * available, automatically extracting the CSRF token from cookies.
112
+ *
113
+ * Does not require the interceptor to be {@link enable}d — works
114
+ * independently of the Network domain.
115
+ *
116
+ * @param path - Voyager API path (e.g. `/voyager/api/feed/dash/feedUpdates`).
117
+ * Full URLs starting with `https://` are also accepted.
118
+ * @param options - Optional fetch configuration.
119
+ */
120
+ async fetch(path, options) {
121
+ const fullUrl = path.startsWith("https://")
122
+ ? path
123
+ : `https://www.linkedin.com${path.startsWith("/") ? "" : "/"}${path}`;
124
+ // Guard: only send credentials to LinkedIn origins
125
+ const parsed = new URL(fullUrl);
126
+ if (parsed.hostname !== "www.linkedin.com" &&
127
+ parsed.hostname !== "linkedin.com" &&
128
+ !parsed.hostname.endsWith(".linkedin.com")) {
129
+ throw new Error(`Voyager fetch restricted to linkedin.com origins, got: ${parsed.hostname}`);
130
+ }
131
+ const extraHeaders = JSON.stringify(options?.headers ?? {});
132
+ const result = await this.client.evaluate(`(async () => {
133
+ try {
134
+ const jsessionid = document.cookie
135
+ .split(";")
136
+ .map(c => c.trim())
137
+ .find(c => c.startsWith("JSESSIONID="));
138
+ let csrfToken = jsessionid
139
+ ? jsessionid.substring(jsessionid.indexOf("=") + 1).replace(/"/g, "")
140
+ : "";
141
+ if (!csrfToken.startsWith("ajax:")) {
142
+ csrfToken = "ajax:" + csrfToken;
143
+ }
144
+
145
+ const response = await fetch(${JSON.stringify(fullUrl)}, {
146
+ headers: {
147
+ "Csrf-Token": csrfToken,
148
+ "X-RestLi-Protocol-Version": "2.0.0",
149
+ ...${extraHeaders},
150
+ },
151
+ credentials: "include",
152
+ });
153
+
154
+ const text = await response.text();
155
+ let body;
156
+ try {
157
+ body = JSON.parse(text);
158
+ } catch {
159
+ body = text;
160
+ }
161
+
162
+ return { url: response.url, status: response.status, body };
163
+ } catch (e) {
164
+ return { url: ${JSON.stringify(fullUrl)}, status: 0, body: null, error: String(e) };
165
+ }
166
+ })()`, true);
167
+ if (result.error) {
168
+ throw new CDPEvaluationError(`Voyager fetch failed: ${result.error}`);
169
+ }
170
+ return {
171
+ url: result.url,
172
+ status: result.status,
173
+ body: result.body,
174
+ };
175
+ }
176
+ // ---------------------------------------------------------------------------
177
+ // Private — CDP event handlers
178
+ // ---------------------------------------------------------------------------
179
+ handleResponseReceived = (params) => {
180
+ const { requestId, response } = params;
181
+ if (VOYAGER_URL_PATTERN.test(response.url)) {
182
+ this.pendingRequests.set(requestId, {
183
+ url: response.url,
184
+ status: response.status,
185
+ });
186
+ }
187
+ };
188
+ handleLoadingFinished = (params) => {
189
+ const { requestId } = params;
190
+ const pending = this.pendingRequests.get(requestId);
191
+ if (!pending)
192
+ return;
193
+ this.pendingRequests.delete(requestId);
194
+ void this.fetchAndEmitBody(requestId, pending);
195
+ };
196
+ handleLoadingFailed = (params) => {
197
+ const { requestId } = params;
198
+ this.pendingRequests.delete(requestId);
199
+ };
200
+ async fetchAndEmitBody(requestId, meta) {
201
+ let body;
202
+ try {
203
+ const result = (await this.client.send("Network.getResponseBody", {
204
+ requestId,
205
+ }));
206
+ const raw = result.base64Encoded
207
+ ? Buffer.from(result.body, "base64").toString("utf8")
208
+ : result.body;
209
+ try {
210
+ body = JSON.parse(raw);
211
+ }
212
+ catch {
213
+ body = raw;
214
+ }
215
+ }
216
+ catch {
217
+ // Body retrieval can fail for cached or evicted responses — skip silently
218
+ return;
219
+ }
220
+ const response = {
221
+ url: meta.url,
222
+ status: meta.status,
223
+ body,
224
+ };
225
+ for (const handler of this.handlers) {
226
+ try {
227
+ handler(response);
228
+ }
229
+ catch {
230
+ // Isolate handler errors so one failing handler doesn't block others
231
+ }
232
+ }
233
+ }
234
+ }
235
+ //# sourceMappingURL=interceptor.js.map