@trycourier/courier 3.9.0 → 3.12.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/CHANGELOG.md CHANGED
@@ -5,6 +5,21 @@ This project adheres to [Semantic Versioning](http://semver.org/).
5
5
 
6
6
  ## [Unreleased][unreleased]
7
7
 
8
+ ## [3.12.0] - 2022-03-31
9
+
10
+ - adds support for message trace id (`message.metadata.trace_id`)
11
+
12
+ ## [3.11.0] - 2022-03-23
13
+
14
+ - adds support for `audiences`
15
+
16
+
17
+ ## [3.10.1] - 2022-03-20
18
+ - adds support for messages timeout (`message.timeout`)
19
+
20
+ ## [3.10.0] - 2020-03-24
21
+ - adds support for messages brand_id (`message.brand_id`)
22
+
8
23
  ## [3.9.0] - 2022-03-17
9
24
 
10
25
  - adds support for bulk messaging API v2 support
@@ -218,7 +233,9 @@ This project adheres to [Semantic Versioning](http://semver.org/).
218
233
 
219
234
  ## v1.0.1 - 2019-07-12
220
235
 
221
- [unreleased]: https://github.com/trycourier/courier-node/compare/v3.9.0...HEAD
236
+ [unreleased]: https://github.com/trycourier/courier-node/compare/v3.11.0...HEAD
237
+ [v3.11.0]: https://github.com/trycourier/courier-node/compare/v3.10.0...v3.11.0
238
+ [v3.10.0]: https://github.com/trycourier/courier-node/compare/v3.9.0...v3.10.0
222
239
  [v3.9.0]: https://github.com/trycourier/courier-node/compare/v3.8.0...v3.9.0
223
240
  [v3.8.0]: https://github.com/trycourier/courier-node/compare/v3.7.0...v3.8.0
224
241
  [v3.7.0]: https://github.com/trycourier/courier-node/compare/v3.6.0...v3.7.0
package/README.md CHANGED
@@ -160,6 +160,52 @@ const { requestId } = await courier.send({
160
160
  },
161
161
  },
162
162
  });
163
+
164
+ // Example: send a basic message that expires after the specified timeout
165
+ const { requestId } = await courier.send({
166
+ message: {
167
+ to: {
168
+ data: {
169
+ name: "Marty",
170
+ },
171
+ email: "marty_mcfly@email.com",
172
+ },
173
+ content: {
174
+ title: "Back to the Future",
175
+ body: "Oh my {{name}}, we need 1.21 Gigawatts!",
176
+ },
177
+ routing: {
178
+ method: "single",
179
+ channels: ["email"],
180
+ },
181
+ timeout: {
182
+ message: 3600000 // 1 hour in milliseconds
183
+ },
184
+ },
185
+ });
186
+
187
+ // Example: send a basic message with a trace id
188
+ const { requestId } = await courier.send({
189
+ message: {
190
+ to: {
191
+ data: {
192
+ name: "Marty",
193
+ },
194
+ email: "marty_mcfly@email.com",
195
+ },
196
+ content: {
197
+ title: "Back to the Future",
198
+ body: "Oh my {{name}}, we need 1.21 Gigawatts!",
199
+ },
200
+ routing: {
201
+ method: "single",
202
+ channels: ["email"],
203
+ },
204
+ metadata: {
205
+ trace_id: "ravenclaw-for-the-win"
206
+ },
207
+ },
208
+ });
163
209
  ```
164
210
 
165
211
  ## Environment Variables
@@ -596,6 +642,42 @@ async function run() {
596
642
  run();
597
643
  ```
598
644
 
