ab-ecosystem-cpass 1.0.0 → 1.0.6

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 (86) hide show
  1. package/README.md +121 -21
  2. package/dist/client.d.ts +38 -0
  3. package/dist/client.js +49 -5
  4. package/dist/client.js.map +1 -1
  5. package/dist/http.d.ts +15 -0
  6. package/dist/http.js +21 -1
  7. package/dist/http.js.map +1 -1
  8. package/dist/index.d.ts +11 -0
  9. package/dist/index.js +24 -1
  10. package/dist/index.js.map +1 -1
  11. package/dist/internal/bytes.d.ts +38 -0
  12. package/dist/internal/bytes.js +84 -0
  13. package/dist/internal/bytes.js.map +1 -0
  14. package/dist/internal/device.d.ts +24 -0
  15. package/dist/internal/device.js +91 -0
  16. package/dist/internal/device.js.map +1 -0
  17. package/dist/internal/md5.d.ts +4 -0
  18. package/dist/internal/md5.js +109 -0
  19. package/dist/internal/md5.js.map +1 -0
  20. package/dist/internal/receiver-file.d.ts +106 -0
  21. package/dist/internal/receiver-file.js +128 -0
  22. package/dist/internal/receiver-file.js.map +1 -0
  23. package/dist/realtime/client.d.ts +85 -0
  24. package/dist/realtime/client.js +126 -0
  25. package/dist/realtime/client.js.map +1 -0
  26. package/dist/realtime/events.d.ts +147 -0
  27. package/dist/realtime/events.js +3 -0
  28. package/dist/realtime/events.js.map +1 -0
  29. package/dist/realtime/inbox.d.ts +173 -0
  30. package/dist/realtime/inbox.js +263 -0
  31. package/dist/realtime/inbox.js.map +1 -0
  32. package/dist/realtime/index.d.ts +16 -0
  33. package/dist/realtime/index.js +37 -0
  34. package/dist/realtime/index.js.map +1 -0
  35. package/dist/resources/audience/contacts.d.ts +19 -3
  36. package/dist/resources/audience/contacts.js +19 -3
  37. package/dist/resources/audience/contacts.js.map +1 -1
  38. package/dist/resources/audience/inbox-media.d.ts +92 -0
  39. package/dist/resources/audience/inbox-media.js +127 -0
  40. package/dist/resources/audience/inbox-media.js.map +1 -0
  41. package/dist/resources/audience/notifications.d.ts +171 -0
  42. package/dist/resources/audience/notifications.js +215 -0
  43. package/dist/resources/audience/notifications.js.map +1 -0
  44. package/dist/resources/audience/scheduled-messages.d.ts +234 -0
  45. package/dist/resources/audience/scheduled-messages.js +259 -0
  46. package/dist/resources/audience/scheduled-messages.js.map +1 -0
  47. package/dist/resources/campaign-audience.d.ts +132 -0
  48. package/dist/resources/campaign-audience.js +224 -0
  49. package/dist/resources/campaign-audience.js.map +1 -0
  50. package/dist/resources/campaign-report-exports.d.ts +14 -0
  51. package/dist/resources/campaign-report-exports.js +28 -0
  52. package/dist/resources/campaign-report-exports.js.map +1 -0
  53. package/dist/resources/campaign-reports.d.ts +15 -0
  54. package/dist/resources/campaign-reports.js +25 -0
  55. package/dist/resources/campaign-reports.js.map +1 -0
  56. package/dist/resources/campaigns.d.ts +239 -0
  57. package/dist/resources/campaigns.js +300 -0
  58. package/dist/resources/campaigns.js.map +1 -0
  59. package/dist/types/audience.d.ts +93 -1
  60. package/dist/types/campaign.d.ts +229 -0
  61. package/dist/types/campaign.js +3 -0
  62. package/dist/types/campaign.js.map +1 -0
  63. package/dist/types/contact-filter.d.ts +3 -2
  64. package/dist/types/contact-filter.js +3 -2
  65. package/dist/types/contact-filter.js.map +1 -1
  66. package/dist/types/inbox.d.ts +391 -0
  67. package/dist/types/inbox.js +16 -0
  68. package/dist/types/inbox.js.map +1 -0
  69. package/dist/types/index.d.ts +3 -0
  70. package/dist/types/index.js +5 -0
  71. package/dist/types/index.js.map +1 -1
  72. package/dist/types/scheduled-message.d.ts +221 -0
  73. package/dist/types/scheduled-message.js +16 -0
  74. package/dist/types/scheduled-message.js.map +1 -0
  75. package/docs/audience/contacts.md +34 -4
  76. package/docs/audience/notifications.md +263 -0
  77. package/docs/audience/scheduled-messages.md +557 -0
  78. package/docs/campaign/campaigns.md +489 -0
  79. package/docs/contact-filter.md +2 -1
  80. package/docs/inbox/chats.md +356 -0
  81. package/docs/inbox/connection.md +171 -0
  82. package/docs/inbox/media.md +202 -0
  83. package/docs/inbox/messages.md +338 -0
  84. package/docs/inbox/referrals.md +72 -0
  85. package/docs/inbox/sessions.md +74 -0
  86. package/package.json +28 -2
