@trycourier/courier-js 1.4.2 → 2.0.1-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.
Files changed (38) hide show
  1. package/dist/__tests__/brand-client.test.d.ts +1 -0
  2. package/dist/__tests__/courier-client.test.d.ts +1 -0
  3. package/dist/__tests__/inbox-client.test.d.ts +1 -0
  4. package/dist/__tests__/lists-client.test.d.ts +1 -0
  5. package/dist/__tests__/preferences-client.test.d.ts +1 -0
  6. package/dist/__tests__/shared-instance.test.d.ts +1 -0
  7. package/dist/__tests__/token-client.test.d.ts +1 -0
  8. package/dist/__tests__/tracking-client.test.d.ts +1 -0
  9. package/dist/__tests__/utils.d.ts +2 -0
  10. package/dist/client/brand-client.d.ts +12 -0
  11. package/dist/client/client.d.ts +5 -0
  12. package/dist/client/courier-client.d.ts +38 -0
  13. package/dist/client/inbox-client.d.ts +80 -0
  14. package/dist/client/list-client.d.ts +21 -0
  15. package/dist/client/preference-client.d.ts +46 -0
  16. package/dist/client/token-client.d.ts +24 -0
  17. package/dist/client/tracking-client.d.ts +32 -0
  18. package/dist/index.d.ts +19 -40
  19. package/dist/index.js +1 -189
  20. package/dist/index.mjs +1028 -133
  21. package/dist/jest.setup.d.ts +0 -0
  22. package/dist/shared/authentication-listener.d.ts +9 -0
  23. package/dist/shared/courier.d.ts +68 -0
  24. package/dist/socket/courier-socket.d.ts +24 -0
  25. package/dist/socket/inbox-socket.d.ts +19 -0
  26. package/dist/types/brands.d.ts +36 -0
  27. package/dist/types/courier-api-urls.d.ts +11 -0
  28. package/dist/types/inbox.d.ts +43 -0
  29. package/dist/types/pagination.d.ts +4 -0
  30. package/dist/types/preference.d.ts +37 -0
  31. package/dist/types/token.d.ts +12 -0
  32. package/dist/types/tracking-event.d.ts +1 -0
  33. package/dist/utils/coding.d.ts +2 -0
  34. package/dist/utils/logger.d.ts +10 -0
  35. package/dist/utils/request.d.ts +21 -0
  36. package/dist/utils/uuid.d.ts +3 -0
  37. package/package.json +32 -21
  38. package/README.md +0 -123
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,2 @@
1
+ import { CourierClient } from '../client/courier-client';
2
+ export declare function getClient(tenantId?: string): CourierClient;
@@ -0,0 +1,12 @@
1
+ import { CourierBrand } from '../types/brands';
2
+ import { Client } from './client';
3
+ export declare class BrandClient extends Client {
4
+ /**
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
8
+ */
9
+ getBrand(props: {
10
+ brandId: string;
11
+ }): Promise<CourierBrand>;
12
+ }
@@ -0,0 +1,5 @@
1
+ import { CourierClientOptions } from './courier-client';
2
+ export declare class Client {
3
+ readonly options: CourierClientOptions;
4
+ constructor(options: CourierClientOptions);
5
+ }
@@ -0,0 +1,38 @@
1
+ import { CourierApiUrls } from '../types/courier-api-urls';
2
+ import { Logger } from '../utils/logger';
3
+ import { BrandClient } from './brand-client';
4
+ import { InboxClient } from './inbox-client';
5
+ import { PreferenceClient } from './preference-client';
6
+ import { TokenClient } from './token-client';
7
+ import { Client } from './client';
8
+ import { ListClient } from './list-client';
9
+ import { TrackingClient } from './tracking-client';
10
+ export interface CourierProps {
11
+ jwt?: string;
12
+ publicApiKey?: string;
13
+ userId: string;
14
+ connectionId?: string;
15
+ tenantId?: string;
16
+ showLogs?: boolean;
17
+ apiUrls?: CourierApiUrls;
18
+ }
19
+ export interface CourierClientOptions {
20
+ readonly jwt?: string;
21
+ readonly publicApiKey?: string;
22
+ readonly userId: string;
23
+ readonly connectionId?: string;
24
+ readonly tenantId?: string;
25
+ readonly showLogs?: boolean;
26
+ readonly accessToken?: string;
27
+ readonly logger: Logger;
28
+ readonly apiUrls: CourierApiUrls;
29
+ }
30
+ export declare class CourierClient extends Client {
31
+ readonly tokens: TokenClient;
32
+ readonly brands: BrandClient;
33
+ readonly preferences: PreferenceClient;
34
+ readonly inbox: InboxClient;
35
+ readonly lists: ListClient;
36
+ readonly tracking: TrackingClient;
37
+ constructor(props: CourierProps);
38
+ }
@@ -0,0 +1,80 @@
1
+ import { InboxSocket } from '../socket/inbox-socket';
2
+ import { CourierGetInboxMessagesResponse } from '../types/inbox';
3
+ import { Client } from './client';
4
+ import { CourierClientOptions } from './courier-client';
5
+ export declare class InboxClient extends Client {
6
+ readonly socket: InboxSocket;
7
+ constructor(options: CourierClientOptions);
8
+ /**
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
13
+ */
14
+ getMessages(props?: {
15
+ paginationLimit?: number;
16
+ startCursor?: string;
17
+ }): Promise<CourierGetInboxMessagesResponse>;
18
+ /**
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
23
+ */
24
+ getArchivedMessages(props?: {
25
+ paginationLimit?: number;
26
+ startCursor?: string;
27
+ }): Promise<CourierGetInboxMessagesResponse>;
28
+ /**
29
+ * Get unread message count
30
+ * @returns Promise resolving to number of unread messages
31
+ */
32
+ getUnreadMessageCount(): Promise<number>;
33
+ /**
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
38
+ */
39
+ click(props: {
40
+ messageId: string;
41
+ trackingId: string;
42
+ }): Promise<void>;
43
+ /**
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
47
+ */
48
+ read(props: {
49
+ messageId: string;
50
+ }): Promise<void>;
51
+ /**
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
55
+ */
56
+ unread(props: {
57
+ messageId: string;
58
+ }): Promise<void>;
59
+ /**
60
+ * Mark all messages as read
61
+ * @returns Promise resolving when all messages are marked as read
62
+ */
63
+ readAll(): Promise<void>;
64
+ /**
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
68
+ */
69
+ open(props: {
70
+ messageId: string;
71
+ }): Promise<void>;
72
+ /**
73
+ * Archive a message
74
+ * @param messageId - ID of the message to archive
75
+ * @returns Promise resolving when message is archived
76
+ */
77
+ archive(props: {
78
+ messageId: string;
79
+ }): Promise<void>;
80
+ }
@@ -0,0 +1,21 @@
1
+ import { Client } from './client';
2
+ export declare class ListClient extends Client {
3
+ /**
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
7
+ * @see https://www.courier.com/docs/reference/lists/recipient-subscribe
8
+ */
9
+ putSubscription(props: {
10
+ listId: string;
11
+ }): Promise<void>;
12
+ /**
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
16
+ * @see https://www.courier.com/docs/reference/lists/delete-subscription
17
+ */
18
+ deleteSubscription(props: {
19
+ listId: string;
20
+ }): Promise<void>;
21
+ }
@@ -0,0 +1,46 @@
1
+ import { CourierUserPreferences, CourierUserPreferencesChannel, CourierUserPreferencesStatus, CourierUserPreferencesTopic } from '../types/preference';
2
+ import { Client } from './client';
3
+ export declare class PreferenceClient extends Client {
4
+ private transformer;
5
+ /**
6
+ * Get all preferences for a user
7
+ * @param paginationCursor - Optional cursor for pagination
8
+ * @returns Promise resolving to user preferences
9
+ * @see https://www.courier.com/docs/reference/user-preferences/list-all-user-preferences
10
+ */
11
+ getUserPreferences(props?: {
12
+ paginationCursor?: string;
13
+ }): Promise<CourierUserPreferences>;
14
+ /**
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
18
+ * @see https://www.courier.com/docs/reference/user-preferences/get-subscription-topic-preferences
19
+ */
20
+ getUserPreferenceTopic(props: {
21
+ topicId: string;
22
+ }): Promise<CourierUserPreferencesTopic>;
23
+ /**
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
30
+ * @see https://www.courier.com/docs/reference/user-preferences/update-subscription-topic-preferences
31
+ */
32
+ putUserPreferenceTopic(props: {
33
+ topicId: string;
34
+ status: CourierUserPreferencesStatus;
35
+ hasCustomRouting: boolean;
36
+ customRouting: CourierUserPreferencesChannel[];
37
+ }): Promise<void>;
38
+ /**
39
+ * Get the notification center URL
40
+ * @param clientKey - The client key to use for the URL
41
+ * @returns The notification center URL
42
+ */
43
+ getNotificationCenterUrl(props: {
44
+ clientKey: string;
45
+ }): string;
46
+ }
@@ -0,0 +1,24 @@
1
+ import { CourierDevice } from '../types/token';
2
+ import { Client } from './client';
3
+ export declare class TokenClient extends Client {
4
+ /**
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
9
+ * @see https://www.courier.com/docs/reference/token-management/put-token
10
+ */
11
+ putUserToken(props: {
12
+ token: string;
13
+ provider: string;
14
+ device?: CourierDevice;
15
+ }): Promise<void>;
16
+ /**
17
+ * Delete a push notification token for a user
18
+ * @param token - The push notification token
19
+ * @returns Promise resolving when token is deleted
20
+ */
21
+ deleteUserToken(props: {
22
+ token: string;
23
+ }): Promise<void>;
24
+ }
@@ -0,0 +1,32 @@
1
+ import { CourierTrackingEvent } from '../types/tracking-event';
2
+ import { Client } from './client';
3
+ export declare class TrackingClient extends Client {
4
+ /**
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
11
+ * @see https://www.courier.com/docs/reference/inbound/courier-track-event
12
+ */
13
+ postInboundCourier(props: {
14
+ event: string;
15
+ messageId: string;
16
+ type: 'track';
17
+ properties?: Record<string, any>;
18
+ }): Promise<{
19
+ messageId: string;
20
+ }>;
21
+ /**
22
+ * Post a tracking URL event
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
27
+ */
28
+ postTrackingUrl(props: {
29
+ url: string;
30
+ event: CourierTrackingEvent;
31
+ }): Promise<void>;
32
+ }
package/dist/index.d.ts CHANGED
@@ -1,40 +1,19 @@
1
- type CourierOptions = {
2
- authorization?: string;
3
- baseUrl?: string;
4
- clientKey?: string;
5
- debug?: boolean;
6
- userId?: string;
7
- userSignature?: string;
8
- };
9
- type PreferenceLinkOptions = {
10
- brandId?: string;
11
- tenantId?: string;
12
- };
13
- declare class Courier {
14
- private authorization?;
15
- private baseUrl;
16
- private clientKey;
17
- private debug?;
18
- private userId?;
19
- private userSignature?;
20
- constructor({ authorization, baseUrl, clientKey, debug, userId, userSignature, }: CourierOptions);
21
- private getHeaders;
22
- post<T>(path: string, body: T, useClientPath?: boolean): Promise<void>;
23
- put<T>(path: string, body?: T, useClientPath?: boolean): Promise<void>;
24
- delete(path: string, useClientPath?: boolean): Promise<void>;
25
- generatePreferencesUrl(userId: string, options?: PreferenceLinkOptions): string;
26
- private getPathURL;
27
- }
28
-
29
- declare const client: {
30
- __instance: Courier | null;
31
- init(options: CourierOptions): void;
32
- readonly instance: Courier;
33
- identify(userId: string, payload: Record<string, unknown>): Promise<void>;
34
- subscribe(userId: string, listId: string): Promise<void>;
35
- track(event: string, properties?: Record<string, unknown>): Promise<void>;
36
- unsubscribe(userId: string, listId: string): Promise<void>;
37
- generatePreferencesUrl(userId: string, options?: PreferenceLinkOptions): string;
38
- };
39
-
40
- export { client as default };
1
+ import { CourierApiUrls } from './types/courier-api-urls';
2
+ import { CourierBrand } from './types/brands';
3
+ import { CourierUserPreferences, CourierUserPreferencesStatus, CourierUserPreferencesChannel, CourierUserPreferencesPaging, CourierUserPreferencesTopic, CourierUserPreferencesTopicResponse } from './types/preference';
4
+ import { CourierDevice, CourierToken } from './types/token';
5
+ import { CourierGetInboxMessageResponse, CourierGetInboxMessagesResponse, InboxMessage, InboxAction } from './types/inbox';
6
+ import { MessageEvent, EventType } from './socket/inbox-socket';
7
+ import { CourierSocket } from './socket/courier-socket';
8
+ import { CourierClient, CourierClientOptions, CourierProps } from './client/courier-client';
9
+ import { BrandClient } from './client/brand-client';
10
+ import { TokenClient } from './client/token-client';
11
+ import { PreferenceClient } from './client/preference-client';
12
+ import { InboxClient } from './client/inbox-client';
13
+ import { ListClient } from './client/list-client';
14
+ import { AuthenticationListener } from './shared/authentication-listener';
15
+ import { Courier } from './shared/courier';
16
+ export type { CourierProps, CourierClientOptions, CourierBrand, CourierApiUrls, CourierUserPreferences, CourierUserPreferencesStatus, CourierUserPreferencesChannel, CourierUserPreferencesPaging, CourierUserPreferencesTopic, CourierUserPreferencesTopicResponse, CourierDevice, CourierToken, CourierGetInboxMessageResponse, CourierGetInboxMessagesResponse, InboxMessage, InboxAction, MessageEvent, EventType, };
17
+ export { CourierClient, BrandClient, TokenClient, PreferenceClient, InboxClient, ListClient, CourierSocket };
18
+ export type { AuthenticationListener };
19
+ export { Courier };
package/dist/index.js CHANGED
@@ -1,189 +1 @@
1
- "use strict";
2
- var __defProp = Object.defineProperty;
3
- var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
4
- var __getOwnPropNames = Object.getOwnPropertyNames;
5
- var __hasOwnProp = Object.prototype.hasOwnProperty;
6
- var __export = (target, all) => {
7
- for (var name in all)
8
- __defProp(target, name, { get: all[name], enumerable: true });
9
- };
10
- var __copyProps = (to, from, except, desc) => {
11
- if (from && typeof from === "object" || typeof from === "function") {
12
- for (let key of __getOwnPropNames(from))
13
- if (!__hasOwnProp.call(to, key) && key !== except)
14
- __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
15
- }
16
- return to;
17
- };
18
- var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
19
-
20
- // src/index.ts
21
- var src_exports = {};
22
- __export(src_exports, {
23
- default: () => src_default
24
- });
25
- module.exports = __toCommonJS(src_exports);
26
-
27
- // package.json
28
- var version = "1.4.2";
29
-
30
- // src/helpers/decode.ts
31
- function decode(clientKey) {
32
- const binaryString = atob(clientKey);
33
- const bytes = new Uint8Array(binaryString.length);
34
- for (let i = 0; i < binaryString.length; i++) {
35
- bytes[i] = binaryString.charCodeAt(i);
36
- }
37
- return String.fromCharCode(...bytes);
38
- }
39
- function encode(key) {
40
- const bytes = new Uint8Array(key.length);
41
- for (let i = 0; i < key.length; i++) {
42
- bytes[i] = key.charCodeAt(i);
43
- }
44
- return btoa(String.fromCharCode(...bytes));
45
- }
46
-
47
- // src/helpers/client.ts
48
- async function tryCatch(fn, debug = true) {
49
- var _a, _b;
50
- const response = await fn();
51
- if (!response.ok && debug) {
52
- console.error(
53
- `Error invoking ${response.url}: ${(_a = response.status) != null ? _a : 404} because ${JSON.stringify((_b = await response.json()) == null ? void 0 : _b.message)}`
54
- );
55
- }
56
- }
57
- var Courier = class {
58
- constructor({
59
- authorization,
60
- baseUrl,
61
- clientKey,
62
- debug = false,
63
- userId,
64
- userSignature
65
- }) {
66
- if (!clientKey) {
67
- throw new Error("Courier client key is required");
68
- }
69
- this.authorization = authorization;
70
- this.baseUrl = `${baseUrl != null ? baseUrl : "https://api.courier.com"}`;
71
- this.clientKey = clientKey;
72
- this.debug = debug;
73
- this.userId = userId;
74
- this.userSignature = userSignature;
75
- }
76
- getHeaders() {
77
- return new Headers({
78
- "Content-Type": "application/json",
79
- "x-courier-client-version": `courier-js@${version}`,
80
- "Access-Control-Allow-Origin": "*",
81
- ...this.authorization && { Authorization: this.authorization },
82
- ...this.userId && { "x-courier-user-id": this.userId },
83
- ...this.userSignature && {
84
- "x-courier-user-signature": this.userSignature
85
- },
86
- ...this.clientKey && { "x-courier-client-key": this.clientKey }
87
- });
88
- }
89
- async post(path, body, useClientPath = true) {
90
- const postFn = () => {
91
- return fetch(this.getPathURL(path, useClientPath), {
92
- body: JSON.stringify(body),
93
- headers: this.getHeaders(),
94
- method: "POST"
95
- });
96
- };
97
- await tryCatch(postFn, this.debug);
98
- }
99
- async put(path, body, useClientPath = true) {
100
- const putFn = () => {
101
- return fetch(this.getPathURL(path, useClientPath), {
102
- ...body ? { body: JSON.stringify(body) } : {},
103
- headers: this.getHeaders(),
104
- method: "PUT"
105
- });
106
- };
107
- await tryCatch(putFn, this.debug);
108
- }
109
- async delete(path, useClientPath = true) {
110
- const deleteFn = () => {
111
- return fetch(this.getPathURL(path, useClientPath), {
112
- headers: this.getHeaders(),
113
- method: "DELETE"
114
- });
115
- };
116
- await tryCatch(deleteFn, this.debug);
117
- }
118
- generatePreferencesUrl(userId, options) {
119
- var _a;
120
- if (!userId) {
121
- throw new Error("User ID is required to generate preferences URL");
122
- }
123
- const id = decode(this.clientKey);
124
- return `https://view.notificationcenter.app/p/${encode(
125
- `${id}#${(_a = options == null ? void 0 : options.brandId) != null ? _a : ""}#${userId}${(options == null ? void 0 : options.tenantId) ? `#${options.tenantId}` : ""}#${false}`
126
- )}`;
127
- }
128
- getPathURL(path, useClientPath) {
129
- let pathUrl = this.baseUrl;
130
- if (useClientPath) {
131
- pathUrl = pathUrl.concat("/client");
132
- }
133
- return pathUrl.concat(path);
134
- }
135
- };
136
-
137
- // src/index.ts
138
- var client = {
139
- __instance: null,
140
- init(options) {
141
- this.__instance = new Courier(options);
142
- },
143
- get instance() {
144
- if (!this.__instance) {
145
- throw new Error("Courier instance not initialized");
146
- }
147
- return this.__instance;
148
- },
149
- async identify(userId, payload) {
150
- if (!userId) {
151
- throw new Error("userId is required");
152
- }
153
- await this.instance.post(`/identify/${userId}`, {
154
- profile: {
155
- ...payload
156
- }
157
- });
158
- },
159
- async subscribe(userId, listId) {
160
- if (!userId || !listId) {
161
- throw new Error("userId is required");
162
- }
163
- await this.instance.put(`/lists/${listId}/subscribe/${userId}`);
164
- },
165
- async track(event, properties) {
166
- if (!event) {
167
- throw new Error("event is required");
168
- }
169
- let indempotentKey = self.crypto.randomUUID ? self.crypto.randomUUID() : Math.random().toString(36).substring(2, 15) + Math.random().toString(36).substring(2, 15);
170
- await this.instance.post(`/inbound/courier`, {
171
- messageId: indempotentKey,
172
- type: "track",
173
- event,
174
- properties: { ...properties }
175
- }, false);
176
- },
177
- async unsubscribe(userId, listId) {
178
- if (!userId || !listId) {
179
- throw new Error("userId is required");
180
- }
181
- this.instance.delete(`/lists/${listId}/unsubscribe/${userId}`);
182
- },
183
- generatePreferencesUrl(userId, options) {
184
- return this.instance.generatePreferencesUrl(userId, options);
185
- }
186
- };
187
- var src_default = client;
188
- // Annotate the CommonJS export names for ESM import in node:
189
- 0 && (module.exports = {});
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})}}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.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 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=i,t.InboxClient=I,t.ListClient=w,t.PreferenceClient=v,t.TokenClient=y,Object.defineProperty(t,Symbol.toStringTag,{value:"Module"})}));