@textbee/sdk 0.0.3 → 0.1.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.
- package/README.md +22 -6
- package/dist/index.cjs +43 -14
- package/dist/index.d.cts +81 -16
- package/dist/index.d.ts +81 -16
- package/dist/index.js +43 -14
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -71,17 +71,33 @@ await textbee.setDefaultDevice(deviceId)
|
|
|
71
71
|
|
|
72
72
|
## Messages and delivery status
|
|
73
73
|
|
|
74
|
+
History is account-level: one call covers every device, and `deviceIds` narrows it.
|
|
75
|
+
|
|
74
76
|
```js
|
|
75
|
-
// Paginated history, filterable and searchable
|
|
76
|
-
const { data, meta } = await textbee.getMessages(
|
|
77
|
-
|
|
77
|
+
// Paginated history across the whole account, filterable and searchable
|
|
78
|
+
const { data, meta } = await textbee.getMessages({
|
|
79
|
+
direction: 'received', // 'all' | 'sent' | 'received'
|
|
80
|
+
deviceIds: [deviceId], // omit for every device
|
|
81
|
+
status: 'delivered', // delivery state; direction=sent + status=failed lists failed sends
|
|
82
|
+
search: 'invoice',
|
|
83
|
+
from: '2026-08-01', // dates are UTC; datetimes need an explicit timezone
|
|
84
|
+
to: '2026-09-01T00:00:00Z', // exclusive, so windows never double-count
|
|
78
85
|
page: 1,
|
|
79
86
|
limit: 50,
|
|
80
|
-
search: 'invoice',
|
|
81
87
|
})
|
|
82
88
|
|
|
83
|
-
//
|
|
84
|
-
data.filter((m) => m.
|
|
89
|
+
// direction on each message is lowercase and feeds straight back into filters
|
|
90
|
+
data.filter((m) => m.direction === 'received')
|
|
91
|
+
|
|
92
|
+
// Which recipients of a bulk send failed: filter by the batch a send returned
|
|
93
|
+
const { smsBatchId } = await textbee.sendSms({ recipients, message })
|
|
94
|
+
const failed = await textbee.getMessages({ smsBatchId, status: 'failed' })
|
|
95
|
+
|
|
96
|
+
// Drain everything matching a filter: iterateMessages follows the
|
|
97
|
+
// pagination cursor for you until there is nothing left
|
|
98
|
+
for await (const message of textbee.iterateMessages({ direction: 'received', order: 'asc' })) {
|
|
99
|
+
console.log(message.sender, message.message)
|
|
100
|
+
}
|
|
85
101
|
|
|
86
102
|
// A single message and its current status
|
|
87
103
|
const sms = await textbee.getSms(deviceId, smsId)
|
package/dist/index.cjs
CHANGED
|
@@ -42,7 +42,7 @@ var TextbeeError = class extends Error {
|
|
|
42
42
|
|
|
43
43
|
// src/client.ts
|
|
44
44
|
var DEFAULT_BASE_URL = "https://api.textbee.dev/api/v1";
|
|
45
|
-
var CLIENT_ID = `textbee-js/${"0.0
|
|
45
|
+
var CLIENT_ID = `textbee-js/${"0.1.0"}`;
|
|
46
46
|
var Textbee = class {
|
|
47
47
|
#apiKey;
|
|
48
48
|
#baseUrl;
|
|
@@ -99,20 +99,46 @@ var Textbee = class {
|
|
|
99
99
|
);
|
|
100
100
|
return payload.data;
|
|
101
101
|
}
|
|
102
|
-
/**
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
102
|
+
/**
|
|
103
|
+
* Page through the account's sent and received messages, filtered by
|
|
104
|
+
* device, batch, direction, status, text, and time range.
|
|
105
|
+
*/
|
|
106
|
+
async getMessages(options = {}) {
|
|
107
|
+
return await this.#request("GET", "/gateway/messages", {
|
|
108
|
+
query: {
|
|
109
|
+
deviceIds: options.deviceIds?.length ? options.deviceIds.join(",") : void 0,
|
|
110
|
+
smsBatchId: options.smsBatchId,
|
|
111
|
+
direction: options.direction,
|
|
112
|
+
status: options.status,
|
|
113
|
+
search: options.search,
|
|
114
|
+
from: toIsoString(options.from),
|
|
115
|
+
to: toIsoString(options.to),
|
|
116
|
+
order: options.order,
|
|
117
|
+
page: options.page,
|
|
118
|
+
limit: options.limit,
|
|
119
|
+
cursor: options.cursor
|
|
114
120
|
}
|
|
115
|
-
);
|
|
121
|
+
});
|
|
122
|
+
}
|
|
123
|
+
/**
|
|
124
|
+
* Iterate every message matching the filters, following the pagination
|
|
125
|
+
* cursor until the end. Use `order: 'asc'` with a `from` bound to drain
|
|
126
|
+
* forward when polling; keep the last message's `createdAt` (or track
|
|
127
|
+
* `meta.nextCursor` via `getMessages`) to resume the next poll.
|
|
128
|
+
*
|
|
129
|
+
* ```ts
|
|
130
|
+
* for await (const message of textbee.iterateMessages({ direction: 'received' })) {
|
|
131
|
+
* handle(message)
|
|
132
|
+
* }
|
|
133
|
+
* ```
|
|
134
|
+
*/
|
|
135
|
+
async *iterateMessages(options = {}) {
|
|
136
|
+
let page = await this.getMessages(options);
|
|
137
|
+
yield* page.data;
|
|
138
|
+
while (page.meta.nextCursor) {
|
|
139
|
+
page = await this.getMessages({ ...options, cursor: page.meta.nextCursor });
|
|
140
|
+
yield* page.data;
|
|
141
|
+
}
|
|
116
142
|
}
|
|
117
143
|
/** Fetch a single message, including its delivery status. */
|
|
118
144
|
async getSms(deviceId, smsId) {
|
|
@@ -158,6 +184,9 @@ var Textbee = class {
|
|
|
158
184
|
return payload;
|
|
159
185
|
}
|
|
160
186
|
};
|
|
187
|
+
function toIsoString(value) {
|
|
188
|
+
return value instanceof Date ? value.toISOString() : value;
|
|
189
|
+
}
|
|
161
190
|
async function readBody(response) {
|
|
162
191
|
const text = await response.text();
|
|
163
192
|
if (!text) {
|
package/dist/index.d.cts
CHANGED
|
@@ -54,16 +54,42 @@ interface SendSmsImmediateResponse {
|
|
|
54
54
|
* with `'smsBatchId' in result` before reading batch fields.
|
|
55
55
|
*/
|
|
56
56
|
type SendSmsResponse = SendSmsQueuedResponse | SendSmsImmediateResponse;
|
|
57
|
-
interface
|
|
57
|
+
interface ListMessagesOptions {
|
|
58
|
+
/** Only messages from these devices. Omit for every device on the account. */
|
|
59
|
+
deviceIds?: string[];
|
|
60
|
+
/**
|
|
61
|
+
* Only messages from this batch, using the `smsBatchId` a send returns.
|
|
62
|
+
* Combine with `status: 'failed'` to list the recipients that failed.
|
|
63
|
+
*/
|
|
64
|
+
smsBatchId?: string;
|
|
58
65
|
/** Filter by direction. Defaults to `all`. */
|
|
59
|
-
|
|
60
|
-
/**
|
|
66
|
+
direction?: 'all' | 'sent' | 'received';
|
|
67
|
+
/** Filter by delivery state, e.g. `failed` to list sends that failed. */
|
|
68
|
+
status?: 'pending' | 'dispatched' | 'sent' | 'delivered' | 'failed' | 'unknown' | 'received';
|
|
69
|
+
/** Free text match across the message body, recipient, and sender. */
|
|
70
|
+
search?: string;
|
|
71
|
+
/**
|
|
72
|
+
* Inclusive lower bound on when the platform stored the message. A string
|
|
73
|
+
* must carry an explicit timezone (`2026-08-01T00:00:00Z`); a bare date like
|
|
74
|
+
* `2026-08-01` is read as UTC midnight.
|
|
75
|
+
*/
|
|
76
|
+
from?: string | Date;
|
|
77
|
+
/** Exclusive upper bound, same formats as `from`. */
|
|
78
|
+
to?: string | Date;
|
|
79
|
+
/** `desc` (default) for newest first, `asc` to walk forward when polling. */
|
|
80
|
+
order?: 'desc' | 'asc';
|
|
81
|
+
/** 1-based page number. Defaults to 1. Mutually exclusive with `cursor`. */
|
|
61
82
|
page?: number;
|
|
62
83
|
/** Items per page. Defaults to 50, capped at 100 by the API. */
|
|
63
84
|
limit?: number;
|
|
64
|
-
/**
|
|
65
|
-
|
|
85
|
+
/**
|
|
86
|
+
* Opaque position from a previous response's `meta.nextCursor`. When set,
|
|
87
|
+
* `meta` switches to cursor mode and omits the total count.
|
|
88
|
+
*/
|
|
89
|
+
cursor?: string;
|
|
66
90
|
}
|
|
91
|
+
/** Everything `iterateMessages` accepts: a filter set, minus the paging knobs it drives itself. */
|
|
92
|
+
type IterateMessagesOptions = Omit<ListMessagesOptions, 'page' | 'cursor'>;
|
|
67
93
|
interface Device {
|
|
68
94
|
_id: string;
|
|
69
95
|
name?: string;
|
|
@@ -82,14 +108,29 @@ interface Device {
|
|
|
82
108
|
createdAt?: string;
|
|
83
109
|
updatedAt?: string;
|
|
84
110
|
}
|
|
111
|
+
interface MessageDevice {
|
|
112
|
+
_id: string;
|
|
113
|
+
brand?: string;
|
|
114
|
+
model?: string;
|
|
115
|
+
buildId?: string;
|
|
116
|
+
enabled?: boolean;
|
|
117
|
+
}
|
|
85
118
|
interface Message {
|
|
86
119
|
_id: string;
|
|
87
120
|
message: string;
|
|
88
121
|
/**
|
|
89
|
-
* Direction, uppercase.
|
|
90
|
-
*
|
|
122
|
+
* Direction, uppercase.
|
|
123
|
+
*
|
|
124
|
+
* @deprecated Read `direction` instead: it is lowercase and matches the
|
|
125
|
+
* `direction` filter, so a response value feeds straight back into a query.
|
|
91
126
|
*/
|
|
92
127
|
type: 'SENT' | 'RECEIVED';
|
|
128
|
+
/** Direction, lowercase. Matches the `direction` filter values. */
|
|
129
|
+
direction?: 'sent' | 'received';
|
|
130
|
+
/** Message channel. Currently always `sms`; absent means `sms`. */
|
|
131
|
+
channel?: string;
|
|
132
|
+
/** The sending or receiving device, populated by the history endpoints. */
|
|
133
|
+
device?: MessageDevice;
|
|
93
134
|
/** Lowercase, and absent on messages stored before status tracking. */
|
|
94
135
|
status?: 'pending' | 'dispatched' | 'sent' | 'delivered' | 'failed' | 'unknown' | 'received';
|
|
95
136
|
sender?: string;
|
|
@@ -120,15 +161,23 @@ interface SmsBatch {
|
|
|
120
161
|
createdAt?: string;
|
|
121
162
|
updatedAt?: string;
|
|
122
163
|
}
|
|
123
|
-
|
|
124
|
-
|
|
164
|
+
/**
|
|
165
|
+
* Meta for the account-level message list. Page mode carries the counters and
|
|
166
|
+
* the cursor fields; cursor mode carries `limit`, `nextCursor`, and `hasMore`
|
|
167
|
+
* only, skipping the expensive total count.
|
|
168
|
+
*/
|
|
169
|
+
interface MessageListMeta {
|
|
125
170
|
limit: number;
|
|
126
|
-
|
|
127
|
-
|
|
171
|
+
page?: number;
|
|
172
|
+
total?: number;
|
|
173
|
+
totalPages?: number;
|
|
174
|
+
/** Opaque position after the last message. Null on the final page. */
|
|
175
|
+
nextCursor?: string | null;
|
|
176
|
+
hasMore?: boolean;
|
|
128
177
|
}
|
|
129
|
-
interface
|
|
178
|
+
interface MessageList {
|
|
130
179
|
data: Message[];
|
|
131
|
-
meta:
|
|
180
|
+
meta: MessageListMeta;
|
|
132
181
|
}
|
|
133
182
|
interface SmsBatchResult {
|
|
134
183
|
batch: SmsBatch;
|
|
@@ -148,8 +197,24 @@ declare class Textbee {
|
|
|
148
197
|
getDevice(deviceId: string): Promise<Device>;
|
|
149
198
|
/** Make a device the default sender for requests that omit `deviceId`. */
|
|
150
199
|
setDefaultDevice(deviceId: string): Promise<Device>;
|
|
151
|
-
/**
|
|
152
|
-
|
|
200
|
+
/**
|
|
201
|
+
* Page through the account's sent and received messages, filtered by
|
|
202
|
+
* device, batch, direction, status, text, and time range.
|
|
203
|
+
*/
|
|
204
|
+
getMessages(options?: ListMessagesOptions): Promise<MessageList>;
|
|
205
|
+
/**
|
|
206
|
+
* Iterate every message matching the filters, following the pagination
|
|
207
|
+
* cursor until the end. Use `order: 'asc'` with a `from` bound to drain
|
|
208
|
+
* forward when polling; keep the last message's `createdAt` (or track
|
|
209
|
+
* `meta.nextCursor` via `getMessages`) to resume the next poll.
|
|
210
|
+
*
|
|
211
|
+
* ```ts
|
|
212
|
+
* for await (const message of textbee.iterateMessages({ direction: 'received' })) {
|
|
213
|
+
* handle(message)
|
|
214
|
+
* }
|
|
215
|
+
* ```
|
|
216
|
+
*/
|
|
217
|
+
iterateMessages(options?: IterateMessagesOptions): AsyncGenerator<Message, void, undefined>;
|
|
153
218
|
/** Fetch a single message, including its delivery status. */
|
|
154
219
|
getSms(deviceId: string, smsId: string): Promise<Message>;
|
|
155
220
|
/** Fetch a batch and every message in it. Pair this with `smsBatchId` from a send. */
|
|
@@ -191,4 +256,4 @@ interface VerifyWebhookSignatureOptions {
|
|
|
191
256
|
*/
|
|
192
257
|
declare function verifyWebhookSignature(options: VerifyWebhookSignatureOptions): Promise<boolean>;
|
|
193
258
|
|
|
194
|
-
export { type Device, type
|
|
259
|
+
export { type Device, type IterateMessagesOptions, type ListMessagesOptions, type Message, type MessageDevice, type MessageList, type MessageListMeta, type SendSmsImmediateResponse, type SendSmsQueuedResponse, type SendSmsRequest, type SendSmsResponse, type SmsBatch, type SmsBatchResult, Textbee, TextbeeError, type TextbeeOptions, type VerifyWebhookSignatureOptions, type WebhookEvent, verifyWebhookSignature };
|
package/dist/index.d.ts
CHANGED
|
@@ -54,16 +54,42 @@ interface SendSmsImmediateResponse {
|
|
|
54
54
|
* with `'smsBatchId' in result` before reading batch fields.
|
|
55
55
|
*/
|
|
56
56
|
type SendSmsResponse = SendSmsQueuedResponse | SendSmsImmediateResponse;
|
|
57
|
-
interface
|
|
57
|
+
interface ListMessagesOptions {
|
|
58
|
+
/** Only messages from these devices. Omit for every device on the account. */
|
|
59
|
+
deviceIds?: string[];
|
|
60
|
+
/**
|
|
61
|
+
* Only messages from this batch, using the `smsBatchId` a send returns.
|
|
62
|
+
* Combine with `status: 'failed'` to list the recipients that failed.
|
|
63
|
+
*/
|
|
64
|
+
smsBatchId?: string;
|
|
58
65
|
/** Filter by direction. Defaults to `all`. */
|
|
59
|
-
|
|
60
|
-
/**
|
|
66
|
+
direction?: 'all' | 'sent' | 'received';
|
|
67
|
+
/** Filter by delivery state, e.g. `failed` to list sends that failed. */
|
|
68
|
+
status?: 'pending' | 'dispatched' | 'sent' | 'delivered' | 'failed' | 'unknown' | 'received';
|
|
69
|
+
/** Free text match across the message body, recipient, and sender. */
|
|
70
|
+
search?: string;
|
|
71
|
+
/**
|
|
72
|
+
* Inclusive lower bound on when the platform stored the message. A string
|
|
73
|
+
* must carry an explicit timezone (`2026-08-01T00:00:00Z`); a bare date like
|
|
74
|
+
* `2026-08-01` is read as UTC midnight.
|
|
75
|
+
*/
|
|
76
|
+
from?: string | Date;
|
|
77
|
+
/** Exclusive upper bound, same formats as `from`. */
|
|
78
|
+
to?: string | Date;
|
|
79
|
+
/** `desc` (default) for newest first, `asc` to walk forward when polling. */
|
|
80
|
+
order?: 'desc' | 'asc';
|
|
81
|
+
/** 1-based page number. Defaults to 1. Mutually exclusive with `cursor`. */
|
|
61
82
|
page?: number;
|
|
62
83
|
/** Items per page. Defaults to 50, capped at 100 by the API. */
|
|
63
84
|
limit?: number;
|
|
64
|
-
/**
|
|
65
|
-
|
|
85
|
+
/**
|
|
86
|
+
* Opaque position from a previous response's `meta.nextCursor`. When set,
|
|
87
|
+
* `meta` switches to cursor mode and omits the total count.
|
|
88
|
+
*/
|
|
89
|
+
cursor?: string;
|
|
66
90
|
}
|
|
91
|
+
/** Everything `iterateMessages` accepts: a filter set, minus the paging knobs it drives itself. */
|
|
92
|
+
type IterateMessagesOptions = Omit<ListMessagesOptions, 'page' | 'cursor'>;
|
|
67
93
|
interface Device {
|
|
68
94
|
_id: string;
|
|
69
95
|
name?: string;
|
|
@@ -82,14 +108,29 @@ interface Device {
|
|
|
82
108
|
createdAt?: string;
|
|
83
109
|
updatedAt?: string;
|
|
84
110
|
}
|
|
111
|
+
interface MessageDevice {
|
|
112
|
+
_id: string;
|
|
113
|
+
brand?: string;
|
|
114
|
+
model?: string;
|
|
115
|
+
buildId?: string;
|
|
116
|
+
enabled?: boolean;
|
|
117
|
+
}
|
|
85
118
|
interface Message {
|
|
86
119
|
_id: string;
|
|
87
120
|
message: string;
|
|
88
121
|
/**
|
|
89
|
-
* Direction, uppercase.
|
|
90
|
-
*
|
|
122
|
+
* Direction, uppercase.
|
|
123
|
+
*
|
|
124
|
+
* @deprecated Read `direction` instead: it is lowercase and matches the
|
|
125
|
+
* `direction` filter, so a response value feeds straight back into a query.
|
|
91
126
|
*/
|
|
92
127
|
type: 'SENT' | 'RECEIVED';
|
|
128
|
+
/** Direction, lowercase. Matches the `direction` filter values. */
|
|
129
|
+
direction?: 'sent' | 'received';
|
|
130
|
+
/** Message channel. Currently always `sms`; absent means `sms`. */
|
|
131
|
+
channel?: string;
|
|
132
|
+
/** The sending or receiving device, populated by the history endpoints. */
|
|
133
|
+
device?: MessageDevice;
|
|
93
134
|
/** Lowercase, and absent on messages stored before status tracking. */
|
|
94
135
|
status?: 'pending' | 'dispatched' | 'sent' | 'delivered' | 'failed' | 'unknown' | 'received';
|
|
95
136
|
sender?: string;
|
|
@@ -120,15 +161,23 @@ interface SmsBatch {
|
|
|
120
161
|
createdAt?: string;
|
|
121
162
|
updatedAt?: string;
|
|
122
163
|
}
|
|
123
|
-
|
|
124
|
-
|
|
164
|
+
/**
|
|
165
|
+
* Meta for the account-level message list. Page mode carries the counters and
|
|
166
|
+
* the cursor fields; cursor mode carries `limit`, `nextCursor`, and `hasMore`
|
|
167
|
+
* only, skipping the expensive total count.
|
|
168
|
+
*/
|
|
169
|
+
interface MessageListMeta {
|
|
125
170
|
limit: number;
|
|
126
|
-
|
|
127
|
-
|
|
171
|
+
page?: number;
|
|
172
|
+
total?: number;
|
|
173
|
+
totalPages?: number;
|
|
174
|
+
/** Opaque position after the last message. Null on the final page. */
|
|
175
|
+
nextCursor?: string | null;
|
|
176
|
+
hasMore?: boolean;
|
|
128
177
|
}
|
|
129
|
-
interface
|
|
178
|
+
interface MessageList {
|
|
130
179
|
data: Message[];
|
|
131
|
-
meta:
|
|
180
|
+
meta: MessageListMeta;
|
|
132
181
|
}
|
|
133
182
|
interface SmsBatchResult {
|
|
134
183
|
batch: SmsBatch;
|
|
@@ -148,8 +197,24 @@ declare class Textbee {
|
|
|
148
197
|
getDevice(deviceId: string): Promise<Device>;
|
|
149
198
|
/** Make a device the default sender for requests that omit `deviceId`. */
|
|
150
199
|
setDefaultDevice(deviceId: string): Promise<Device>;
|
|
151
|
-
/**
|
|
152
|
-
|
|
200
|
+
/**
|
|
201
|
+
* Page through the account's sent and received messages, filtered by
|
|
202
|
+
* device, batch, direction, status, text, and time range.
|
|
203
|
+
*/
|
|
204
|
+
getMessages(options?: ListMessagesOptions): Promise<MessageList>;
|
|
205
|
+
/**
|
|
206
|
+
* Iterate every message matching the filters, following the pagination
|
|
207
|
+
* cursor until the end. Use `order: 'asc'` with a `from` bound to drain
|
|
208
|
+
* forward when polling; keep the last message's `createdAt` (or track
|
|
209
|
+
* `meta.nextCursor` via `getMessages`) to resume the next poll.
|
|
210
|
+
*
|
|
211
|
+
* ```ts
|
|
212
|
+
* for await (const message of textbee.iterateMessages({ direction: 'received' })) {
|
|
213
|
+
* handle(message)
|
|
214
|
+
* }
|
|
215
|
+
* ```
|
|
216
|
+
*/
|
|
217
|
+
iterateMessages(options?: IterateMessagesOptions): AsyncGenerator<Message, void, undefined>;
|
|
153
218
|
/** Fetch a single message, including its delivery status. */
|
|
154
219
|
getSms(deviceId: string, smsId: string): Promise<Message>;
|
|
155
220
|
/** Fetch a batch and every message in it. Pair this with `smsBatchId` from a send. */
|
|
@@ -191,4 +256,4 @@ interface VerifyWebhookSignatureOptions {
|
|
|
191
256
|
*/
|
|
192
257
|
declare function verifyWebhookSignature(options: VerifyWebhookSignatureOptions): Promise<boolean>;
|
|
193
258
|
|
|
194
|
-
export { type Device, type
|
|
259
|
+
export { type Device, type IterateMessagesOptions, type ListMessagesOptions, type Message, type MessageDevice, type MessageList, type MessageListMeta, type SendSmsImmediateResponse, type SendSmsQueuedResponse, type SendSmsRequest, type SendSmsResponse, type SmsBatch, type SmsBatchResult, Textbee, TextbeeError, type TextbeeOptions, type VerifyWebhookSignatureOptions, type WebhookEvent, verifyWebhookSignature };
|
package/dist/index.js
CHANGED
|
@@ -14,7 +14,7 @@ var TextbeeError = class extends Error {
|
|
|
14
14
|
|
|
15
15
|
// src/client.ts
|
|
16
16
|
var DEFAULT_BASE_URL = "https://api.textbee.dev/api/v1";
|
|
17
|
-
var CLIENT_ID = `textbee-js/${"0.0
|
|
17
|
+
var CLIENT_ID = `textbee-js/${"0.1.0"}`;
|
|
18
18
|
var Textbee = class {
|
|
19
19
|
#apiKey;
|
|
20
20
|
#baseUrl;
|
|
@@ -71,20 +71,46 @@ var Textbee = class {
|
|
|
71
71
|
);
|
|
72
72
|
return payload.data;
|
|
73
73
|
}
|
|
74
|
-
/**
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
74
|
+
/**
|
|
75
|
+
* Page through the account's sent and received messages, filtered by
|
|
76
|
+
* device, batch, direction, status, text, and time range.
|
|
77
|
+
*/
|
|
78
|
+
async getMessages(options = {}) {
|
|
79
|
+
return await this.#request("GET", "/gateway/messages", {
|
|
80
|
+
query: {
|
|
81
|
+
deviceIds: options.deviceIds?.length ? options.deviceIds.join(",") : void 0,
|
|
82
|
+
smsBatchId: options.smsBatchId,
|
|
83
|
+
direction: options.direction,
|
|
84
|
+
status: options.status,
|
|
85
|
+
search: options.search,
|
|
86
|
+
from: toIsoString(options.from),
|
|
87
|
+
to: toIsoString(options.to),
|
|
88
|
+
order: options.order,
|
|
89
|
+
page: options.page,
|
|
90
|
+
limit: options.limit,
|
|
91
|
+
cursor: options.cursor
|
|
86
92
|
}
|
|
87
|
-
);
|
|
93
|
+
});
|
|
94
|
+
}
|
|
95
|
+
/**
|
|
96
|
+
* Iterate every message matching the filters, following the pagination
|
|
97
|
+
* cursor until the end. Use `order: 'asc'` with a `from` bound to drain
|
|
98
|
+
* forward when polling; keep the last message's `createdAt` (or track
|
|
99
|
+
* `meta.nextCursor` via `getMessages`) to resume the next poll.
|
|
100
|
+
*
|
|
101
|
+
* ```ts
|
|
102
|
+
* for await (const message of textbee.iterateMessages({ direction: 'received' })) {
|
|
103
|
+
* handle(message)
|
|
104
|
+
* }
|
|
105
|
+
* ```
|
|
106
|
+
*/
|
|
107
|
+
async *iterateMessages(options = {}) {
|
|
108
|
+
let page = await this.getMessages(options);
|
|
109
|
+
yield* page.data;
|
|
110
|
+
while (page.meta.nextCursor) {
|
|
111
|
+
page = await this.getMessages({ ...options, cursor: page.meta.nextCursor });
|
|
112
|
+
yield* page.data;
|
|
113
|
+
}
|
|
88
114
|
}
|
|
89
115
|
/** Fetch a single message, including its delivery status. */
|
|
90
116
|
async getSms(deviceId, smsId) {
|
|
@@ -130,6 +156,9 @@ var Textbee = class {
|
|
|
130
156
|
return payload;
|
|
131
157
|
}
|
|
132
158
|
};
|
|
159
|
+
function toIsoString(value) {
|
|
160
|
+
return value instanceof Date ? value.toISOString() : value;
|
|
161
|
+
}
|
|
133
162
|
async function readBody(response) {
|
|
134
163
|
const text = await response.text();
|
|
135
164
|
if (!text) {
|