@@ -0,0 +1,126 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.InboxClient = void 0;
4
+ const socket_io_client_1 = require("socket.io-client");
5
+ const errors_1 = require("../errors");
6
+ const DEFAULT_TIMEOUT = 20_000;
7
+ /**
8
+ * The live-chat inbox over a socket.
9
+ *
10
+ * Requests are promises: each emit carries an acknowledgement callback, so two
11
+ * concurrent reads of different threads cannot be confused for one another. The
12
+ * server also emits replies under the request's own event name for older clients
13
+ * -- {@link InboxClient.on} sees those too, which is why a handler for
14
+ * `chat.action` receives both your own actions and other agents'.
15
+ *
16
+ * Credentials travel in `auth`, not in a header: a browser cannot set headers on
17
+ * a WebSocket upgrade, so a header-based handshake only works for as long as the
18
+ * connection stays on long-polling.
19
+ */
20
+ class InboxClient {
21
+ options;
22
+ socket;
23
+ timeout;
24
+ /**
25
+ * The uploader this client was built with, if any.
26
+ *
27
+ * Read by `messages.sendMedia` when it is handed a file rather than a link.
28
+ */
29
+ get uploadMedia() {
30
+ return this.options.uploadMedia;
31
+ }
32
+ constructor(options) {
33
+ this.options = options;
34
+ if (!options.url)
35
+ throw new errors_1.CrmConfigError('An inbox socket url is required');
36
+ if (!options.clientId)
37
+ throw new errors_1.CrmConfigError('A clientId is required');
38
+ this.timeout = options.timeout ?? DEFAULT_TIMEOUT;
39
+ this.socket = (0, socket_io_client_1.io)(options.url, {
40
+ path: options.path ?? '/socket.io',
41
+ autoConnect: options.autoConnect ?? true,
42
+ transports: ['websocket', 'polling'],
43
+ auth: (cb) => {
44
+ void this.credentials().then(cb);
45
+ },
46
+ ...options.socketOptions,
47
+ });
48
+ }
49
+ /** Resolved per connect, so a reconnect never reuses an expired token. */
50
+ async credentials() {
51
+ const token = typeof this.options.token === 'function' ? await this.options.token() : this.options.token;
52
+ return { token, client_id: this.options.clientId };
53
+ }
54
+ /** The underlying socket, for lifecycle events and anything not wrapped here. */
55
+ get raw() {
56
+ return this.socket;
57
+ }
58
+ get connected() {
59
+ return this.socket.connected;
60
+ }
61
+ connect() {
62
+ this.socket.connect();
63
+ return this;
64
+ }
65
+ disconnect() {
66
+ this.socket.disconnect();
67
+ return this;
68
+ }
69
+ /** Resolves once connected, or rejects with the handshake's reason. */
70
+ ready() {
71
+ if (this.socket.connected)
72
+ return Promise.resolve();
73
+ return new Promise((resolve, reject) => {
74
+ const onConnect = () => {
75
+ this.socket.off('connect_error', onError);
76
+ resolve();
77
+ };
78
+ const onError = (err) => {
79
+ this.socket.off('connect', onConnect);
80
+ reject(new errors_1.CrmApiError(401, 'unauthorized', err.message));
81
+ };
82
+ this.socket.once('connect', onConnect);
83
+ this.socket.once('connect_error', onError);
84
+ });
85
+ }
86
+ /**
87
+ * Sends one request and waits for its answer.
88
+ *
89
+ * A refusal rejects with a {@link CrmApiError} carrying the same code and status
90
+ * the REST API would have returned, so one error path covers both transports.
91
+ */
92
+ request(event, payload) {
93
+ return new Promise((resolve, reject) => {
94
+ this.socket
95
+ .timeout(this.timeout)
96
+ .emit(event, payload, (err, ack) => {
97
+ if (err) {
98
+ reject(new errors_1.CrmApiError(504, 'timeout', `${event} did not answer in ${this.timeout}ms`));
99
+ return;
100
+ }
101
+ if (!ack?.ok) {
102
+ const error = ack?.error;
103
+ reject(new errors_1.CrmApiError(error?.status ?? 500, error?.code ?? 'internal_error', error?.message ?? `${event} failed`, error?.details));
104
+ return;
105
+ }
106
+ resolve(ack.data);
107
+ });
108
+ });
109
+ }
110
+ /**
111
+ * Listens for a pushed event. Returns the unsubscribe function, so a component
112
+ * can tear its own listener down without knowing what else is attached.
113
+ */
114
+ on(event, handler) {
115
+ this.socket.on(event, handler);
116
+ return () => {
117
+ this.socket.off(event, handler);
118
+ };
119
+ }
120
+ /** Fires once, then unsubscribes. */
121
+ once(event, handler) {
122
+ this.socket.once(event, handler);
123
+ }
124
+ }
125
+ exports.InboxClient = InboxClient;
126
+ //# sourceMappingURL=client.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"client.js","sourceRoot":"","sources":["../../src/realtime/client.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,147 @@
1
+ import type { AssignBotPayload, BulkTransferResult, Chat, ChatActionPayload, ChatActionResult, ChatList, ChatSession, CtwaReferral, DeleteMessagePayload, FetchMessagePayload, ListChatsPayload, Message, MessageDeleteResult, MessageStatusUpdate, RetryDownloadPayload, SendMessagePayload, UpdateChatPayload, UpdateChatResult } from '../types/inbox';
2
+ /** What a rejected event sends back. The HTTP error body, field for field. */
3
+ export interface InboxError {
4
+ /** The event that failed. */
5
+ event: string;
6
+ code: string;
7
+ message: string;
8
+ status: number;
9
+ details?: unknown;
10
+ requestId: string;
11
+ }
12
+ /** The acknowledgement a request-style event resolves with. */
13
+ export type InboxAck<T> = {
14
+ ok: true;
15
+ data: T;
16
+ } | {
17
+ ok: false;
18
+ error: InboxError;
19
+ };
20
+ /**
21
+ * Every event the client sends, with its payload and what it answers.
22
+ *
23
+ * The server replies two ways, so both generations of client work: through the
24
+ * acknowledgement callback when one is passed, and by emitting the same event
25
+ * name back, which is what the original inbox listens for.
26
+ */
27
+ export interface InboxRequests {
28
+ ping: {
29
+ payload: unknown;
30
+ result: unknown;
31
+ };
32
+ 'contact.list': {
33
+ payload: ListChatsPayload;
34
+ result: ChatList;
35
+ };
36
+ 'contact.fetch': {
37
+ payload: {
38
+ id: string;
39
+ };
40
+ result: Chat;
41
+ };
42
+ 'contact.update': {
43
+ payload: UpdateChatPayload;
44
+ result: UpdateChatResult;
45
+ };
46
+ 'contact.done': {
47
+ payload: {
48
+ id: string;
49
+ isEnded?: boolean;
50
+ };
51
+ result: ChatActionResult;
52
+ };
53
+ 'contact.bot_assign': {
54
+ payload: AssignBotPayload;
55
+ result: {
56
+ success: boolean;
57
+ id: string;
58
+ };
59
+ };
60
+ 'chat.action': {
61
+ payload: ChatActionPayload;
62
+ result: ChatActionResult | BulkTransferResult;
63
+ };
64
+ 'message.list': {
65
+ payload: {
66
+ id: string;
67
+ limit?: number;
68
+ last_message_id?: string;
69
+ };
70
+ result: Message[];
71
+ };
72
+ 'message.fetch': {
73
+ payload: FetchMessagePayload;
74
+ result: Message;
75
+ };
76
+ 'message.send': {
77
+ payload: SendMessagePayload;
78
+ result: Message;
79
+ };
80
+ 'message.delete': {
81
+ payload: DeleteMessagePayload;
82
+ result: MessageDeleteResult;
83
+ };
84
+ 'message.retry_download': {
85
+ payload: RetryDownloadPayload;
86
+ result: Message;
87
+ };
88
+ 'ctwa.list': {
89
+ payload: {
90
+ id: string;
91
+ limit?: number;
92
+ };
93
+ result: CtwaReferral[];
94
+ };
95
+ 'chat_session.list': {
96
+ payload: {
97
+ id: string;
98
+ channel?: string;
99
+ };
100
+ result: ChatSession[];
101
+ };
102
+ }
103
+ export type InboxRequestName = keyof InboxRequests;
104
+ /**
105
+ * Events the server pushes without being asked.
106
+ *
107
+ * `chat.action` and the `message.*` names appear here as well as in the request
108
+ * map on purpose: an archive performed by another agent arrives under the same
109
+ * name and shape as one you asked for, so a client needs only one handler per
110
+ * kind of change rather than one per cause.
111
+ */
112
+ export interface InboxPushes {
113
+ /**
114
+ * A message arrived, or one that was sent now exists as a stored row.
115
+ *
116
+ * The second case is how an optimistic bubble is replaced: `message.send`
117
+ * answered with a queue id, and this carries the same message with the
118
+ * provider's real `message_id`.
119
+ */
120
+ 'message.received': Message;
121
+ /**
122
+ * The same row as `message.received`, in the shape it is stored in.
123
+ *
124
+ * Kept because the inbox this replaced listened for one name, `message.send`,
125
+ * for both its own reply and the row that followed. New clients should use
126
+ * `message.received`, which is mapped; this one carries `_id` and `user` as the
127
+ * database holds them.
128
+ */
129
+ 'message.send': Record<string, unknown>;
130
+ /** A delivery state moved: sent, delivered, read, failed. */
131
+ 'message.status': MessageStatusUpdate;
132
+ /** A chat changed: unread count, assignment, automation, tags. */
133
+ 'chat.action': ChatActionResult;
134
+ /**
135
+ * A contact wrote in for the first time, so a chat row appeared.
136
+ *
137
+ * The stored contact document, not a mapped `Chat` -- it comes from the service
138
+ * that created it.
139
+ */
140
+ 'contact.received': Record<string, unknown>;
141
+ 'message.delete': MessageDeleteResult;
142
+ 'message.retry_download': Message;
143
+ 'contact.done': ChatActionResult;
144
+ /** An event was refused. Carries the event name that failed. */
145
+ error: InboxError;
146
+ }
147
+ export type InboxPushName = keyof InboxPushes;
@@ -0,0 +1,3 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ //# sourceMappingURL=events.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"events.js","sourceRoot":"","sources":["../../src/realtime/events.ts"],"names":[],"mappings":""}
@@ -0,0 +1,173 @@
1
+ import type { AssignBotPayload, BulkTransferResult, Chat, ChatActionPayload, ChatActionResult, ChatBlockUpdate, ChatList, ChatSession, CtwaReferral, ListChatsPayload, Message, MessageDeleteResult, SendMediaPayload, SendMessagePayload, UpdateChatPayload, UpdateChatResult } from '../types/inbox';
2
+ import { InboxClient, type InboxClientOptions } from './client';
3
+ /** The chat list and the thirteen actions that change one. */
4
+ export declare class InboxChats {
5
+ private readonly client;
6
+ constructor(client: InboxClient);
7
+ /**
8
+ * One page of the inbox, ordered by last activity.
9
+ *
10
+ * `contact.list` · scope `contacts:read`
11
+ *
12
+ * The reply's `filter` is the filter that was *applied* -- a team member
13
+ * without the unassigned permission asking for `all` is narrowed to `me` -- and
14
+ * `nextPage` is the cursor for the page after this one, or `null` at the end.
15
+ */
16
+ list(payload?: ListChatsPayload): Promise<ChatList>;
17
+ /**
18
+ * One chat, and a subscription to it: messages and state changes for this
19
+ * thread reach the socket from here on without asking again.
20
+ *
21
+ * `contact.fetch` · scope `contacts:read`
22
+ */
23
+ get(id: string): Promise<Chat>;
24
+ /** Any action, for callers holding a payload they built elsewhere. */
25
+ act(payload: ChatActionPayload): Promise<ChatActionResult | BulkTransferResult>;
26
+ /** Trashes the chat. It leaves every inbox view; the contact row stays. */
27
+ delete(chat: string): Promise<ChatActionResult>;
28
+ /** Assigns the chat to one member and flags it unread for them. */
29
+ transfer(chat: string, member: string): Promise<ChatActionResult>;
30
+ archive(chat: string): Promise<ChatActionResult>;
31
+ unarchive(chat: string): Promise<ChatActionResult>;
32
+ /** Flips one or more block flags. Flags left out keep their current value. */
33
+ block(chat: string, update: ChatBlockUpdate): Promise<ChatActionResult>;
34
+ /** Clears the unread counter and the by-hand unread flag. */
35
+ markAsRead(chat: string): Promise<ChatActionResult>;
36
+ markAsUnread(chat: string): Promise<ChatActionResult>;
37
+ /** Detaches the flow and holds automation for `chat_metadata.pause_duration`. */
38
+ pauseAutomation(chat: string): Promise<ChatActionResult>;
39
+ resumeAutomation(chat: string): Promise<ChatActionResult>;
40
+ /** Closes the chat and detaches the flow, leaving the assignment alone. */
41
+ close(chat: string): Promise<ChatActionResult>;
42
+ /** Marks the chat done, unassigns it and detaches the flow. */
43
+ done(chat: string, isEnded?: boolean): Promise<ChatActionResult>;
44
+ /** Re-arms the automation pause with a new duration, in seconds. */
45
+ pauseTimer(chat: string, duration: number): Promise<ChatActionResult>;
46
+ /** Replaces the chat's tags outright. */
47
+ updateTags(chat: string, tags: string[]): Promise<ChatActionResult>;
48
+ /**
49
+ * Moves every chat held by one member -- or the unassigned queue -- to another
50
+ * member or a team. Capped at 500 chats per call; each moved chat is broadcast
51
+ * individually as a `transfer`.
52
+ */
53
+ bulkTransfer(payload: Omit<Extract<ChatActionPayload, {
54
+ action: 'bulk_transfer';
55
+ }>, 'action'>): Promise<BulkTransferResult>;
56
+ /** The narrower action set, answering with the metadata alone. */
57
+ update(payload: UpdateChatPayload): Promise<UpdateChatResult>;
58
+ /**
59
+ * Attaches a flow to the chat, or hands the chat to the bot server to place.
60
+ *
61
+ * `contact.bot_assign` · scope `contacts:write`
62
+ */
63
+ assignBot(payload: AssignBotPayload): Promise<{
64
+ success: boolean;
65
+ id: string;
66
+ }>;
67
+ private single;
68
+ }
69
+ /** Reading, sending and removing messages in one thread. */
70
+ export declare class InboxMessages {
71
+ private readonly client;
72
+ constructor(client: InboxClient);
73
+ /**
74
+ * One page of a thread, oldest-first, and a subscription to it.
75
+ *
76
+ * `message.list` · scope `messages:read`
77
+ *
78
+ * Pass the `id` of the oldest message you hold as `last_message_id` to walk
79
+ * backwards through the history.
80
+ */
81
+ list<C extends Message['content'] = Message['content']>(id: string, options?: {
82
+ limit?: number;
83
+ last_message_id?: string;
84
+ }): Promise<Message<C>[]>;
85
+ /** One message by its provider id -- a `wamid`, not the document id. */
86
+ get<C extends Message['content'] = Message['content']>(messageId: string): Promise<Message<C>>;
87
+ /**
88
+ * Sends a message and gets the bubble to draw back immediately.
89
+ *
90
+ * `message.send` · scope `messages:write`
91
+ *
92
+ * The returned message carries a queue id in `message_id`, not a provider id:
93
+ * nothing has been written yet. The stored row arrives moments later as a
94
+ * `message.received` push, with the provider's id in its place -- correlate on
95
+ * the queue id you got back here, not on the final `message_id`.
96
+ *
97
+ * Sending by hand also takes the conversation off its bot, which arrives as a
98
+ * `chat.action` with `action: 'pause_automation'`.
99
+ */
100
+ send<C extends Message['content'] = Message['content']>(payload: SendMessagePayload): Promise<Message<C>>;
101
+ /**
102
+ * Sends media, uploading it first if you hand over a file.
103
+ *
104
+ * `message.send` · scope `messages:write`
105
+ *
106
+ * Two ways in. With a `link` -- from `crm.inboxMedia.upload()`, or any publicly
107
+ * fetchable URL -- this is `send()` with the content assembled for you:
108
+ *
109
+ * ```ts
110
+ * const link = await crm.inboxMedia.upload(file, { kind: 'image' });
111
+ * await inbox.messages.sendMedia({ channel, contact, kind: 'image', link, caption: 'Your order' });
112
+ * ```
113
+ *
114
+ * With a `file`, it uploads and sends in one call -- which needs an uploader,
115
+ * because a socket cannot presign. Pass `uploadMedia` when constructing the
116
+ * `Inbox`:
117
+ *
118
+ * ```ts
119
+ * const inbox = new Inbox({ url, clientId, token, uploadMedia: crm.inboxMedia.upload.bind(crm.inboxMedia) });
120
+ * await inbox.messages.sendMedia({ channel, contact, kind: 'image', file, caption: 'Your order' });
121
+ * ```
122
+ *
123
+ * The link is what gets stored on the message, and it does not expire, so the
124
+ * thread still renders the media months later.
125
+ *
126
+ * `filename` is worth setting on a `document`: it is what the recipient sees in
127
+ * their chat, where a bare key would otherwise appear.
128
+ */
129
+ sendMedia<C extends Message['content'] = Message['content']>(payload: SendMediaPayload): Promise<Message<C>>;
130
+ /** Uploads a file through the hook the client was given, or explains its absence. */
131
+ private resolve;
132
+ /** Removes one message from a thread, for everyone with it open. */
133
+ delete(contactId: string, messageId: string): Promise<MessageDeleteResult>;
134
+ /**
135
+ * Re-fetches media whose first download failed. Inbound media only -- an
136
+ * outbound attachment was ours to begin with.
137
+ *
138
+ * `message.retry_download` · scope `messages:write`
139
+ */
140
+ retryDownload<C extends Message['content'] = Message['content']>(messageId: string): Promise<Message<C>>;
141
+ }
142
+ /**
143
+ * The live-chat inbox.
144
+ *
145
+ * ```ts
146
+ * const inbox = new Inbox({ url: 'https://inbox.example.com', clientId, token });
147
+ * await inbox.ready();
148
+ *
149
+ * const { contacts } = await inbox.chats.list({ filter: { assignment: 'me', unread: 'unread' } });
150
+ * inbox.on('message.received', (message) => append(message));
151
+ * ```
152
+ */
153
+ export declare class Inbox extends InboxClient {
154
+ readonly chats: InboxChats;
155
+ readonly messages: InboxMessages;
156
+ constructor(options: InboxClientOptions);
157
+ /**
158
+ * Where a lead came from: the click-to-WhatsApp ad payloads on one contact.
159
+ *
160
+ * `ctwa.list` · scope `contacts:read`
161
+ */
162
+ referrals(contactId: string, limit?: number): Promise<CtwaReferral[]>;
163
+ /**
164
+ * A contact's reply windows, one per channel they have written from. Read these
165
+ * to tell whether a free-form reply is still allowed on a channel or whether
166
+ * the agent has to start from a template.
167
+ *
168
+ * `chat_session.list` · scope `contacts:read`
169
+ */
170
+ sessions(contactId: string, channel?: string): Promise<ChatSession[]>;
171
+ /** Round-trips the payload. Useful for checking the connection is live. */
172
+ ping<T>(payload: T): Promise<T>;
173
+ }