645
+ ### Audiences
646
+
647
+ Audiences APIs are used to create, get, update, and delete audiences. A Courier Audience is a dynamic group of users (created using Courier's Profile API) that matches a set of criteria. Audience is reactive to changes in the user's profile. As you change user profile using `profiles` API, the audience will be updated accordingly. You will not have to maintain a list of users in your audience. Courier takes care of that for you. If you have potentially large set of users, you first create an audience and then use the audience's id to retrieve the list of users. Once you satified with the calculated list of users, you can use the `audienceId` to send notification using `send` API.
648
+
649
+ ```ts
650
+ // Example: create audience which would allow sending notification to all users that match the given filter criteria
651
+ const { audienceId } = await courier.audiences.put({
652
+ id: "<AUDIENCE_ID>",
653
+ filter: {
654
+ "operator": "EQ",
655
+ "path": "title",
656
+ "value": "Software Engineer",
657
+ },
658
+ });
659
+
660
+ // To retrieve list of members in a given audience, you can use the following:
661
+ const { items: audienceMembers } = await courier.audiences.listMembers(
662
+ audienceId
663
+ );
664
+
665
+ // To send a notification to all users that match the given filter criteria, you can use the following:
666
+ const { requestId } = await courier.send({
667
+ message: {
668
+ template: "<TEMPLATE_OR_EVENT_ID>", // This can be inline content as well
669
+ to: {
670
+ audience_id: audienceId,
671
+ },
672
+ data: {}, // optional
673
+ brand_id: "<BRAND_ID>", //optional
674
+ routing: {},
675
+ channels: {}, // optional
676
+ providers: {}, // optional
677
+ },
678
+ });
679
+ ```
680
+
599
681
  ## License
600
682
 
601
683
  [MIT License](http://www.opensource.org/licenses/mit-license.php)
@@ -0,0 +1,9 @@
1
+ import { ICourierClientConfiguration } from "../types";
2
+ import * as AudienceTypes from "./types";
3
+ export declare const audiences: (options: ICourierClientConfiguration) => {
4
+ delete: (audienceId: string) => Promise<void>;
5
+ get: (audienceId: string) => Promise<AudienceTypes.IAudience>;
6
+ listAudiences: () => Promise<AudienceTypes.IAudienceListResponse>;
7
+ listMembers: (audienceId: string) => Promise<AudienceTypes.IAudienceMemberListResponse>;
8
+ put: (audience: Omit<AudienceTypes.IAudience, "created_at" | "updated_at">) => Promise<AudienceTypes.IAudience>;
9
+ };
@@ -0,0 +1,108 @@
1
+ "use strict";
2
+ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
3
+ function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
4
+ return new (P || (P = Promise))(function (resolve, reject) {
5
+ function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
6
+ function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
7
+ function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
8
+ step((generator = generator.apply(thisArg, _arguments || [])).next());
9
+ });
10
+ };
11
+ var __generator = (this && this.__generator) || function (thisArg, body) {
12
+ var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g;
13
+ return g = { next: verb(0), "throw": verb(1), "return": verb(2) }, typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g;
14
+ function verb(n) { return function (v) { return step([n, v]); }; }
15
+ function step(op) {
16
+ if (f) throw new TypeError("Generator is already executing.");
17
+ while (_) try {
18
+ if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t;
19
+ if (y = 0, t) op = [op[0] & 2, t.value];
20
+ switch (op[0]) {
21
+ case 0: case 1: t = op; break;
22
+ case 4: _.label++; return { value: op[1], done: false };
23
+ case 5: _.label++; y = op[1]; op = [0]; continue;
24
+ case 7: op = _.ops.pop(); _.trys.pop(); continue;
25
+ default:
26
+ if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; }
27
+ if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; }
28
+ if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; }
29
+ if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; }
30
+ if (t[2]) _.ops.pop();
31
+ _.trys.pop(); continue;
32
+ }
33
+ op = body.call(thisArg, _);
34
+ } catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; }
35
+ if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true };
36
+ }
37
+ };
38
+ Object.defineProperty(exports, "__esModule", { value: true });
39
+ exports.audiences = void 0;
40
+ var deleteAudience = function (options) { return function (audienceId) { return __awaiter(void 0, void 0, void 0, function () {
41
+ return __generator(this, function (_a) {
42
+ switch (_a.label) {
43
+ case 0: return [4 /*yield*/, options.httpClient.delete("/audiences/" + audienceId)];
44
+ case 1:
45
+ _a.sent();
46
+ return [2 /*return*/];
47
+ }
48
+ });
49
+ }); }; };
50
+ var getAudience = function (options) {
51
+ return function (audienceId) { return __awaiter(void 0, void 0, void 0, function () {
52
+ var response;
53
+ return __generator(this, function (_a) {
54
+ switch (_a.label) {
55
+ case 0: return [4 /*yield*/, options.httpClient.get("/audiences/" + audienceId)];
56
+ case 1:
57
+ response = _a.sent();
58
+ return [2 /*return*/, response.data.audience];
59
+ }
60
+ });
61
+ }); };
62
+ };
63
+ var listAudiences = function (options) {
64
+ return function () { return __awaiter(void 0, void 0, void 0, function () {
65
+ var response;
66
+ return __generator(this, function (_a) {
67
+ switch (_a.label) {
68
+ case 0: return [4 /*yield*/, options.httpClient.get("/audiences")];
69
+ case 1:
70
+ response = _a.sent();
71
+ return [2 /*return*/, response.data];
72
+ }
73
+ });
74
+ }); };
75
+ };
76
+ var listMembers = function (options) {
77
+ return function (audienceId) { return __awaiter(void 0, void 0, void 0, function () {
78
+ var response;
79
+ return __generator(this, function (_a) {
80
+ switch (_a.label) {
81
+ case 0: return [4 /*yield*/, options.httpClient.get("/audiences/" + audienceId + "/members")];
82
+ case 1:
83
+ response = _a.sent();
84
+ return [2 /*return*/, response.data];
85
+ }
86
+ });
87
+ }); };
88
+ };
89
+ var putAudience = function (options) {
90
+ return function (audience) { return __awaiter(void 0, void 0, void 0, function () {
91
+ var response;
92
+ return __generator(this, function (_a) {
93
+ switch (_a.label) {
94
+ case 0: return [4 /*yield*/, options.httpClient.get("/audiences/" + audience.id)];
95
+ case 1:
96
+ response = _a.sent();
97
+ return [2 /*return*/, response.data.audience];
98
+ }
99
+ });
100
+ }); };
101
+ };
102
+ exports.audiences = function (options) { return ({
103
+ delete: deleteAudience(options),
104
+ get: getAudience(options),
105
+ listAudiences: listAudiences(options),
106
+ listMembers: listMembers(options),
107
+ put: putAudience(options),
108
+ }); };
@@ -0,0 +1,61 @@
1
+ export declare type ComparisonOperator = "EQ" | "GT" | "GTE" | "INCLUDES" | "LT" | "LTE" | "NEQ" | "OMIT";
2
+ export declare type LogicalOperator = "AND" | "OR";
3
+ export declare type Operator = ComparisonOperator | LogicalOperator;
4
+ declare type Without<T, U> = {
5
+ [P in Exclude<keyof T, keyof U>]?: never;
6
+ };
7
+ declare type XOR<T, U> = T | U extends object ? (Without<T, U> & U) | (Without<U, T> & T) : T | U;
8
+ interface IBaseFilterConfig {
9
+ operator: Operator;
10
+ }
11
+ interface ISingleFilterConfig extends IBaseFilterConfig {
12
+ path: string;
13
+ value: string;
14
+ }
15
+ interface INestedFilterConfig extends IBaseFilterConfig {
16
+ rules: FilterConfig[];
17
+ }
18
+ export declare type FilterConfig = XOR<ISingleFilterConfig, INestedFilterConfig>;
19
+ export interface IAudience {
20
+ created_at: string;
21
+ description?: string;
22
+ id: string;
23
+ name?: string;
24
+ filter: FilterConfig;
25
+ updated_at: string;
26
+ }
27
+ export interface IAudienceMember {
28
+ added_at: string;
29
+ audience_id: string;
30
+ audience_version: number;
31
+ member_id: string;
32
+ reason: string;
33
+ }
34
+ export interface IAudienceListResponse {
35
+ items: IAudience[];
36
+ paging: {
37
+ cursor: string;
38
+ more: boolean;
39
+ };
40
+ }
41
+ export interface IAudienceMemberGetResponse {
42
+ audienceMember: IAudienceMember;
43
+ }
44
+ export interface IAudienceMemberListResponse {
45
+ items: IAudienceMember[];
46
+ paging: {
47
+ cursor: string;
48
+ more: boolean;
49
+ };
50
+ }
51
+ export interface IAudiencePutResponse {
52
+ audience: IAudience;
53
+ }
54
+ export interface ICourierClientAudiences {
55
+ delete: (id: string) => Promise<void>;
56
+ get: (id: string) => Promise<IAudience>;
57
+ listAudiences: () => Promise<IAudienceListResponse>;
58
+ listMembers: (id: string) => Promise<IAudienceMemberListResponse>;
59
+ put: (audience: Omit<IAudience, "created_at" | "updated_at">) => Promise<IAudience>;
60
+ }
61
+ export {};
@@ -0,0 +1,2 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
package/lib/client.js CHANGED
@@ -37,6 +37,7 @@ var __generator = (this && this.__generator) || function (thisArg, body) {
37
37
  };
