@trycourier/courier-js 2.1.0 ā 2.1.3
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/client/courier-client.d.ts +2 -2
- package/dist/index.d.ts +5 -3
- package/dist/index.js +1 -1
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +21 -3
- package/dist/index.mjs.map +1 -1
- package/dist/socket/courier-inbox-socket.d.ts +8 -1
- package/package.json +8 -3
|
@@ -26,7 +26,7 @@ export interface CourierProps {
|
|
|
26
26
|
*
|
|
27
27
|
* This is an internal prop, intended to be set by other Courier SDKs.
|
|
28
28
|
* If undefined, this defaults to "courier-js".
|
|
29
|
-
* @
|
|
29
|
+
* @internal
|
|
30
30
|
*/
|
|
31
31
|
courierUserAgentName?: string;
|
|
32
32
|
/**
|
|
@@ -34,7 +34,7 @@ export interface CourierProps {
|
|
|
34
34
|
*
|
|
35
35
|
* This is an internal prop, intended to be set by other Courier SDKs.
|
|
36
36
|
* If undefined, this defaults to this package's version.
|
|
37
|
-
* @
|
|
37
|
+
* @internal
|
|
38
38
|
*/
|
|
39
39
|
courierUserAgentVersion?: string;
|
|
40
40
|
}
|
package/dist/index.d.ts
CHANGED
|
@@ -1,19 +1,21 @@
|
|
|
1
1
|
import { CourierApiUrls } from './types/courier-api-urls';
|
|
2
|
-
import { CourierBrand } from './types/brands';
|
|
2
|
+
import { CourierBrand, CourierBrandSettings, CourierBrandColors, CourierBrandEmail, CourierBrandInApp } from './types/brands';
|
|
3
3
|
import { CourierUserPreferences, CourierUserPreferencesStatus, CourierUserPreferencesChannel, CourierUserPreferencesPaging, CourierUserPreferencesTopic, CourierUserPreferencesTopicResponse } from './types/preference';
|
|
4
4
|
import { CourierDevice, CourierToken } from './types/token';
|
|
5
5
|
import { CourierGetInboxMessageResponse, CourierGetInboxMessagesResponse, InboxMessage, InboxAction } from './types/inbox';
|
|
6
6
|
import { InboxMessageEvent, InboxMessageEventEnvelope } from './types/socket/protocol/messages';
|
|
7
|
+
import { CourierTrackingEvent } from './types/tracking-event';
|
|
7
8
|
import { CourierClient, CourierClientOptions, CourierProps } from './client/courier-client';
|
|
8
9
|
import { BrandClient } from './client/brand-client';
|
|
9
10
|
import { TokenClient } from './client/token-client';
|
|
10
11
|
import { PreferenceClient } from './client/preference-client';
|
|
11
12
|
import { InboxClient } from './client/inbox-client';
|
|
12
13
|
import { ListClient } from './client/list-client';
|
|
14
|
+
import { TrackingClient } from './client/tracking-client';
|
|
13
15
|
import { AuthenticationListener } from './shared/authentication-listener';
|
|
14
16
|
import { Courier } from './shared/courier';
|
|
15
|
-
export type { CourierProps, CourierClientOptions, CourierBrand, CourierApiUrls, CourierUserPreferences, CourierUserPreferencesStatus, CourierUserPreferencesChannel, CourierUserPreferencesPaging, CourierUserPreferencesTopic, CourierUserPreferencesTopicResponse, CourierDevice, CourierToken, CourierGetInboxMessageResponse, CourierGetInboxMessagesResponse, InboxMessage, InboxAction, InboxMessageEventEnvelope, };
|
|
17
|
+
export type { CourierProps, CourierClientOptions, CourierBrand, CourierBrandSettings, CourierBrandColors, CourierBrandEmail, CourierBrandInApp, CourierApiUrls, CourierUserPreferences, CourierUserPreferencesStatus, CourierUserPreferencesChannel, CourierUserPreferencesPaging, CourierUserPreferencesTopic, CourierUserPreferencesTopicResponse, CourierDevice, CourierToken, CourierGetInboxMessageResponse, CourierGetInboxMessagesResponse, InboxMessage, InboxAction, InboxMessageEventEnvelope, CourierTrackingEvent, };
|
|
16
18
|
export { InboxMessageEvent, };
|
|
17
|
-
export { CourierClient, BrandClient, TokenClient, PreferenceClient, InboxClient, ListClient, };
|
|
19
|
+
export { CourierClient, BrandClient, TokenClient, PreferenceClient, InboxClient, ListClient, TrackingClient, };
|
|
18
20
|
export type { AuthenticationListener };
|
|
19
21
|
export { Courier };
|
package/dist/index.js
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
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),n=(t=>(t.Subscribe="subscribe",t.Unsubscribe="unsubscribe",t.Pong="pong",t.Ping="ping",t.GetConfig="get-config",t))(n||{}),i=(t=>(t.Ping="ping",t))(i||{}),o=(t=>(t.NewMessage="message",t.Archive="archive",t.ArchiveAll="archive-all",t.ArchiveRead="archive-read",t.Clicked="clicked",t.MarkAllRead="mark-all-read",t.Opened="opened",t.Read="read",t.Unarchive="unarchive",t.Unopened="unopened",t.Unread="unread",t))(o||{});const r=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.io"}});class a{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)}}const c=class t{static nanoid(e=21){let s="",n=crypto.getRandomValues(new Uint8Array(e|=0));for(;e--;)s+=t.ALPHABET[63&n[e]];return s}};s(c,"ALPHABET","useandom-26T198340PX75pxJACKVERYMINDBUSHWOLF_GQZbfghjklqvwyzrict");let u=c;const h="x-courier-ua",d="sdk",l="sdkv",p="cid";class g extends Error{constructor(t,e,s){super(e),this.code=t,this.type=s,this.name="CourierRequestError"}}function I(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 m(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 y(t){const e=t.validCodes??[200],s=t.options.showLogs?u.nanoid():void 0,n=t.options.courierUserAgent.toHttpHeaderValue(),i=new Request(t.url,{method:t.method,headers:{"Content-Type":"application/json",[h]:n,...t.headers},body:t.body?JSON.stringify(t.body):void 0});s&&I(t.options.logger,s,"HTTP",{url:i.url,method:i.method,headers:Object.fromEntries(i.headers.entries()),body:t.body});const o=await fetch(i);if(204===o.status)return;let r;try{r=await o.json()}catch(a){if(200===o.status)return;throw new g(o.status,"Failed to parse response as JSON","PARSE_ERROR")}if(s&&m(t.options.logger,s,"HTTP",{status:o.status,response:r}),!e.includes(o.status))throw new g(o.status,(null==r?void 0:r.message)||"Unknown Error",null==r?void 0:r.type);return r}async function v(t){const e=t.options.showLogs?u.nanoid():void 0,s=t.options.courierUserAgent.toHttpHeaderValue();e&&I(t.options.logger,e,"GraphQL",{url:t.url,headers:t.headers,query:t.query,variables:t.variables});const n=await fetch(t.url,{method:"POST",headers:{"Content-Type":"application/json",[h]:s,...t.headers},body:JSON.stringify({query:t.query,variables:t.variables})});let i;try{i=await n.json()}catch(o){throw new g(n.status,"Failed to parse response as JSON","PARSE_ERROR")}if(e&&m(t.options.logger,e,"GraphQL",{status:n.status,response:i}),!n.ok)throw new g(n.status,(null==i?void 0:i.message)||"Unknown Error",null==i?void 0:i.type);return i}class T{constructor(t){this.options=t}}class b extends T{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 v({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}}const f=1e3,w=class t{constructor(t){s(this,"webSocket",null),s(this,"retryAttempt",0),s(this,"retryTimeoutId",null),s(this,"closeRequested",!1),s(this,"url"),s(this,"options"),this.url=t.apiUrls.inbox.webSocket,this.options=t}async connect(){var e,s;return this.isConnecting||this.isOpen?(null==(s=this.options.logger)||s.info(`Attempted to open a WebSocket connection, but one already exists in state '${null==(e=this.webSocket)?void 0:e.readyState}'.`),Promise.resolve()):(this.clearRetryTimeout(),this.closeRequested=!1,new Promise(((e,s)=>{this.webSocket=new WebSocket(this.getWebSocketUrl()),this.webSocket.addEventListener("open",(t=>{this.retryAttempt=0,this.onOpen(t),e()})),this.webSocket.addEventListener("message",(async t=>{var e;try{const e=JSON.parse(t.data);if("event"in e&&"reconnect"===e.event)return this.close(f),void(await this.retryConnection(1e3*e.retryAfter));this.onMessageReceived(e)}catch(s){null==(e=this.options.logger)||e.error("Error parsing socket message",s)}})),this.webSocket.addEventListener("close",(e=>{if(e.code!==f&&!this.closeRequested){const s=t.parseCloseEvent(e);s.retryAfterSeconds?this.retryConnection(1e3*s.retryAfterSeconds):this.retryConnection()}this.onClose(e)})),this.webSocket.addEventListener("error",(t=>{this.closeRequested||this.retryConnection(),this.onError(t),s(t)}))})))}close(t=1e3,e){null!==this.webSocket&&(this.closeRequested=!0,this.clearRetryTimeout(),this.retryAttempt=0,this.webSocket.close(t,e))}send(t){var e;if(null===this.webSocket||this.isConnecting)return void(null==(e=this.options.logger)||e.info("Attempted to send a message, but the WebSocket is not yet open."));const s=JSON.stringify(t);this.webSocket.send(s)}get userId(){return this.options.userId}get subTenantId(){return this.options.tenantId}get logger(){return this.options.logger}get courierUserAgent(){return this.options.courierUserAgent}get isConnecting(){return null!==this.webSocket&&this.webSocket.readyState===WebSocket.CONNECTING}get isOpen(){return null!==this.webSocket&&this.webSocket.readyState===WebSocket.OPEN}getWebSocketUrl(){const t=this.options.accessToken,e=this.options.connectionId,s=this.userId,n=this.courierUserAgent.getUserAgentInfo()[d],i=this.courierUserAgent.getUserAgentInfo()[l];return`${this.url}?auth=${t}&cid=${e}&iwpv=v1&userId=${s}&${d}=${n}&${l}=${i}`}static parseCloseEvent(e){if(null===e.reason||""===e.reason)return e;try{const s=JSON.parse(e.reason);if(!s[t.RETRY_AFTER_KEY])return e;const n=parseInt(s[t.RETRY_AFTER_KEY]);return Number.isNaN(n)||n<0?e:{...e,retryAfterSeconds:n}}catch(s){return e}}getBackoffTimeInMillis(){const e=t.BACKOFF_INTERVALS_IN_MILLIS[this.retryAttempt],s=e-e*t.BACKOFF_JITTER_FACTOR,n=e+e*t.BACKOFF_JITTER_FACTOR;return Math.floor(Math.random()*(n-s)+s)}async retryConnection(e){var s,n,i;if(null!==this.retryTimeoutId)return void(null==(s=this.logger)||s.debug("Skipping retry attempt because a previous retry is already scheduled."));if(this.retryAttempt>=t.MAX_RETRY_ATTEMPTS)return void(null==(n=this.logger)||n.error(`Max retry attempts (${t.MAX_RETRY_ATTEMPTS}) reached.`));const o=e??this.getBackoffTimeInMillis();this.retryTimeoutId=window.setTimeout((async()=>{try{await this.connect()}catch(t){}}),o),null==(i=this.logger)||i.debug(`Retrying connection in ${Math.floor(o/1e3)}s. Retry attempt ${this.retryAttempt+1} of ${t.MAX_RETRY_ATTEMPTS}.`),this.retryAttempt++}clearRetryTimeout(){null!==this.retryTimeoutId&&(window.clearTimeout(this.retryTimeoutId),this.retryTimeoutId=null)}};s(w,"BACKOFF_JITTER_FACTOR",.5),s(w,"MAX_RETRY_ATTEMPTS",5),s(w,"BACKOFF_INTERVALS_IN_MILLIS",[3e4,6e4,12e4,24e4,48e4]),s(w,"RETRY_AFTER_KEY","Retry-After");let A=w;class ${constructor(t=10){s(this,"outstandingRequestsMap",new Map),s(this,"completedTransactionsQueue",[]),s(this,"completedTransactionsToKeep"),this.completedTransactionsToKeep=t}addOutstandingRequest(t,e){if(this.outstandingRequestsMap.has(t))throw new Error(`Transaction [${t}] already has an outstanding request`);const s={transactionId:t,request:e,response:null,start:new Date,end:null};this.outstandingRequestsMap.set(t,s)}addResponse(t,e){const s=this.outstandingRequestsMap.get(t);if(void 0===s)throw new Error(`Transaction [${t}] does not have an outstanding request`);s.response=e,s.end=new Date,this.outstandingRequestsMap.delete(t),this.addCompletedTransaction(s)}get outstandingRequests(){return Array.from(this.outstandingRequestsMap.values())}get completedTransactions(){return this.completedTransactionsQueue}clearOutstandingRequests(){this.outstandingRequestsMap.clear()}addCompletedTransaction(t){this.completedTransactionsQueue.push(t),this.completedTransactionsQueue.length>this.completedTransactionsToKeep&&this.completedTransactionsQueue.shift()}}function k(t){return function(t){if(t.event===o.NewMessage){const e=t.data;return e.created||(e.created=(new Date).toISOString()),{...t,data:e}}return t}(t)}const R=class t extends A{constructor(t){super(t),s(this,"pingIntervalId",null),s(this,"messageEventListeners",[]),s(this,"config",null),s(this,"pingTransactionManager",new $)}onOpen(t){return this.pingTransactionManager.clearOutstandingRequests(),this.restartPingInterval(),this.sendGetConfig(),this.sendSubscribe(),Promise.resolve()}onMessageReceived(e){if("action"in e&&e.action===i.Ping){const t=e;this.sendPong(t)}if("response"in e&&"pong"===e.response){const t=e;this.pingTransactionManager.addResponse(t.tid,t),this.pingTransactionManager.clearOutstandingRequests()}if("response"in e&&"config"===e.response){const t=e;this.setConfig(t.data)}if("event"in e&&t.isInboxMessageEvent(e.event)){const t=k(e);for(const e of this.messageEventListeners)e(t)}return this.restartPingInterval(),Promise.resolve()}onClose(t){return this.clearPingInterval(),this.clearMessageEventListeners(),this.pingTransactionManager.clearOutstandingRequests(),Promise.resolve()}onError(t){return Promise.resolve()}sendSubscribe(){const t={channel:this.userId,event:"*"};this.subTenantId&&(t.accountId=this.subTenantId);const e={tid:u.nanoid(),action:n.Subscribe,data:t};this.send(e)}sendUnsubscribe(){const t={tid:u.nanoid(),action:n.Unsubscribe,data:{channel:this.userId}};this.send(t)}addMessageEventListener(t){this.messageEventListeners.push(t)}sendPing(){var t;if(this.pingTransactionManager.outstandingRequests.length>=this.maxOutstandingPings)return null==(t=this.logger)||t.debug("Max outstanding pings reached, retrying connection."),this.close(f,"Max outstanding pings reached, retrying connection."),void this.retryConnection();const e={tid:u.nanoid(),action:n.Ping};this.send(e),this.pingTransactionManager.addOutstandingRequest(e.tid,e)}sendPong(t){const e={tid:t.tid,action:n.Pong};this.send(e)}sendGetConfig(){const t={tid:u.nanoid(),action:n.GetConfig};this.send(t)}restartPingInterval(){this.clearPingInterval(),this.pingIntervalId=window.setInterval((()=>{this.sendPing()}),this.pingInterval)}clearPingInterval(){this.pingIntervalId&&window.clearInterval(this.pingIntervalId)}get pingInterval(){return this.config?1e3*this.config.pingInterval:t.DEFAULT_PING_INTERVAL_MILLIS}get maxOutstandingPings(){return this.config?this.config.maxOutstandingPings:t.DEFAULT_MAX_OUTSTANDING_PINGS}setConfig(t){this.config=t}clearMessageEventListeners(){this.messageEventListeners=[]}static isInboxMessageEvent(t){return Object.values(o).includes(t)}};s(R,"DEFAULT_PING_INTERVAL_MILLIS",6e4),s(R,"DEFAULT_MAX_OUTSTANDING_PINGS",3);let E=R;class C extends T{constructor(t){super(t),s(this,"socket"),this.socket=new E(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 v({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 v({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 v({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 v({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 v({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 v({options:this.options,query:e,headers:s,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 v({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 v({options:this.options,query:e,headers:s,url:this.options.apiUrls.inbox.graphql})}async unarchive(t){const e=`\n mutation TrackEvent {\n unarchive(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 v({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 v({options:this.options,query:"\n mutation TrackEvent {\n markAllRead\n }\n ",headers:t,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 v({options:this.options,query:"\n mutation TrackEvent {\n archiveRead\n }\n ",headers:t,url:this.options.apiUrls.inbox.graphql})}async archiveAll(){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 v({options:this.options,query:"\n mutation TrackEvent {\n archiveAll\n }\n ",headers:t,url:this.options.apiUrls.inbox.graphql})}}class S{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 U extends T{constructor(){super(...arguments),s(this,"transformer",new S)}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 y({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 y({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 y({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 x extends T{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 y({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 y({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 P extends T{async putSubscription(t){return await y({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 y({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 q extends T{async postInboundCourier(t){return await y({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 y({url:t.url,options:this.options,method:"POST",body:{event:t.event}})}}class _{constructor(t,e,s){this.clientId=t,this.sdkName=e,this.sdkVersion=s}getUserAgentInfo(){return{[d]:this.sdkName,[l]:this.sdkVersion,[p]:this.clientId}}toHttpHeaderValue(){return Object.entries(this.getUserAgentInfo()).map((([t,e])=>`${t}=${e}`)).join(",")}}const L=class t extends T{constructor(e){var n,i;const o=void 0!==e.showLogs&&e.showLogs,c=u.nanoid(),h={...e,showLogs:o,connectionId:c,apiUrls:e.apiUrls||r(),accessToken:e.jwt??e.publicApiKey},d=new _(c,e.courierUserAgentName||t.COURIER_JS_NAME,e.courierUserAgentVersion||t.COURIER_JS_VERSION);super({...h,logger:new a(h.showLogs),courierUserAgent:d,apiUrls:r(h.apiUrls)}),s(this,"tokens"),s(this,"brands"),s(this,"preferences"),s(this,"inbox"),s(this,"lists"),s(this,"tracking"),this.tokens=new x(this.options),this.brands=new b(this.options),this.preferences=new U(this.options),this.inbox=new C(this.options),this.lists=new P(this.options),this.tracking=new q(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==(n=this.options.logger)||n.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==(i=this.options.logger)||i.warn("Courier Warning: Both a JWT and a Public API Key were provided. The Public API Key will be ignored."))}};s(L,"COURIER_JS_NAME","courier-js"),s(L,"COURIER_JS_VERSION","2.1.0");let M=L;class O{constructor(t){s(this,"callback"),this.callback=t}remove(){B.shared.removeAuthenticationListener(this)}}const N=class t{constructor(){s(this,"id",u.nanoid()),s(this,"instanceClient"),s(this,"courierUserAgentName"),s(this,"courierUserAgentVersion"),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){this.instanceClient&&(this.instanceClient.options.logger.warn("Sign in called but there is already a user signed in. Signing out the current user."),this.signOut()),this.instanceClient=new M({...t,courierUserAgentName:this.courierUserAgentName,courierUserAgentVersion:this.courierUserAgentVersion}),this.notifyAuthenticationListeners({userId:t.userId})}signOut(){var t,e;null==(e=null==(t=this.instanceClient)?void 0:t.inbox.socket)||e.close(),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 O(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(N,"instance");let B=N;t.BrandClient=b,t.Courier=B,t.CourierClient=M,t.InboxClient=C,t.InboxMessageEvent=o,t.ListClient=P,t.PreferenceClient=U,t.TokenClient=x,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),n=(t=>(t.Subscribe="subscribe",t.Unsubscribe="unsubscribe",t.Pong="pong",t.Ping="ping",t.GetConfig="get-config",t))(n||{}),i=(t=>(t.Ping="ping",t))(i||{}),o=(t=>(t.NewMessage="message",t.Archive="archive",t.ArchiveAll="archive-all",t.ArchiveRead="archive-read",t.Clicked="clicked",t.MarkAllRead="mark-all-read",t.Opened="opened",t.Read="read",t.Unarchive="unarchive",t.Unopened="unopened",t.Unread="unread",t))(o||{});const r=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.io"}});class a{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)}}const c=class t{static nanoid(e=21){let s="",n=crypto.getRandomValues(new Uint8Array(e|=0));for(;e--;)s+=t.ALPHABET[63&n[e]];return s}};s(c,"ALPHABET","useandom-26T198340PX75pxJACKVERYMINDBUSHWOLF_GQZbfghjklqvwyzrict");let u=c;const h="x-courier-ua",d="sdk",l="sdkv",p="cid";class g extends Error{constructor(t,e,s){super(e),this.code=t,this.type=s,this.name="CourierRequestError"}}function m(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 I(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 v(t){const e=t.validCodes??[200],s=t.options.showLogs?u.nanoid():void 0,n=t.options.courierUserAgent.toHttpHeaderValue(),i=new Request(t.url,{method:t.method,headers:{"Content-Type":"application/json",[h]:n,...t.headers},body:t.body?JSON.stringify(t.body):void 0});s&&m(t.options.logger,s,"HTTP",{url:i.url,method:i.method,headers:Object.fromEntries(i.headers.entries()),body:t.body});const o=await fetch(i);if(204===o.status)return;let r;try{r=await o.json()}catch(a){if(200===o.status)return;throw new g(o.status,"Failed to parse response as JSON","PARSE_ERROR")}if(s&&I(t.options.logger,s,"HTTP",{status:o.status,response:r}),!e.includes(o.status))throw new g(o.status,(null==r?void 0:r.message)||"Unknown Error",null==r?void 0:r.type);return r}async function y(t){const e=t.options.showLogs?u.nanoid():void 0,s=t.options.courierUserAgent.toHttpHeaderValue();e&&m(t.options.logger,e,"GraphQL",{url:t.url,headers:t.headers,query:t.query,variables:t.variables});const n=await fetch(t.url,{method:"POST",headers:{"Content-Type":"application/json",[h]:s,...t.headers},body:JSON.stringify({query:t.query,variables:t.variables})});let i;try{i=await n.json()}catch(o){throw new g(n.status,"Failed to parse response as JSON","PARSE_ERROR")}if(e&&I(t.options.logger,e,"GraphQL",{status:n.status,response:i}),!n.ok)throw new g(n.status,(null==i?void 0:i.message)||"Unknown Error",null==i?void 0:i.type);return i}class T{constructor(t){this.options=t}}class f extends T{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 y({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}}const b=1e3,w=class t{constructor(t){s(this,"webSocket",null),s(this,"retryAttempt",0),s(this,"retryTimeoutId",null),s(this,"closeRequested",!1),s(this,"url"),s(this,"options"),this.url=t.apiUrls.inbox.webSocket,this.options=t}async connect(){var e,s;return this.isConnecting||this.isOpen?(null==(s=this.options.logger)||s.info(`Attempted to open a WebSocket connection, but one already exists in state '${null==(e=this.webSocket)?void 0:e.readyState}'.`),Promise.resolve()):(this.clearRetryTimeout(),this.closeRequested=!1,new Promise(((e,s)=>{this.webSocket=new WebSocket(this.getWebSocketUrl()),this.webSocket.addEventListener("open",(t=>{this.retryAttempt=0,this.onOpen(t),e()})),this.webSocket.addEventListener("message",(async t=>{var e;try{const e=JSON.parse(t.data);if("event"in e&&"reconnect"===e.event)return this.close(b),void(await this.retryConnection(1e3*e.retryAfter));this.onMessageReceived(e)}catch(s){null==(e=this.options.logger)||e.error("Error parsing socket message",s)}})),this.webSocket.addEventListener("close",(e=>{if(e.code!==b&&!this.closeRequested){const s=t.parseCloseEvent(e);s.retryAfterSeconds?this.retryConnection(1e3*s.retryAfterSeconds):this.retryConnection()}this.onClose(e)})),this.webSocket.addEventListener("error",(t=>{this.closeRequested||this.retryConnection(),this.onError(t),s(t)}))})))}close(t=1e3,e){null!==this.webSocket&&(this.closeRequested=!0,this.clearRetryTimeout(),this.retryAttempt=0,this.webSocket.close(t,e))}send(t){var e;if(null===this.webSocket||this.isConnecting)return void(null==(e=this.options.logger)||e.info("Attempted to send a message, but the WebSocket is not yet open."));const s=JSON.stringify(t);this.webSocket.send(s)}get userId(){return this.options.userId}get subTenantId(){return this.options.tenantId}get logger(){return this.options.logger}get courierUserAgent(){return this.options.courierUserAgent}get isConnecting(){return null!==this.webSocket&&this.webSocket.readyState===WebSocket.CONNECTING}get isOpen(){return null!==this.webSocket&&this.webSocket.readyState===WebSocket.OPEN}getWebSocketUrl(){const t=this.options.accessToken,e=this.options.connectionId,s=this.userId,n=this.courierUserAgent.getUserAgentInfo()[d],i=this.courierUserAgent.getUserAgentInfo()[l];return`${this.url}?auth=${t}&cid=${e}&iwpv=v1&userId=${s}&${d}=${n}&${l}=${i}`}static parseCloseEvent(e){if(null===e.reason||""===e.reason)return e;try{const s=JSON.parse(e.reason);if(!s[t.RETRY_AFTER_KEY])return e;const n=parseInt(s[t.RETRY_AFTER_KEY]);return Number.isNaN(n)||n<0?e:{...e,retryAfterSeconds:n}}catch(s){return e}}getBackoffTimeInMillis(){const e=t.BACKOFF_INTERVALS_IN_MILLIS[this.retryAttempt],s=e-e*t.BACKOFF_JITTER_FACTOR,n=e+e*t.BACKOFF_JITTER_FACTOR;return Math.floor(Math.random()*(n-s)+s)}async retryConnection(e){var s,n,i;if(null!==this.retryTimeoutId)return void(null==(s=this.logger)||s.debug("Skipping retry attempt because a previous retry is already scheduled."));if(this.retryAttempt>=t.MAX_RETRY_ATTEMPTS)return void(null==(n=this.logger)||n.error(`Max retry attempts (${t.MAX_RETRY_ATTEMPTS}) reached.`));const o=e??this.getBackoffTimeInMillis();this.retryTimeoutId=window.setTimeout((async()=>{try{await this.connect()}catch(t){}}),o),null==(i=this.logger)||i.debug(`Retrying connection in ${Math.floor(o/1e3)}s. Retry attempt ${this.retryAttempt+1} of ${t.MAX_RETRY_ATTEMPTS}.`),this.retryAttempt++}clearRetryTimeout(){null!==this.retryTimeoutId&&(window.clearTimeout(this.retryTimeoutId),this.retryTimeoutId=null)}};s(w,"BACKOFF_JITTER_FACTOR",.5),s(w,"MAX_RETRY_ATTEMPTS",5),s(w,"BACKOFF_INTERVALS_IN_MILLIS",[3e4,6e4,12e4,24e4,48e4]),s(w,"RETRY_AFTER_KEY","Retry-After");let A=w;class ${constructor(t=10){s(this,"outstandingRequestsMap",new Map),s(this,"completedTransactionsQueue",[]),s(this,"completedTransactionsToKeep"),this.completedTransactionsToKeep=t}addOutstandingRequest(t,e){if(this.outstandingRequestsMap.has(t))throw new Error(`Transaction [${t}] already has an outstanding request`);const s={transactionId:t,request:e,response:null,start:new Date,end:null};this.outstandingRequestsMap.set(t,s)}addResponse(t,e){const s=this.outstandingRequestsMap.get(t);if(void 0===s)throw new Error(`Transaction [${t}] does not have an outstanding request`);s.response=e,s.end=new Date,this.outstandingRequestsMap.delete(t),this.addCompletedTransaction(s)}get outstandingRequests(){return Array.from(this.outstandingRequestsMap.values())}get completedTransactions(){return this.completedTransactionsQueue}clearOutstandingRequests(){this.outstandingRequestsMap.clear()}addCompletedTransaction(t){this.completedTransactionsQueue.push(t),this.completedTransactionsQueue.length>this.completedTransactionsToKeep&&this.completedTransactionsQueue.shift()}}function k(t){return function(t){if(t.event===o.NewMessage){const e=t.data;return e.created||(e.created=(new Date).toISOString()),{...t,data:e}}return t}(t)}const R=class t extends A{constructor(t){super(t),s(this,"pingIntervalId",null),s(this,"messageEventListeners",[]),s(this,"config",null),s(this,"pingTransactionManager",new $)}onOpen(t){return this.pingTransactionManager.clearOutstandingRequests(),this.restartPingInterval(),this.sendGetConfig(),this.sendSubscribe(),Promise.resolve()}onMessageReceived(e){if("action"in e&&e.action===i.Ping){const t=e;this.sendPong(t)}if("response"in e&&"pong"===e.response){const t=e;this.pingTransactionManager.addResponse(t.tid,t),this.pingTransactionManager.clearOutstandingRequests()}if("response"in e&&"config"===e.response){const t=e;this.setConfig(t.data)}if("event"in e&&t.isInboxMessageEvent(e.event)){const t=k(e);for(const e of this.messageEventListeners)e(t)}return this.restartPingInterval(),Promise.resolve()}onClose(t){return this.clearPingInterval(),this.clearMessageEventListeners(),this.pingTransactionManager.clearOutstandingRequests(),Promise.resolve()}onError(t){return Promise.resolve()}sendSubscribe(){const t={channel:this.userId,event:"*"};this.subTenantId&&(t.accountId=this.subTenantId);const e={tid:u.nanoid(),action:n.Subscribe,data:t};this.send(e)}sendUnsubscribe(){const t={tid:u.nanoid(),action:n.Unsubscribe,data:{channel:this.userId}};this.send(t)}addMessageEventListener(t){return this.messageEventListeners.push(t),()=>{this.removeMessageEventListener(t)}}sendPing(){var t;if(this.pingTransactionManager.outstandingRequests.length>=this.maxOutstandingPings)return null==(t=this.logger)||t.debug("Max outstanding pings reached, retrying connection."),this.close(b,"Max outstanding pings reached, retrying connection."),void this.retryConnection();const e={tid:u.nanoid(),action:n.Ping};this.send(e),this.pingTransactionManager.addOutstandingRequest(e.tid,e)}sendPong(t){const e={tid:t.tid,action:n.Pong};this.send(e)}sendGetConfig(){const t={tid:u.nanoid(),action:n.GetConfig};this.send(t)}restartPingInterval(){this.clearPingInterval(),this.pingIntervalId=window.setInterval((()=>{this.sendPing()}),this.pingInterval)}clearPingInterval(){this.pingIntervalId&&window.clearInterval(this.pingIntervalId)}get pingInterval(){return this.config?1e3*this.config.pingInterval:t.DEFAULT_PING_INTERVAL_MILLIS}get maxOutstandingPings(){return this.config?this.config.maxOutstandingPings:t.DEFAULT_MAX_OUTSTANDING_PINGS}setConfig(t){this.config=t}clearMessageEventListeners(){for(;this.messageEventListeners.length>0;)this.messageEventListeners.pop()}removeMessageEventListener(t){const e=this.messageEventListeners.indexOf(t);e>-1&&this.messageEventListeners.splice(e,1)}static isInboxMessageEvent(t){return Object.values(o).includes(t)}};s(R,"DEFAULT_PING_INTERVAL_MILLIS",6e4),s(R,"DEFAULT_MAX_OUTSTANDING_PINGS",3);let E=R;class C extends T{constructor(t){super(t),s(this,"socket"),this.socket=new E(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 y({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 y({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 y({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 y({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 y({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 y({options:this.options,query:e,headers:s,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 y({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 y({options:this.options,query:e,headers:s,url:this.options.apiUrls.inbox.graphql})}async unarchive(t){const e=`\n mutation TrackEvent {\n unarchive(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 y({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 y({options:this.options,query:"\n mutation TrackEvent {\n markAllRead\n }\n ",headers:t,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 y({options:this.options,query:"\n mutation TrackEvent {\n archiveRead\n }\n ",headers:t,url:this.options.apiUrls.inbox.graphql})}async archiveAll(){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 y({options:this.options,query:"\n mutation TrackEvent {\n archiveAll\n }\n ",headers:t,url:this.options.apiUrls.inbox.graphql})}}class S{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 U extends T{constructor(){super(...arguments),s(this,"transformer",new S)}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 v({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 v({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 v({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 x extends T{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 v({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 v({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 P extends T{async putSubscription(t){return await v({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 v({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 L extends T{async postInboundCourier(t){return await v({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 v({url:t.url,options:this.options,method:"POST",body:{event:t.event}})}}class q{constructor(t,e,s){this.clientId=t,this.sdkName=e,this.sdkVersion=s}getUserAgentInfo(){return{[d]:this.sdkName,[l]:this.sdkVersion,[p]:this.clientId}}toHttpHeaderValue(){return Object.entries(this.getUserAgentInfo()).map((([t,e])=>`${t}=${e}`)).join(",")}}const _=class t extends T{constructor(e){var n,i;const o=void 0!==e.showLogs&&e.showLogs,c=u.nanoid(),h={...e,showLogs:o,connectionId:c,apiUrls:e.apiUrls||r(),accessToken:e.jwt??e.publicApiKey},d=new q(c,e.courierUserAgentName||t.COURIER_JS_NAME,e.courierUserAgentVersion||t.COURIER_JS_VERSION);super({...h,logger:new a(h.showLogs),courierUserAgent:d,apiUrls:r(h.apiUrls)}),s(this,"tokens"),s(this,"brands"),s(this,"preferences"),s(this,"inbox"),s(this,"lists"),s(this,"tracking"),this.tokens=new x(this.options),this.brands=new f(this.options),this.preferences=new U(this.options),this.inbox=new C(this.options),this.lists=new P(this.options),this.tracking=new L(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==(n=this.options.logger)||n.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==(i=this.options.logger)||i.warn("Courier Warning: Both a JWT and a Public API Key were provided. The Public API Key will be ignored."))}};s(_,"COURIER_JS_NAME","courier-js"),s(_,"COURIER_JS_VERSION","2.1.3");let M=_;class O{constructor(t){s(this,"callback"),this.callback=t}remove(){B.shared.removeAuthenticationListener(this)}}const N=class t{constructor(){s(this,"id",u.nanoid()),s(this,"instanceClient"),s(this,"courierUserAgentName"),s(this,"courierUserAgentVersion"),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){this.instanceClient&&(this.instanceClient.options.logger.warn("Sign in called but there is already a user signed in. Signing out the current user."),this.signOut()),this.instanceClient=new M({...t,courierUserAgentName:this.courierUserAgentName,courierUserAgentVersion:this.courierUserAgentVersion}),this.notifyAuthenticationListeners({userId:t.userId})}signOut(){var t,e;null==(e=null==(t=this.instanceClient)?void 0:t.inbox.socket)||e.close(),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 O(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(N,"instance");let B=N;t.BrandClient=f,t.Courier=B,t.CourierClient=M,t.InboxClient=C,t.InboxMessageEvent=o,t.ListClient=P,t.PreferenceClient=U,t.TokenClient=x,t.TrackingClient=L,Object.defineProperty(t,Symbol.toStringTag,{value:"Module"})}));
|
|
2
2
|
//# sourceMappingURL=index.js.map
|