ebchat_core 1.1.1
ebchat_core: ^1.1.1 copied to clipboard
Pure-Dart client for the ebchat first-party livechat protocol: REST client, conversation controller and Pusher/Soketi realtime transport. No Flutter dependency. Most apps want the ebchat package, whic [...]
Changelog #
1.1.1 #
- Docs: the
LivechatApiClient.baseUrlexample pointed athttps://api.enable.tech, which is the Enable platform API, not the ebchat gateway. Calls sent there fail with a confusing401 "Token is Not formed well"from a different service. The gateway ishttps://ebchat-backend.e-butler.com.
1.1.0 #
- Delivery acks both ways: the controller acknowledges the newest inbound operator/bot message (debounced, cumulative — one ack per burst) so the operator's dashboard tick reflects that the guest's client actually has it.
LivechatMessage: newdeliveredTolist anddeliveryStatusgetter with theLivechatDeliveryStatusenum (pending / sent / delivered / read / failed) for WhatsApp-style tick marks. Optimistic messages (local placeholder ids) reportpending;failedis client-local, set when a send doesn't go through.- Reconnection: new
realtimeFactoryonEbchatConversationController— transports are single-use, so a factory is what makes reconnect possible at all. On socket death the controller flips to fast polling, retries with exponential backoff, and runs a 30 s safety poll even while connected (zombie sockets die without an onDone). NewLivechatConnectionState(connected / reconnecting / pollingOnly) exposed asconnectionState/currentConnectionState, plusresync()for app-resume refetch + socket revival. - Failed-send retry: network failures no longer delete the optimistic
bubble — the message is kept, marked
sendFailed, andretry(clientId)re-sends the exact same request (same idempotency key, so a duplicate is impossible even if the original landed). Only 409conversation_closedstill removes the bubble, since a retry can never succeed there. - Silent token refresh: new
onAuthExpiredcallback — on an expired-token failure the controller re-mints once (single-flight across concurrent expiries), retries the failed call, and rebuilds the realtime socket on the new token.setTypingbecame best-effort (a lost typing signal costs an indicator, never a message). - Both error-envelope shapes parsed: the protocol's
{ error: { code } }AND the NestJS flat{ statusCode, message, error }the gateway actually sends (machine code riding inmessage) — without this,isTokenExpired/isConversationClosednever matched real responses and silent re-session could never trigger. - No-op ingest detection: the polling refetch compares what the UI renders from (text, receipts, attachment actions, failure state) and skips the emit when nothing changed — the transcript no longer rebuilds every 5 seconds for no visible change.
LivechatMessage.isNote+ the controller dropsisNotemessages at ingest: internal operator notes are never surfaced to a guest, even if a gateway sends one.- Pagination offset fix: the offset now advances by the raw page size whenever
the server reports more (
hasMore), so a page thinned by note-filtering no longer refetches the same window forever. message.updatedrealtime events now applyseenBy/deliveredTodeltas (both wire shapes), so tick marks update live instead of only on refetch. Updates apply viacopyWithand preserve every field the delta doesn't name — a delivery ack on an order message used to erase the receipt.
1.0.0 #
- Initial
ebchat_core: pure-Dart client for the livechat protocol v1. - Includes the Pusher/Soketi realtime transport (
PusherConfig,PusherLivechatRealtime) — still no Flutter dependency. - Models: bootstrap config, session, conversation, message, attachment, choice action, location, send request.
LivechatApiClientcovering all/livechat/v1REST endpoints + typedLivechatApiException(conversation-closed / token-expired helpers).EbchatConversationController: message state, optimistic send with clientId de-dupe, pagination, read/typing, and live updates via a pluggableLivechatRealtimetransport or built-in polling.SessionStore(in-memory default) for guest-session persistence.