38
38
  Object.defineProperty(exports, "__esModule", { value: true });
39
39
  exports.client = void 0;
40
+ var audiences_1 = require("./audiences");
40
41
  var automations_1 = require("./automations");
41
42
  var brands_1 = require("./brands");
42
43
  var bulk_1 = require("./bulk");
@@ -98,8 +99,8 @@ var getMessages = function (options) {
98
99
  notification: params === null || params === void 0 ? void 0 : params.notificationId,
99
100
  recipient: params === null || params === void 0 ? void 0 : params.recipientId,
100
101
  status: params === null || params === void 0 ? void 0 : params.status,
101
- tags: params === null || params === void 0 ? void 0 : params.tags
102
- }
102
+ tags: params === null || params === void 0 ? void 0 : params.tags,
103
+ },
103
104
  })];
104
105
  case 1:
105
106
  res = _a.sent();
@@ -111,6 +112,7 @@ var getMessages = function (options) {
111
112
  exports.client = function (options) {
112
113
  return {
113
114
  addRecipientToLists: profile_1.addRecipientToLists(options),
115
+ audiences: audiences_1.audiences(options),
114
116
  automations: automations_1.automations(options),
115
117
  bulk: bulk_1.bulk(options),
116
118
  createBrand: brands_1.createBrand(options),
@@ -131,6 +133,6 @@ exports.client = function (options) {
131
133
  removeRecipientFromAllLists: profile_1.removeRecipientFromAllLists(options),
132
134
  replaceBrand: brands_1.replaceBrand(options),
133
135
  replaceProfile: profile_1.replaceProfile(options),
134
- send: send_1.send(options)
136
+ send: send_1.send(options),
135
137
  };
136
138
  };
@@ -222,6 +222,10 @@ interface InvalidUserRecipient {
222
222
  declare type UserRecipientType = Record<string, unknown> & {
223
223
  [key in keyof InvalidUserRecipient]?: never;
224
224
  };
225
+ export interface AudienceRecipient {
226
+ audience_id: string;
227
+ data?: MessageData;
228
+ }
225
229
  export interface UserRecipient extends UserRecipientType {
226
230
  data?: MessageData;
227
231
  email?: string;
@@ -230,19 +234,28 @@ export interface UserRecipient extends UserRecipientType {
230
234
  phone_number?: string;
231
235
  preferences?: IProfilePreferences;
232
236
  }
233
- export declare type Recipient = ListRecipient | ListPatternRecipient | UserRecipient;
237
+ export declare type Recipient = AudienceRecipient | ListRecipient | ListPatternRecipient | UserRecipient;
234
238
  export declare type MessageRecipient = Recipient | Recipient[];
235
239
  export interface ElementalContentSugar {
236
240
  body?: string;
237
241
  title?: string;
238
242
  }
243
+ export interface Timeout {
244
+ provider?: number;
245
+ channel?: number;
246
+ message?: number;
247
+ escalation?: number;
248
+ criteria?: "no-escalation" | "delivered" | "viewed" | "engaged";
249
+ }
239
250
  export declare type Content = ElementalContentSugar | ElementalContent;
240
251
  export interface BaseMessage {
252
+ brand_id?: string;
241
253
  channels?: MessageChannels;
242
254
  data?: MessageData;
243
255
  metadata?: MessageMetadata;
244
256
  providers?: MessageProviders;
245
257
  routing?: Routing;
258
+ timeout?: Timeout;
246
259
  to: MessageRecipient;
247
260
  }
248
261
  interface TrackingOverride {
@@ -327,6 +340,7 @@ export interface MessageMetadata {
327
340
  term?: string;
328
341
  content?: string;
329
342
  };
343
+ trace_id?: string;
330
344
  }
331
345
  export interface ContentMessage extends BaseMessage {
332
346
  content: Content;
package/lib/types.d.ts CHANGED
@@ -1,4 +1,5 @@
1
1
  import { AxiosRequestConfig } from "axios";
2
+ import { ICourierClientAudiences } from "./audiences/types";
2
3
  import { ICourierClientAutomations } from "./automations/types";
3
4
  import { ICourierClientBulk } from "./bulk/types";
4
5
  import { ICourierClientLists, ICourierList, ICourierRecipientSubscriptionsResponse } from "./lists/types";
@@ -286,6 +287,7 @@ export interface ICourierBrandGetAllResponse {
286
287
  export declare type SendResponse<T extends ICourierSendParameters | ICourierSendMessageParameters> = T extends ICourierSendParameters ? ICourierSendResponse : ICourierSendMessageResponse;
287
288
  export interface ICourierClient {
288
289
  addRecipientToLists: (params: ICourierProfileListsPostParameters) => Promise<ICourierProfilePostResponse>;
290
+ audiences: ICourierClientAudiences;
289
291
  automations: ICourierClientAutomations;
290
292
  bulk: ICourierClientBulk;
291
293
  createBrand: (params: ICourierBrandParameters, config?: ICourierBrandPostConfig) => Promise<ICourierBrand>;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@trycourier/courier",
3
- "version": "3.9.0",
3
+ "version": "3.12.0",
4
4
  "description": "A node.js module for communicating with the Courier REST API.",
5
5
  "main": "lib/index.js",
6
6
  "types": "lib/index.d.ts",