@trycourier/courier-js 2.0.0-beta → 2.0.2-beta
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 -0
- package/dist/client/brand-client.d.ts +2 -0
- package/dist/client/courier-client.d.ts +1 -2
- package/dist/client/inbox-client.d.ts +23 -0
- package/dist/client/list-client.d.ts +4 -0
- package/dist/client/preference-client.d.ts +15 -6
- package/dist/client/token-client.d.ts +5 -0
- package/dist/client/tracking-client.d.ts +8 -0
- package/dist/index.js +1 -1
- package/dist/index.mjs +101 -31
- package/dist/socket/inbox-socket.d.ts +1 -1
- package/package.json +3 -1
package/README.md
ADDED
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
# @trycourier/courier-js
|
|
2
|
+
|
|
3
|
+
The base API client and shared instance singleton for Courier's JavaScript Browser SDK.
|
|
4
|
+
|
|
5
|
+
## Installation
|
|
6
|
+
|
|
7
|
+
```ts
|
|
8
|
+
npm i @trycourier/courier-js@2.0.1-beta
|
|
9
|
+
```
|
|
10
|
+
|
|
11
|
+
## Usage
|
|
12
|
+
|
|
13
|
+
```ts
|
|
14
|
+
const courierClient = new CourierClient({
|
|
15
|
+
userId: 'mike',
|
|
16
|
+
jwt: 'ey...n0'
|
|
17
|
+
});
|
|
18
|
+
|
|
19
|
+
// Fetch the inbox messages for the user
|
|
20
|
+
const messages = await courierClient.inbox.getMessages();
|
|
21
|
+
console.log(messages);
|
|
22
|
+
```
|
|
@@ -3,6 +3,8 @@ import { Client } from './client';
|
|
|
3
3
|
export declare class BrandClient extends Client {
|
|
4
4
|
/**
|
|
5
5
|
* Get a brand by ID using GraphQL
|
|
6
|
+
* @param brandId - The ID of the brand to retrieve
|
|
7
|
+
* @returns Promise resolving to the requested brand
|
|
6
8
|
*/
|
|
7
9
|
getBrand(props: {
|
|
8
10
|
brandId: string;
|
|
@@ -23,10 +23,9 @@ export interface CourierClientOptions {
|
|
|
23
23
|
readonly connectionId?: string;
|
|
24
24
|
readonly tenantId?: string;
|
|
25
25
|
readonly showLogs?: boolean;
|
|
26
|
-
readonly apiUrls?: CourierApiUrls;
|
|
27
26
|
readonly accessToken?: string;
|
|
28
27
|
readonly logger: Logger;
|
|
29
|
-
readonly
|
|
28
|
+
readonly apiUrls: CourierApiUrls;
|
|
30
29
|
}
|
|
31
30
|
export declare class CourierClient extends Client {
|
|
32
31
|
readonly tokens: TokenClient;
|
|
@@ -7,6 +7,9 @@ export declare class InboxClient extends Client {
|
|
|
7
7
|
constructor(options: CourierClientOptions);
|
|
8
8
|
/**
|
|
9
9
|
* Get paginated messages
|
|
10
|
+
* @param paginationLimit - Number of messages to return per page (default: 24)
|
|
11
|
+
* @param startCursor - Cursor for pagination
|
|
12
|
+
* @returns Promise resolving to paginated messages response
|
|
10
13
|
*/
|
|
11
14
|
getMessages(props?: {
|
|
12
15
|
paginationLimit?: number;
|
|
@@ -14,6 +17,9 @@ export declare class InboxClient extends Client {
|
|
|
14
17
|
}): Promise<CourierGetInboxMessagesResponse>;
|
|
15
18
|
/**
|
|
16
19
|
* Get paginated archived messages
|
|
20
|
+
* @param paginationLimit - Number of messages to return per page (default: 24)
|
|
21
|
+
* @param startCursor - Cursor for pagination
|
|
22
|
+
* @returns Promise resolving to paginated archived messages response
|
|
17
23
|
*/
|
|
18
24
|
getArchivedMessages(props?: {
|
|
19
25
|
paginationLimit?: number;
|
|
@@ -21,10 +27,14 @@ export declare class InboxClient extends Client {
|
|
|
21
27
|
}): Promise<CourierGetInboxMessagesResponse>;
|
|
22
28
|
/**
|
|
23
29
|
* Get unread message count
|
|
30
|
+
* @returns Promise resolving to number of unread messages
|
|
24
31
|
*/
|
|
25
32
|
getUnreadMessageCount(): Promise<number>;
|
|
26
33
|
/**
|
|
27
34
|
* Track a click event
|
|
35
|
+
* @param messageId - ID of the message
|
|
36
|
+
* @param trackingId - ID for tracking the click
|
|
37
|
+
* @returns Promise resolving when click is tracked
|
|
28
38
|
*/
|
|
29
39
|
click(props: {
|
|
30
40
|
messageId: string;
|
|
@@ -32,30 +42,43 @@ export declare class InboxClient extends Client {
|
|
|
32
42
|
}): Promise<void>;
|
|
33
43
|
/**
|
|
34
44
|
* Mark a message as read
|
|
45
|
+
* @param messageId - ID of the message to mark as read
|
|
46
|
+
* @returns Promise resolving when message is marked as read
|
|
35
47
|
*/
|
|
36
48
|
read(props: {
|
|
37
49
|
messageId: string;
|
|
38
50
|
}): Promise<void>;
|
|
39
51
|
/**
|
|
40
52
|
* Mark a message as unread
|
|
53
|
+
* @param messageId - ID of the message to mark as unread
|
|
54
|
+
* @returns Promise resolving when message is marked as unread
|
|
41
55
|
*/
|
|
42
56
|
unread(props: {
|
|
43
57
|
messageId: string;
|
|
44
58
|
}): Promise<void>;
|
|
45
59
|
/**
|
|
46
60
|
* Mark all messages as read
|
|
61
|
+
* @returns Promise resolving when all messages are marked as read
|
|
47
62
|
*/
|
|
48
63
|
readAll(): Promise<void>;
|
|
49
64
|
/**
|
|
50
65
|
* Mark a message as opened
|
|
66
|
+
* @param messageId - ID of the message to mark as opened
|
|
67
|
+
* @returns Promise resolving when message is marked as opened
|
|
51
68
|
*/
|
|
52
69
|
open(props: {
|
|
53
70
|
messageId: string;
|
|
54
71
|
}): Promise<void>;
|
|
55
72
|
/**
|
|
56
73
|
* Archive a message
|
|
74
|
+
* @param messageId - ID of the message to archive
|
|
75
|
+
* @returns Promise resolving when message is archived
|
|
57
76
|
*/
|
|
58
77
|
archive(props: {
|
|
59
78
|
messageId: string;
|
|
60
79
|
}): Promise<void>;
|
|
80
|
+
/**
|
|
81
|
+
* Archive all read messages.
|
|
82
|
+
*/
|
|
83
|
+
archiveRead(): Promise<void>;
|
|
61
84
|
}
|
|
@@ -2,6 +2,8 @@ import { Client } from './client';
|
|
|
2
2
|
export declare class ListClient extends Client {
|
|
3
3
|
/**
|
|
4
4
|
* Subscribe a user to a list
|
|
5
|
+
* @param listId - The ID of the list to subscribe to
|
|
6
|
+
* @returns Promise resolving when subscription is complete
|
|
5
7
|
* @see https://www.courier.com/docs/reference/lists/recipient-subscribe
|
|
6
8
|
*/
|
|
7
9
|
putSubscription(props: {
|
|
@@ -9,6 +11,8 @@ export declare class ListClient extends Client {
|
|
|
9
11
|
}): Promise<void>;
|
|
10
12
|
/**
|
|
11
13
|
* Unsubscribe a user from a list
|
|
14
|
+
* @param listId - The ID of the list to unsubscribe from
|
|
15
|
+
* @returns Promise resolving when unsubscription is complete
|
|
12
16
|
* @see https://www.courier.com/docs/reference/lists/delete-subscription
|
|
13
17
|
*/
|
|
14
18
|
deleteSubscription(props: {
|
|
@@ -4,23 +4,32 @@ export declare class PreferenceClient extends Client {
|
|
|
4
4
|
private transformer;
|
|
5
5
|
/**
|
|
6
6
|
* Get all preferences for a user
|
|
7
|
+
* @param paginationCursor - Optional cursor for pagination
|
|
8
|
+
* @returns Promise resolving to user preferences
|
|
7
9
|
* @see https://www.courier.com/docs/reference/user-preferences/list-all-user-preferences
|
|
8
10
|
*/
|
|
9
|
-
getUserPreferences(
|
|
11
|
+
getUserPreferences(props?: {
|
|
10
12
|
paginationCursor?: string;
|
|
11
13
|
}): Promise<CourierUserPreferences>;
|
|
12
14
|
/**
|
|
13
15
|
* Get preferences for a specific topic
|
|
16
|
+
* @param topicId - The ID of the topic to get preferences for
|
|
17
|
+
* @returns Promise resolving to topic preferences
|
|
14
18
|
* @see https://www.courier.com/docs/reference/user-preferences/get-subscription-topic-preferences
|
|
15
19
|
*/
|
|
16
|
-
getUserPreferenceTopic(
|
|
20
|
+
getUserPreferenceTopic(props: {
|
|
17
21
|
topicId: string;
|
|
18
22
|
}): Promise<CourierUserPreferencesTopic>;
|
|
19
23
|
/**
|
|
20
24
|
* Update preferences for a specific topic
|
|
25
|
+
* @param topicId - The ID of the topic to update preferences for
|
|
26
|
+
* @param status - The new status for the topic
|
|
27
|
+
* @param hasCustomRouting - Whether the topic has custom routing
|
|
28
|
+
* @param customRouting - The custom routing channels for the topic
|
|
29
|
+
* @returns Promise resolving when update is complete
|
|
21
30
|
* @see https://www.courier.com/docs/reference/user-preferences/update-subscription-topic-preferences
|
|
22
31
|
*/
|
|
23
|
-
putUserPreferenceTopic(
|
|
32
|
+
putUserPreferenceTopic(props: {
|
|
24
33
|
topicId: string;
|
|
25
34
|
status: CourierUserPreferencesStatus;
|
|
26
35
|
hasCustomRouting: boolean;
|
|
@@ -28,10 +37,10 @@ export declare class PreferenceClient extends Client {
|
|
|
28
37
|
}): Promise<void>;
|
|
29
38
|
/**
|
|
30
39
|
* Get the notification center URL
|
|
31
|
-
* @param
|
|
32
|
-
* @returns
|
|
40
|
+
* @param clientKey - The client key to use for the URL
|
|
41
|
+
* @returns The notification center URL
|
|
33
42
|
*/
|
|
34
|
-
getNotificationCenterUrl(
|
|
43
|
+
getNotificationCenterUrl(props: {
|
|
35
44
|
clientKey: string;
|
|
36
45
|
}): string;
|
|
37
46
|
}
|
|
@@ -3,6 +3,9 @@ import { Client } from './client';
|
|
|
3
3
|
export declare class TokenClient extends Client {
|
|
4
4
|
/**
|
|
5
5
|
* Store a push notification token for a user
|
|
6
|
+
* @param token - The push notification token
|
|
7
|
+
* @param provider - The provider of the token
|
|
8
|
+
* @param device - The device information
|
|
6
9
|
* @see https://www.courier.com/docs/reference/token-management/put-token
|
|
7
10
|
*/
|
|
8
11
|
putUserToken(props: {
|
|
@@ -12,6 +15,8 @@ export declare class TokenClient extends Client {
|
|
|
12
15
|
}): Promise<void>;
|
|
13
16
|
/**
|
|
14
17
|
* Delete a push notification token for a user
|
|
18
|
+
* @param token - The push notification token
|
|
19
|
+
* @returns Promise resolving when token is deleted
|
|
15
20
|
*/
|
|
16
21
|
deleteUserToken(props: {
|
|
17
22
|
token: string;
|
|
@@ -3,6 +3,11 @@ import { Client } from './client';
|
|
|
3
3
|
export declare class TrackingClient extends Client {
|
|
4
4
|
/**
|
|
5
5
|
* Post an inbound courier event
|
|
6
|
+
* @param event - The event type: Example: "New Order Placed"
|
|
7
|
+
* @param messageId - The message ID
|
|
8
|
+
* @param type - The type of event: Available options: "track"
|
|
9
|
+
* @param properties - The properties of the event
|
|
10
|
+
* @returns Promise resolving to the message ID
|
|
6
11
|
* @see https://www.courier.com/docs/reference/inbound/courier-track-event
|
|
7
12
|
*/
|
|
8
13
|
postInboundCourier(props: {
|
|
@@ -16,6 +21,9 @@ export declare class TrackingClient extends Client {
|
|
|
16
21
|
/**
|
|
17
22
|
* Post a tracking URL event
|
|
18
23
|
* These urls are found in messages sent from Courier
|
|
24
|
+
* @param url - The URL to post the event to
|
|
25
|
+
* @param event - The event type: Available options: "click", "open", "unsubscribe"
|
|
26
|
+
* @returns Promise resolving when the event is posted
|
|
19
27
|
*/
|
|
20
28
|
postTrackingUrl(props: {
|
|
21
29
|
url: string;
|
package/dist/index.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
!function(t,e){"object"==typeof exports&&"undefined"!=typeof module?e(exports):"function"==typeof define&&define.amd?define(["exports"],e):e((t="undefined"!=typeof globalThis?globalThis:t||self).CourierJS={})}(this,(function(t){"use strict";var e=Object.defineProperty,s=(t,s,n)=>((t,s,n)=>s in t?e(t,s,{enumerable:!0,configurable:!0,writable:!0,value:n}):t[s]=n)(t,"symbol"!=typeof s?s+"":s,n);const n=class t{constructor(t,e){s(this,"webSocket",null),s(this,"pingInterval",null),s(this,"onOpen"),s(this,"onMessageReceived"),s(this,"onClose"),s(this,"onError"),s(this,"url"),s(this,"options"),this.url=t,this.options=e}get isConnected(){return null!==this.webSocket}async connect(){return this.disconnect(),new Promise(((t,e)=>{try{this.webSocket=new WebSocket(this.url),this.webSocket.onopen=()=>{var e;null==(e=this.onOpen)||e.call(this),t()},this.webSocket.onmessage=t=>{var e;null==(e=this.onMessageReceived)||e.call(this,t.data)},this.webSocket.onclose=t=>{var e;this.webSocket=null,null==(e=this.onClose)||e.call(this,t.code,t.reason)},this.webSocket.onerror=t=>{var s;this.webSocket=null;const n=new Error("Courier Socket connection failed");n.originalEvent=t,null==(s=this.onError)||s.call(this,n),e(n)}}catch(s){this.webSocket=null,e(s)}}))}disconnect(){this.stopPing(),this.webSocket&&(this.webSocket.close(t.NORMAL_CLOSURE_STATUS),this.webSocket=null)}async send(t){if(!this.webSocket)return!1;const e=JSON.stringify(t);return void 0!==this.webSocket.send(e)}keepAlive(t){this.stopPing(),this.pingInterval=setInterval((async()=>{var t;try{await this.send({action:"keepAlive"})}catch(e){null==(t=this.options.logger)||t.error("Error occurred on Keep Alive:",e)}}),(null==t?void 0:t.intervalInMillis)??3e5)}stopPing(){this.pingInterval&&(clearInterval(this.pingInterval),this.pingInterval=null)}};s(n,"NORMAL_CLOSURE_STATUS",1e3);let o=n;const i=t=>({courier:{rest:(null==t?void 0:t.courier.rest)||"https://api.courier.com",graphql:(null==t?void 0:t.courier.graphql)||"https://api.courier.com/client/q"},inbox:{graphql:(null==t?void 0:t.inbox.graphql)||"https://inbox.courier.com/q",webSocket:(null==t?void 0:t.inbox.webSocket)||"wss://realtime.courier.com"}});class r{constructor(t){s(this,"PREFIX","[COURIER]"),this.showLogs=t}warn(t,...e){this.showLogs&&console.warn(`${this.PREFIX} ${t}`,...e)}log(t,...e){this.showLogs&&console.log(`${this.PREFIX} ${t}`,...e)}error(t,...e){this.showLogs&&console.error(`${this.PREFIX} ${t}`,...e)}debug(t,...e){this.showLogs&&console.debug(`${this.PREFIX} ${t}`,...e)}info(t,...e){this.showLogs&&console.info(`${this.PREFIX} ${t}`,...e)}}class a{static generate(t){const e=Math.random().toString(36).substring(2,15)+Math.random().toString(36).substring(2,15);return t?t+e:e}}class c extends Error{constructor(t,e,s){super(e),this.code=t,this.type=s,this.name="CourierRequestError"}}function u(t,e,s,n){t.log(`\n📡 New Courier ${s} Request: ${e}\nURL: ${n.url}\n${n.method?`Method: ${n.method}`:""}\n${n.query?`Query: ${n.query}`:""}\n${n.variables?`Variables: ${JSON.stringify(n.variables,null,2)}`:""}\nHeaders: ${JSON.stringify(n.headers,null,2)}\nBody: ${n.body?JSON.stringify(n.body,null,2):"Empty"}\n `)}function h(t,e,s,n){t.log(`\n📡 New Courier ${s} Response: ${e}\nStatus Code: ${n.status}\nResponse JSON: ${JSON.stringify(n.response,null,2)}\n `)}async function l(t){const e=t.validCodes??[200],s=t.options.showLogs?a.generate():void 0,n=new Request(t.url,{method:t.method,headers:{"Content-Type":"application/json",...t.headers},body:t.body?JSON.stringify(t.body):void 0});s&&u(t.options.logger,s,"HTTP",{url:n.url,method:n.method,headers:Object.fromEntries(n.headers.entries()),body:t.body});const o=await fetch(n);if(204===o.status)return;let i;try{i=await o.json()}catch(r){if(200===o.status)return;throw new c(o.status,"Failed to parse response as JSON","PARSE_ERROR")}if(s&&h(t.options.logger,s,"HTTP",{status:o.status,response:i}),!e.includes(o.status))throw new c(o.status,(null==i?void 0:i.message)||"Unknown Error",null==i?void 0:i.type);return i}async function d(t){const e=t.options.showLogs?a.generate():void 0;e&&u(t.options.logger,e,"GraphQL",{url:t.url,headers:t.headers,query:t.query,variables:t.variables});const s=await fetch(t.url,{method:"POST",headers:{"Content-Type":"application/json",...t.headers},body:JSON.stringify({query:t.query,variables:t.variables})});let n;try{n=await s.json()}catch(o){throw new c(s.status,"Failed to parse response as JSON","PARSE_ERROR")}if(e&&h(t.options.logger,e,"GraphQL",{status:s.status,response:n}),!s.ok)throw new c(s.status,(null==n?void 0:n.message)||"Unknown Error",null==n?void 0:n.type);return n}class p{constructor(t){this.options=t}}class g extends p{async getBrand(t){const e=`\n query GetBrand {\n brand(brandId: "${t.brandId}") {\n settings {\n colors {\n primary\n secondary\n tertiary\n }\n inapp {\n borderRadius\n disableCourierFooter\n }\n }\n }\n }\n `;return(await d({options:this.options,url:this.options.urls.courier.graphql,headers:{"x-courier-user-id":this.options.userId,"x-courier-client-key":"empty",Authorization:`Bearer ${this.options.accessToken}`},query:e,variables:{brandId:t.brandId}})).data.brand}}class m extends o{constructor(t){super(m.buildUrl(t),t),s(this,"receivedMessage"),s(this,"receivedMessageEvent"),this.onMessageReceived=t=>this.convertToType(t)}convertToType(t){var e,s,n,o;try{switch(JSON.parse(t).type){case"event":const n=JSON.parse(t);null==(e=this.receivedMessageEvent)||e.call(this,n);break;case"message":const o=JSON.parse(t);null==(s=this.receivedMessage)||s.call(this,o)}}catch(i){null==(n=this.options.logger)||n.error("Error parsing socket message",i),i instanceof Error&&(null==(o=this.onError)||o.call(this,i))}}async sendSubscribe(t){var e;const s={action:"subscribe",data:{userAgent:"courier-js",channel:this.options.userId,event:"*",version:(null==t?void 0:t.version)??5}};this.options.connectionId&&(s.data.clientSourceId=this.options.connectionId),this.options.tenantId&&(s.data.accountId=this.options.tenantId),null==(e=this.options.logger)||e.debug("Sending subscribe request",s),await this.send(s)}static buildUrl(t){var e;let s=(null==(e=t.apiUrls)?void 0:e.inbox.webSocket)??"";return t.accessToken&&(s+=`/?auth=${t.accessToken}`),s}}class I extends p{constructor(t){super(t),s(this,"socket"),this.socket=new m(t)}async getMessages(t){const e=`\n query GetInboxMessages(\n $params: FilterParamsInput = { ${this.options.tenantId?`accountId: "${this.options.tenantId}"`:""} }\n $limit: Int = ${(null==t?void 0:t.paginationLimit)??24}\n $after: String ${(null==t?void 0:t.startCursor)?`= "${t.startCursor}"`:""}\n ) {\n count(params: $params)\n messages(params: $params, limit: $limit, after: $after) {\n totalCount\n pageInfo {\n startCursor\n hasNextPage\n }\n nodes {\n messageId\n read\n archived\n created\n opened\n title\n preview\n data\n tags\n trackingIds {\n clickTrackingId\n }\n actions {\n content\n data\n href\n }\n }\n }\n }\n `;return await d({options:this.options,query:e,headers:{"x-courier-user-id":this.options.userId,Authorization:`Bearer ${this.options.accessToken}`},url:this.options.urls.inbox.graphql})}async getArchivedMessages(t){const e=`\n query GetInboxMessages(\n $params: FilterParamsInput = { ${this.options.tenantId?`accountId: "${this.options.tenantId}"`:""}, archived: true }\n $limit: Int = ${(null==t?void 0:t.paginationLimit)??24}\n $after: String ${(null==t?void 0:t.startCursor)?`= "${t.startCursor}"`:""}\n ) {\n count(params: $params)\n messages(params: $params, limit: $limit, after: $after) {\n totalCount\n pageInfo {\n startCursor\n hasNextPage\n }\n nodes {\n messageId\n read\n archived\n created\n opened\n title\n preview\n data\n tags\n trackingIds {\n clickTrackingId\n }\n actions {\n content\n data\n href\n }\n }\n }\n }\n `;return d({options:this.options,query:e,headers:{"x-courier-user-id":this.options.userId,Authorization:`Bearer ${this.options.accessToken}`},url:this.options.urls.inbox.graphql})}async getUnreadMessageCount(){var t;const e=`\n query GetMessages {\n count(params: { status: "unread" ${this.options.tenantId?`, accountId: "${this.options.tenantId}"`:""} })\n }\n `;return(null==(t=(await d({options:this.options,query:e,headers:{"x-courier-user-id":this.options.userId,Authorization:`Bearer ${this.options.accessToken}`},url:this.options.urls.inbox.graphql})).data)?void 0:t.count)??0}async click(t){const e=`\n mutation TrackEvent {\n clicked(messageId: "${t.messageId}", trackingId: "${t.trackingId}")\n }\n `,s={"x-courier-user-id":this.options.userId,Authorization:`Bearer ${this.options.accessToken}`};this.options.connectionId&&(s["x-courier-client-source-id"]=this.options.connectionId),await d({options:this.options,query:e,headers:s,url:this.options.urls.inbox.graphql})}async read(t){const e=`\n mutation TrackEvent {\n read(messageId: "${t.messageId}")\n }\n `,s={"x-courier-user-id":this.options.userId,Authorization:`Bearer ${this.options.accessToken}`};this.options.connectionId&&(s["x-courier-client-source-id"]=this.options.connectionId),await d({options:this.options,query:e,headers:s,url:this.options.urls.inbox.graphql})}async unread(t){const e=`\n mutation TrackEvent {\n unread(messageId: "${t.messageId}")\n }\n `,s={"x-courier-user-id":this.options.userId,Authorization:`Bearer ${this.options.accessToken}`};this.options.connectionId&&(s["x-courier-client-source-id"]=this.options.connectionId),await d({options:this.options,query:e,headers:s,url:this.options.urls.inbox.graphql})}async readAll(){const t={"x-courier-user-id":this.options.userId,Authorization:`Bearer ${this.options.accessToken}`};this.options.connectionId&&(t["x-courier-client-source-id"]=this.options.connectionId),await d({options:this.options,query:"\n mutation TrackEvent {\n markAllRead\n }\n ",headers:t,url:this.options.urls.inbox.graphql})}async open(t){const e=`\n mutation TrackEvent {\n opened(messageId: "${t.messageId}")\n }\n `,s={"x-courier-user-id":this.options.userId,Authorization:`Bearer ${this.options.accessToken}`};this.options.connectionId&&(s["x-courier-client-source-id"]=this.options.connectionId),await d({options:this.options,query:e,headers:s,url:this.options.urls.inbox.graphql})}async archive(t){const e=`\n mutation TrackEvent {\n archive(messageId: "${t.messageId}")\n }\n `,s={"x-courier-user-id":this.options.userId,Authorization:`Bearer ${this.options.accessToken}`};this.options.connectionId&&(s["x-courier-client-source-id"]=this.options.connectionId),await d({options:this.options,query:e,headers:s,url:this.options.urls.inbox.graphql})}}class b{transformItem(t){return{topicId:t.topic_id,topicName:t.topic_name,sectionId:t.section_id,sectionName:t.section_name,status:t.status,defaultStatus:t.default_status,hasCustomRouting:t.has_custom_routing,customRouting:t.custom_routing||[]}}*transform(t){for(const e of t)yield this.transformItem(e)}}class v extends p{constructor(){super(...arguments),s(this,"transformer",new b)}async getUserPreferences(t){let e=`${this.options.urls.courier.rest}/users/${this.options.userId}/preferences`;(null==t?void 0:t.paginationCursor)&&(e+=`?cursor=${t.paginationCursor}`);const s=await l({options:this.options,url:e,method:"GET",headers:{Authorization:`Bearer ${this.options.accessToken}`}});return{items:[...this.transformer.transform(s.items)],paging:s.paging}}async getUserPreferenceTopic(t){const e=await l({options:this.options,url:`${this.options.urls.courier.rest}/users/${this.options.userId}/preferences/${t.topicId}`,method:"GET",headers:{Authorization:`Bearer ${this.options.accessToken}`}});return this.transformer.transformItem(e.topic)}async putUserPreferenceTopic(t){const e={topic:{status:t.status,has_custom_routing:t.hasCustomRouting,custom_routing:t.customRouting}};await l({options:this.options,url:`${this.options.urls.courier.rest}/users/${this.options.userId}/preferences/${t.topicId}`,method:"PUT",headers:{Authorization:`Bearer ${this.options.accessToken}`},body:e})}getNotificationCenterUrl(t){return`https://view.notificationcenter.app/p/${function(t){const e=new Uint8Array(t.length);for(let s=0;s<t.length;s++)e[s]=t.charCodeAt(s);return btoa(String.fromCharCode(...e))}(`${function(t){const e=atob(t),s=new Uint8Array(e.length);for(let n=0;n<e.length;n++)s[n]=e.charCodeAt(n);return String.fromCharCode(...s)}(t.clientKey)}#${this.options.userId}${this.options.tenantId?`#${this.options.tenantId}`:""}#false`)}`}}class y extends p{async putUserToken(t){const e={provider_key:t.provider,...t.device&&{device:{app_id:t.device.appId,ad_id:t.device.adId,device_id:t.device.deviceId,platform:t.device.platform,manufacturer:t.device.manufacturer,model:t.device.model}}};await l({options:this.options,url:`${this.options.urls.courier.rest}/users/${this.options.userId}/tokens/${t.token}`,method:"PUT",headers:{Authorization:`Bearer ${this.options.accessToken}`},body:e,validCodes:[200,204]})}async deleteUserToken(t){await l({options:this.options,url:`${this.options.urls.courier.rest}/users/${this.options.userId}/tokens/${t.token}`,method:"DELETE",headers:{Authorization:`Bearer ${this.options.accessToken}`},validCodes:[200,204]})}}class w extends p{async putSubscription(t){return await l({url:`${this.options.urls.courier.rest}/lists/${t.listId}/subscriptions/${this.options.userId}`,options:this.options,method:"PUT",headers:{Authorization:`Bearer ${this.options.accessToken}`}})}async deleteSubscription(t){return await l({url:`${this.options.urls.courier.rest}/lists/${t.listId}/subscriptions/${this.options.userId}`,options:this.options,method:"DELETE",headers:{Authorization:`Bearer ${this.options.accessToken}`}})}}class $ extends p{async postInboundCourier(t){return await l({url:`${this.options.urls.courier.rest}/inbound/courier`,options:this.options,method:"POST",headers:{Authorization:`Bearer ${this.options.accessToken}`},body:{...t,userId:this.options.userId},validCodes:[200,202]})}async postTrackingUrl(t){return await l({url:t.url,options:this.options,method:"POST",body:{event:t.event}})}}class f extends p{constructor(t){var e,n;const o=void 0!==t.showLogs?t.showLogs:"development"===process.env.NODE_ENV,a={...t,showLogs:o,apiUrls:t.apiUrls||i(),accessToken:t.jwt??t.publicApiKey};super({...a,logger:new r(a.showLogs),urls:i(a.apiUrls)}),s(this,"tokens"),s(this,"brands"),s(this,"preferences"),s(this,"inbox"),s(this,"lists"),s(this,"tracking"),this.tokens=new y(this.options),this.brands=new g(this.options),this.preferences=new v(this.options),this.inbox=new I(this.options),this.lists=new w(this.options),this.tracking=new $(this.options),this.options.jwt||this.options.publicApiKey||this.options.logger.warn("Courier Client initialized with no authentication method. Please provide a JWT or public API key."),this.options.publicApiKey&&(null==(e=this.options.logger)||e.warn("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.")),this.options.jwt&&this.options.publicApiKey&&(null==(n=this.options.logger)||n.warn("Courier Warning: Both a JWT and a Public API Key were provided. The Public API Key will be ignored."))}}class k{constructor(t){s(this,"callback"),this.callback=t}remove(){S.shared.removeAuthenticationListener(this)}}const T=class t{constructor(){s(this,"id",a.generate()),s(this,"instanceClient"),s(this,"_paginationLimit",24),s(this,"authenticationListeners",[])}get paginationLimit(){return this._paginationLimit}set paginationLimit(t){this._paginationLimit=Math.min(Math.max(t,1),100)}get client(){return this.instanceClient}static get shared(){return t.instance||(t.instance=new t),t.instance}signIn(t){const e=t.connectionId??a.generate();this.instanceClient=new f({...t,connectionId:e}),this.notifyAuthenticationListeners({userId:t.userId})}signOut(){this.instanceClient=void 0,this.notifyAuthenticationListeners({userId:void 0})}addAuthenticationListener(t){var e;null==(e=this.instanceClient)||e.options.logger.info("Adding authentication listener");const s=new k(t);return this.authenticationListeners.push(s),s}removeAuthenticationListener(t){var e;null==(e=this.instanceClient)||e.options.logger.info("Removing authentication listener"),this.authenticationListeners=this.authenticationListeners.filter((e=>e!==t))}notifyAuthenticationListeners(t){this.authenticationListeners.forEach((e=>e.callback(t)))}};s(T,"instance");let S=T;t.BrandClient=g,t.Courier=S,t.CourierClient=f,t.CourierSocket=o,t.InboxClient=I,t.ListClient=w,t.PreferenceClient=v,t.TokenClient=y,Object.defineProperty(t,Symbol.toStringTag,{value:"Module"})}));
|
|
1
|
+
!function(t,e){"object"==typeof exports&&"undefined"!=typeof module?e(exports):"function"==typeof define&&define.amd?define(["exports"],e):e((t="undefined"!=typeof globalThis?globalThis:t||self).CourierJS={})}(this,(function(t){"use strict";var e=Object.defineProperty,s=(t,s,n)=>((t,s,n)=>s in t?e(t,s,{enumerable:!0,configurable:!0,writable:!0,value:n}):t[s]=n)(t,"symbol"!=typeof s?s+"":s,n);const n=class t{constructor(t,e){s(this,"webSocket",null),s(this,"pingInterval",null),s(this,"onOpen"),s(this,"onMessageReceived"),s(this,"onClose"),s(this,"onError"),s(this,"url"),s(this,"options"),this.url=t,this.options=e}get isConnected(){return null!==this.webSocket}async connect(){return this.disconnect(),new Promise(((t,e)=>{try{this.webSocket=new WebSocket(this.url),this.webSocket.onopen=()=>{var e;null==(e=this.onOpen)||e.call(this),t()},this.webSocket.onmessage=t=>{var e;null==(e=this.onMessageReceived)||e.call(this,t.data)},this.webSocket.onclose=t=>{var e;this.webSocket=null,null==(e=this.onClose)||e.call(this,t.code,t.reason)},this.webSocket.onerror=t=>{var s;this.webSocket=null;const n=new Error("Courier Socket connection failed");n.originalEvent=t,null==(s=this.onError)||s.call(this,n),e(n)}}catch(s){this.webSocket=null,e(s)}}))}disconnect(){this.stopPing(),this.webSocket&&(this.webSocket.close(t.NORMAL_CLOSURE_STATUS),this.webSocket=null)}async send(t){if(!this.webSocket)return!1;const e=JSON.stringify(t);return void 0!==this.webSocket.send(e)}keepAlive(t){this.stopPing(),this.pingInterval=setInterval((async()=>{var t;try{await this.send({action:"keepAlive"})}catch(e){null==(t=this.options.logger)||t.error("Error occurred on Keep Alive:",e)}}),(null==t?void 0:t.intervalInMillis)??3e5)}stopPing(){this.pingInterval&&(clearInterval(this.pingInterval),this.pingInterval=null)}};s(n,"NORMAL_CLOSURE_STATUS",1e3);let i=n;const o=t=>({courier:{rest:(null==t?void 0:t.courier.rest)||"https://api.courier.com",graphql:(null==t?void 0:t.courier.graphql)||"https://api.courier.com/client/q"},inbox:{graphql:(null==t?void 0:t.inbox.graphql)||"https://inbox.courier.com/q",webSocket:(null==t?void 0:t.inbox.webSocket)||"wss://realtime.courier.com"}});class r{constructor(t){s(this,"PREFIX","[COURIER]"),this.showLogs=t}warn(t,...e){this.showLogs&&console.warn(`${this.PREFIX} ${t}`,...e)}log(t,...e){this.showLogs&&console.log(`${this.PREFIX} ${t}`,...e)}error(t,...e){this.showLogs&&console.error(`${this.PREFIX} ${t}`,...e)}debug(t,...e){this.showLogs&&console.debug(`${this.PREFIX} ${t}`,...e)}info(t,...e){this.showLogs&&console.info(`${this.PREFIX} ${t}`,...e)}}class a{static generate(t){const e=Math.random().toString(36).substring(2,15)+Math.random().toString(36).substring(2,15);return t?t+e:e}}class c extends Error{constructor(t,e,s){super(e),this.code=t,this.type=s,this.name="CourierRequestError"}}function u(t,e,s,n){t.log(`\n📡 New Courier ${s} Request: ${e}\nURL: ${n.url}\n${n.method?`Method: ${n.method}`:""}\n${n.query?`Query: ${n.query}`:""}\n${n.variables?`Variables: ${JSON.stringify(n.variables,null,2)}`:""}\nHeaders: ${JSON.stringify(n.headers,null,2)}\nBody: ${n.body?JSON.stringify(n.body,null,2):"Empty"}\n `)}function h(t,e,s,n){t.log(`\n📡 New Courier ${s} Response: ${e}\nStatus Code: ${n.status}\nResponse JSON: ${JSON.stringify(n.response,null,2)}\n `)}async function l(t){const e=t.validCodes??[200],s=t.options.showLogs?a.generate():void 0,n=new Request(t.url,{method:t.method,headers:{"Content-Type":"application/json",...t.headers},body:t.body?JSON.stringify(t.body):void 0});s&&u(t.options.logger,s,"HTTP",{url:n.url,method:n.method,headers:Object.fromEntries(n.headers.entries()),body:t.body});const i=await fetch(n);if(204===i.status)return;let o;try{o=await i.json()}catch(r){if(200===i.status)return;throw new c(i.status,"Failed to parse response as JSON","PARSE_ERROR")}if(s&&h(t.options.logger,s,"HTTP",{status:i.status,response:o}),!e.includes(i.status))throw new c(i.status,(null==o?void 0:o.message)||"Unknown Error",null==o?void 0:o.type);return o}async function d(t){const e=t.options.showLogs?a.generate():void 0;e&&u(t.options.logger,e,"GraphQL",{url:t.url,headers:t.headers,query:t.query,variables:t.variables});const s=await fetch(t.url,{method:"POST",headers:{"Content-Type":"application/json",...t.headers},body:JSON.stringify({query:t.query,variables:t.variables})});let n;try{n=await s.json()}catch(i){throw new c(s.status,"Failed to parse response as JSON","PARSE_ERROR")}if(e&&h(t.options.logger,e,"GraphQL",{status:s.status,response:n}),!s.ok)throw new c(s.status,(null==n?void 0:n.message)||"Unknown Error",null==n?void 0:n.type);return n}class p{constructor(t){this.options=t}}class g extends p{async getBrand(t){const e=`\n query GetBrand {\n brand(brandId: "${t.brandId}") {\n settings {\n colors {\n primary\n secondary\n tertiary\n }\n inapp {\n borderRadius\n disableCourierFooter\n }\n }\n }\n }\n `;return(await d({options:this.options,url:this.options.apiUrls.courier.graphql,headers:{"x-courier-user-id":this.options.userId,"x-courier-client-key":"empty",Authorization:`Bearer ${this.options.accessToken}`},query:e,variables:{brandId:t.brandId}})).data.brand}}class m extends i{constructor(t){super(m.buildUrl(t),t),s(this,"receivedMessage"),s(this,"receivedMessageEvent"),this.onMessageReceived=t=>this.convertToType(t)}convertToType(t){var e,s,n,i;try{switch(JSON.parse(t).type){case"event":const n=JSON.parse(t);null==(e=this.receivedMessageEvent)||e.call(this,n);break;case"message":const i=JSON.parse(t);null==(s=this.receivedMessage)||s.call(this,i)}}catch(o){null==(n=this.options.logger)||n.error("Error parsing socket message",o),o instanceof Error&&(null==(i=this.onError)||i.call(this,o))}}async sendSubscribe(t){var e;const s={action:"subscribe",data:{userAgent:"courier-js",channel:this.options.userId,event:"*",version:(null==t?void 0:t.version)??5}};this.options.connectionId&&(s.data.clientSourceId=this.options.connectionId),this.options.tenantId&&(s.data.accountId=this.options.tenantId),null==(e=this.options.logger)||e.debug("Sending subscribe request",s),await this.send(s)}static buildUrl(t){var e;let s=(null==(e=t.apiUrls)?void 0:e.inbox.webSocket)??"";return t.accessToken&&(s+=`/?auth=${t.accessToken}`),s}}class I extends p{constructor(t){super(t),s(this,"socket"),this.socket=new m(t)}async getMessages(t){const e=`\n query GetInboxMessages(\n $params: FilterParamsInput = { ${this.options.tenantId?`accountId: "${this.options.tenantId}"`:""} }\n $limit: Int = ${(null==t?void 0:t.paginationLimit)??24}\n $after: String ${(null==t?void 0:t.startCursor)?`= "${t.startCursor}"`:""}\n ) {\n count(params: $params)\n messages(params: $params, limit: $limit, after: $after) {\n totalCount\n pageInfo {\n startCursor\n hasNextPage\n }\n nodes {\n messageId\n read\n archived\n created\n opened\n title\n preview\n data\n tags\n trackingIds {\n clickTrackingId\n }\n actions {\n content\n data\n href\n }\n }\n }\n }\n `;return await d({options:this.options,query:e,headers:{"x-courier-user-id":this.options.userId,Authorization:`Bearer ${this.options.accessToken}`},url:this.options.apiUrls.inbox.graphql})}async getArchivedMessages(t){const e=`\n query GetInboxMessages(\n $params: FilterParamsInput = { ${this.options.tenantId?`accountId: "${this.options.tenantId}"`:""}, archived: true }\n $limit: Int = ${(null==t?void 0:t.paginationLimit)??24}\n $after: String ${(null==t?void 0:t.startCursor)?`= "${t.startCursor}"`:""}\n ) {\n count(params: $params)\n messages(params: $params, limit: $limit, after: $after) {\n totalCount\n pageInfo {\n startCursor\n hasNextPage\n }\n nodes {\n messageId\n read\n archived\n created\n opened\n title\n preview\n data\n tags\n trackingIds {\n clickTrackingId\n }\n actions {\n content\n data\n href\n }\n }\n }\n }\n `;return d({options:this.options,query:e,headers:{"x-courier-user-id":this.options.userId,Authorization:`Bearer ${this.options.accessToken}`},url:this.options.apiUrls.inbox.graphql})}async getUnreadMessageCount(){var t;const e=`\n query GetMessages {\n count(params: { status: "unread" ${this.options.tenantId?`, accountId: "${this.options.tenantId}"`:""} })\n }\n `;return(null==(t=(await d({options:this.options,query:e,headers:{"x-courier-user-id":this.options.userId,Authorization:`Bearer ${this.options.accessToken}`},url:this.options.apiUrls.inbox.graphql})).data)?void 0:t.count)??0}async click(t){const e=`\n mutation TrackEvent {\n clicked(messageId: "${t.messageId}", trackingId: "${t.trackingId}")\n }\n `,s={"x-courier-user-id":this.options.userId,Authorization:`Bearer ${this.options.accessToken}`};this.options.connectionId&&(s["x-courier-client-source-id"]=this.options.connectionId),await d({options:this.options,query:e,headers:s,url:this.options.apiUrls.inbox.graphql})}async read(t){const e=`\n mutation TrackEvent {\n read(messageId: "${t.messageId}")\n }\n `,s={"x-courier-user-id":this.options.userId,Authorization:`Bearer ${this.options.accessToken}`};this.options.connectionId&&(s["x-courier-client-source-id"]=this.options.connectionId),await d({options:this.options,query:e,headers:s,url:this.options.apiUrls.inbox.graphql})}async unread(t){const e=`\n mutation TrackEvent {\n unread(messageId: "${t.messageId}")\n }\n `,s={"x-courier-user-id":this.options.userId,Authorization:`Bearer ${this.options.accessToken}`};this.options.connectionId&&(s["x-courier-client-source-id"]=this.options.connectionId),await d({options:this.options,query:e,headers:s,url:this.options.apiUrls.inbox.graphql})}async readAll(){const t={"x-courier-user-id":this.options.userId,Authorization:`Bearer ${this.options.accessToken}`};this.options.connectionId&&(t["x-courier-client-source-id"]=this.options.connectionId),await d({options:this.options,query:"\n mutation TrackEvent {\n markAllRead\n }\n ",headers:t,url:this.options.apiUrls.inbox.graphql})}async open(t){const e=`\n mutation TrackEvent {\n opened(messageId: "${t.messageId}")\n }\n `,s={"x-courier-user-id":this.options.userId,Authorization:`Bearer ${this.options.accessToken}`};this.options.connectionId&&(s["x-courier-client-source-id"]=this.options.connectionId),await d({options:this.options,query:e,headers:s,url:this.options.apiUrls.inbox.graphql})}async archive(t){const e=`\n mutation TrackEvent {\n archive(messageId: "${t.messageId}")\n }\n `,s={"x-courier-user-id":this.options.userId,Authorization:`Bearer ${this.options.accessToken}`};this.options.connectionId&&(s["x-courier-client-source-id"]=this.options.connectionId),await d({options:this.options,query:e,headers:s,url:this.options.apiUrls.inbox.graphql})}async archiveRead(){const t={"x-courier-user-id":this.options.userId,Authorization:`Bearer ${this.options.accessToken}`};this.options.connectionId&&(t["x-courier-client-source-id"]=this.options.connectionId),await d({options:this.options,query:"\n mutation TrackEvent {\n archiveRead\n }\n ",headers:t,url:this.options.apiUrls.inbox.graphql})}}class v{transformItem(t){return{topicId:t.topic_id,topicName:t.topic_name,sectionId:t.section_id,sectionName:t.section_name,status:t.status,defaultStatus:t.default_status,hasCustomRouting:t.has_custom_routing,customRouting:t.custom_routing||[]}}*transform(t){for(const e of t)yield this.transformItem(e)}}class b extends p{constructor(){super(...arguments),s(this,"transformer",new v)}async getUserPreferences(t){let e=`${this.options.apiUrls.courier.rest}/users/${this.options.userId}/preferences`;(null==t?void 0:t.paginationCursor)&&(e+=`?cursor=${t.paginationCursor}`);const s=await l({options:this.options,url:e,method:"GET",headers:{Authorization:`Bearer ${this.options.accessToken}`}});return{items:[...this.transformer.transform(s.items)],paging:s.paging}}async getUserPreferenceTopic(t){const e=await l({options:this.options,url:`${this.options.apiUrls.courier.rest}/users/${this.options.userId}/preferences/${t.topicId}`,method:"GET",headers:{Authorization:`Bearer ${this.options.accessToken}`}});return this.transformer.transformItem(e.topic)}async putUserPreferenceTopic(t){const e={topic:{status:t.status,has_custom_routing:t.hasCustomRouting,custom_routing:t.customRouting}};await l({options:this.options,url:`${this.options.apiUrls.courier.rest}/users/${this.options.userId}/preferences/${t.topicId}`,method:"PUT",headers:{Authorization:`Bearer ${this.options.accessToken}`},body:e})}getNotificationCenterUrl(t){return`https://view.notificationcenter.app/p/${function(t){const e=new Uint8Array(t.length);for(let s=0;s<t.length;s++)e[s]=t.charCodeAt(s);return btoa(String.fromCharCode(...e))}(`${function(t){const e=atob(t),s=new Uint8Array(e.length);for(let n=0;n<e.length;n++)s[n]=e.charCodeAt(n);return String.fromCharCode(...s)}(t.clientKey)}#${this.options.userId}${this.options.tenantId?`#${this.options.tenantId}`:""}#false`)}`}}class y extends p{async putUserToken(t){const e={provider_key:t.provider,...t.device&&{device:{app_id:t.device.appId,ad_id:t.device.adId,device_id:t.device.deviceId,platform:t.device.platform,manufacturer:t.device.manufacturer,model:t.device.model}}};await l({options:this.options,url:`${this.options.apiUrls.courier.rest}/users/${this.options.userId}/tokens/${t.token}`,method:"PUT",headers:{Authorization:`Bearer ${this.options.accessToken}`},body:e,validCodes:[200,204]})}async deleteUserToken(t){await l({options:this.options,url:`${this.options.apiUrls.courier.rest}/users/${this.options.userId}/tokens/${t.token}`,method:"DELETE",headers:{Authorization:`Bearer ${this.options.accessToken}`},validCodes:[200,204]})}}class w extends p{async putSubscription(t){return await l({url:`${this.options.apiUrls.courier.rest}/lists/${t.listId}/subscriptions/${this.options.userId}`,options:this.options,method:"PUT",headers:{Authorization:`Bearer ${this.options.accessToken}`}})}async deleteSubscription(t){return await l({url:`${this.options.apiUrls.courier.rest}/lists/${t.listId}/subscriptions/${this.options.userId}`,options:this.options,method:"DELETE",headers:{Authorization:`Bearer ${this.options.accessToken}`}})}}class $ extends p{async postInboundCourier(t){return await l({url:`${this.options.apiUrls.courier.rest}/inbound/courier`,options:this.options,method:"POST",headers:{Authorization:`Bearer ${this.options.accessToken}`},body:{...t,userId:this.options.userId},validCodes:[200,202]})}async postTrackingUrl(t){return await l({url:t.url,options:this.options,method:"POST",body:{event:t.event}})}}class f extends p{constructor(t){var e,n;const i=void 0!==t.showLogs?t.showLogs:"development"===process.env.NODE_ENV,a={...t,showLogs:i,apiUrls:t.apiUrls||o(),accessToken:t.jwt??t.publicApiKey};super({...a,logger:new r(a.showLogs),apiUrls:o(a.apiUrls)}),s(this,"tokens"),s(this,"brands"),s(this,"preferences"),s(this,"inbox"),s(this,"lists"),s(this,"tracking"),this.tokens=new y(this.options),this.brands=new g(this.options),this.preferences=new b(this.options),this.inbox=new I(this.options),this.lists=new w(this.options),this.tracking=new $(this.options),this.options.jwt||this.options.publicApiKey||this.options.logger.warn("Courier Client initialized with no authentication method. Please provide a JWT or public API key."),this.options.publicApiKey&&(null==(e=this.options.logger)||e.warn("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.")),this.options.jwt&&this.options.publicApiKey&&(null==(n=this.options.logger)||n.warn("Courier Warning: Both a JWT and a Public API Key were provided. The Public API Key will be ignored."))}}class k{constructor(t){s(this,"callback"),this.callback=t}remove(){S.shared.removeAuthenticationListener(this)}}const T=class t{constructor(){s(this,"id",a.generate()),s(this,"instanceClient"),s(this,"_paginationLimit",24),s(this,"authenticationListeners",[])}get paginationLimit(){return this._paginationLimit}set paginationLimit(t){this._paginationLimit=Math.min(Math.max(t,1),100)}get client(){return this.instanceClient}static get shared(){return t.instance||(t.instance=new t),t.instance}signIn(t){const e=t.connectionId??a.generate();this.instanceClient=new f({...t,connectionId:e}),this.notifyAuthenticationListeners({userId:t.userId})}signOut(){this.instanceClient=void 0,this.notifyAuthenticationListeners({userId:void 0})}addAuthenticationListener(t){var e;null==(e=this.instanceClient)||e.options.logger.info("Adding authentication listener");const s=new k(t);return this.authenticationListeners.push(s),s}removeAuthenticationListener(t){var e;null==(e=this.instanceClient)||e.options.logger.info("Removing authentication listener"),this.authenticationListeners=this.authenticationListeners.filter((e=>e!==t))}notifyAuthenticationListeners(t){this.authenticationListeners.forEach((e=>e.callback(t)))}};s(T,"instance");let S=T;t.BrandClient=g,t.Courier=S,t.CourierClient=f,t.CourierSocket=i,t.InboxClient=I,t.ListClient=w,t.PreferenceClient=b,t.TokenClient=y,Object.defineProperty(t,Symbol.toStringTag,{value:"Module"})}));
|
package/dist/index.mjs
CHANGED
|
@@ -269,6 +269,8 @@ class Client {
|
|
|
269
269
|
class BrandClient extends Client {
|
|
270
270
|
/**
|
|
271
271
|
* Get a brand by ID using GraphQL
|
|
272
|
+
* @param brandId - The ID of the brand to retrieve
|
|
273
|
+
* @returns Promise resolving to the requested brand
|
|
272
274
|
*/
|
|
273
275
|
async getBrand(props) {
|
|
274
276
|
const query = `
|
|
@@ -290,7 +292,7 @@ class BrandClient extends Client {
|
|
|
290
292
|
`;
|
|
291
293
|
const json = await graphql({
|
|
292
294
|
options: this.options,
|
|
293
|
-
url: this.options.
|
|
295
|
+
url: this.options.apiUrls.courier.graphql,
|
|
294
296
|
headers: {
|
|
295
297
|
"x-courier-user-id": this.options.userId,
|
|
296
298
|
"x-courier-client-key": "empty",
|
|
@@ -370,6 +372,9 @@ class InboxClient extends Client {
|
|
|
370
372
|
}
|
|
371
373
|
/**
|
|
372
374
|
* Get paginated messages
|
|
375
|
+
* @param paginationLimit - Number of messages to return per page (default: 24)
|
|
376
|
+
* @param startCursor - Cursor for pagination
|
|
377
|
+
* @returns Promise resolving to paginated messages response
|
|
373
378
|
*/
|
|
374
379
|
async getMessages(props) {
|
|
375
380
|
const query = `
|
|
@@ -414,11 +419,14 @@ class InboxClient extends Client {
|
|
|
414
419
|
"x-courier-user-id": this.options.userId,
|
|
415
420
|
"Authorization": `Bearer ${this.options.accessToken}`
|
|
416
421
|
},
|
|
417
|
-
url: this.options.
|
|
422
|
+
url: this.options.apiUrls.inbox.graphql
|
|
418
423
|
});
|
|
419
424
|
}
|
|
420
425
|
/**
|
|
421
426
|
* Get paginated archived messages
|
|
427
|
+
* @param paginationLimit - Number of messages to return per page (default: 24)
|
|
428
|
+
* @param startCursor - Cursor for pagination
|
|
429
|
+
* @returns Promise resolving to paginated archived messages response
|
|
422
430
|
*/
|
|
423
431
|
async getArchivedMessages(props) {
|
|
424
432
|
const query = `
|
|
@@ -463,11 +471,12 @@ class InboxClient extends Client {
|
|
|
463
471
|
"x-courier-user-id": this.options.userId,
|
|
464
472
|
"Authorization": `Bearer ${this.options.accessToken}`
|
|
465
473
|
},
|
|
466
|
-
url: this.options.
|
|
474
|
+
url: this.options.apiUrls.inbox.graphql
|
|
467
475
|
});
|
|
468
476
|
}
|
|
469
477
|
/**
|
|
470
478
|
* Get unread message count
|
|
479
|
+
* @returns Promise resolving to number of unread messages
|
|
471
480
|
*/
|
|
472
481
|
async getUnreadMessageCount() {
|
|
473
482
|
var _a;
|
|
@@ -483,12 +492,15 @@ class InboxClient extends Client {
|
|
|
483
492
|
"x-courier-user-id": this.options.userId,
|
|
484
493
|
"Authorization": `Bearer ${this.options.accessToken}`
|
|
485
494
|
},
|
|
486
|
-
url: this.options.
|
|
495
|
+
url: this.options.apiUrls.inbox.graphql
|
|
487
496
|
});
|
|
488
497
|
return ((_a = response.data) == null ? void 0 : _a.count) ?? 0;
|
|
489
498
|
}
|
|
490
499
|
/**
|
|
491
500
|
* Track a click event
|
|
501
|
+
* @param messageId - ID of the message
|
|
502
|
+
* @param trackingId - ID for tracking the click
|
|
503
|
+
* @returns Promise resolving when click is tracked
|
|
492
504
|
*/
|
|
493
505
|
async click(props) {
|
|
494
506
|
const query = `
|
|
@@ -507,11 +519,13 @@ class InboxClient extends Client {
|
|
|
507
519
|
options: this.options,
|
|
508
520
|
query,
|
|
509
521
|
headers,
|
|
510
|
-
url: this.options.
|
|
522
|
+
url: this.options.apiUrls.inbox.graphql
|
|
511
523
|
});
|
|
512
524
|
}
|
|
513
525
|
/**
|
|
514
526
|
* Mark a message as read
|
|
527
|
+
* @param messageId - ID of the message to mark as read
|
|
528
|
+
* @returns Promise resolving when message is marked as read
|
|
515
529
|
*/
|
|
516
530
|
async read(props) {
|
|
517
531
|
const query = `
|
|
@@ -530,11 +544,13 @@ class InboxClient extends Client {
|
|
|
530
544
|
options: this.options,
|
|
531
545
|
query,
|
|
532
546
|
headers,
|
|
533
|
-
url: this.options.
|
|
547
|
+
url: this.options.apiUrls.inbox.graphql
|
|
534
548
|
});
|
|
535
549
|
}
|
|
536
550
|
/**
|
|
537
551
|
* Mark a message as unread
|
|
552
|
+
* @param messageId - ID of the message to mark as unread
|
|
553
|
+
* @returns Promise resolving when message is marked as unread
|
|
538
554
|
*/
|
|
539
555
|
async unread(props) {
|
|
540
556
|
const query = `
|
|
@@ -553,11 +569,12 @@ class InboxClient extends Client {
|
|
|
553
569
|
options: this.options,
|
|
554
570
|
query,
|
|
555
571
|
headers,
|
|
556
|
-
url: this.options.
|
|
572
|
+
url: this.options.apiUrls.inbox.graphql
|
|
557
573
|
});
|
|
558
574
|
}
|
|
559
575
|
/**
|
|
560
576
|
* Mark all messages as read
|
|
577
|
+
* @returns Promise resolving when all messages are marked as read
|
|
561
578
|
*/
|
|
562
579
|
async readAll() {
|
|
563
580
|
const query = `
|
|
@@ -576,11 +593,13 @@ class InboxClient extends Client {
|
|
|
576
593
|
options: this.options,
|
|
577
594
|
query,
|
|
578
595
|
headers,
|
|
579
|
-
url: this.options.
|
|
596
|
+
url: this.options.apiUrls.inbox.graphql
|
|
580
597
|
});
|
|
581
598
|
}
|
|
582
599
|
/**
|
|
583
600
|
* Mark a message as opened
|
|
601
|
+
* @param messageId - ID of the message to mark as opened
|
|
602
|
+
* @returns Promise resolving when message is marked as opened
|
|
584
603
|
*/
|
|
585
604
|
async open(props) {
|
|
586
605
|
const query = `
|
|
@@ -599,11 +618,13 @@ class InboxClient extends Client {
|
|
|
599
618
|
options: this.options,
|
|
600
619
|
query,
|
|
601
620
|
headers,
|
|
602
|
-
url: this.options.
|
|
621
|
+
url: this.options.apiUrls.inbox.graphql
|
|
603
622
|
});
|
|
604
623
|
}
|
|
605
624
|
/**
|
|
606
625
|
* Archive a message
|
|
626
|
+
* @param messageId - ID of the message to archive
|
|
627
|
+
* @returns Promise resolving when message is archived
|
|
607
628
|
*/
|
|
608
629
|
async archive(props) {
|
|
609
630
|
const query = `
|
|
@@ -622,7 +643,30 @@ class InboxClient extends Client {
|
|
|
622
643
|
options: this.options,
|
|
623
644
|
query,
|
|
624
645
|
headers,
|
|
625
|
-
url: this.options.
|
|
646
|
+
url: this.options.apiUrls.inbox.graphql
|
|
647
|
+
});
|
|
648
|
+
}
|
|
649
|
+
/**
|
|
650
|
+
* Archive all read messages.
|
|
651
|
+
*/
|
|
652
|
+
async archiveRead() {
|
|
653
|
+
const query = `
|
|
654
|
+
mutation TrackEvent {
|
|
655
|
+
archiveRead
|
|
656
|
+
}
|
|
657
|
+
`;
|
|
658
|
+
const headers = {
|
|
659
|
+
"x-courier-user-id": this.options.userId,
|
|
660
|
+
"Authorization": `Bearer ${this.options.accessToken}`
|
|
661
|
+
};
|
|
662
|
+
if (this.options.connectionId) {
|
|
663
|
+
headers["x-courier-client-source-id"] = this.options.connectionId;
|
|
664
|
+
}
|
|
665
|
+
await graphql({
|
|
666
|
+
options: this.options,
|
|
667
|
+
query,
|
|
668
|
+
headers,
|
|
669
|
+
url: this.options.apiUrls.inbox.graphql
|
|
626
670
|
});
|
|
627
671
|
}
|
|
628
672
|
}
|
|
@@ -677,12 +721,14 @@ class PreferenceClient extends Client {
|
|
|
677
721
|
}
|
|
678
722
|
/**
|
|
679
723
|
* Get all preferences for a user
|
|
724
|
+
* @param paginationCursor - Optional cursor for pagination
|
|
725
|
+
* @returns Promise resolving to user preferences
|
|
680
726
|
* @see https://www.courier.com/docs/reference/user-preferences/list-all-user-preferences
|
|
681
727
|
*/
|
|
682
|
-
async getUserPreferences(
|
|
683
|
-
let url = `${this.options.
|
|
684
|
-
if (
|
|
685
|
-
url += `?cursor=${
|
|
728
|
+
async getUserPreferences(props) {
|
|
729
|
+
let url = `${this.options.apiUrls.courier.rest}/users/${this.options.userId}/preferences`;
|
|
730
|
+
if (props == null ? void 0 : props.paginationCursor) {
|
|
731
|
+
url += `?cursor=${props.paginationCursor}`;
|
|
686
732
|
}
|
|
687
733
|
const json = await http({
|
|
688
734
|
options: this.options,
|
|
@@ -700,12 +746,14 @@ class PreferenceClient extends Client {
|
|
|
700
746
|
}
|
|
701
747
|
/**
|
|
702
748
|
* Get preferences for a specific topic
|
|
749
|
+
* @param topicId - The ID of the topic to get preferences for
|
|
750
|
+
* @returns Promise resolving to topic preferences
|
|
703
751
|
* @see https://www.courier.com/docs/reference/user-preferences/get-subscription-topic-preferences
|
|
704
752
|
*/
|
|
705
|
-
async getUserPreferenceTopic(
|
|
753
|
+
async getUserPreferenceTopic(props) {
|
|
706
754
|
const json = await http({
|
|
707
755
|
options: this.options,
|
|
708
|
-
url: `${this.options.
|
|
756
|
+
url: `${this.options.apiUrls.courier.rest}/users/${this.options.userId}/preferences/${props.topicId}`,
|
|
709
757
|
method: "GET",
|
|
710
758
|
headers: {
|
|
711
759
|
"Authorization": `Bearer ${this.options.accessToken}`
|
|
@@ -716,19 +764,24 @@ class PreferenceClient extends Client {
|
|
|
716
764
|
}
|
|
717
765
|
/**
|
|
718
766
|
* Update preferences for a specific topic
|
|
767
|
+
* @param topicId - The ID of the topic to update preferences for
|
|
768
|
+
* @param status - The new status for the topic
|
|
769
|
+
* @param hasCustomRouting - Whether the topic has custom routing
|
|
770
|
+
* @param customRouting - The custom routing channels for the topic
|
|
771
|
+
* @returns Promise resolving when update is complete
|
|
719
772
|
* @see https://www.courier.com/docs/reference/user-preferences/update-subscription-topic-preferences
|
|
720
773
|
*/
|
|
721
|
-
async putUserPreferenceTopic(
|
|
774
|
+
async putUserPreferenceTopic(props) {
|
|
722
775
|
const payload = {
|
|
723
776
|
topic: {
|
|
724
|
-
status:
|
|
725
|
-
has_custom_routing:
|
|
726
|
-
custom_routing:
|
|
777
|
+
status: props.status,
|
|
778
|
+
has_custom_routing: props.hasCustomRouting,
|
|
779
|
+
custom_routing: props.customRouting
|
|
727
780
|
}
|
|
728
781
|
};
|
|
729
782
|
await http({
|
|
730
783
|
options: this.options,
|
|
731
|
-
url: `${this.options.
|
|
784
|
+
url: `${this.options.apiUrls.courier.rest}/users/${this.options.userId}/preferences/${props.topicId}`,
|
|
732
785
|
method: "PUT",
|
|
733
786
|
headers: {
|
|
734
787
|
"Authorization": `Bearer ${this.options.accessToken}`
|
|
@@ -738,11 +791,11 @@ class PreferenceClient extends Client {
|
|
|
738
791
|
}
|
|
739
792
|
/**
|
|
740
793
|
* Get the notification center URL
|
|
741
|
-
* @param
|
|
742
|
-
* @returns
|
|
794
|
+
* @param clientKey - The client key to use for the URL
|
|
795
|
+
* @returns The notification center URL
|
|
743
796
|
*/
|
|
744
|
-
getNotificationCenterUrl(
|
|
745
|
-
const rootTenantId = decode(
|
|
797
|
+
getNotificationCenterUrl(props) {
|
|
798
|
+
const rootTenantId = decode(props.clientKey);
|
|
746
799
|
const url = encode(`${rootTenantId}#${this.options.userId}${this.options.tenantId ? `#${this.options.tenantId}` : ""}#${false}`);
|
|
747
800
|
return `https://view.notificationcenter.app/p/${url}`;
|
|
748
801
|
}
|
|
@@ -750,6 +803,9 @@ class PreferenceClient extends Client {
|
|
|
750
803
|
class TokenClient extends Client {
|
|
751
804
|
/**
|
|
752
805
|
* Store a push notification token for a user
|
|
806
|
+
* @param token - The push notification token
|
|
807
|
+
* @param provider - The provider of the token
|
|
808
|
+
* @param device - The device information
|
|
753
809
|
* @see https://www.courier.com/docs/reference/token-management/put-token
|
|
754
810
|
*/
|
|
755
811
|
async putUserToken(props) {
|
|
@@ -768,7 +824,7 @@ class TokenClient extends Client {
|
|
|
768
824
|
};
|
|
769
825
|
await http({
|
|
770
826
|
options: this.options,
|
|
771
|
-
url: `${this.options.
|
|
827
|
+
url: `${this.options.apiUrls.courier.rest}/users/${this.options.userId}/tokens/${props.token}`,
|
|
772
828
|
method: "PUT",
|
|
773
829
|
headers: {
|
|
774
830
|
"Authorization": `Bearer ${this.options.accessToken}`
|
|
@@ -779,11 +835,13 @@ class TokenClient extends Client {
|
|
|
779
835
|
}
|
|
780
836
|
/**
|
|
781
837
|
* Delete a push notification token for a user
|
|
838
|
+
* @param token - The push notification token
|
|
839
|
+
* @returns Promise resolving when token is deleted
|
|
782
840
|
*/
|
|
783
841
|
async deleteUserToken(props) {
|
|
784
842
|
await http({
|
|
785
843
|
options: this.options,
|
|
786
|
-
url: `${this.options.
|
|
844
|
+
url: `${this.options.apiUrls.courier.rest}/users/${this.options.userId}/tokens/${props.token}`,
|
|
787
845
|
method: "DELETE",
|
|
788
846
|
headers: {
|
|
789
847
|
"Authorization": `Bearer ${this.options.accessToken}`
|
|
@@ -795,11 +853,13 @@ class TokenClient extends Client {
|
|
|
795
853
|
class ListClient extends Client {
|
|
796
854
|
/**
|
|
797
855
|
* Subscribe a user to a list
|
|
856
|
+
* @param listId - The ID of the list to subscribe to
|
|
857
|
+
* @returns Promise resolving when subscription is complete
|
|
798
858
|
* @see https://www.courier.com/docs/reference/lists/recipient-subscribe
|
|
799
859
|
*/
|
|
800
860
|
async putSubscription(props) {
|
|
801
861
|
return await http({
|
|
802
|
-
url: `${this.options.
|
|
862
|
+
url: `${this.options.apiUrls.courier.rest}/lists/${props.listId}/subscriptions/${this.options.userId}`,
|
|
803
863
|
options: this.options,
|
|
804
864
|
method: "PUT",
|
|
805
865
|
headers: {
|
|
@@ -809,11 +869,13 @@ class ListClient extends Client {
|
|
|
809
869
|
}
|
|
810
870
|
/**
|
|
811
871
|
* Unsubscribe a user from a list
|
|
872
|
+
* @param listId - The ID of the list to unsubscribe from
|
|
873
|
+
* @returns Promise resolving when unsubscription is complete
|
|
812
874
|
* @see https://www.courier.com/docs/reference/lists/delete-subscription
|
|
813
875
|
*/
|
|
814
876
|
async deleteSubscription(props) {
|
|
815
877
|
return await http({
|
|
816
|
-
url: `${this.options.
|
|
878
|
+
url: `${this.options.apiUrls.courier.rest}/lists/${props.listId}/subscriptions/${this.options.userId}`,
|
|
817
879
|
options: this.options,
|
|
818
880
|
method: "DELETE",
|
|
819
881
|
headers: {
|
|
@@ -825,11 +887,16 @@ class ListClient extends Client {
|
|
|
825
887
|
class TrackingClient extends Client {
|
|
826
888
|
/**
|
|
827
889
|
* Post an inbound courier event
|
|
890
|
+
* @param event - The event type: Example: "New Order Placed"
|
|
891
|
+
* @param messageId - The message ID
|
|
892
|
+
* @param type - The type of event: Available options: "track"
|
|
893
|
+
* @param properties - The properties of the event
|
|
894
|
+
* @returns Promise resolving to the message ID
|
|
828
895
|
* @see https://www.courier.com/docs/reference/inbound/courier-track-event
|
|
829
896
|
*/
|
|
830
897
|
async postInboundCourier(props) {
|
|
831
898
|
return await http({
|
|
832
|
-
url: `${this.options.
|
|
899
|
+
url: `${this.options.apiUrls.courier.rest}/inbound/courier`,
|
|
833
900
|
options: this.options,
|
|
834
901
|
method: "POST",
|
|
835
902
|
headers: {
|
|
@@ -845,6 +912,9 @@ class TrackingClient extends Client {
|
|
|
845
912
|
/**
|
|
846
913
|
* Post a tracking URL event
|
|
847
914
|
* These urls are found in messages sent from Courier
|
|
915
|
+
* @param url - The URL to post the event to
|
|
916
|
+
* @param event - The event type: Available options: "click", "open", "unsubscribe"
|
|
917
|
+
* @returns Promise resolving when the event is posted
|
|
848
918
|
*/
|
|
849
919
|
async postTrackingUrl(props) {
|
|
850
920
|
return await http({
|
|
@@ -870,7 +940,7 @@ class CourierClient extends Client {
|
|
|
870
940
|
super({
|
|
871
941
|
...baseOptions,
|
|
872
942
|
logger: new Logger(baseOptions.showLogs),
|
|
873
|
-
|
|
943
|
+
apiUrls: getCourierApiUrls(baseOptions.apiUrls)
|
|
874
944
|
});
|
|
875
945
|
__publicField(this, "tokens");
|
|
876
946
|
__publicField(this, "brands");
|
|
@@ -6,7 +6,7 @@ export interface MessageEvent {
|
|
|
6
6
|
messageId?: string;
|
|
7
7
|
type: string;
|
|
8
8
|
}
|
|
9
|
-
export type EventType = 'read' | '
|
|
9
|
+
export type EventType = 'archive-read' | 'archive' | 'click' | 'mark-all-read' | 'opened' | 'read' | 'unarchive' | 'unopened' | 'unread';
|
|
10
10
|
export declare class InboxSocket extends CourierSocket {
|
|
11
11
|
receivedMessage?: (message: InboxMessage) => void;
|
|
12
12
|
receivedMessageEvent?: (event: MessageEvent) => void;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@trycourier/courier-js",
|
|
3
|
-
"version": "2.0.
|
|
3
|
+
"version": "2.0.2-beta",
|
|
4
4
|
"description": "A browser-safe API wrapper",
|
|
5
5
|
"main": "dist/index.js",
|
|
6
6
|
"module": "dist/index.mjs",
|
|
@@ -29,6 +29,8 @@
|
|
|
29
29
|
"@types/jest": "29.5.14",
|
|
30
30
|
"dotenv": "16.4.7",
|
|
31
31
|
"jest": "29.7.0",
|
|
32
|
+
"jest-environment-jsdom": "29.7.0",
|
|
33
|
+
"jest-fetch-mock": "^3.0.3",
|
|
32
34
|
"terser": "5.39.0",
|
|
33
35
|
"ts-jest": "29.1.1",
|
|
34
36
|
"vite": "6.2.6",
|