doover-js 0.11.0 → 0.13.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 (389) hide show
  1. package/README.md +106 -0
  2. package/dist/apis/_args.js +5 -5
  3. package/dist/apis/agents-api.d.ts +4 -4
  4. package/dist/apis/agents-api.js +2 -2
  5. package/dist/apis/aggregates-api.d.ts +4 -4
  6. package/dist/apis/aggregates-api.js +5 -5
  7. package/dist/apis/alarms-api.d.ts +2 -2
  8. package/dist/apis/alarms-api.js +3 -3
  9. package/dist/apis/channels-api.d.ts +3 -3
  10. package/dist/apis/channels-api.js +6 -6
  11. package/dist/apis/connections-api.d.ts +2 -2
  12. package/dist/apis/connections-api.js +6 -6
  13. package/dist/apis/messages-api.d.ts +4 -4
  14. package/dist/apis/messages-api.js +11 -11
  15. package/dist/apis/notifications-api.d.ts +2 -2
  16. package/dist/apis/notifications-api.js +4 -4
  17. package/dist/apis/organisations-api.d.ts +2 -2
  18. package/dist/apis/permissions-api.d.ts +2 -2
  19. package/dist/apis/permissions-api.js +3 -3
  20. package/dist/apis/processors-api.d.ts +2 -2
  21. package/dist/apis/turn-api.d.ts +2 -2
  22. package/dist/apis/users-api.d.ts +2 -2
  23. package/dist/auth/auth-store.d.ts +1 -1
  24. package/dist/auth/build-auth.d.ts +3 -3
  25. package/dist/auth/build-auth.js +8 -8
  26. package/dist/auth/cookie-auth.d.ts +1 -1
  27. package/dist/auth/cookie-auth.js +2 -2
  28. package/dist/auth/doover-auth.d.ts +2 -2
  29. package/dist/auth/doover-token-auth.d.ts +3 -3
  30. package/dist/auth/doover-token-auth.js +13 -13
  31. package/dist/auth/index.d.ts +10 -0
  32. package/dist/auth/index.js +15 -0
  33. package/dist/client/data-client.d.ts +17 -14
  34. package/dist/client/doover-client.d.ts +9 -7
  35. package/dist/client/doover-client.js +44 -42
  36. package/dist/client/errors.d.ts +2 -2
  37. package/dist/client/errors.js +4 -4
  38. package/dist/client/index.d.ts +6 -0
  39. package/dist/client/index.js +12 -0
  40. package/dist/client/local-agent-client.d.ts +3 -3
  41. package/dist/client/local-agent-client.js +19 -19
  42. package/dist/client/multiplex-client.d.ts +5 -5
  43. package/dist/client/multiplex-client.js +25 -25
  44. package/dist/client/multiplex-gateway.d.ts +3 -3
  45. package/dist/client/multiplex-merge.d.ts +1 -1
  46. package/dist/client/network-status.d.ts +17 -0
  47. package/dist/client/network-status.js +70 -0
  48. package/dist/client/offline-cache.d.ts +9 -4
  49. package/dist/client/offline-cache.js +34 -22
  50. package/dist/client/provenance.d.ts +1 -1
  51. package/dist/client/request-options.d.ts +1 -1
  52. package/dist/client/singleton.d.ts +2 -2
  53. package/dist/client/singleton.js +2 -2
  54. package/dist/client/status-tracker.d.ts +1 -1
  55. package/dist/esm/apis/_args.d.ts +16 -0
  56. package/dist/esm/apis/_args.js +27 -0
  57. package/dist/esm/apis/agents-api.d.ts +196 -0
  58. package/dist/esm/apis/agents-api.js +327 -0
  59. package/dist/esm/apis/aggregates-api.d.ts +67 -0
  60. package/dist/esm/apis/aggregates-api.js +64 -0
  61. package/dist/esm/apis/alarms-api.d.ts +48 -0
  62. package/dist/esm/apis/alarms-api.js +75 -0
  63. package/dist/esm/apis/channels-api.d.ts +83 -0
  64. package/dist/esm/apis/channels-api.js +65 -0
  65. package/dist/esm/apis/connections-api.d.ts +45 -0
  66. package/dist/esm/apis/connections-api.js +44 -0
  67. package/dist/esm/apis/messages-api.d.ts +128 -0
  68. package/dist/esm/apis/messages-api.js +179 -0
  69. package/dist/esm/apis/notifications-api.d.ts +94 -0
  70. package/dist/esm/apis/notifications-api.js +153 -0
  71. package/dist/esm/apis/organisations-api.d.ts +26 -0
  72. package/dist/esm/apis/organisations-api.js +41 -0
  73. package/dist/esm/apis/permissions-api.d.ts +17 -0
  74. package/dist/esm/apis/permissions-api.js +23 -0
  75. package/dist/esm/apis/processors-api.d.ts +56 -0
  76. package/dist/esm/apis/processors-api.js +97 -0
  77. package/dist/esm/apis/turn-api.d.ts +7 -0
  78. package/dist/esm/apis/turn-api.js +8 -0
  79. package/dist/esm/apis/users-api.d.ts +8 -0
  80. package/dist/esm/apis/users-api.js +9 -0
  81. package/dist/esm/auth/auth-profile.d.ts +45 -0
  82. package/dist/esm/auth/auth-profile.js +68 -0
  83. package/dist/esm/auth/auth-store.d.ts +14 -0
  84. package/dist/esm/auth/build-auth.d.ts +38 -0
  85. package/dist/esm/auth/build-auth.js +92 -0
  86. package/dist/esm/auth/cookie-auth.d.ts +91 -0
  87. package/dist/esm/auth/cookie-auth.js +196 -0
  88. package/dist/esm/auth/doover-auth.d.ts +52 -0
  89. package/dist/esm/auth/doover-auth.js +28 -0
  90. package/dist/esm/auth/doover-token-auth.d.ts +39 -0
  91. package/dist/esm/auth/doover-token-auth.js +217 -0
  92. package/dist/esm/auth/errors.d.ts +3 -0
  93. package/dist/esm/auth/errors.js +6 -0
  94. package/dist/esm/auth/index.d.ts +10 -0
  95. package/dist/esm/auth/index.js +6 -0
  96. package/dist/esm/auth/jwt.d.ts +6 -0
  97. package/dist/esm/auth/jwt.js +26 -0
  98. package/dist/esm/client/capabilities.d.ts +10 -0
  99. package/dist/esm/client/capabilities.js +42 -0
  100. package/dist/esm/client/data-client.d.ts +107 -0
  101. package/dist/esm/client/doover-client.d.ts +48 -0
  102. package/dist/esm/client/doover-client.js +96 -0
  103. package/dist/esm/client/errors.d.ts +32 -0
  104. package/dist/esm/client/errors.js +64 -0
  105. package/dist/esm/client/index.d.ts +6 -0
  106. package/dist/esm/client/index.js +3 -0
  107. package/dist/esm/client/local-agent-client.d.ts +65 -0
  108. package/dist/esm/client/local-agent-client.js +225 -0
  109. package/dist/esm/client/multiplex-client.d.ts +165 -0
  110. package/dist/esm/client/multiplex-client.js +842 -0
  111. package/dist/esm/client/multiplex-gateway.d.ts +49 -0
  112. package/dist/esm/client/multiplex-gateway.js +110 -0
  113. package/dist/esm/client/multiplex-merge.d.ts +12 -0
  114. package/dist/esm/client/multiplex-merge.js +38 -0
  115. package/dist/esm/client/network-status.d.ts +17 -0
  116. package/dist/esm/client/network-status.js +66 -0
  117. package/dist/esm/client/offline-cache.d.ts +167 -0
  118. package/dist/esm/client/offline-cache.js +769 -0
  119. package/dist/esm/client/provenance.d.ts +60 -0
  120. package/dist/esm/client/provenance.js +108 -0
  121. package/dist/esm/client/request-options.d.ts +23 -0
  122. package/dist/esm/client/request-options.js +23 -0
  123. package/dist/esm/client/singleton.d.ts +26 -0
  124. package/dist/esm/client/singleton.js +54 -0
  125. package/dist/esm/client/stats.d.ts +79 -0
  126. package/dist/esm/client/stats.js +155 -0
  127. package/dist/esm/client/status-tracker.d.ts +24 -0
  128. package/dist/esm/client/status-tracker.js +86 -0
  129. package/dist/esm/gateway/gateway-client.d.ts +86 -0
  130. package/dist/esm/gateway/gateway-client.js +463 -0
  131. package/dist/esm/gateway/index.d.ts +3 -0
  132. package/dist/esm/gateway/index.js +1 -0
  133. package/dist/esm/gateway/types.d.ts +142 -0
  134. package/dist/esm/http/errors.d.ts +19 -0
  135. package/dist/esm/http/errors.js +22 -0
  136. package/dist/esm/http/index.d.ts +3 -0
  137. package/dist/esm/http/index.js +2 -0
  138. package/dist/esm/http/rest-client.d.ts +64 -0
  139. package/dist/esm/http/rest-client.js +181 -0
  140. package/dist/esm/index.d.ts +64 -0
  141. package/dist/esm/index.js +38 -0
  142. package/dist/esm/node/config-manager.d.ts +34 -0
  143. package/dist/esm/node/config-manager.js +140 -0
  144. package/dist/esm/node/index.d.ts +1 -0
  145. package/dist/esm/node/index.js +1 -0
  146. package/dist/esm/package.json +1 -0
  147. package/dist/esm/react/context.d.ts +23 -0
  148. package/dist/esm/react/context.js +28 -0
  149. package/dist/esm/react/index.d.ts +38 -0
  150. package/dist/esm/react/index.js +21 -0
  151. package/dist/esm/react/messageRangeStore.d.ts +93 -0
  152. package/dist/esm/react/messageRangeStore.js +140 -0
  153. package/dist/esm/react/sharedQueryClient.d.ts +21 -0
  154. package/dist/esm/react/sharedQueryClient.js +35 -0
  155. package/dist/esm/react/useAgentChannel.d.ts +8 -0
  156. package/dist/esm/react/useAgentChannel.js +9 -0
  157. package/dist/esm/react/useAgentConnections.d.ts +8 -0
  158. package/dist/esm/react/useAgentConnections.js +20 -0
  159. package/dist/esm/react/useAgentTokenState.d.ts +70 -0
  160. package/dist/esm/react/useAgentTokenState.js +127 -0
  161. package/dist/esm/react/useChannelAggregate.d.ts +64 -0
  162. package/dist/esm/react/useChannelAggregate.js +77 -0
  163. package/dist/esm/react/useChannelMessage.d.ts +45 -0
  164. package/dist/esm/react/useChannelMessage.js +79 -0
  165. package/dist/esm/react/useChannelMessages.d.ts +83 -0
  166. package/dist/esm/react/useChannelMessages.js +214 -0
  167. package/dist/esm/react/useChannelSubscription.d.ts +27 -0
  168. package/dist/esm/react/useChannelSubscription.js +30 -0
  169. package/dist/esm/react/useClientStatus.d.ts +10 -0
  170. package/dist/esm/react/useClientStatus.js +19 -0
  171. package/dist/esm/react/useConnectionState.d.ts +26 -0
  172. package/dist/esm/react/useConnectionState.js +45 -0
  173. package/dist/esm/react/useDeviceMap.d.ts +109 -0
  174. package/dist/esm/react/useDeviceMap.js +59 -0
  175. package/dist/esm/react/useInvocationLogs.d.ts +23 -0
  176. package/dist/esm/react/useInvocationLogs.js +37 -0
  177. package/dist/esm/react/useMultiAgentAggregates.d.ts +38 -0
  178. package/dist/esm/react/useMultiAgentAggregates.js +104 -0
  179. package/dist/esm/react/useMultiAgentChannelMessages.d.ts +79 -0
  180. package/dist/esm/react/useMultiAgentChannelMessages.js +169 -0
  181. package/dist/esm/react/useOfflineStatus.d.ts +8 -0
  182. package/dist/esm/react/useOfflineStatus.js +37 -0
  183. package/dist/esm/react/useSendMessage.d.ts +16 -0
  184. package/dist/esm/react/useSendMessage.js +26 -0
  185. package/dist/esm/react/useSendRpc.d.ts +68 -0
  186. package/dist/esm/react/useSendRpc.js +164 -0
  187. package/dist/esm/react/useTurnCredentials.d.ts +12 -0
  188. package/dist/esm/react/useTurnCredentials.js +22 -0
  189. package/dist/esm/react/useUpdateAggregate.d.ts +27 -0
  190. package/dist/esm/react/useUpdateAggregate.js +39 -0
  191. package/dist/esm/react/useUpdateMessage.d.ts +38 -0
  192. package/dist/esm/react/useUpdateMessage.js +36 -0
  193. package/dist/esm/refine/index.d.ts +72 -0
  194. package/dist/esm/refine/index.js +215 -0
  195. package/dist/esm/rpc/errors.d.ts +10 -0
  196. package/dist/esm/rpc/errors.js +19 -0
  197. package/dist/esm/rpc/index.d.ts +3 -0
  198. package/dist/esm/rpc/index.js +2 -0
  199. package/dist/esm/rpc/rpc-dispatcher.d.ts +41 -0
  200. package/dist/esm/rpc/rpc-dispatcher.js +141 -0
  201. package/dist/esm/types/audit.d.ts +53 -0
  202. package/dist/esm/types/audit.js +11 -0
  203. package/dist/esm/types/batch.d.ts +85 -0
  204. package/dist/esm/types/batch.js +42 -0
  205. package/dist/esm/types/common.d.ts +250 -0
  206. package/dist/esm/types/connection.d.ts +72 -0
  207. package/dist/esm/types/connection.js +7 -0
  208. package/dist/esm/types/index.d.ts +9 -0
  209. package/dist/esm/types/openapi.d.ts +195 -0
  210. package/dist/esm/types/provenance.d.ts +45 -0
  211. package/dist/esm/types/viewer.d.ts +122 -0
  212. package/dist/esm/utils/snowflake.d.ts +21 -0
  213. package/dist/esm/utils/snowflake.js +33 -0
  214. package/dist/esm/viewer/doover-data-provider.d.ts +90 -0
  215. package/dist/esm/viewer/doover-data-provider.js +189 -0
  216. package/dist/esm/viewer/path-parsing.d.ts +5 -0
  217. package/dist/esm/viewer/path-parsing.js +35 -0
  218. package/dist/gateway/gateway-client.d.ts +5 -5
  219. package/dist/gateway/gateway-client.js +5 -5
  220. package/dist/gateway/index.d.ts +3 -0
  221. package/dist/gateway/index.js +5 -0
  222. package/dist/gateway/types.d.ts +1 -1
  223. package/dist/http/index.d.ts +3 -0
  224. package/dist/http/index.js +9 -0
  225. package/dist/http/rest-client.d.ts +5 -3
  226. package/dist/http/rest-client.js +2 -2
  227. package/dist/index.d.ts +64 -62
  228. package/dist/index.js +92 -89
  229. package/dist/node/config-manager.d.ts +2 -2
  230. package/dist/node/config-manager.js +5 -5
  231. package/dist/node/index.d.ts +1 -1
  232. package/dist/node/index.js +2 -2
  233. package/dist/react/context.d.ts +1 -1
  234. package/dist/react/index.d.ts +38 -38
  235. package/dist/react/index.js +59 -59
  236. package/dist/react/messageRangeStore.d.ts +1 -1
  237. package/dist/react/useAgentChannel.d.ts +3 -3
  238. package/dist/react/useAgentChannel.js +2 -2
  239. package/dist/react/useAgentConnections.d.ts +1 -1
  240. package/dist/react/useAgentConnections.js +2 -2
  241. package/dist/react/useAgentTokenState.d.ts +3 -3
  242. package/dist/react/useAgentTokenState.js +8 -8
  243. package/dist/react/useChannelAggregate.d.ts +3 -3
  244. package/dist/react/useChannelAggregate.js +8 -8
  245. package/dist/react/useChannelMessage.d.ts +2 -2
  246. package/dist/react/useChannelMessage.js +4 -4
  247. package/dist/react/useChannelMessages.d.ts +3 -3
  248. package/dist/react/useChannelMessages.js +10 -10
  249. package/dist/react/useChannelSubscription.d.ts +2 -2
  250. package/dist/react/useChannelSubscription.js +2 -2
  251. package/dist/react/useClientStatus.d.ts +1 -1
  252. package/dist/react/useClientStatus.js +2 -2
  253. package/dist/react/useConnectionState.js +2 -2
  254. package/dist/react/useDeviceMap.js +2 -2
  255. package/dist/react/useInvocationLogs.d.ts +1 -1
  256. package/dist/react/useInvocationLogs.js +2 -2
  257. package/dist/react/useMultiAgentAggregates.d.ts +1 -1
  258. package/dist/react/useMultiAgentAggregates.js +5 -5
  259. package/dist/react/useMultiAgentChannelMessages.d.ts +1 -1
  260. package/dist/react/useMultiAgentChannelMessages.js +2 -2
  261. package/dist/react/useOfflineStatus.d.ts +2 -2
  262. package/dist/react/useOfflineStatus.js +31 -17
  263. package/dist/react/useSendMessage.d.ts +2 -2
  264. package/dist/react/useSendMessage.js +2 -2
  265. package/dist/react/useSendRpc.d.ts +2 -2
  266. package/dist/react/useSendRpc.js +2 -2
  267. package/dist/react/useTurnCredentials.d.ts +2 -2
  268. package/dist/react/useTurnCredentials.js +2 -2
  269. package/dist/react/useUpdateAggregate.d.ts +3 -3
  270. package/dist/react/useUpdateAggregate.js +4 -4
  271. package/dist/react/useUpdateMessage.d.ts +2 -2
  272. package/dist/react/useUpdateMessage.js +2 -2
  273. package/dist/refine/index.d.ts +1 -1
  274. package/dist/rpc/errors.d.ts +1 -1
  275. package/dist/rpc/index.d.ts +3 -0
  276. package/dist/rpc/index.js +7 -0
  277. package/dist/rpc/rpc-dispatcher.d.ts +4 -4
  278. package/dist/rpc/rpc-dispatcher.js +2 -2
  279. package/dist/types/common.d.ts +1 -1
  280. package/dist/types/index.d.ts +9 -0
  281. package/dist/types/index.js +2 -0
  282. package/dist/types/openapi.d.ts +1 -1
  283. package/dist/types/viewer.d.ts +2 -2
  284. package/dist/viewer/doover-data-provider.d.ts +10 -10
  285. package/dist/viewer/doover-data-provider.js +25 -25
  286. package/dist/viewer/path-parsing.d.ts +1 -1
  287. package/package.json +795 -8
  288. package/dist/test/api-args.test.js +0 -48
  289. package/dist/test/api-overloads.test.d.ts +0 -9
  290. package/dist/test/api-overloads.test.js +0 -330
  291. package/dist/test/apis.test.js +0 -408
  292. package/dist/test/auth.test.js +0 -708
  293. package/dist/test/batch-apis.test.js +0 -183
  294. package/dist/test/capabilities.test.js +0 -27
  295. package/dist/test/config-manager.test.js +0 -160
  296. package/dist/test/data-client-errors.test.js +0 -24
  297. package/dist/test/data-client-shape.test.js +0 -28
  298. package/dist/test/doover-client-dataclient.test.d.ts +0 -1
  299. package/dist/test/doover-client-dataclient.test.js +0 -58
  300. package/dist/test/doover-client-provenance.test.d.ts +0 -1
  301. package/dist/test/doover-client-provenance.test.js +0 -32
  302. package/dist/test/doover-client.test.d.ts +0 -1
  303. package/dist/test/doover-client.test.js +0 -42
  304. package/dist/test/doover-data-provider.test.d.ts +0 -1
  305. package/dist/test/doover-data-provider.test.js +0 -657
  306. package/dist/test/exports.test.d.ts +0 -1
  307. package/dist/test/exports.test.js +0 -80
  308. package/dist/test/gateway-client.test.d.ts +0 -1
  309. package/dist/test/gateway-client.test.js +0 -474
  310. package/dist/test/gateway-provenance.test.d.ts +0 -1
  311. package/dist/test/gateway-provenance.test.js +0 -29
  312. package/dist/test/gateway-subscriptions.test.d.ts +0 -1
  313. package/dist/test/gateway-subscriptions.test.js +0 -95
  314. package/dist/test/helpers.d.ts +0 -32
  315. package/dist/test/helpers.js +0 -115
  316. package/dist/test/local-agent-client.test.d.ts +0 -1
  317. package/dist/test/local-agent-client.test.js +0 -202
  318. package/dist/test/message-range-store.test.d.ts +0 -1
  319. package/dist/test/message-range-store.test.js +0 -183
  320. package/dist/test/multiplex-capabilities.test.d.ts +0 -1
  321. package/dist/test/multiplex-capabilities.test.js +0 -37
  322. package/dist/test/multiplex-conflicts.test.d.ts +0 -1
  323. package/dist/test/multiplex-conflicts.test.js +0 -35
  324. package/dist/test/multiplex-gateway.test.d.ts +0 -1
  325. package/dist/test/multiplex-gateway.test.js +0 -103
  326. package/dist/test/multiplex-merge.test.d.ts +0 -1
  327. package/dist/test/multiplex-merge.test.js +0 -19
  328. package/dist/test/multiplex-noncore.test.d.ts +0 -1
  329. package/dist/test/multiplex-noncore.test.js +0 -82
  330. package/dist/test/multiplex-passthrough.test.d.ts +0 -1
  331. package/dist/test/multiplex-passthrough.test.js +0 -35
  332. package/dist/test/multiplex-reads.test.d.ts +0 -1
  333. package/dist/test/multiplex-reads.test.js +0 -87
  334. package/dist/test/multiplex-registry.test.d.ts +0 -1
  335. package/dist/test/multiplex-registry.test.js +0 -81
  336. package/dist/test/multiplex-routing.test.d.ts +0 -1
  337. package/dist/test/multiplex-routing.test.js +0 -45
  338. package/dist/test/multiplex-status.test.d.ts +0 -1
  339. package/dist/test/multiplex-status.test.js +0 -63
  340. package/dist/test/multiplex-writes.test.d.ts +0 -1
  341. package/dist/test/multiplex-writes.test.js +0 -93
  342. package/dist/test/offline-cache.test.d.ts +0 -1
  343. package/dist/test/offline-cache.test.js +0 -289
  344. package/dist/test/provenance-regression.test.d.ts +0 -1
  345. package/dist/test/provenance-regression.test.js +0 -45
  346. package/dist/test/provenance-stamper.test.d.ts +0 -1
  347. package/dist/test/provenance-stamper.test.js +0 -41
  348. package/dist/test/provenance-type.test.d.ts +0 -1
  349. package/dist/test/provenance-type.test.js +0 -15
  350. package/dist/test/react-channel-messages-forward.test.d.ts +0 -1
  351. package/dist/test/react-channel-messages-forward.test.js +0 -139
  352. package/dist/test/react-channel-messages-range.test.d.ts +0 -1
  353. package/dist/test/react-channel-messages-range.test.js +0 -109
  354. package/dist/test/react-client-status.test.d.ts +0 -1
  355. package/dist/test/react-client-status.test.js +0 -35
  356. package/dist/test/react-dataclient.test.d.ts +0 -1
  357. package/dist/test/react-dataclient.test.js +0 -28
  358. package/dist/test/react-exports.test.d.ts +0 -1
  359. package/dist/test/react-exports.test.js +0 -46
  360. package/dist/test/react-multiagent-messages.test.d.ts +0 -1
  361. package/dist/test/react-multiagent-messages.test.js +0 -113
  362. package/dist/test/react-sources-option.test.d.ts +0 -1
  363. package/dist/test/react-sources-option.test.js +0 -41
  364. package/dist/test/react.test.d.ts +0 -1
  365. package/dist/test/react.test.js +0 -482
  366. package/dist/test/refine.test.d.ts +0 -1
  367. package/dist/test/refine.test.js +0 -71
  368. package/dist/test/rest-client.test.d.ts +0 -1
  369. package/dist/test/rest-client.test.js +0 -197
  370. package/dist/test/rpc-dispatcher.test.d.ts +0 -1
  371. package/dist/test/rpc-dispatcher.test.js +0 -251
  372. package/dist/test/singleton.test.d.ts +0 -1
  373. package/dist/test/singleton.test.js +0 -62
  374. package/dist/test/stats-rpc.test.d.ts +0 -1
  375. package/dist/test/stats-rpc.test.js +0 -69
  376. package/dist/test/status-tracker.test.d.ts +0 -1
  377. package/dist/test/status-tracker.test.js +0 -85
  378. package/dist/test/users-api.test.d.ts +0 -1
  379. package/dist/test/users-api.test.js +0 -19
  380. package/dist/test/utils.test.d.ts +0 -1
  381. package/dist/test/utils.test.js +0 -64
  382. /package/dist/{test/api-args.test.d.ts → esm/auth/auth-store.js} +0 -0
  383. /package/dist/{test/apis.test.d.ts → esm/client/data-client.js} +0 -0
  384. /package/dist/{test/auth.test.d.ts → esm/gateway/types.js} +0 -0
  385. /package/dist/{test/batch-apis.test.d.ts → esm/types/common.js} +0 -0
  386. /package/dist/{test/capabilities.test.d.ts → esm/types/index.js} +0 -0
  387. /package/dist/{test/config-manager.test.d.ts → esm/types/openapi.js} +0 -0
  388. /package/dist/{test/data-client-errors.test.d.ts → esm/types/provenance.js} +0 -0
  389. /package/dist/{test/data-client-shape.test.d.ts → esm/types/viewer.js} +0 -0
