@trycourier/courier-js 2.1.3 → 3.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.mjs CHANGED
@@ -857,13 +857,18 @@ class InboxClient extends Client {
857
857
  * @returns Promise resolving to paginated messages response
858
858
  */
859
859
  async getMessages(props) {
860
+ const filter = (props == null ? void 0 : props.filter) || {};
861
+ const filterParams = this.createFilterParams(filter);
862
+ const unreadCountFilterParams = this.createUnreadCountFilterParams(filter);
860
863
  const query = `
861
864
  query GetInboxMessages(
862
- $params: FilterParamsInput = { ${this.options.tenantId ? `accountId: "${this.options.tenantId}"` : ""} }
865
+ $params: FilterParamsInput = ${filterParams}
866
+ $unreadCountParams: FilterParamsInput = ${unreadCountFilterParams}
863
867
  $limit: Int = ${(props == null ? void 0 : props.paginationLimit) ?? 24}
864
868
  $after: String ${(props == null ? void 0 : props.startCursor) ? `= "${props.startCursor}"` : ""}
865
869
  ) {
866
- count(params: $params)
870
+ count: count(params: $params)
871
+ unreadCount: count(params: $unreadCountParams)
867
872
  messages(params: $params, limit: $limit, after: $after) {
868
873
  totalCount
869
874
  pageInfo {
@@ -903,48 +908,42 @@ class InboxClient extends Client {
903
908
  });
904
909
  }
905
910
  /**
906
- * Get paginated archived messages
907
- * @param paginationLimit - Number of messages to return per page (default: 24)
908
- * @param startCursor - Cursor for pagination
909
- * @returns Promise resolving to paginated archived messages response
911
+ * Get unread counts for multiple filters in a single query.
912
+ *
913
+ * @param filtersMap - Map of dataset ID to filter
914
+ * @returns Promise resolving to map of dataset ID to unread count
910
915
  */
911
- async getArchivedMessages(props) {
916
+ async getUnreadCounts(filtersMap) {
917
+ const result = {};
918
+ const filtersToQuery = {};
919
+ for (const [datasetId, filter] of Object.entries(filtersMap)) {
920
+ if (filter.status === "read") {
921
+ result[datasetId] = 0;
922
+ } else {
923
+ filtersToQuery[datasetId] = filter;
924
+ }
925
+ }
926
+ if (Object.keys(filtersToQuery).length === 0) {
927
+ return result;
928
+ }
929
+ const variables = [];
930
+ const fields = [];
931
+ const sanitizedIdMapping = {};
932
+ for (const [datasetId, filter] of Object.entries(filtersToQuery)) {
933
+ const sanitizedId = InboxClient.sanitizeGraphQLIdentifier(datasetId);
934
+ sanitizedIdMapping[sanitizedId] = datasetId;
935
+ const unreadCountFilterParams = this.createUnreadCountFilterParams(filter);
936
+ variables.push(`$${sanitizedId}: FilterParamsInput = ${unreadCountFilterParams}`);
937
+ fields.push(`${sanitizedId}: count(params: $${sanitizedId})`);
938
+ }
912
939
  const query = `
913
- query GetInboxMessages(
914
- $params: FilterParamsInput = { ${this.options.tenantId ? `accountId: "${this.options.tenantId}"` : ""}, archived: true }
915
- $limit: Int = ${(props == null ? void 0 : props.paginationLimit) ?? 24}
916
- $after: String ${(props == null ? void 0 : props.startCursor) ? `= "${props.startCursor}"` : ""}
940
+ query GetUnreadCounts(
941
+ ${variables.join("\n")}
917
942
  ) {
918
- count(params: $params)
919
- messages(params: $params, limit: $limit, after: $after) {
920
- totalCount
921
- pageInfo {
922
- startCursor
923
- hasNextPage
924
- }
925
- nodes {
926
- messageId
927
- read
928
- archived
929
- created
930
- opened
931
- title
932
- preview
933
- data
934
- tags
935
- trackingIds {
936
- clickTrackingId
937
- }
938
- actions {
939
- content
940
- data
941
- href
942
- }
943
- }
944
- }
943
+ ${fields.join("\n")}
945
944
  }
946
945
  `;
947
- return graphql({
946
+ const response = await graphql({
948
947
  options: this.options,
949
948
  query,
950
949
  headers: {
@@ -953,6 +952,27 @@ class InboxClient extends Client {
953
952
  },
954
953
  url: this.options.apiUrls.inbox.graphql
955
954
  });
955
+ if (response.data) {
956
+ for (const [sanitizedId, originalId] of Object.entries(sanitizedIdMapping)) {
957
+ result[originalId] = response.data[sanitizedId] ?? 0;
958
+ }
959
+ }
960
+ return result;
961
+ }
962
+ /**
963
+ * Get paginated archived messages
964
+ * @param paginationLimit - Number of messages to return per page (default: 24)
965
+ * @param startCursor - Cursor for pagination
966
+ * @returns Promise resolving to paginated archived messages response
967
+ *
968
+ * @deprecated - replace usages with {@link InboxClient.getMessages}, passing the filter `{ archived: true }`
969
+ */
970
+ async getArchivedMessages(props) {
971
+ return this.getMessages({
972
+ paginationLimit: props == null ? void 0 : props.paginationLimit,
973
+ startCursor: props == null ? void 0 : props.startCursor,
974
+ filter: { archived: true }
975
+ });
956
976
  }
957
977
  /**
958
978
  * Get unread message count
@@ -1197,6 +1217,51 @@ class InboxClient extends Client {
1197
1217
  url: this.options.apiUrls.inbox.graphql
1198
1218
  });
1199
1219
  }
1220
+ /**
1221
+ * Create FilterParamsInput for the given filters.
1222
+ *
1223
+ * @param filter - the filtering options to include in the output
1224
+ * @returns the FilterParamsInput to pass to a GraphQL query for messages
1225
+ */
1226
+ createFilterParams(filter) {
1227
+ const parts = [];
1228
+ if (this.options.tenantId) {
1229
+ parts.push(`accountId: "${this.options.tenantId}"`);
1230
+ }
1231
+ if (filter.tags) {
1232
+ parts.push(`tags: [${filter.tags.map((tag) => `"${tag}"`).join(",")}]`);
1233
+ }
1234
+ if (filter.status) {
1235
+ parts.push(`status: "${filter.status}"`);
1236
+ }
1237
+ if (filter.archived) {
1238
+ parts.push(`archived: ${filter.archived}`);
1239
+ }
1240
+ return `{ ${parts.join(",")} }`;
1241
+ }
1242
+ /**
1243
+ * Create FilterParamsInput for the unread message count.
1244
+ *
1245
+ * The status: "unread" filter is only added if status is unset. This is because:
1246
+ * - If status is "unread", the params already include the filter that would be added.
1247
+ * - If status is "read", the unread count for the dataset would be a different set
1248
+ * of messages rather than a count of the unread subset.
1249
+ */
1250
+ createUnreadCountFilterParams(filter) {
1251
+ if (!filter.status) {
1252
+ return this.createFilterParams({ ...filter, status: "unread" });
1253
+ }
1254
+ return this.createFilterParams(filter);
1255
+ }
1256
+ /**
1257
+ * Sanitize dataset IDs for use as GraphQL identifiers.
1258
+ *
1259
+ * GraphQL identifiers must contain only alphanumerics/underscores and begin with a letter or underscore.
1260
+ * https://spec.graphql.org/draft/#sec-Names
1261
+ */
1262
+ static sanitizeGraphQLIdentifier(id) {
1263
+ return `id_${id.replace(/_/g, "__").replace(/-/g, "_")}`;
1264
+ }
1200
1265
  }
1201
1266
  class PreferenceTransformer {
1202
1267
  /**
@@ -1251,7 +1316,7 @@ class PreferenceClient extends Client {
1251
1316
  * Get all preferences for a user
1252
1317
  * @param paginationCursor - Optional cursor for pagination
1253
1318
  * @returns Promise resolving to user preferences
1254
- * @see https://www.courier.com/docs/reference/user-preferences/list-all-user-preferences
1319
+ * @see https://www.courier.com/docs/api-reference/user-preferences/get-user-preferences
1255
1320
  */
1256
1321
  async getUserPreferences(props) {
1257
1322
  let url = `${this.options.apiUrls.courier.rest}/users/${this.options.userId}/preferences`;
@@ -1276,7 +1341,7 @@ class PreferenceClient extends Client {
1276
1341
  * Get preferences for a specific topic
1277
1342
  * @param topicId - The ID of the topic to get preferences for
1278
1343
  * @returns Promise resolving to topic preferences
1279
- * @see https://www.courier.com/docs/reference/user-preferences/get-subscription-topic-preferences
1344
+ * @see https://www.courier.com/docs/api-reference/user-preferences/get-user-subscription-topic
1280
1345
  */
1281
1346
  async getUserPreferenceTopic(props) {
1282
1347
  const json = await http({
@@ -1297,7 +1362,7 @@ class PreferenceClient extends Client {
1297
1362
  * @param hasCustomRouting - Whether the topic has custom routing
1298
1363
  * @param customRouting - The custom routing channels for the topic
1299
1364
  * @returns Promise resolving when update is complete
1300
- * @see https://www.courier.com/docs/reference/user-preferences/update-subscription-topic-preferences
1365
+ * @see https://www.courier.com/docs/api-reference/user-preferences/update-or-create-user-preferences-for-subscription-topic
1301
1366
  */
1302
1367
  async putUserPreferenceTopic(props) {
1303
1368
  const payload = {
@@ -1334,7 +1399,7 @@ class TokenClient extends Client {
1334
1399
  * @param token - The push notification token
1335
1400
  * @param provider - The provider of the token
1336
1401
  * @param device - The device information
1337
- * @see https://www.courier.com/docs/reference/token-management/put-token
1402
+ * @see https://www.courier.com/docs/api-reference/device-tokens/add-single-token-to-user
1338
1403
  */
1339
1404
  async putUserToken(props) {
1340
1405
  const payload = {
@@ -1383,7 +1448,7 @@ class ListClient extends Client {
1383
1448
  * Subscribe a user to a list
1384
1449
  * @param listId - The ID of the list to subscribe to
1385
1450
  * @returns Promise resolving when subscription is complete
1386
- * @see https://www.courier.com/docs/reference/lists/recipient-subscribe
1451
+ * @see https://www.courier.com/docs/api-reference/lists/subscribe-user-profile-to-list
1387
1452
  */
1388
1453
  async putSubscription(props) {
1389
1454
  return await http({
@@ -1399,7 +1464,7 @@ class ListClient extends Client {
1399
1464
  * Unsubscribe a user from a list
1400
1465
  * @param listId - The ID of the list to unsubscribe from
1401
1466
  * @returns Promise resolving when unsubscription is complete
1402
- * @see https://www.courier.com/docs/reference/lists/delete-subscription
1467
+ * @see https://www.courier.com/docs/api-reference/lists/unsubscribe-user-profile-from-list
1403
1468
  */
1404
1469
  async deleteSubscription(props) {
1405
1470
  return await http({
@@ -1414,24 +1479,32 @@ class ListClient extends Client {
1414
1479
  }
1415
1480
  class TrackingClient extends Client {
1416
1481
  /**
1417
- * Post an inbound courier event
1418
- * @param event - The event type: Example: "New Order Placed"
1419
- * @param messageId - The message ID
1420
- * @param type - The type of event: Available options: "track"
1421
- * @param properties - The properties of the event
1422
- * @returns Promise resolving to the message ID
1423
- * @see https://www.courier.com/docs/reference/inbound/courier-track-event
1482
+ * @deprecated This method is deprecated and will be removed or changed significantly in a future release.
1483
+ *
1484
+ * Post an inbound courier event. This is typically used for tracking custom events
1485
+ * related to a specific message in Courier.
1486
+ *
1487
+ * @param props - The event properties object containing:
1488
+ * - `clientKey`: The client key associated with your Courier project.
1489
+ * You can get your client key here: https://app.courier.com/settings/api-keys
1490
+ * - `event`: The name of the event (e.g., "New Order Placed").
1491
+ * - `messageId`: The unique ID of the message this event relates to.
1492
+ * - `type`: The type of event. Only supported value: "track".
1493
+ * - `properties`: (Optional) Additional custom properties for the event.
1494
+ * @returns Promise resolving to an object containing the messageId.
1495
+ * @see https://www.courier.com/docs/api-reference/inbound/courier-track-event
1424
1496
  */
1425
1497
  async postInboundCourier(props) {
1498
+ const { clientKey, ...bodyProps } = props;
1426
1499
  return await http({
1427
1500
  url: `${this.options.apiUrls.courier.rest}/inbound/courier`,
1428
1501
  options: this.options,
1429
1502
  method: "POST",
1430
1503
  headers: {
1431
- Authorization: `Bearer ${this.options.accessToken}`
1504
+ "x-courier-client-key": clientKey
1432
1505
  },
1433
1506
  body: {
1434
- ...props,
1507
+ ...bodyProps,
1435
1508
  userId: this.options.userId
1436
1509
  },
1437
1510
  validCodes: [200, 202]
@@ -1520,7 +1593,7 @@ const _CourierClient = class _CourierClient extends Client {
1520
1593
  }
1521
1594
  if (this.options.publicApiKey) {
1522
1595
  (_a = this.options.logger) == null ? void 0 : _a.warn(
1523
- "Courier Warning: Public API Keys are for testing only. Please use JWTs for production.\nYou can generate a JWT with this endpoint: https://www.courier.com/docs/reference/auth/issue-token\nThis endpoint should be called from your backend server, not the SDK."
1596
+ "Courier Warning: Public API Keys are for testing only. Please use JWTs for production.\nYou can generate a JWT with this endpoint: https://www.courier.com/docs/api-reference/authentication/create-jwt\nThis endpoint should be called from your backend server, not the SDK."
1524
1597
  );
1525
1598
  }
1526
1599
  if (this.options.jwt && this.options.publicApiKey) {
@@ -1536,7 +1609,7 @@ __publicField(_CourierClient, "COURIER_JS_NAME", "courier-js");
1536
1609
  * User agent reporting version of the courier-js package.
1537
1610
  * Inlined from package.json at build time.
1538
1611
  */
1539
- __publicField(_CourierClient, "COURIER_JS_VERSION", "2.1.3");
1612
+ __publicField(_CourierClient, "COURIER_JS_VERSION", "3.0.0");
1540
1613
  let CourierClient = _CourierClient;
1541
1614
  class AuthenticationListener {
1542
1615
  constructor(callback) {