@smsmode/rcs 1.0.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/dist/index.cjs ADDED
@@ -0,0 +1,416 @@
1
+ "use strict";
2
+ var __defProp = Object.defineProperty;
3
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
4
+ var __getOwnPropNames = Object.getOwnPropertyNames;
5
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
6
+ var __export = (target, all) => {
7
+ for (var name in all)
8
+ __defProp(target, name, { get: all[name], enumerable: true });
9
+ };
10
+ var __copyProps = (to, from, except, desc) => {
11
+ if (from && typeof from === "object" || typeof from === "function") {
12
+ for (let key of __getOwnPropNames(from))
13
+ if (!__hasOwnProp.call(to, key) && key !== except)
14
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
15
+ }
16
+ return to;
17
+ };
18
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
19
+
20
+ // src/index.ts
21
+ var index_exports = {};
22
+ __export(index_exports, {
23
+ AuthError: () => AuthError,
24
+ RateLimitError: () => RateLimitError,
25
+ RcsError: () => RcsError,
26
+ SmsModeApiError: () => SmsModeApiError,
27
+ SmsModeHttpError: () => SmsModeHttpError,
28
+ SmsmodeRcsClient: () => SmsmodeRcsClient,
29
+ ValidationError: () => ValidationError,
30
+ isDeliveryReport: () => isDeliveryReport,
31
+ isIncomingMessage: () => isIncomingMessage,
32
+ parseWebhookPayload: () => parseWebhookPayload
33
+ });
34
+ module.exports = __toCommonJS(index_exports);
35
+
36
+ // src/common/constants.ts
37
+ var BASE_URL = "https://rest.smsmode.com";
38
+ var RCS_API_PATH = "/rcs/v1";
39
+ var DEFAULT_HEADERS = {
40
+ Accept: "application/json",
41
+ "Content-Type": "application/json"
42
+ };
43
+ var API_KEY_HEADER = "X-Api-Key";
44
+
45
+ // src/common/errors.ts
46
+ var RcsError = class extends Error {
47
+ constructor(message) {
48
+ super(message);
49
+ this.name = "RcsError";
50
+ Object.setPrototypeOf(this, new.target.prototype);
51
+ }
52
+ };
53
+ var SmsModeApiError = class extends RcsError {
54
+ httpStatus;
55
+ title;
56
+ detail;
57
+ errorCode;
58
+ docsUrl;
59
+ details;
60
+ constructor(httpStatus, body) {
61
+ super(String(body["message"]));
62
+ this.name = "SmsModeApiError";
63
+ this.httpStatus = httpStatus;
64
+ this.title = String(body["title"]);
65
+ this.detail = String(body["detail"]);
66
+ this.errorCode = String(body["errorCode"]);
67
+ this.docsUrl = typeof body["type"] === "string" ? body["type"] : "";
68
+ this.details = body;
69
+ }
70
+ toString() {
71
+ return `[${String(this.httpStatus)}] ${this.title} \u2014 ${this.message} (${this.detail}) [errorCode: ${this.errorCode}]`;
72
+ }
73
+ };
74
+ var SmsModeHttpError = class extends RcsError {
75
+ constructor(httpStatus, statusText) {
76
+ super(`HTTP ${String(httpStatus)}: ${statusText}`);
77
+ this.httpStatus = httpStatus;
78
+ this.statusText = statusText;
79
+ this.name = "SmsModeHttpError";
80
+ }
81
+ httpStatus;
82
+ statusText;
83
+ toString() {
84
+ return `HTTP ${String(this.httpStatus)}: ${this.statusText}`;
85
+ }
86
+ };
87
+ var AuthError = class extends SmsModeApiError {
88
+ constructor(httpStatus, body) {
89
+ super(httpStatus, body);
90
+ this.name = "AuthError";
91
+ }
92
+ };
93
+ var RateLimitError = class extends SmsModeApiError {
94
+ constructor(httpStatus, body, retryAfter) {
95
+ super(httpStatus, body);
96
+ this.retryAfter = retryAfter;
97
+ this.name = "RateLimitError";
98
+ }
99
+ retryAfter;
100
+ };
101
+ var ValidationError = class extends RcsError {
102
+ constructor(message) {
103
+ super(message);
104
+ this.name = "ValidationError";
105
+ }
106
+ };
107
+
108
+ // src/base-client.ts
109
+ function isStructuredApiError(value) {
110
+ return typeof value === "object" && value !== null && "errorCode" in value && typeof value["errorCode"] === "string" && "message" in value;
111
+ }
112
+ var BaseClient = class {
113
+ apiKey;
114
+ baseUrl;
115
+ timeout;
116
+ constructor(options) {
117
+ if (!options.apiKey) {
118
+ throw new Error("API key is required");
119
+ }
120
+ this.apiKey = options.apiKey;
121
+ this.baseUrl = (options.baseUrl ?? BASE_URL).replace(/\/$/, "");
122
+ this.timeout = options.timeout ?? 1e4;
123
+ }
124
+ encodeParams(params) {
125
+ const searchParams = new URLSearchParams();
126
+ for (const [key, value] of Object.entries(params)) {
127
+ if (value !== void 0) {
128
+ searchParams.append(key, String(value));
129
+ }
130
+ }
131
+ return searchParams.toString();
132
+ }
133
+ buildUrl(path, params) {
134
+ const url = `${this.baseUrl}${path}`;
135
+ if (params && Object.keys(params).length > 0) {
136
+ return `${url}?${this.encodeParams(params)}`;
137
+ }
138
+ return url;
139
+ }
140
+ async handleErrorResponse(response) {
141
+ let errorData;
142
+ try {
143
+ errorData = await response.json();
144
+ } catch {
145
+ errorData = void 0;
146
+ }
147
+ if (!isStructuredApiError(errorData)) {
148
+ throw new SmsModeHttpError(response.status, response.statusText);
149
+ }
150
+ switch (response.status) {
151
+ case 401:
152
+ throw new AuthError(response.status, errorData);
153
+ case 429: {
154
+ const retryAfter = response.headers.get("Retry-After");
155
+ throw new RateLimitError(response.status, errorData, retryAfter ? parseInt(retryAfter, 10) : void 0);
156
+ }
157
+ default:
158
+ throw new SmsModeApiError(response.status, errorData);
159
+ }
160
+ }
161
+ async request(path, options = {}) {
162
+ const { method = "GET", body, params } = options;
163
+ const url = this.buildUrl(path, params);
164
+ const headers = {
165
+ ...DEFAULT_HEADERS,
166
+ [API_KEY_HEADER]: this.apiKey
167
+ };
168
+ if (method === "GET" || method === "DELETE") {
169
+ delete headers["Content-Type"];
170
+ }
171
+ const controller = new AbortController();
172
+ const timeoutId = setTimeout(() => {
173
+ controller.abort();
174
+ }, this.timeout);
175
+ try {
176
+ const fetchOptions = {
177
+ method,
178
+ headers,
179
+ signal: controller.signal
180
+ };
181
+ if (body) {
182
+ fetchOptions.body = JSON.stringify(body);
183
+ }
184
+ const response = await fetch(url, fetchOptions);
185
+ if (!response.ok) {
186
+ await this.handleErrorResponse(response);
187
+ }
188
+ if (response.status === 204) {
189
+ return void 0;
190
+ }
191
+ return await response.json();
192
+ } finally {
193
+ clearTimeout(timeoutId);
194
+ }
195
+ }
196
+ async get(path, params) {
197
+ const options = { method: "GET" };
198
+ if (params) options.params = params;
199
+ return this.request(path, options);
200
+ }
201
+ async post(path, body, params) {
202
+ const options = { method: "POST" };
203
+ if (body) options.body = body;
204
+ if (params) options.params = params;
205
+ return this.request(path, options);
206
+ }
207
+ async patch(path, body, params) {
208
+ const options = { method: "PATCH" };
209
+ if (body) options.body = body;
210
+ if (params) options.params = params;
211
+ return this.request(path, options);
212
+ }
213
+ async delete(path, params) {
214
+ const options = { method: "DELETE" };
215
+ if (params) options.params = params;
216
+ return this.request(path, options);
217
+ }
218
+ };
219
+
220
+ // src/common/utils.ts
221
+ function flattenGroup(prefix, group) {
222
+ if (!group) return {};
223
+ return Object.fromEntries(
224
+ Object.entries(group).filter(([, value]) => value !== void 0).map(([key, value]) => [`${prefix}[${key}]`, String(value)])
225
+ );
226
+ }
227
+
228
+ // src/resources/messages.ts
229
+ var MessagesResource = class {
230
+ constructor(client) {
231
+ this.client = client;
232
+ }
233
+ client;
234
+ buildBasePath(options) {
235
+ const base = RCS_API_PATH;
236
+ if (options?.channelId && options.campaignId) {
237
+ return `${base}/channels/${options.channelId}/campaigns/${options.campaignId}`;
238
+ }
239
+ if (options?.channelId) return `${base}/channels/${options.channelId}`;
240
+ if (options?.campaignId) return `${base}/campaigns/${options.campaignId}`;
241
+ return base;
242
+ }
243
+ buildMessagePath(messageId, options) {
244
+ return `${this.buildBasePath(options)}/messages/${messageId}`;
245
+ }
246
+ flattenListParams(params) {
247
+ if (!params) return {};
248
+ const { searchBy, sortBy, ...rest } = params;
249
+ return {
250
+ ...rest,
251
+ ...flattenGroup("searchBy", searchBy),
252
+ ...flattenGroup("sortBy", sortBy)
253
+ };
254
+ }
255
+ async send(payload, options) {
256
+ const response = await this.client.post(
257
+ `${this.buildBasePath(options)}/messages`,
258
+ payload
259
+ );
260
+ if (Array.isArray(response)) {
261
+ return response.map((item) => item.message);
262
+ }
263
+ return response;
264
+ }
265
+ /** List messages with optional filters and pagination */
266
+ async list(params, options) {
267
+ return this.client.get(
268
+ `${this.buildBasePath(options)}/messages`,
269
+ this.flattenListParams(params)
270
+ );
271
+ }
272
+ /** Get a message by ID */
273
+ async get(messageId, options) {
274
+ if (!messageId) throw new Error("messageId is required");
275
+ return this.client.get(this.buildMessagePath(messageId, options));
276
+ }
277
+ /** Update a scheduled message before it is sent */
278
+ async update(messageId, payload, options) {
279
+ if (!messageId) throw new Error("messageId is required");
280
+ return this.client.patch(this.buildMessagePath(messageId, options), payload);
281
+ }
282
+ /** Cancel a scheduled message before it is sent */
283
+ async cancel(messageId, options) {
284
+ if (!messageId) throw new Error("messageId is required");
285
+ await this.client.delete(this.buildMessagePath(messageId, options));
286
+ }
287
+ };
288
+
289
+ // src/resources/campaigns.ts
290
+ var CampaignsResource = class {
291
+ constructor(client) {
292
+ this.client = client;
293
+ }
294
+ client;
295
+ buildBasePath(options) {
296
+ if (options?.channelId) return `${RCS_API_PATH}/channels/${options.channelId}`;
297
+ return RCS_API_PATH;
298
+ }
299
+ buildCampaignPath(campaignId, options) {
300
+ return `${this.buildBasePath(options)}/campaigns/${campaignId}`;
301
+ }
302
+ flattenListParams(params) {
303
+ if (!params) return {};
304
+ const { searchBy, sortBy, ...rest } = params;
305
+ return {
306
+ ...rest,
307
+ ...flattenGroup("searchBy", searchBy),
308
+ ...flattenGroup("sortBy", sortBy)
309
+ };
310
+ }
311
+ /** Send or schedule a campaign (max 1000 recipients) */
312
+ async send(payload, options) {
313
+ return this.client.post(`${this.buildBasePath(options)}/campaigns`, payload);
314
+ }
315
+ /** List campaigns with optional filters and pagination */
316
+ async list(params, options) {
317
+ return this.client.get(
318
+ `${this.buildBasePath(options)}/campaigns`,
319
+ this.flattenListParams(params)
320
+ );
321
+ }
322
+ /** Get a campaign by ID */
323
+ async get(campaignId, options) {
324
+ if (!campaignId) throw new Error("campaignId is required");
325
+ return this.client.get(this.buildCampaignPath(campaignId, options));
326
+ }
327
+ /** Update a scheduled campaign before it is sent */
328
+ async update(campaignId, payload, options) {
329
+ if (!campaignId) throw new Error("campaignId is required");
330
+ return this.client.patch(
331
+ this.buildCampaignPath(campaignId, options),
332
+ payload
333
+ );
334
+ }
335
+ /** Cancel a scheduled campaign before it is sent */
336
+ async cancel(campaignId, options) {
337
+ if (!campaignId) throw new Error("campaignId is required");
338
+ await this.client.delete(this.buildCampaignPath(campaignId, options));
339
+ }
340
+ };
341
+
342
+ // src/client.ts
343
+ var SmsmodeRcsClient = class {
344
+ messages;
345
+ campaigns;
346
+ constructor(options) {
347
+ const baseClient = new BaseClient(options);
348
+ this.messages = new MessagesResource(baseClient);
349
+ this.campaigns = new CampaignsResource(baseClient);
350
+ }
351
+ send(payload, options) {
352
+ return this.messages.send(payload, options);
353
+ }
354
+ /** List messages with optional filters and pagination */
355
+ list(params, options) {
356
+ return this.messages.list(params, options);
357
+ }
358
+ /** Get a message by ID */
359
+ get(messageId, options) {
360
+ return this.messages.get(messageId, options);
361
+ }
362
+ /** Update a scheduled message before it is sent */
363
+ update(messageId, payload, options) {
364
+ return this.messages.update(messageId, payload, options);
365
+ }
366
+ /** Cancel a scheduled message before it is sent */
367
+ cancel(messageId, options) {
368
+ return this.messages.cancel(messageId, options);
369
+ }
370
+ };
371
+
372
+ // src/resources/webhooks.ts
373
+ function parseWebhookPayload(body) {
374
+ let parsed = body;
375
+ if (typeof parsed === "string") {
376
+ try {
377
+ parsed = JSON.parse(parsed);
378
+ } catch {
379
+ throw new ValidationError("Invalid webhook payload: not valid JSON");
380
+ }
381
+ }
382
+ if (parsed === null || typeof parsed !== "object") {
383
+ throw new ValidationError("Invalid webhook payload: expected an object");
384
+ }
385
+ const record = parsed;
386
+ if (record.type !== "RCS") {
387
+ throw new ValidationError('Invalid webhook payload: missing or unexpected `type` (expected "RCS")');
388
+ }
389
+ if (record.direction !== "MT" && record.direction !== "MO") {
390
+ throw new ValidationError('Invalid webhook payload: `direction` must be "MT" or "MO"');
391
+ }
392
+ if (typeof record.messageId !== "string") {
393
+ throw new ValidationError("Invalid webhook payload: missing `messageId`");
394
+ }
395
+ return parsed;
396
+ }
397
+ function isDeliveryReport(payload) {
398
+ return payload.direction === "MT";
399
+ }
400
+ function isIncomingMessage(payload) {
401
+ return payload.direction === "MO";
402
+ }
403
+ // Annotate the CommonJS export names for ESM import in node:
404
+ 0 && (module.exports = {
405
+ AuthError,
406
+ RateLimitError,
407
+ RcsError,
408
+ SmsModeApiError,
409
+ SmsModeHttpError,
410
+ SmsmodeRcsClient,
411
+ ValidationError,
412
+ isDeliveryReport,
413
+ isIncomingMessage,
414
+ parseWebhookPayload
415
+ });
416
+ //# sourceMappingURL=index.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/index.ts","../src/common/constants.ts","../src/common/errors.ts","../src/base-client.ts","../src/common/utils.ts","../src/resources/messages.ts","../src/resources/campaigns.ts","../src/client.ts","../src/resources/webhooks.ts"],"sourcesContent":["export { SmsmodeRcsClient } from './client.js';\r\n\r\nexport type {\r\n SmsmodeClientOptions,\r\n PaginatedResponse,\r\n MessagePathOptions,\r\n CampaignPathOptions,\r\n // RCS Enums\r\n RcsDirection,\r\n RcsStatusValue,\r\n RcsStatusDetail,\r\n RcsBodyType,\r\n RcsSuggestionType,\r\n RcsWebviewSize,\r\n RcsMediaHeight,\r\n RcsCardOrientation,\r\n RcsCardAlignment,\r\n RcsCardWidth,\r\n // RCS Suggestions\r\n RcsSuggestionBase,\r\n RcsReplySuggestion,\r\n RcsOpenUrlSuggestion,\r\n RcsDialPhoneSuggestion,\r\n RcsShowLocationSuggestion,\r\n RcsRequestLocationSuggestion,\r\n RcsCreateCalendarEventSuggestion,\r\n RcsSuggestion,\r\n // RCS Card sub-structures\r\n RcsCardMedia,\r\n RcsCardContent,\r\n // RCS Body\r\n RcsBasicBody,\r\n RcsTextBody,\r\n RcsFileBody,\r\n RcsCardBody,\r\n RcsCarouselBody,\r\n RcsBody,\r\n // RCS Sub-structures\r\n RcsPrice,\r\n RcsValidity,\r\n RcsStatus,\r\n RcsRecipient,\r\n RcsChannel,\r\n // RCS Message\r\n RcsMessage,\r\n RcsSendPayload,\r\n RcsBatchSendPayload,\r\n RcsSortOrder,\r\n RcsListParams,\r\n RcsUpdatePayload,\r\n // RCS Campaign\r\n RcsCampaignStatus,\r\n RcsCampaign,\r\n RcsCampaignSendPayload,\r\n RcsCampaignListParams,\r\n RcsCampaignUpdatePayload,\r\n // RCS Webhooks\r\n RcsDeliveryReportPayload,\r\n RcsIncomingMessagePayload,\r\n RcsWebhookPayload,\r\n} from './common/types.js';\r\n\r\nexport {\r\n RcsError,\r\n SmsModeApiError,\r\n SmsModeHttpError,\r\n AuthError,\r\n RateLimitError,\r\n ValidationError,\r\n} from './common/errors.js';\r\n\r\nexport {\r\n parseWebhookPayload,\r\n isDeliveryReport,\r\n isIncomingMessage,\r\n} from './resources/webhooks.js';\r\n","export const BASE_URL = 'https://rest.smsmode.com';\r\n\r\nexport const RCS_API_PATH = '/rcs/v1';\r\n\r\nexport const DEFAULT_HEADERS = {\r\n Accept: 'application/json',\r\n 'Content-Type': 'application/json',\r\n} as const;\r\n\r\nexport const API_KEY_HEADER = 'X-Api-Key';\r\n","/** Base class for all SDK errors — enables a unified `instanceof RcsError` check. */\r\nexport class RcsError extends Error {\r\n constructor(message: string) {\r\n super(message);\r\n this.name = 'RcsError';\r\n Object.setPrototypeOf(this, new.target.prototype);\r\n }\r\n}\r\n\r\n/** Thrown when the response contains a structured smsmode error body. All fields are guaranteed. */\r\nexport class SmsModeApiError extends RcsError {\r\n readonly httpStatus: number;\r\n readonly title: string;\r\n readonly detail: string;\r\n readonly errorCode: string;\r\n readonly docsUrl: string;\r\n readonly details: unknown;\r\n\r\n constructor(httpStatus: number, body: Record<string, unknown>) {\r\n super(String(body['message']));\r\n this.name = 'SmsModeApiError';\r\n this.httpStatus = httpStatus;\r\n this.title = String(body['title']);\r\n this.detail = String(body['detail']);\r\n this.errorCode = String(body['errorCode']);\r\n this.docsUrl = typeof body['type'] === 'string' ? body['type'] : '';\r\n this.details = body;\r\n }\r\n\r\n override toString(): string {\r\n return `[${String(this.httpStatus)}] ${this.title} — ${this.message} (${this.detail}) [errorCode: ${this.errorCode}]`;\r\n }\r\n}\r\n\r\n/** Thrown when no structured smsmode body is present (5xx, proxy errors, empty bodies). */\r\nexport class SmsModeHttpError extends RcsError {\r\n constructor(\r\n public readonly httpStatus: number,\r\n public readonly statusText: string,\r\n ) {\r\n super(`HTTP ${String(httpStatus)}: ${statusText}`);\r\n this.name = 'SmsModeHttpError';\r\n }\r\n\r\n override toString(): string {\r\n return `HTTP ${String(this.httpStatus)}: ${this.statusText}`;\r\n }\r\n}\r\n\r\n/** Thrown on HTTP 401 — invalid or missing API key. */\r\nexport class AuthError extends SmsModeApiError {\r\n constructor(httpStatus: number, body: Record<string, unknown>) {\r\n super(httpStatus, body);\r\n this.name = 'AuthError';\r\n }\r\n}\r\n\r\n/** Thrown on HTTP 429 — rate limit exceeded. Check retryAfter for delay in seconds. */\r\nexport class RateLimitError extends SmsModeApiError {\r\n constructor(\r\n httpStatus: number,\r\n body: Record<string, unknown>,\r\n public readonly retryAfter?: number,\r\n ) {\r\n super(httpStatus, body);\r\n this.name = 'RateLimitError';\r\n }\r\n}\r\n\r\n/** Thrown when a webhook payload fails local structural validation (not an HTTP error). */\r\nexport class ValidationError extends RcsError {\r\n constructor(message: string) {\r\n super(message);\r\n this.name = 'ValidationError';\r\n }\r\n}\r\n","import { BASE_URL, DEFAULT_HEADERS, API_KEY_HEADER } from './common/constants.js';\r\nimport { SmsModeApiError, SmsModeHttpError, AuthError, RateLimitError } from './common/errors.js';\r\n\r\nfunction isStructuredApiError(value: unknown): value is Record<string, unknown> {\r\n return (\r\n typeof value === 'object' &&\r\n value !== null &&\r\n 'errorCode' in value &&\r\n typeof (value as Record<string, unknown>)['errorCode'] === 'string' &&\r\n 'message' in value\r\n );\r\n}\r\nimport type { SmsmodeClientOptions, RequestOptions } from './common/types.js';\r\n\r\nexport class BaseClient {\r\n private readonly apiKey: string;\r\n private readonly baseUrl: string;\r\n private readonly timeout: number;\r\n\r\n constructor(options: SmsmodeClientOptions) {\r\n if (!options.apiKey) {\r\n throw new Error('API key is required');\r\n }\r\n this.apiKey = options.apiKey;\r\n this.baseUrl = (options.baseUrl ?? BASE_URL).replace(/\\/$/, '');\r\n this.timeout = options.timeout ?? 10000;\r\n }\r\n\r\n private encodeParams(params: Record<string, string | number | boolean | undefined>): string {\r\n const searchParams = new URLSearchParams();\r\n\r\n for (const [key, value] of Object.entries(params)) {\r\n if (value !== undefined) {\r\n searchParams.append(key, String(value));\r\n }\r\n }\r\n\r\n return searchParams.toString();\r\n }\r\n\r\n private buildUrl(path: string, params?: Record<string, string | number | boolean | undefined>): string {\r\n const url = `${this.baseUrl}${path}`;\r\n if (params && Object.keys(params).length > 0) {\r\n return `${url}?${this.encodeParams(params)}`;\r\n }\r\n return url;\r\n }\r\n\r\n private async handleErrorResponse(response: Response): Promise<never> {\r\n let errorData: unknown;\r\n try {\r\n errorData = await response.json();\r\n } catch {\r\n errorData = undefined;\r\n }\r\n\r\n if (!isStructuredApiError(errorData)) {\r\n throw new SmsModeHttpError(response.status, response.statusText);\r\n }\r\n\r\n switch (response.status) {\r\n case 401:\r\n throw new AuthError(response.status, errorData);\r\n case 429: {\r\n const retryAfter = response.headers.get('Retry-After');\r\n throw new RateLimitError(response.status, errorData, retryAfter ? parseInt(retryAfter, 10) : undefined);\r\n }\r\n default:\r\n throw new SmsModeApiError(response.status, errorData);\r\n }\r\n }\r\n\r\n async request<T>(path: string, options: RequestOptions = {}): Promise<T> {\r\n const { method = 'GET', body, params } = options;\r\n const url = this.buildUrl(path, params);\r\n\r\n const headers: Record<string, string> = {\r\n ...DEFAULT_HEADERS,\r\n [API_KEY_HEADER]: this.apiKey,\r\n };\r\n\r\n if (method === 'GET' || method === 'DELETE') {\r\n delete headers['Content-Type'];\r\n }\r\n\r\n const controller = new AbortController();\r\n const timeoutId = setTimeout(() => {\r\n controller.abort();\r\n }, this.timeout);\r\n\r\n try {\r\n const fetchOptions: RequestInit = {\r\n method,\r\n headers,\r\n signal: controller.signal,\r\n };\r\n if (body) {\r\n fetchOptions.body = JSON.stringify(body);\r\n }\r\n\r\n const response = await fetch(url, fetchOptions);\r\n\r\n if (!response.ok) {\r\n await this.handleErrorResponse(response);\r\n }\r\n\r\n if (response.status === 204) {\r\n return undefined as T;\r\n }\r\n\r\n return (await response.json()) as T;\r\n } finally {\r\n clearTimeout(timeoutId);\r\n }\r\n }\r\n\r\n async get<T>(path: string, params?: Record<string, string | number | boolean | undefined>): Promise<T> {\r\n const options: RequestOptions = { method: 'GET' };\r\n if (params) options.params = params;\r\n return this.request<T>(path, options);\r\n }\r\n\r\n async post<T>(\r\n path: string,\r\n body?: unknown,\r\n params?: Record<string, string | number | boolean | undefined>\r\n ): Promise<T> {\r\n const options: RequestOptions = { method: 'POST' };\r\n if (body) options.body = body;\r\n if (params) options.params = params;\r\n return this.request<T>(path, options);\r\n }\r\n\r\n async patch<T>(\r\n path: string,\r\n body?: unknown,\r\n params?: Record<string, string | number | boolean | undefined>\r\n ): Promise<T> {\r\n const options: RequestOptions = { method: 'PATCH' };\r\n if (body) options.body = body;\r\n if (params) options.params = params;\r\n return this.request<T>(path, options);\r\n }\r\n\r\n async delete<T>(path: string, params?: Record<string, string | number | boolean | undefined>): Promise<T> {\r\n const options: RequestOptions = { method: 'DELETE' };\r\n if (params) options.params = params;\r\n return this.request<T>(path, options);\r\n }\r\n}\r\n","export function flattenGroup(\r\n prefix: string,\r\n group?: object\r\n): Record<string, string> {\r\n if (!group) return {};\r\n\r\n return Object.fromEntries(\r\n Object.entries(group)\r\n .filter(([, value]) => value !== undefined)\r\n .map(([key, value]) => [`${prefix}[${key}]`, String(value)])\r\n );\r\n}\r\n","import type { BaseClient } from '../base-client.js';\r\nimport { RCS_API_PATH } from '../common/constants.js';\r\nimport { flattenGroup } from '../common/utils.js';\r\nimport type {\r\n MessagePathOptions,\r\n PaginatedResponse,\r\n RcsBatchSendPayload,\r\n RcsListParams,\r\n RcsMessage,\r\n RcsSendPayload,\r\n RcsUpdatePayload,\r\n} from '../common/types.js';\r\n\r\n/**\r\n * Messages resource — RCS unit and batch sends, listing, retrieval,\r\n * update of scheduled messages and cancellation.\r\n *\r\n * Typically accessed as flat methods on {@link SmsmodeRcsClient} rather than\r\n * instantiated directly.\r\n */\r\nexport class MessagesResource {\r\n constructor(private readonly client: BaseClient) {}\r\n\r\n private buildBasePath(options?: MessagePathOptions): string {\r\n const base = RCS_API_PATH;\r\n if (options?.channelId && options.campaignId) {\r\n return `${base}/channels/${options.channelId}/campaigns/${options.campaignId}`;\r\n }\r\n if (options?.channelId) return `${base}/channels/${options.channelId}`;\r\n if (options?.campaignId) return `${base}/campaigns/${options.campaignId}`;\r\n return base;\r\n }\r\n\r\n private buildMessagePath(messageId: string, options?: MessagePathOptions): string {\r\n return `${this.buildBasePath(options)}/messages/${messageId}`;\r\n }\r\n\r\n private flattenListParams(\r\n params?: RcsListParams\r\n ): Record<string, string | number | boolean | undefined> {\r\n if (!params) return {};\r\n const { searchBy, sortBy, ...rest } = params;\r\n return {\r\n ...rest,\r\n ...flattenGroup('searchBy', searchBy),\r\n ...flattenGroup('sortBy', sortBy),\r\n };\r\n }\r\n\r\n /** Send a single RCS message or a batch (max 1000) */\r\n async send(payload: RcsSendPayload, options?: MessagePathOptions): Promise<RcsMessage>;\r\n async send(payload: RcsBatchSendPayload, options?: MessagePathOptions): Promise<RcsMessage[]>;\r\n async send(\r\n payload: RcsSendPayload | RcsBatchSendPayload,\r\n options?: MessagePathOptions\r\n ): Promise<RcsMessage | RcsMessage[]> {\r\n const response = await this.client.post<RcsMessage | Array<{ message: RcsMessage }>>(\r\n `${this.buildBasePath(options)}/messages`,\r\n payload\r\n );\r\n if (Array.isArray(response)) {\r\n return response.map((item) => item.message);\r\n }\r\n return response;\r\n }\r\n\r\n /** List messages with optional filters and pagination */\r\n async list(\r\n params?: RcsListParams,\r\n options?: MessagePathOptions\r\n ): Promise<PaginatedResponse<RcsMessage>> {\r\n return this.client.get<PaginatedResponse<RcsMessage>>(\r\n `${this.buildBasePath(options)}/messages`,\r\n this.flattenListParams(params)\r\n );\r\n }\r\n\r\n /** Get a message by ID */\r\n async get(messageId: string, options?: MessagePathOptions): Promise<RcsMessage> {\r\n if (!messageId) throw new Error('messageId is required');\r\n return this.client.get<RcsMessage>(this.buildMessagePath(messageId, options));\r\n }\r\n\r\n /** Update a scheduled message before it is sent */\r\n async update(\r\n messageId: string,\r\n payload: RcsUpdatePayload,\r\n options?: MessagePathOptions\r\n ): Promise<RcsMessage> {\r\n if (!messageId) throw new Error('messageId is required');\r\n return this.client.patch<RcsMessage>(this.buildMessagePath(messageId, options), payload);\r\n }\r\n\r\n /** Cancel a scheduled message before it is sent */\r\n async cancel(messageId: string, options?: MessagePathOptions): Promise<void> {\r\n if (!messageId) throw new Error('messageId is required');\r\n await this.client.delete(this.buildMessagePath(messageId, options));\r\n }\r\n}\r\n","import type { BaseClient } from '../base-client.js';\r\nimport { RCS_API_PATH } from '../common/constants.js';\r\nimport { flattenGroup } from '../common/utils.js';\r\nimport type {\r\n CampaignPathOptions,\r\n PaginatedResponse,\r\n RcsCampaign,\r\n RcsCampaignListParams,\r\n RcsCampaignSendPayload,\r\n RcsCampaignUpdatePayload,\r\n} from '../common/types.js';\r\n\r\n/**\r\n * Campaigns resource — grouped RCS sends (max 1000 recipients per campaign)\r\n * and campaign statistics. Accessed via `client.campaigns` on {@link SmsmodeRcsClient}.\r\n */\r\nexport class CampaignsResource {\r\n constructor(private readonly client: BaseClient) {}\r\n\r\n private buildBasePath(options?: CampaignPathOptions): string {\r\n if (options?.channelId) return `${RCS_API_PATH}/channels/${options.channelId}`;\r\n return RCS_API_PATH;\r\n }\r\n\r\n private buildCampaignPath(campaignId: string, options?: CampaignPathOptions): string {\r\n return `${this.buildBasePath(options)}/campaigns/${campaignId}`;\r\n }\r\n\r\n private flattenListParams(\r\n params?: RcsCampaignListParams\r\n ): Record<string, string | number | boolean | undefined> {\r\n if (!params) return {};\r\n const { searchBy, sortBy, ...rest } = params;\r\n return {\r\n ...rest,\r\n ...flattenGroup('searchBy', searchBy),\r\n ...flattenGroup('sortBy', sortBy),\r\n };\r\n }\r\n\r\n /** Send or schedule a campaign (max 1000 recipients) */\r\n async send(\r\n payload: RcsCampaignSendPayload,\r\n options?: CampaignPathOptions\r\n ): Promise<RcsCampaign> {\r\n return this.client.post<RcsCampaign>(`${this.buildBasePath(options)}/campaigns`, payload);\r\n }\r\n\r\n /** List campaigns with optional filters and pagination */\r\n async list(\r\n params?: RcsCampaignListParams,\r\n options?: CampaignPathOptions\r\n ): Promise<PaginatedResponse<RcsCampaign>> {\r\n return this.client.get<PaginatedResponse<RcsCampaign>>(\r\n `${this.buildBasePath(options)}/campaigns`,\r\n this.flattenListParams(params)\r\n );\r\n }\r\n\r\n /** Get a campaign by ID */\r\n async get(campaignId: string, options?: CampaignPathOptions): Promise<RcsCampaign> {\r\n if (!campaignId) throw new Error('campaignId is required');\r\n return this.client.get<RcsCampaign>(this.buildCampaignPath(campaignId, options));\r\n }\r\n\r\n /** Update a scheduled campaign before it is sent */\r\n async update(\r\n campaignId: string,\r\n payload: RcsCampaignUpdatePayload,\r\n options?: CampaignPathOptions\r\n ): Promise<RcsCampaign> {\r\n if (!campaignId) throw new Error('campaignId is required');\r\n return this.client.patch<RcsCampaign>(\r\n this.buildCampaignPath(campaignId, options),\r\n payload\r\n );\r\n }\r\n\r\n /** Cancel a scheduled campaign before it is sent */\r\n async cancel(campaignId: string, options?: CampaignPathOptions): Promise<void> {\r\n if (!campaignId) throw new Error('campaignId is required');\r\n await this.client.delete(this.buildCampaignPath(campaignId, options));\r\n }\r\n}\r\n","import { BaseClient } from './base-client.js';\r\nimport { MessagesResource } from './resources/messages.js';\r\nimport { CampaignsResource } from './resources/campaigns.js';\r\nimport type {\r\n MessagePathOptions,\r\n PaginatedResponse,\r\n RcsBatchSendPayload,\r\n RcsListParams,\r\n RcsMessage,\r\n RcsSendPayload,\r\n RcsUpdatePayload,\r\n SmsmodeClientOptions,\r\n} from './common/types.js';\r\n\r\n/**\r\n * Main entry point of the `@smsmode/rcs`.\r\n *\r\n * Exposes RCS message methods directly on the instance, and namespaces the\r\n * Campaign resource under `.campaigns`.\r\n *\r\n * @example\r\n * ```ts\r\n * const client = new SmsmodeRcsClient({ apiKey: 'your-api-key' });\r\n * await client.send({ recipient: { to: '33612345678' }, body: { type: 'TEXT' } });\r\n * await client.campaigns.list();\r\n * ```\r\n */\r\nexport class SmsmodeRcsClient {\r\n private readonly messages: MessagesResource;\r\n public readonly campaigns: CampaignsResource;\r\n\r\n constructor(options: SmsmodeClientOptions) {\r\n const baseClient = new BaseClient(options);\r\n this.messages = new MessagesResource(baseClient);\r\n this.campaigns = new CampaignsResource(baseClient);\r\n }\r\n\r\n /** Send a single RCS message or a batch (max 1000) */\r\n send(payload: RcsSendPayload, options?: MessagePathOptions): Promise<RcsMessage>;\r\n send(payload: RcsBatchSendPayload, options?: MessagePathOptions): Promise<RcsMessage[]>;\r\n send(\r\n payload: RcsSendPayload | RcsBatchSendPayload,\r\n options?: MessagePathOptions\r\n ): Promise<RcsMessage | RcsMessage[]> {\r\n return this.messages.send(payload as RcsBatchSendPayload, options);\r\n }\r\n\r\n /** List messages with optional filters and pagination */\r\n list(\r\n params?: RcsListParams,\r\n options?: MessagePathOptions\r\n ): Promise<PaginatedResponse<RcsMessage>> {\r\n return this.messages.list(params, options);\r\n }\r\n\r\n /** Get a message by ID */\r\n get(messageId: string, options?: MessagePathOptions): Promise<RcsMessage> {\r\n return this.messages.get(messageId, options);\r\n }\r\n\r\n /** Update a scheduled message before it is sent */\r\n update(\r\n messageId: string,\r\n payload: RcsUpdatePayload,\r\n options?: MessagePathOptions\r\n ): Promise<RcsMessage> {\r\n return this.messages.update(messageId, payload, options);\r\n }\r\n\r\n /** Cancel a scheduled message before it is sent */\r\n cancel(messageId: string, options?: MessagePathOptions): Promise<void> {\r\n return this.messages.cancel(messageId, options);\r\n }\r\n}\r\n","import { ValidationError } from '../common/errors.js';\r\nimport type {\r\n RcsDeliveryReportPayload,\r\n RcsIncomingMessagePayload,\r\n RcsWebhookPayload,\r\n} from '../common/types.js';\r\n\r\n/**\r\n * Parse a raw webhook body (object or JSON string) into a typed RCS webhook payload.\r\n * Performs a minimal structural check — downstream code should rely on the\r\n * discriminated union (`direction`) via `isDeliveryReport` / `isIncomingMessage`.\r\n *\r\n * @throws {ValidationError} if the body is not a valid RCS webhook payload.\r\n */\r\nexport function parseWebhookPayload(body: unknown): RcsWebhookPayload {\r\n let parsed: unknown = body;\r\n\r\n if (typeof parsed === 'string') {\r\n try {\r\n parsed = JSON.parse(parsed);\r\n } catch {\r\n throw new ValidationError('Invalid webhook payload: not valid JSON');\r\n }\r\n }\r\n\r\n if (parsed === null || typeof parsed !== 'object') {\r\n throw new ValidationError('Invalid webhook payload: expected an object');\r\n }\r\n\r\n const record = parsed as Record<string, unknown>;\r\n\r\n if (record.type !== 'RCS') {\r\n throw new ValidationError('Invalid webhook payload: missing or unexpected `type` (expected \"RCS\")');\r\n }\r\n if (record.direction !== 'MT' && record.direction !== 'MO') {\r\n throw new ValidationError('Invalid webhook payload: `direction` must be \"MT\" or \"MO\"');\r\n }\r\n if (typeof record.messageId !== 'string') {\r\n throw new ValidationError('Invalid webhook payload: missing `messageId`');\r\n }\r\n\r\n return parsed as RcsWebhookPayload;\r\n}\r\n\r\n/** Type guard — true when the payload is a Delivery Report (MT). */\r\nexport function isDeliveryReport(\r\n payload: RcsWebhookPayload\r\n): payload is RcsDeliveryReportPayload {\r\n return payload.direction === 'MT';\r\n}\r\n\r\n/** Type guard — true when the payload is an Incoming Message (MO). */\r\nexport function isIncomingMessage(\r\n payload: RcsWebhookPayload\r\n): payload is RcsIncomingMessagePayload {\r\n return payload.direction === 'MO';\r\n}\r\n"],"mappings":"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","names":[]}