@@ -0,0 +1,64 @@
1
+ import { type UseQueryResult } from "@tanstack/react-query";
2
+ import type { Aggregate } from "../types/common.js";
3
+ import type { ChannelIdentifier } from "../types/viewer.js";
4
+ import { type OfflineStatusSnapshot } from "./useOfflineStatus.js";
5
+ export declare function channelAggregateQueryKey(agentId: string | undefined, channelName: string | undefined, sources?: string[]): readonly ["doover", "agent", string | undefined, "channel", string | undefined, "src", string];
6
+ /**
7
+ * Shape returned by `useChannelAggregate`. Shadows the react-query
8
+ * `data` field with the unwrapped aggregate payload (`TData`) so the
9
+ * common call-site pattern — `const { data } = useChannelAggregate(…)` —
10
+ * just works without a secondary `.data` access or cast. The
11
+ * `attachments` and `last_updated` slots are hoisted alongside for the
12
+ * same reason; everything else (isLoading, isError, refetch, status,
13
+ * …) passes through from react-query unchanged.
14
+ */
15
+ export interface UseChannelAggregateResult<TData> extends Omit<UseQueryResult<Aggregate<TData> | undefined>, "data"> {
16
+ /** The aggregate payload. `undefined` until the first fetch lands. */
17
+ data: TData | undefined;
18
+ /** Attachments (files/blobs) on the aggregate. */
19
+ attachments: Aggregate["attachments"] | undefined;
20
+ /**
21
+ * Server timestamp (epoch **milliseconds**) of the last aggregate update —
22
+ * matches the `Date` / `dayjs()` constructor. Use `dayjs(last_updated)`, not
23
+ * `dayjs.unix(last_updated)` (the latter assumes seconds and lands ~58000
24
+ * years in the future).
25
+ */
26
+ last_updated: number | null | undefined;
27
+ /** Offline/cache status when the provided client supports offline caching. */
28
+ offline: OfflineStatusSnapshot;
29
+ }
30
+ export interface UseChannelAggregateOptions {
31
+ /**
32
+ * Whether to fetch the initial aggregate over REST on mount.
33
+ *
34
+ * Defaults to `true` — the hook does a one-shot HTTP GET to seed the cache
35
+ * before the gateway WebSocket has connected, so the first paint isn't
36
+ * empty.
37
+ *
38
+ * Set to `false` for purely WS-driven consumers that don't want the REST
39
+ * round-trip (e.g. when the gateway's upsert-on-subscribe semantics make
40
+ * the REST call redundant or actively wrong, like channels that don't yet
41
+ * exist). The cache is then populated only by `ChannelSync` /
42
+ * `AggregateUpdate` events.
43
+ */
44
+ fetchInitial?: boolean;
45
+ /**
46
+ * Restrict to these source ids on a `MultiplexClient`. Ignored for a plain
47
+ * `DooverClient` or `LocalAgentClient`. When set, the query key is
48
+ * source-dimensioned so data from different source subsets is cached
49
+ * independently.
50
+ */
51
+ sources?: string[];
52
+ }
53
+ /**
54
+ * Fetch a channel's aggregate and keep it live via the gateway. Incoming
55
+ * `channelSync` and `aggregateUpdate` events patch the react-query cache
56
+ * under `channelAggregateQueryKey(agentId, channelName)`.
57
+ *
58
+ * Typed on `TData` — the shape of `aggregate.data`. Defaults to the generic
59
+ * `Record<string, JSONValue>` used by `Aggregate`. No `extends` constraint
60
+ * on the generic: typed aggregate interfaces (e.g. `{ enabled: boolean }`)
61
+ * don't have the implicit index signature that `Aggregate["data"]` carries
62
+ * and enforcing compatibility there just forces `as` casts at call sites.
63
+ */
64
+ export declare function useChannelAggregate<TData = Aggregate["data"]>(identifier: ChannelIdentifier, options?: UseChannelAggregateOptions): UseChannelAggregateResult<TData>;
@@ -0,0 +1,77 @@
1
+ import { useCallback } from "react";
2
+ import { useQuery, useQueryClient } from "@tanstack/react-query";
3
+ import { DooverApiError } from "../http/errors.js";
4
+ import { useDooverClient } from "./context.js";
5
+ import { useChannelSubscription } from "./useChannelSubscription.js";
6
+ import { useOfflineStatus } from "./useOfflineStatus.js";
7
+ export function channelAggregateQueryKey(agentId, channelName, sources) {
8
+ const sourceDim = sources && sources.length ? [...sources].sort().join(",") : "*";
9
+ return ["doover", "agent", agentId, "channel", channelName, "src", sourceDim];
10
+ }
11
+ /**
12
+ * Fetch a channel's aggregate and keep it live via the gateway. Incoming
13
+ * `channelSync` and `aggregateUpdate` events patch the react-query cache
14
+ * under `channelAggregateQueryKey(agentId, channelName)`.
15
+ *
16
+ * Typed on `TData` — the shape of `aggregate.data`. Defaults to the generic
17
+ * `Record<string, JSONValue>` used by `Aggregate`. No `extends` constraint
18
+ * on the generic: typed aggregate interfaces (e.g. `{ enabled: boolean }`)
19
+ * don't have the implicit index signature that `Aggregate["data"]` carries
20
+ * and enforcing compatibility there just forces `as` casts at call sites.
21
+ */
22
+ export function useChannelAggregate(identifier, options) {
23
+ const client = useDooverClient();
24
+ const offline = useOfflineStatus();
25
+ const queryClient = useQueryClient();
26
+ const { agentId, channelName } = identifier;
27
+ const sources = options?.sources;
28
+ const key = channelAggregateQueryKey(agentId, channelName, sources);
29
+ const fetchInitial = options?.fetchInitial ?? true;
30
+ const onAggregate = useCallback((aggregate) => {
31
+ queryClient.setQueryData(key, aggregate);
32
+ },
33
+ // The key array is structurally stable per (agentId, channelName, sourceDim).
34
+ // eslint-disable-next-line react-hooks/exhaustive-deps
35
+ [queryClient, agentId, channelName, sources?.join(",")]);
36
+ useChannelSubscription(identifier, { onAggregate });
37
+ const query = useQuery({
38
+ queryKey: key,
39
+ enabled: fetchInitial && !!agentId && !!channelName,
40
+ staleTime: Infinity,
41
+ queryFn: async () => {
42
+ if (!agentId || !channelName)
43
+ return undefined;
44
+ const id = { agentId, channelName };
45
+ // Pass `{ sources }` as a trailing bag only when set. The TypeScript
46
+ // overloads don't declare it, so we cast through `never` — the runtime
47
+ // implementation reads it via `...args: unknown[]`.
48
+ const sourcesArg = sources ? { sources } : undefined;
49
+ const channel = sourcesArg
50
+ ? await client.channels.getChannel(id, sourcesArg)
51
+ : await client.channels.getChannel(id);
52
+ if (channel.aggregate)
53
+ return channel.aggregate;
54
+ return (sourcesArg
55
+ ? await client.aggregates.getAggregate(id, sourcesArg)
56
+ : await client.aggregates.getAggregate(id));
57
+ },
58
+ // A 404 means the aggregate doesn't exist — retrying won't change that,
59
+ // and the caller needs the error promptly to render an empty/"not
60
+ // installed" state. Fall back to the react-query default (3 retries) for
61
+ // every other failure.
62
+ retry: (failureCount, error) => {
63
+ if (error instanceof DooverApiError && error.status === 404)
64
+ return false;
65
+ return failureCount < 3;
66
+ },
67
+ });
68
+ const aggregate = query.data;
69
+ const { data: _ignored, ...rest } = query;
70
+ return {
71
+ ...rest,
72
+ data: aggregate?.data,
73
+ attachments: aggregate?.attachments,
74
+ last_updated: aggregate?.last_updated,
75
+ offline,
76
+ };
77
+ }
@@ -0,0 +1,45 @@
1
+ import { type UseQueryResult } from "@tanstack/react-query";
2
+ import type { JSONValue, MessageAttachment, MessageStructure } from "../types/common.js";
3
+ import type { ChannelIdentifier } from "../types/viewer.js";
4
+ export declare function channelMessageQueryKey(agentId: string | undefined, channelName: string | undefined, messageId: string | undefined, sources?: string[]): readonly ["doover", "agent", string | undefined, "channel", string | undefined, "message", string | undefined, "src", string];
5
+ export interface UseChannelMessageOptions {
6
+ /** If false, skip subscribing for live message-update events. Defaults true. */
7
+ liveUpdates?: boolean;
8
+ /**
9
+ * Restrict to these source ids on a `MultiplexClient`. Ignored for a plain
10
+ * `DooverClient` or `LocalAgentClient`. When set, the query key is
11
+ * source-dimensioned so data from different source subsets is cached
12
+ * independently.
13
+ */
14
+ sources?: string[];
15
+ }
16
+ /**
17
+ * Shape returned by `useChannelMessage`. Mirrors `UseChannelAggregateResult`:
18
+ * `data` is unwrapped to the message payload (`message.data`) so the common
19
+ * `const { data } = useChannelMessage(…)` pattern works without a secondary
20
+ * access. The full `MessageStructure` and a couple of useful slots
21
+ * (`attachments`, `timestamp`) are hoisted alongside.
22
+ */
23
+ export interface UseChannelMessageResult<TData> extends Omit<UseQueryResult<MessageStructure<TData> | undefined>, "data"> {
24
+ /** Unwrapped message payload (`message.data`). Undefined until first fetch. */
25
+ data: TData | undefined;
26
+ /** Full message structure, or undefined until first fetch. */
27
+ message: MessageStructure<TData> | undefined;
28
+ attachments: MessageAttachment[] | undefined;
29
+ /** Server timestamp reported by the message. */
30
+ timestamp: number | undefined;
31
+ }
32
+ /**
33
+ * Fetch a single channel message by id and keep it live via gateway
34
+ * `MessageUpdate` events. Mirrors `useChannelAggregate`'s pattern: REST seeds
35
+ * the cache, then `onMessageUpdate` patches it whenever the message body is
36
+ * mutated server-side — handy for watching long-running RPC-style messages
37
+ * where the receiver writes progress into a `response` field.
38
+ *
39
+ * Channel subscriptions deliver every message in the channel, so the
40
+ * handlers filter to the requested `messageId` before patching the cache.
41
+ *
42
+ * Typed on `TData` — the shape of `message.data`. Defaults to `JSONValue` to
43
+ * match `MessageStructure`.
44
+ */
45
+ export declare function useChannelMessage<TData = JSONValue>(identifier: ChannelIdentifier, messageId: string | undefined, options?: UseChannelMessageOptions): UseChannelMessageResult<TData>;
@@ -0,0 +1,79 @@
1
+ import { useCallback } from "react";
2
+ import { useQuery, useQueryClient, } from "@tanstack/react-query";
3
+ import { useDooverClient } from "./context.js";
4
+ import { useChannelSubscription } from "./useChannelSubscription.js";
5
+ export function channelMessageQueryKey(agentId, channelName, messageId, sources) {
6
+ const sourceDim = sources && sources.length ? [...sources].sort().join(",") : "*";
7
+ return [
8
+ "doover",
9
+ "agent",
10
+ agentId,
11
+ "channel",
12
+ channelName,
13
+ "message",
14
+ messageId,
15
+ "src",
16
+ sourceDim,
17
+ ];
18
+ }
19
+ /**
20
+ * Fetch a single channel message by id and keep it live via gateway
21
+ * `MessageUpdate` events. Mirrors `useChannelAggregate`'s pattern: REST seeds
22
+ * the cache, then `onMessageUpdate` patches it whenever the message body is
23
+ * mutated server-side — handy for watching long-running RPC-style messages
24
+ * where the receiver writes progress into a `response` field.
25
+ *
26
+ * Channel subscriptions deliver every message in the channel, so the
27
+ * handlers filter to the requested `messageId` before patching the cache.
28
+ *
29
+ * Typed on `TData` — the shape of `message.data`. Defaults to `JSONValue` to
30
+ * match `MessageStructure`.
31
+ */
32
+ export function useChannelMessage(identifier, messageId, options) {
33
+ const client = useDooverClient();
34
+ const queryClient = useQueryClient();
35
+ const { agentId, channelName } = identifier;
36
+ const liveUpdates = options?.liveUpdates ?? true;
37
+ const sources = options?.sources;
38
+ const key = channelMessageQueryKey(agentId, channelName, messageId, sources);
39
+ const onMessageUpdate = useCallback((message) => {
40
+ if (message.id !== messageId)
41
+ return;
42
+ queryClient.setQueryData(key, message);
43
+ },
44
+ // The key array is structurally stable per (agentId, channelName, messageId, sourceDim).
45
+ // eslint-disable-next-line react-hooks/exhaustive-deps
46
+ [queryClient, agentId, channelName, messageId, sources?.join(",")]);
47
+ // Cover the case where the caller has the id before the create event has
48
+ // landed on this client — patch the cache when it shows up.
49
+ const onMessage = useCallback((message) => {
50
+ if (message.id !== messageId)
51
+ return;
52
+ queryClient.setQueryData(key, message);
53
+ },
54
+ // eslint-disable-next-line react-hooks/exhaustive-deps
55
+ [queryClient, agentId, channelName, messageId, sources?.join(",")]);
56
+ useChannelSubscription(liveUpdates && messageId ? identifier : undefined, { onMessage, onMessageUpdate });
57
+ const query = useQuery({
58
+ queryKey: key,
59
+ enabled: !!agentId && !!channelName && !!messageId,
60
+ staleTime: Infinity,
61
+ queryFn: () => {
62
+ // Pass `{ sources }` as a trailing bag only when set — cast through
63
+ // `never` since the TypeScript overloads don't declare it.
64
+ const sourcesArg = sources ? { sources } : undefined;
65
+ return (sourcesArg
66
+ ? client.messages.getMessage(agentId, channelName, messageId, sourcesArg)
67
+ : client.messages.getMessage(agentId, channelName, messageId));
68
+ },
69
+ });
70
+ const message = query.data;
71
+ const { data: _ignored, ...rest } = query;
72
+ return {
73
+ ...rest,
74
+ data: message?.data,
75
+ message,
76
+ attachments: message?.attachments,
77
+ timestamp: message?.timestamp,
78
+ };
79
+ }
@@ -0,0 +1,83 @@
1
+ import { type InfiniteData, type UseInfiniteQueryResult } from "@tanstack/react-query";
2
+ import type { MessageStructure } from "../types/common.js";
3
+ import type { ChannelIdentifier } from "../types/viewer.js";
4
+ import { type OfflineStatusSnapshot } from "./useOfflineStatus.js";
5
+ export declare function channelMessagesQueryKey(agentId: string | undefined, channelName: string | undefined, fields?: readonly string[], sources?: string[], anchor?: string): readonly ["doover", "agent", string | undefined, "channel", string | undefined, "messages", "src", string] | readonly ["doover", "agent", string | undefined, "channel", string | undefined, "messages", "src", string, {
6
+ readonly anchor: string;
7
+ }] | readonly ["doover", "agent", string | undefined, "channel", string | undefined, "messages", "src", string, {
8
+ readonly fields: string[];
9
+ }] | readonly ["doover", "agent", string | undefined, "channel", string | undefined, "messages", "src", string, {
10
+ readonly anchor: string;
11
+ }, {
12
+ readonly fields: string[];
13
+ }];
14
+ export interface UseChannelMessagesOptions {
15
+ limit?: number;
16
+ /** If false, skip subscribing for live message-create updates. Defaults true. */
17
+ liveUpdates?: boolean;
18
+ /**
19
+ * Restrict the returned messages to those whose payload contains any of
20
+ * these top-level field names. Passed through as `field_name` on the
21
+ * REST call.
22
+ */
23
+ fields?: string[];
24
+ /**
25
+ * Optional first-page `before` cursor (snowflake id). Defaults to
26
+ * unset, which returns the latest messages. Use this when you need to
27
+ * guard against client-side clock skew (seed with a slightly-future
28
+ * snowflake so server-stamped messages don't get missed).
29
+ */
30
+ initialBefore?: string;
31
+ /**
32
+ * Pin the window to a point in history (snowflake id), for "jump to this
33
+ * date" navigation. Changing it re-anchors and refetches.
34
+ *
35
+ * Distinct from `initialBefore`, which is a clock-skew seed regenerated per
36
+ * mount and therefore must NOT dimension the cache key. An anchor identifies
37
+ * a stream the caller means to look at, so it does. Pass a stable value — a
38
+ * per-render `now` would refetch on every render.
39
+ *
40
+ * Cheaper than it looks: anchored windows share the range cache with every
41
+ * other window on the channel, so re-anchoring over already-fetched history
42
+ * costs no requests.
43
+ */
44
+ anchor?: string;
45
+ /**
46
+ * Optional lower-bound snowflake id. The server only returns messages
47
+ * newer than this on every page, so paginating older eventually returns
48
+ * an empty page and `hasNextPage` flips to false — useful for fetching
49
+ * a bounded time window (e.g. last 24h) without a manual cutoff loop on
50
+ * the consumer side.
51
+ */
52
+ after?: string;
53
+ /**
54
+ * Keep paging older automatically until `hasNextPage` is false. Almost
55
+ * always combined with `after` (or a small channel) — without a lower
56
+ * bound this will walk the channel back to its first message.
57
+ */
58
+ autoPaginate?: boolean;
59
+ /**
60
+ * Restrict to these source ids on a `MultiplexClient`. Ignored for a plain
61
+ * `DooverClient` or `LocalAgentClient`. When set, the query key is
62
+ * source-dimensioned so data from different source subsets is cached
63
+ * independently.
64
+ */
65
+ sources?: string[];
66
+ }
67
+ type Page<TData> = MessageStructure<TData>[];
68
+ export interface UseChannelMessagesResult<TData> extends Omit<UseInfiniteQueryResult<InfiniteData<Page<TData>>>, "data"> {
69
+ /** Flat chronological list across all loaded pages. */
70
+ messages: MessageStructure<TData>[];
71
+ /** Raw react-query data (pages). */
72
+ data: InfiniteData<Page<TData>> | undefined;
73
+ /** Offline/cache status when the provided client supports offline caching. */
74
+ offline: OfflineStatusSnapshot;
75
+ }
76
+ /**
77
+ * Paginated infinite query over `DooverDataProvider.getMessages`, with live
78
+ * `messageCreate` pushes are appended to the newest page and `messageUpdate`
79
+ * pushes replace matching cached messages. The "next" page fetches older
80
+ * messages (cursor = oldest-loaded message id).
81
+ */
82
+ export declare function useChannelMessages<TData = unknown>(identifier: ChannelIdentifier, options?: UseChannelMessagesOptions): UseChannelMessagesResult<TData>;
83
+ export {};
@@ -0,0 +1,214 @@
1
+ import { useCallback, useEffect, useMemo } from "react";
2
+ import { useInfiniteQuery, useQueryClient, } from "@tanstack/react-query";
3
+ import { generateSnowflakeIdAtTime } from "../utils/snowflake.js";
4
+ import { getChannelRangeStore } from "./messageRangeStore.js";
5
+ import { useDooverClient } from "./context.js";
6
+ import { useChannelSubscription } from "./useChannelSubscription.js";
7
+ import { useOfflineStatus } from "./useOfflineStatus.js";
8
+ export function channelMessagesQueryKey(agentId, channelName, fields, sources, anchor) {
9
+ // Source-dimension the key (multiplex source subsets cache independently);
10
+ // "*" means "all/unspecified" for a plain DooverClient/LocalAgentClient.
11
+ const sourceDim = sources && sources.length ? [...sources].sort().join(",") : "*";
12
+ const base = ["doover", "agent", agentId, "channel", channelName, "messages", "src", sourceDim];
13
+ // An anchored window is its own chain of cursors, so it must not share a cache
14
+ // entry with the live one — same reasoning as `fields` below. Note this is
15
+ // deliberately absent from the range store's key: sharing ranges across
16
+ // anchors is the point of it.
17
+ const key = anchor ? [...base, { anchor }] : base;
18
+ if (!fields || fields.length === 0)
19
+ return key;
20
+ // A `field_name`-filtered request returns a different message stream than
21
+ // the unfiltered (or differently-filtered) one, so it must live under its
22
+ // own cache entry — otherwise one filter's pagination cursor leaks into
23
+ // another's `getNextPageParam`, and the "next page" fetch ends up anchored
24
+ // to an unrelated (often much older) message id. Sort so call-site argument
25
+ // order doesn't fragment the cache.
26
+ return [...key, { fields: [...fields].sort() }];
27
+ }
28
+ /** Mirrors `MessagesApi.listMessages`'s own default. */
29
+ const DEFAULT_PAGE_LIMIT = 10;
30
+ /**
31
+ * Paginated infinite query over `DooverDataProvider.getMessages`, with live
32
+ * `messageCreate` pushes are appended to the newest page and `messageUpdate`
33
+ * pushes replace matching cached messages. The "next" page fetches older
34
+ * messages (cursor = oldest-loaded message id).
35
+ */
36
+ export function useChannelMessages(identifier, options) {
37
+ const client = useDooverClient();
38
+ const offline = useOfflineStatus();
39
+ const queryClient = useQueryClient();
40
+ const { agentId, channelName } = identifier;
41
+ const limit = options?.limit;
42
+ const liveUpdates = options?.liveUpdates ?? true;
43
+ const fields = options?.fields;
44
+ const initialBefore = options?.initialBefore;
45
+ const anchor = options?.anchor;
46
+ const after = options?.after;
47
+ const autoPaginate = options?.autoPaginate ?? false;
48
+ const sources = options?.sources;
49
+ const key = channelMessagesQueryKey(agentId, channelName, fields, sources, anchor);
50
+ // Keyed per stream, NOT per anchor — every window on this channel shares it.
51
+ const storeKey = JSON.stringify(channelMessagesQueryKey(agentId, channelName, fields, sources));
52
+ const store = getChannelRangeStore(storeKey);
53
+ // `after`/`sources` change what a page means (a short page proves a bound was
54
+ // hit, not that history ran out; multiplex merges several streams), so those
55
+ // requests bypass the range cache rather than record unsound coverage.
56
+ const rangeCacheable = after === undefined && !sources;
57
+ // A dropped socket may have swallowed messages, so the live feed stops being
58
+ // proof of coverage until a fetch re-establishes it.
59
+ useEffect(() => {
60
+ const onClose = () => store.sealTips();
61
+ client.gateway.on("close", onClose);
62
+ return () => {
63
+ client.gateway.off("close", onClose);
64
+ };
65
+ }, [client, store]);
66
+ const onMessage = useCallback((message) => {
67
+ // This cache entry is scoped to `fields`; the gateway delivers every
68
+ // message on the channel, so drop live pushes whose payload doesn't
69
+ // carry one of those fields rather than letting them pollute it.
70
+ if (fields && fields.length > 0) {
71
+ const data = message.data;
72
+ if (!data ||
73
+ typeof data !== "object" ||
74
+ !fields.some((f) => f in data)) {
75
+ return;
76
+ }
77
+ }
78
+ if (rangeCacheable)
79
+ store.recordLive(message);
80
+ queryClient.setQueryData(key, (current) => {
81
+ if (!current)
82
+ return current;
83
+ const typed = message;
84
+ // Newest page is index 0 — prepend there.
85
+ const [firstPage, ...rest] = current.pages;
86
+ return {
87
+ ...current,
88
+ pages: [[...(firstPage ?? []), typed], ...rest],
89
+ };
90
+ });
91
+ },
92
+ // eslint-disable-next-line react-hooks/exhaustive-deps
93
+ [queryClient, agentId, channelName, fields?.join(","), sources?.join(",")]);
94
+ const onMessageUpdate = useCallback((message) => {
95
+ // A filtered stream must not accept an update that does not belong to it.
96
+ // Newly qualifying messages are left for a refetch because inserting one
97
+ // into an arbitrary cursor page could invalidate that page's boundaries.
98
+ if (fields && fields.length > 0) {
99
+ const data = message.data;
100
+ if (!data ||
101
+ typeof data !== "object" ||
102
+ !fields.some((field) => field in data)) {
103
+ return;
104
+ }
105
+ }
106
+ if (rangeCacheable)
107
+ store.recordUpdate(message);
108
+ queryClient.setQueryData(key, (current) => {
109
+ if (!current)
110
+ return current;
111
+ let changed = false;
112
+ const typed = message;
113
+ const pages = current.pages.map((page) => page.map((item) => {
114
+ if (item.id !== typed.id)
115
+ return item;
116
+ changed = true;
117
+ return typed;
118
+ }));
119
+ return changed ? { ...current, pages } : current;
120
+ });
121
+ },
122
+ // eslint-disable-next-line react-hooks/exhaustive-deps
123
+ [queryClient, agentId, channelName, fields?.join(","), sources?.join(",")]);
124
+ useChannelSubscription(liveUpdates ? identifier : undefined, {
125
+ onMessage,
126
+ onMessageUpdate,
127
+ });
128
+ const query = useInfiniteQuery({
129
+ queryKey: key,
130
+ enabled: !!agentId && !!channelName,
131
+ staleTime: Infinity,
132
+ initialPageParam: { before: anchor ?? initialBefore },
133
+ // Older (down): the next cursor is the oldest id currently held.
134
+ getNextPageParam: (lastPage) => lastPage && lastPage.length > 0
135
+ ? { before: lastPage[0]?.id }
136
+ : undefined,
137
+ // Newer (up): only for an anchored window — the live window already begins
138
+ // at "now", so it has nothing above to page into. `after` = newest id held;
139
+ // the server returns the oldest messages above it, walking up toward now.
140
+ // An empty page whose own cursor was already a forward `after` means the
141
+ // top is reached; an empty *initial* page (nothing below the anchor) still
142
+ // seeds the walk from the anchor, since messages may sit above it.
143
+ getPreviousPageParam: (firstPage, _all, firstPageParam) => {
144
+ if (!anchor)
145
+ return undefined;
146
+ if (firstPage && firstPage.length > 0) {
147
+ return { after: firstPage[firstPage.length - 1]?.id };
148
+ }
149
+ if (firstPageParam?.after !== undefined)
150
+ return undefined;
151
+ return { after: anchor };
152
+ },
153
+ queryFn: async ({ pageParam }) => {
154
+ if (!agentId || !channelName)
155
+ return [];
156
+ const id = { agentId, channelName };
157
+ const param = (pageParam ?? {});
158
+ // Mirrors the API's own default; the store needs the limit actually applied
159
+ const effectiveLimit = limit ?? DEFAULT_PAGE_LIMIT;
160
+ // Pass `{ sources }` as a trailing bag only when set — cast through
161
+ // `unknown` since the TypeScript overloads don't declare it.
162
+ const runList = (params) => sources
163
+ ? client.messages.listMessages(id, params, { sources })
164
+ : client.messages.listMessages(id, params);
165
+ // Forward (newer) page: `after` alone pages oldest-first upward. Bypasses
166
+ // the range store, which models before-anchored windows only.
167
+ if (param.after !== undefined && param.before === undefined) {
168
+ const page = await runList({
169
+ after: param.after,
170
+ ...(limit !== undefined ? { limit } : {}),
171
+ ...(fields && fields.length > 0 ? { field_name: fields } : {}),
172
+ order: "asc",
173
+ });
174
+ return page;
175
+ }
176
+ // Older page. Resolve `before` here rather than letting the API default
177
+ // it, so the range store records the exact bound the request proved.
178
+ const before = typeof param.before === "string"
179
+ ? param.before
180
+ : generateSnowflakeIdAtTime(new Date());
181
+ if (rangeCacheable) {
182
+ const cached = store.read(BigInt(before), effectiveLimit);
183
+ if (cached)
184
+ return cached;
185
+ }
186
+ const requestedAt = Date.now();
187
+ const page = await runList({
188
+ before,
189
+ ...(limit !== undefined ? { limit } : {}),
190
+ ...(fields && fields.length > 0 ? { field_name: fields } : {}),
191
+ ...(after !== undefined ? { after } : {}),
192
+ order: "asc",
193
+ });
194
+ if (rangeCacheable) {
195
+ store.record({
196
+ before: BigInt(before),
197
+ limit: effectiveLimit,
198
+ page: page,
199
+ at: requestedAt,
200
+ });
201
+ }
202
+ return page;
203
+ },
204
+ });
205
+ useEffect(() => {
206
+ if (!autoPaginate)
207
+ return;
208
+ if (query.isFetching || !query.hasNextPage)
209
+ return;
210
+ query.fetchNextPage();
211
+ }, [autoPaginate, query.isFetching, query.hasNextPage, query.fetchNextPage]);
212
+ const messages = useMemo(() => (query.data?.pages ?? []).flat(), [query.data]);
213
+ return { ...query, messages, offline };
214
+ }
@@ -0,0 +1,27 @@
1
+ import type { Aggregate, JSONValue, MessageStructure } from "../types/common.js";
2
+ import type { ChannelIdentifier } from "../types/viewer.js";
3
+ export interface ChannelSubscriptionHandlers {
4
+ onMessage?: (message: MessageStructure) => void;
5
+ /**
6
+ * Fires on server-side MessageUpdate events. `message` is the full updated
7
+ * MessageStructure; `request_data` (optional) is the diff of what changed
8
+ * in this specific update. Most consumers only need `message`.
9
+ */
10
+ onMessageUpdate?: (message: MessageStructure, request_data?: JSONValue) => void;
11
+ onAggregate?: (aggregate: Aggregate) => void;
12
+ /**
13
+ * Reserved for future use. The composite gateway already routes by
14
+ * `channel.agent_id`, so this option is a no-op in v1. Pass it for
15
+ * forward-compatibility; it has no effect on the subscription.
16
+ */
17
+ sources?: string[];
18
+ }
19
+ /**
20
+ * Attach live-update handlers to a channel for the lifetime of the host
21
+ * component. Wraps `DooverDataProvider.subscribeToChannel` with ref-counted
22
+ * subscribe/unsubscribe and handler refs so changes to the handler closures
23
+ * don't re-trigger the underlying subscribe.
24
+ *
25
+ * Passing `undefined` (or an identifier without both fields) is a no-op.
26
+ */
27
+ export declare function useChannelSubscription(identifier: ChannelIdentifier | undefined, handlers: ChannelSubscriptionHandlers): void;
@@ -0,0 +1,30 @@
1
+ import { useEffect, useRef } from "react";
2
+ import { useDooverClient } from "./context.js";
3
+ /**
4
+ * Attach live-update handlers to a channel for the lifetime of the host
5
+ * component. Wraps `DooverDataProvider.subscribeToChannel` with ref-counted
6
+ * subscribe/unsubscribe and handler refs so changes to the handler closures
7
+ * don't re-trigger the underlying subscribe.
8
+ *
9
+ * Passing `undefined` (or an identifier without both fields) is a no-op.
10
+ */
11
+ export function useChannelSubscription(identifier, handlers) {
12
+ const client = useDooverClient();
13
+ const handlersRef = useRef(handlers);
14
+ handlersRef.current = handlers;
15
+ useEffect(() => {
16
+ if (!identifier?.agentId || !identifier?.channelName)
17
+ return;
18
+ const channel = { agent_id: identifier.agentId, name: identifier.channelName };
19
+ const off = client.gateway.subscribeToChannel(channel, {
20
+ onMessage: (msg) => handlersRef.current.onMessage?.(msg),
21
+ onMessageUpdate: (msg, rd) => handlersRef.current.onMessageUpdate?.(msg, rd),
22
+ onAggregate: (agg) => handlersRef.current.onAggregate?.(agg),
23
+ });
24
+ void client.gateway.connect();
25
+ return () => off();
26
+ // Identifier fields are the real deps; we intentionally leave `handlers`
27
+ // out because it's read through handlersRef.
28
+ // eslint-disable-next-line react-hooks/exhaustive-deps
29
+ }, [client, identifier?.agentId, identifier?.channelName]);
30
+ }
@@ -0,0 +1,10 @@
1
+ import type { DataClientStatus } from "../client/data-client.js";
2
+ /**
3
+ * Returns the live `DataClientStatus` for the client in context. Seeds with
4
+ * `client.getStatus()`, subscribes via `client.onStatusChange(...)` for the
5
+ * component's lifetime. Works for a `DooverClient` (single-source) or a
6
+ * `MultiplexClient` (rolled-up status with a `members` breakdown). Prefer this
7
+ * over `useConnectionState` for new code — it carries session, latency, last
8
+ * error and per-source state.
9
+ */
10
+ export declare function useClientStatus(): DataClientStatus;
@@ -0,0 +1,19 @@
1
+ import { useEffect, useState } from "react";
2
+ import { useDooverClient } from "./context.js";
3
+ /**
4
+ * Returns the live `DataClientStatus` for the client in context. Seeds with
5
+ * `client.getStatus()`, subscribes via `client.onStatusChange(...)` for the
6
+ * component's lifetime. Works for a `DooverClient` (single-source) or a
7
+ * `MultiplexClient` (rolled-up status with a `members` breakdown). Prefer this
8
+ * over `useConnectionState` for new code — it carries session, latency, last
9
+ * error and per-source state.
10
+ */
11
+ export function useClientStatus() {
12
+ const client = useDooverClient();
13
+ const [status, setStatus] = useState(() => client.getStatus());
14
+ useEffect(() => {
15
+ setStatus(client.getStatus());
16
+ return client.onStatusChange(setStatus);
17
+ }, [client]);
18
+ return status;
19
+ }