Skip to content

Commit d90fc94

Browse files
committed
feat(messages): typingIndicator option on markRead
Pins the BSR module to ff29794 (spectrum-whatsapp-business 2cab0fb), which added MarkReadRequest.typing_indicator. markRead() now accepts { typingIndicator: true } to show a typing bubble as a rider on the read receipt — Meta dismisses it after 25s or on the next send; there is no stop API. Bumps version to 0.2.1.
1 parent fb842c3 commit d90fc94

7 files changed

Lines changed: 84 additions & 6 deletions

File tree

buf.gen.yaml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
11
version: v2
22
inputs:
3-
# Pinned BSR commit (main @ spectrum-whatsapp-business 17e7e9c).
3+
# Pinned BSR commit (main @ spectrum-whatsapp-business 2cab0fb).
44
# To pick up schema changes: update the ref, run `bun run generate`, commit both.
5-
- module: buf.build/photon-hq/whatsapp:b218d3336d65421c8b215137797db344
5+
- module: buf.build/photon-hq/whatsapp:ff29794be4d4464b9ae22fd1c90d8229
66
plugins:
77
- local: protoc-gen-ts_proto
88
out: src/generated

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "@photon-ai/whatsapp-business",
3-
"version": "0.2.0",
3+
"version": "0.2.1",
44
"description": "TypeScript SDK for WhatsApp Business API via Spectrum",
55
"type": "module",
66
"exports": {

src/generated/photon/whatsapp/v1/message_service.ts

Lines changed: 28 additions & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

src/index.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -89,6 +89,7 @@ export type {
8989
ContactCardInput,
9090
InteractiveInput,
9191
LocationInput,
92+
MarkReadOptions,
9293
MediaInput,
9394
MessageContent,
9495
ReactionInput,

src/resources/messages.ts

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ import type { MessageServiceClient } from "../transport/grpc-client.ts";
33
import { mapSendParams } from "../transport/mapper.ts";
44
import type { RequestOptions } from "../types/client.ts";
55
import type {
6+
MarkReadOptions,
67
SendMessageParams,
78
SendMessageResult,
89
} from "../types/messages.ts";
@@ -32,9 +33,15 @@ export class MessagesResource {
3233
}
3334
}
3435

35-
async markRead(messageId: string, options?: RequestOptions): Promise<void> {
36+
async markRead(
37+
messageId: string,
38+
options?: RequestOptions & MarkReadOptions
39+
): Promise<void> {
3640
try {
37-
await this._client.markRead({ messageId }, { signal: options?.signal });
41+
await this._client.markRead(
42+
{ messageId, typingIndicator: options?.typingIndicator ?? false },
43+
{ signal: options?.signal }
44+
);
3845
} catch (err) {
3946
throw fromGrpcError(err);
4047
}

src/types/messages.ts

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -151,3 +151,17 @@ export interface SendMessageResult {
151151
readonly messageId: string;
152152
readonly messageStatus: string;
153153
}
154+
155+
// ---------------------------------------------------------------------------
156+
// Mark read options
157+
// ---------------------------------------------------------------------------
158+
159+
export interface MarkReadOptions {
160+
/**
161+
* Also display a typing indicator in the chat. Meta dismisses it after
162+
* 25 seconds or when the business sends a message, whichever comes first —
163+
* there is no explicit "stop typing" call. The message being marked read
164+
* must be an inbound message.
165+
*/
166+
readonly typingIndicator?: boolean;
167+
}

tests/unit/messages.test.ts

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
import { describe, expect, it } from "bun:test";
2+
import type { MarkReadRequest } from "../../src/generated/photon/whatsapp/v1/message_service.ts";
3+
import { MessagesResource } from "../../src/resources/messages.ts";
4+
import type { MessageServiceClient } from "../../src/transport/grpc-client.ts";
5+
6+
function makeResource() {
7+
const calls: MarkReadRequest[] = [];
8+
const client = {
9+
markRead: (request: MarkReadRequest) => {
10+
calls.push(request);
11+
return Promise.resolve({});
12+
},
13+
} as unknown as MessageServiceClient;
14+
return { messages: new MessagesResource(client), calls };
15+
}
16+
17+
describe("MessagesResource.markRead", () => {
18+
it("sends a plain read receipt by default", async () => {
19+
const { messages, calls } = makeResource();
20+
await messages.markRead("wamid.abc");
21+
expect(calls).toEqual([{ messageId: "wamid.abc", typingIndicator: false }]);
22+
});
23+
24+
it("passes typingIndicator through when requested", async () => {
25+
const { messages, calls } = makeResource();
26+
await messages.markRead("wamid.abc", { typingIndicator: true });
27+
expect(calls).toEqual([{ messageId: "wamid.abc", typingIndicator: true }]);
28+
});
29+
});

0 commit comments

Comments
 (0)