@cossistant/core 0.0.19 → 0.0.20
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/api.d.ts.map +1 -1
- package/client.d.ts.map +1 -1
- package/client.js +4 -4
- package/client.js.map +1 -1
- package/conversation.d.ts +13 -13
- package/conversation.d.ts.map +1 -1
- package/core.d.ts.map +1 -1
- package/package.json +1 -1
- package/realtime-events.d.ts +7 -7
- package/rest-client.js +1 -1
- package/rest-client.js.map +1 -1
- package/schemas.d.ts.map +1 -1
- package/schemas3.d.ts +3 -3
- package/store/create-store.d.ts.map +1 -1
- package/timeline-item.d.ts +8 -8
- package/timeline-item.d.ts.map +1 -1
- package/visitor-tracker.js +1 -1
- package/visitor-tracker.js.map +1 -1
package/realtime-events.d.ts
CHANGED
|
@@ -83,8 +83,8 @@ declare const realtimeSchema: {
|
|
|
83
83
|
private: "private";
|
|
84
84
|
}>;
|
|
85
85
|
type: ZodEnum<{
|
|
86
|
-
event: "event";
|
|
87
86
|
message: "message";
|
|
87
|
+
event: "event";
|
|
88
88
|
identification: "identification";
|
|
89
89
|
}>;
|
|
90
90
|
text: ZodNullable<ZodString>;
|
|
@@ -111,8 +111,8 @@ declare const realtimeSchema: {
|
|
|
111
111
|
visitorId: ZodString;
|
|
112
112
|
websiteId: ZodString;
|
|
113
113
|
status: ZodDefault<ZodEnum<{
|
|
114
|
-
resolved: "resolved";
|
|
115
114
|
open: "open";
|
|
115
|
+
resolved: "resolved";
|
|
116
116
|
spam: "spam";
|
|
117
117
|
}>>;
|
|
118
118
|
deletedAt: ZodDefault<ZodNullable<ZodString>>;
|
|
@@ -125,8 +125,8 @@ declare const realtimeSchema: {
|
|
|
125
125
|
private: "private";
|
|
126
126
|
}>;
|
|
127
127
|
type: ZodEnum<{
|
|
128
|
-
event: "event";
|
|
129
128
|
message: "message";
|
|
129
|
+
event: "event";
|
|
130
130
|
identification: "identification";
|
|
131
131
|
}>;
|
|
132
132
|
text: ZodNullable<ZodString>;
|
|
@@ -137,6 +137,7 @@ declare const realtimeSchema: {
|
|
|
137
137
|
}, $strip>, ZodObject<{
|
|
138
138
|
type: ZodLiteral<"event">;
|
|
139
139
|
eventType: ZodEnum<{
|
|
140
|
+
resolved: "resolved";
|
|
140
141
|
assigned: "assigned";
|
|
141
142
|
unassigned: "unassigned";
|
|
142
143
|
participant_requested: "participant_requested";
|
|
@@ -146,7 +147,6 @@ declare const realtimeSchema: {
|
|
|
146
147
|
priority_changed: "priority_changed";
|
|
147
148
|
tag_added: "tag_added";
|
|
148
149
|
tag_removed: "tag_removed";
|
|
149
|
-
resolved: "resolved";
|
|
150
150
|
reopened: "reopened";
|
|
151
151
|
visitor_blocked: "visitor_blocked";
|
|
152
152
|
visitor_unblocked: "visitor_unblocked";
|
|
@@ -182,8 +182,8 @@ declare const realtimeSchema: {
|
|
|
182
182
|
header: ZodObject<{
|
|
183
183
|
id: ZodString;
|
|
184
184
|
status: ZodEnum<{
|
|
185
|
-
resolved: "resolved";
|
|
186
185
|
open: "open";
|
|
186
|
+
resolved: "resolved";
|
|
187
187
|
spam: "spam";
|
|
188
188
|
}>;
|
|
189
189
|
priority: ZodEnum<{
|
|
@@ -231,8 +231,8 @@ declare const realtimeSchema: {
|
|
|
231
231
|
private: "private";
|
|
232
232
|
}>;
|
|
233
233
|
type: ZodEnum<{
|
|
234
|
-
event: "event";
|
|
235
234
|
message: "message";
|
|
235
|
+
event: "event";
|
|
236
236
|
identification: "identification";
|
|
237
237
|
}>;
|
|
238
238
|
text: ZodNullable<ZodString>;
|
|
@@ -243,6 +243,7 @@ declare const realtimeSchema: {
|
|
|
243
243
|
}, $strip>, ZodObject<{
|
|
244
244
|
type: ZodLiteral<"event">;
|
|
245
245
|
eventType: ZodEnum<{
|
|
246
|
+
resolved: "resolved";
|
|
246
247
|
assigned: "assigned";
|
|
247
248
|
unassigned: "unassigned";
|
|
248
249
|
participant_requested: "participant_requested";
|
|
@@ -252,7 +253,6 @@ declare const realtimeSchema: {
|
|
|
252
253
|
priority_changed: "priority_changed";
|
|
253
254
|
tag_added: "tag_added";
|
|
254
255
|
tag_removed: "tag_removed";
|
|
255
|
-
resolved: "resolved";
|
|
256
256
|
reopened: "reopened";
|
|
257
257
|
visitor_blocked: "visitor_blocked";
|
|
258
258
|
visitor_unblocked: "visitor_unblocked";
|
package/rest-client.js
CHANGED
|
@@ -15,7 +15,7 @@ var CossistantRestClient = class {
|
|
|
15
15
|
constructor(config) {
|
|
16
16
|
this.config = config;
|
|
17
17
|
this.publicKey = config.publicKey || (typeof process !== "undefined" ? process.env.NEXT_PUBLIC_COSSISTANT_API_KEY : void 0) || (typeof process !== "undefined" ? process.env.COSSISTANT_API_KEY : void 0) || (typeof process !== "undefined" ? process.env.NEXT_PUBLIC_COSSISTANT_KEY : void 0) || "";
|
|
18
|
-
if (!this.publicKey) throw new Error("Public key is required. Please provide it in the config or set NEXT_PUBLIC_COSSISTANT_API_KEY or
|
|
18
|
+
if (!this.publicKey) throw new Error("Public key is required. Please provide it in the config or set NEXT_PUBLIC_COSSISTANT_API_KEY or COSSISTANT_API_KEY environment variable.");
|
|
19
19
|
this.baseHeaders = {
|
|
20
20
|
"Content-Type": "application/json",
|
|
21
21
|
"X-Public-Key": this.publicKey
|
package/rest-client.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"rest-client.js","names":["headers: Record<string, string>","body: CreateConversationRequestBody","body: MarkConversationSeenRequestBody","body: SetConversationTypingRequestBody"],"sources":["../src/rest-client.ts"],"sourcesContent":["import type { IdentifyContactResponse } from \"@cossistant/types/api/contact\";\nimport type {\n\tCreateConversationRequestBody,\n\tCreateConversationResponseBody,\n\tGetConversationRequest,\n\tGetConversationResponse,\n\tGetConversationSeenDataResponse,\n\tListConversationsRequest,\n\tListConversationsResponse,\n\tMarkConversationSeenRequestBody,\n\tMarkConversationSeenResponseBody,\n\tSetConversationTypingRequestBody,\n\tSetConversationTypingResponseBody,\n} from \"@cossistant/types/api/conversation\";\nimport type {\n\tGetConversationTimelineItemsRequest,\n\tGetConversationTimelineItemsResponse,\n\tSendTimelineItemRequest,\n\tSendTimelineItemResponse,\n} from \"@cossistant/types/api/timeline-item\";\nimport { logger } from \"./logger\";\nimport {\n\tCossistantAPIError,\n\ttype CossistantConfig,\n\ttype PublicWebsiteResponse,\n\ttype UpdateVisitorRequest,\n\ttype VisitorMetadata,\n\ttype VisitorResponse,\n} from \"./types\";\nimport { generateConversationId } from \"./utils\";\nimport { collectVisitorData } from \"./visitor-data\";\nimport {\n\tgetExistingVisitorId,\n\tgetVisitorId,\n\tsetVisitorId,\n} from \"./visitor-tracker\";\n\nexport class CossistantRestClient {\n\tprivate config: CossistantConfig;\n\tprivate baseHeaders: Record<string, string>;\n\tprivate publicKey: string;\n\tprivate websiteId: string | null = null;\n\tprivate visitorId: string | null = null;\n\tprivate visitorBlocked = false;\n\n\tconstructor(config: CossistantConfig) {\n\t\tthis.config = config;\n\n\t\t// Get public key from config or environment variables\n\t\tthis.publicKey =\n\t\t\tconfig.publicKey ||\n\t\t\t(typeof process !== \"undefined\"\n\t\t\t\t? process.env.NEXT_PUBLIC_COSSISTANT_API_KEY\n\t\t\t\t: undefined) ||\n\t\t\t(typeof process !== \"undefined\"\n\t\t\t\t? process.env.COSSISTANT_API_KEY\n\t\t\t\t: undefined) ||\n\t\t\t(typeof process !== \"undefined\"\n\t\t\t\t? process.env.NEXT_PUBLIC_COSSISTANT_KEY\n\t\t\t\t: undefined) ||\n\t\t\t\"\";\n\n\t\tif (!this.publicKey) {\n\t\t\tthrow new Error(\n\t\t\t\t\"Public key is required. Please provide it in the config or set NEXT_PUBLIC_COSSISTANT_API_KEY or COSSISTANT_PUBLIC_KEY environment variable.\"\n\t\t\t);\n\t\t}\n\n\t\tthis.baseHeaders = {\n\t\t\t\"Content-Type\": \"application/json\",\n\t\t\t\"X-Public-Key\": this.publicKey,\n\t\t};\n\n\t\tif (config.userId) {\n\t\t\tthis.baseHeaders[\"X-User-ID\"] = config.userId;\n\t\t}\n\n\t\tif (config.organizationId) {\n\t\t\tthis.baseHeaders[\"X-Organization-ID\"] = config.organizationId;\n\t\t}\n\t}\n\n\tprivate normalizeVisitorResponse(payload: VisitorResponse): VisitorResponse {\n\t\tconst contact = payload.contact ? payload.contact : null;\n\t\treturn {\n\t\t\t...payload,\n\t\t\t// Ensure latitude and longitude are numbers or null\n\t\t\tlatitude:\n\t\t\t\ttypeof payload.latitude === \"string\"\n\t\t\t\t\t? Number.parseFloat(payload.latitude)\n\t\t\t\t\t: payload.latitude,\n\t\t\tlongitude:\n\t\t\t\ttypeof payload.longitude === \"string\"\n\t\t\t\t\t? Number.parseFloat(payload.longitude)\n\t\t\t\t\t: payload.longitude,\n\t\t\tcreatedAt: payload.createdAt,\n\t\t\tupdatedAt: payload.updatedAt,\n\t\t\tlastSeenAt: payload.lastSeenAt ? payload.lastSeenAt : null,\n\t\t\tblockedAt: payload.blockedAt ? payload.blockedAt : null,\n\t\t\tcontact: payload.contact ? payload.contact : null,\n\t\t};\n\t}\n\n\tprivate resolveVisitorId(): string {\n\t\tif (this.visitorId) {\n\t\t\treturn this.visitorId;\n\t\t}\n\n\t\tif (this.websiteId) {\n\t\t\tconst storedVisitorId = getVisitorId(this.websiteId);\n\t\t\tif (storedVisitorId) {\n\t\t\t\tthis.visitorId = storedVisitorId;\n\t\t\t\treturn storedVisitorId;\n\t\t\t}\n\t\t}\n\n\t\tthrow new Error(\"Visitor ID is required\");\n\t}\n\n\tprivate async syncVisitorSnapshot(visitorId: string): Promise<void> {\n\t\ttry {\n\t\t\tconst visitorData = await collectVisitorData();\n\t\t\tif (!visitorData) {\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tconst payload = Object.entries(visitorData).reduce<\n\t\t\t\tPartial<UpdateVisitorRequest>\n\t\t\t>((acc, [key, value]) => {\n\t\t\t\tif (value === null || value === undefined) {\n\t\t\t\t\treturn acc;\n\t\t\t\t}\n\t\t\t\t(acc as Record<string, unknown>)[key] = value;\n\t\t\t\treturn acc;\n\t\t\t}, {});\n\n\t\t\tif (Object.keys(payload).length === 0) {\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tawait this.request<VisitorResponse>(`/visitors/${visitorId}`, {\n\t\t\t\tmethod: \"PATCH\",\n\t\t\t\tbody: JSON.stringify(payload),\n\t\t\t\theaders: {\n\t\t\t\t\t\"X-Visitor-Id\": visitorId,\n\t\t\t\t},\n\t\t\t});\n\t\t} catch (error) {\n\t\t\tlogger.warn(\"Failed to sync visitor data\", error);\n\t\t}\n\t}\n\n\tprivate async request<T>(\n\t\tpath: string,\n\t\toptions: RequestInit = {}\n\t): Promise<T> {\n\t\tif (this.visitorBlocked) {\n\t\t\tconst method = (options.method ?? \"GET\").toUpperCase();\n\t\t\tconst [rawPath] = path.split(\"?\");\n\t\t\tconst normalizedPath = rawPath?.endsWith(\"/\")\n\t\t\t\t? rawPath.slice(0, -1)\n\t\t\t\t: rawPath;\n\t\t\tconst isWebsitesRoot = normalizedPath === \"/websites\";\n\t\t\tconst isSafeMethod = method === \"GET\" || method === \"HEAD\";\n\n\t\t\tif (!(isWebsitesRoot && isSafeMethod)) {\n\t\t\t\tthrow new CossistantAPIError({\n\t\t\t\t\tcode: \"VISITOR_BLOCKED\",\n\t\t\t\t\tmessage: \"Visitor is blocked and cannot perform this action.\",\n\t\t\t\t\tdetails: { path, method },\n\t\t\t\t});\n\t\t\t}\n\t\t}\n\n\t\tconst url = `${this.config.apiUrl}${path}`;\n\n\t\tconst response = await fetch(url, {\n\t\t\t...options,\n\t\t\theaders: {\n\t\t\t\t...this.baseHeaders,\n\t\t\t\t...options.headers,\n\t\t\t},\n\t\t});\n\n\t\tif (!response.ok) {\n\t\t\tconst errorData = await response.json().catch(() => ({}));\n\t\t\tconst statusCode = response.status;\n\t\t\tconst errorCode = errorData.code || `HTTP_${statusCode}`;\n\t\t\tconst serverMessage = errorData.message;\n\n\t\t\t// Determine if this is an authentication/authorization error\n\t\t\tconst isAuthError =\n\t\t\t\tstatusCode === 401 ||\n\t\t\t\tstatusCode === 403 ||\n\t\t\t\terrorCode === \"UNAUTHORIZED\" ||\n\t\t\t\terrorCode === \"FORBIDDEN\" ||\n\t\t\t\terrorCode === \"INVALID_API_KEY\" ||\n\t\t\t\terrorCode === \"API_KEY_EXPIRED\" ||\n\t\t\t\terrorCode === \"API_KEY_MISSING\" ||\n\t\t\t\terrorCode?.toUpperCase().includes(\"AUTH\") ||\n\t\t\t\terrorCode?.toUpperCase().includes(\"API_KEY\");\n\n\t\t\t// Use appropriate error message based on error type\n\t\t\tconst errorMessage = isAuthError\n\t\t\t\t? \"Your Cossistant public API key is invalid, expired, missing or not authorized to access this resource.\"\n\t\t\t\t: serverMessage || `Request failed with status ${statusCode}`;\n\n\t\t\t// Log with appropriate level based on error type\n\t\t\tif (isAuthError) {\n\t\t\t\tlogger.error(errorMessage, {\n\t\t\t\t\tdetails: errorData.details,\n\t\t\t\t\tpath,\n\t\t\t\t\tstatus: statusCode,\n\t\t\t\t\tcode: errorCode,\n\t\t\t\t});\n\t\t\t} else {\n\t\t\t\tlogger.error(\"API request failed\", {\n\t\t\t\t\tmessage: errorMessage,\n\t\t\t\t\tdetails: errorData.details,\n\t\t\t\t\tpath,\n\t\t\t\t\tstatus: statusCode,\n\t\t\t\t\tcode: errorCode,\n\t\t\t\t});\n\t\t\t}\n\n\t\t\tthrow new CossistantAPIError({\n\t\t\t\tcode: errorCode,\n\t\t\t\tmessage: errorMessage,\n\t\t\t\tdetails: errorData.details,\n\t\t\t});\n\t\t}\n\n\t\treturn response.json();\n\t}\n\n\tasync getWebsite(): Promise<PublicWebsiteResponse> {\n\t\t// Make the request with visitor ID if we have one stored\n\t\tconst headers: Record<string, string> = {};\n\n\t\t// First, check if we already know the website ID and have a visitor ID for it\n\t\tif (this.websiteId) {\n\t\t\tconst storedVisitorId = getVisitorId(this.websiteId);\n\t\t\tif (storedVisitorId) {\n\t\t\t\theaders[\"X-Visitor-Id\"] = storedVisitorId;\n\t\t\t}\n\t\t} else {\n\t\t\t// We don't know the website ID yet, but check if we have any existing visitor\n\t\t\t// This prevents creating duplicate visitors on page refresh\n\t\t\tconst existingVisitor = getExistingVisitorId(this.publicKey);\n\t\t\tif (existingVisitor) {\n\t\t\t\theaders[\"X-Visitor-Id\"] = existingVisitor.visitorId;\n\t\t\t\t// Pre-populate our local state\n\t\t\t\tthis.websiteId = existingVisitor.websiteId;\n\t\t\t\tthis.visitorId = existingVisitor.visitorId;\n\t\t\t}\n\t\t}\n\n\t\tconst response = await this.request<PublicWebsiteResponse>(\"/websites\", {\n\t\t\theaders,\n\t\t});\n\n\t\t// Store the website ID for future requests\n\t\tthis.websiteId = response.id;\n\n\t\t// Store the visitor ID if we got one\n\t\tthis.visitorBlocked = response.visitor?.isBlocked ?? false;\n\n\t\tif (response.visitor?.id) {\n\t\t\tif (this.visitorBlocked) {\n\t\t\t\tthis.visitorId = response.visitor.id;\n\t\t\t\tsetVisitorId(response.id, response.visitor.id);\n\t\t\t\treturn response;\n\t\t\t}\n\n\t\t\tthis.visitorId = response.visitor.id;\n\t\t\tsetVisitorId(response.id, response.visitor.id);\n\t\t\tthis.syncVisitorSnapshot(response.visitor.id);\n\t\t}\n\n\t\treturn response;\n\t}\n\n\t// Manually prime website and visitor context when the caller already has it\n\tsetWebsiteContext(websiteId: string, visitorId?: string): void {\n\t\tthis.websiteId = websiteId;\n\t\tif (visitorId) {\n\t\t\tthis.visitorId = visitorId;\n\t\t\tsetVisitorId(websiteId, visitorId);\n\t\t}\n\t}\n\n\tsetVisitorBlocked(isBlocked: boolean): void {\n\t\tthis.visitorBlocked = isBlocked;\n\t}\n\n\tgetCurrentWebsiteId(): string | null {\n\t\treturn this.websiteId;\n\t}\n\n\tgetCurrentVisitorId(): string | null {\n\t\tif (this.visitorId) {\n\t\t\treturn this.visitorId;\n\t\t}\n\n\t\tif (!this.websiteId) {\n\t\t\treturn null;\n\t\t}\n\n\t\treturn getVisitorId(this.websiteId) ?? null;\n\t}\n\n\tasync updateVisitorMetadata(\n\t\tmetadata: VisitorMetadata\n\t): Promise<VisitorResponse> {\n\t\tconst visitorId = this.resolveVisitorId();\n\t\tconst response = await this.request<VisitorResponse>(\n\t\t\t`/visitors/${visitorId}/metadata`,\n\t\t\t{\n\t\t\t\tmethod: \"PATCH\",\n\t\t\t\tbody: JSON.stringify({ metadata }),\n\t\t\t\theaders: {\n\t\t\t\t\t\"X-Visitor-Id\": visitorId,\n\t\t\t\t},\n\t\t\t}\n\t\t);\n\n\t\treturn this.normalizeVisitorResponse(response);\n\t}\n\n\t/**\n\t * Identify a visitor by creating or updating their contact information\n\t * This will link the visitor to a contact record that can be tracked across devices\n\t */\n\tasync identify(params: {\n\t\texternalId?: string;\n\t\temail?: string;\n\t\tname?: string;\n\t\timage?: string;\n\t\tmetadata?: Record<string, unknown>;\n\t\tcontactOrganizationId?: string;\n\t}): Promise<IdentifyContactResponse> {\n\t\tconst visitorId = this.resolveVisitorId();\n\n\t\tconst response = await this.request<IdentifyContactResponse>(\n\t\t\t\"/contacts/identify\",\n\t\t\t{\n\t\t\t\tmethod: \"POST\",\n\t\t\t\tbody: JSON.stringify({\n\t\t\t\t\tvisitorId,\n\t\t\t\t\t...params,\n\t\t\t\t}),\n\t\t\t\theaders: {\n\t\t\t\t\t\"X-Visitor-Id\": visitorId,\n\t\t\t\t},\n\t\t\t}\n\t\t);\n\n\t\treturn {\n\t\t\tcontact: {\n\t\t\t\t...response.contact,\n\t\t\t\t// Ensure metadata is properly typed\n\t\t\t\tmetadata:\n\t\t\t\t\ttypeof response.contact.metadata === \"string\"\n\t\t\t\t\t\t? JSON.parse(response.contact.metadata)\n\t\t\t\t\t\t: response.contact.metadata,\n\t\t\t\tcreatedAt: response.contact.createdAt,\n\t\t\t\tupdatedAt: response.contact.updatedAt,\n\t\t\t},\n\t\t\tvisitorId: response.visitorId,\n\t\t};\n\t}\n\n\t/**\n\t * Update metadata for the contact associated with the current visitor\n\t * Note: The visitor must be identified first via the identify() method\n\t */\n\tasync updateContactMetadata(\n\t\tmetadata: Record<string, unknown>\n\t): Promise<VisitorResponse> {\n\t\t// This still uses the visitor metadata endpoint for backward compatibility\n\t\t// The endpoint will internally update the contact metadata\n\t\treturn this.updateVisitorMetadata(metadata as VisitorMetadata);\n\t}\n\n\tasync createConversation(\n\t\tparams: Partial<CreateConversationRequestBody> = {}\n\t): Promise<CreateConversationResponseBody> {\n\t\tconst conversationId = params.conversationId || generateConversationId();\n\n\t\t// Get visitor ID from storage if we have the website ID, or use the provided one\n\t\tconst storedVisitorId = this.websiteId\n\t\t\t? getVisitorId(this.websiteId)\n\t\t\t: undefined;\n\t\tconst visitorId = params.visitorId || storedVisitorId;\n\n\t\tif (!visitorId) {\n\t\t\tthrow new Error(\"Visitor ID is required\");\n\t\t}\n\n\t\tconst body: CreateConversationRequestBody = {\n\t\t\tconversationId,\n\t\t\tvisitorId,\n\t\t\tdefaultTimelineItems: params.defaultTimelineItems || [],\n\t\t\tchannel: params.channel || \"widget\",\n\t\t};\n\n\t\t// Add visitor ID header if available\n\t\tconst headers: Record<string, string> = {};\n\t\tif (visitorId) {\n\t\t\theaders[\"X-Visitor-Id\"] = visitorId;\n\t\t}\n\n\t\tconst response = await this.request<CreateConversationResponseBody>(\n\t\t\t\"/conversations\",\n\t\t\t{\n\t\t\t\tmethod: \"POST\",\n\t\t\t\tbody: JSON.stringify(body),\n\t\t\t\theaders,\n\t\t\t}\n\t\t);\n\n\t\t// Convert date strings to Date objects\n\t\treturn {\n\t\t\tconversation: {\n\t\t\t\t...response.conversation,\n\t\t\t\tcreatedAt: response.conversation.createdAt,\n\t\t\t\tupdatedAt: response.conversation.updatedAt,\n\t\t\t\tdeletedAt: response.conversation.deletedAt ?? null,\n\t\t\t\tlastTimelineItem: response.conversation.lastTimelineItem,\n\t\t\t},\n\t\t\tinitialTimelineItems: response.initialTimelineItems,\n\t\t};\n\t}\n\n\tasync updateConfiguration(config: Partial<CossistantConfig>): Promise<void> {\n\t\tif (config.publicKey) {\n\t\t\tthis.publicKey = config.publicKey;\n\t\t\tthis.baseHeaders[\"X-Public-Key\"] = config.publicKey;\n\t\t}\n\n\t\tif (config.userId) {\n\t\t\tthis.baseHeaders[\"X-User-ID\"] = config.userId;\n\t\t} else if (config.userId === null) {\n\t\t\tconst { \"X-User-ID\": _, ...rest } = this.baseHeaders;\n\t\t\tthis.baseHeaders = rest;\n\t\t}\n\n\t\tif (config.organizationId) {\n\t\t\tthis.baseHeaders[\"X-Organization-ID\"] = config.organizationId;\n\t\t} else if (config.organizationId === null) {\n\t\t\tconst { \"X-Organization-ID\": _, ...rest } = this.baseHeaders;\n\t\t\tthis.baseHeaders = rest;\n\t\t}\n\n\t\tthis.config = { ...this.config, ...config };\n\t}\n\n\tasync listConversations(\n\t\tparams: Partial<ListConversationsRequest> = {}\n\t): Promise<ListConversationsResponse> {\n\t\t// Get visitor ID from storage if we have the website ID, or use the provided one\n\t\tconst storedVisitorId = this.websiteId\n\t\t\t? getVisitorId(this.websiteId)\n\t\t\t: undefined;\n\t\tconst visitorId = params.visitorId || storedVisitorId;\n\n\t\tif (!visitorId) {\n\t\t\tthrow new Error(\"Visitor ID is required\");\n\t\t}\n\n\t\t// Create query parameters\n\t\tconst queryParams = new URLSearchParams();\n\n\t\tif (visitorId) {\n\t\t\tqueryParams.set(\"visitorId\", visitorId);\n\t\t}\n\n\t\tif (params.page) {\n\t\t\tqueryParams.set(\"page\", params.page.toString());\n\t\t}\n\n\t\tif (params.limit) {\n\t\t\tqueryParams.set(\"limit\", params.limit.toString());\n\t\t}\n\n\t\tif (params.status) {\n\t\t\tqueryParams.set(\"status\", params.status);\n\t\t}\n\n\t\tif (params.orderBy) {\n\t\t\tqueryParams.set(\"orderBy\", params.orderBy);\n\t\t}\n\n\t\tif (params.order) {\n\t\t\tqueryParams.set(\"order\", params.order);\n\t\t}\n\n\t\t// Add visitor ID header if available\n\t\tconst headers: Record<string, string> = {};\n\t\tif (visitorId) {\n\t\t\theaders[\"X-Visitor-Id\"] = visitorId;\n\t\t}\n\n\t\tconst response = await this.request<ListConversationsResponse>(\n\t\t\t`/conversations?${queryParams.toString()}`,\n\t\t\t{\n\t\t\t\theaders,\n\t\t\t}\n\t\t);\n\n\t\t// Convert date strings to Date objects\n\t\treturn {\n\t\t\tconversations: response.conversations.map((conv) => ({\n\t\t\t\t...conv,\n\t\t\t\tcreatedAt: conv.createdAt,\n\t\t\t\tupdatedAt: conv.updatedAt,\n\t\t\t\tdeletedAt: conv.deletedAt ?? null,\n\t\t\t\tlastTimelineItem: conv.lastTimelineItem,\n\t\t\t})),\n\t\t\tpagination: response.pagination,\n\t\t};\n\t}\n\n\tasync getConversation(\n\t\tparams: GetConversationRequest\n\t): Promise<GetConversationResponse> {\n\t\t// Get visitor ID from storage if we have the website ID\n\t\tconst visitorId = this.websiteId ? getVisitorId(this.websiteId) : undefined;\n\n\t\t// Add visitor ID header if available\n\t\tconst headers: Record<string, string> = {};\n\t\tif (visitorId) {\n\t\t\theaders[\"X-Visitor-Id\"] = visitorId;\n\t\t}\n\n\t\tconst response = await this.request<GetConversationResponse>(\n\t\t\t`/conversations/${params.conversationId}`,\n\t\t\t{\n\t\t\t\theaders,\n\t\t\t}\n\t\t);\n\n\t\t// Convert date strings to Date objects\n\t\treturn {\n\t\t\tconversation: {\n\t\t\t\t...response.conversation,\n\t\t\t\tcreatedAt: response.conversation.createdAt,\n\t\t\t\tupdatedAt: response.conversation.updatedAt,\n\t\t\t\tdeletedAt: response.conversation.deletedAt ?? null,\n\t\t\t\tlastTimelineItem: response.conversation.lastTimelineItem,\n\t\t\t},\n\t\t};\n\t}\n\n\tasync markConversationSeen(\n\t\tparams: {\n\t\t\tconversationId: string;\n\t\t} & Partial<MarkConversationSeenRequestBody>\n\t): Promise<MarkConversationSeenResponseBody> {\n\t\tconst storedVisitorId = this.websiteId\n\t\t\t? getVisitorId(this.websiteId)\n\t\t\t: undefined;\n\t\tconst visitorId = params.visitorId || storedVisitorId;\n\n\t\tif (!visitorId) {\n\t\t\tthrow new Error(\"Visitor ID is required to mark a conversation as seen\");\n\t\t}\n\n\t\tconst headers: Record<string, string> = {};\n\t\tif (visitorId) {\n\t\t\theaders[\"X-Visitor-Id\"] = visitorId;\n\t\t}\n\n\t\tconst body: MarkConversationSeenRequestBody = {};\n\t\tif (params.visitorId) {\n\t\t\tbody.visitorId = params.visitorId;\n\t\t}\n\n\t\tconst response = await this.request<MarkConversationSeenResponseBody>(\n\t\t\t`/conversations/${params.conversationId}/seen`,\n\t\t\t{\n\t\t\t\tmethod: \"POST\",\n\t\t\t\tbody: JSON.stringify(body),\n\t\t\t\theaders,\n\t\t\t}\n\t\t);\n\n\t\treturn {\n\t\t\tconversationId: response.conversationId,\n\t\t\tlastSeenAt: response.lastSeenAt,\n\t\t};\n\t}\n\n\tasync getConversationSeenData(params: {\n\t\tconversationId: string;\n\t}): Promise<GetConversationSeenDataResponse> {\n\t\tconst response = await this.request<GetConversationSeenDataResponse>(\n\t\t\t`/conversations/${params.conversationId}/seen`,\n\t\t\t{\n\t\t\t\tmethod: \"GET\",\n\t\t\t}\n\t\t);\n\n\t\treturn {\n\t\t\tseenData: response.seenData.map((item) => ({\n\t\t\t\t...item,\n\t\t\t\tlastSeenAt: item.lastSeenAt,\n\t\t\t\tcreatedAt: item.createdAt,\n\t\t\t\tupdatedAt: item.updatedAt,\n\t\t\t\tdeletedAt: item.deletedAt ? item.deletedAt : null,\n\t\t\t})),\n\t\t};\n\t}\n\n\tasync setConversationTyping(params: {\n\t\tconversationId: string;\n\t\tisTyping: boolean;\n\t\tvisitorPreview?: string | null;\n\t\tvisitorId?: string;\n\t}): Promise<SetConversationTypingResponseBody> {\n\t\tconst storedVisitorId = this.websiteId\n\t\t\t? getVisitorId(this.websiteId)\n\t\t\t: undefined;\n\t\tconst visitorId = params.visitorId || storedVisitorId;\n\n\t\tif (!visitorId) {\n\t\t\tthrow new Error(\"Visitor ID is required to report typing state\");\n\t\t}\n\n\t\tconst headers: Record<string, string> = {};\n\t\tif (visitorId) {\n\t\t\theaders[\"X-Visitor-Id\"] = visitorId;\n\t\t}\n\n\t\tconst body: SetConversationTypingRequestBody = {\n\t\t\tisTyping: params.isTyping,\n\t\t};\n\n\t\tif (params.visitorId) {\n\t\t\tbody.visitorId = params.visitorId;\n\t\t}\n\n\t\tif (params.visitorPreview && params.isTyping) {\n\t\t\tbody.visitorPreview = params.visitorPreview.slice(0, 2000);\n\t\t}\n\n\t\tconst response = await this.request<SetConversationTypingResponseBody>(\n\t\t\t`/conversations/${params.conversationId}/typing`,\n\t\t\t{\n\t\t\t\tmethod: \"POST\",\n\t\t\t\tbody: JSON.stringify(body),\n\t\t\t\theaders,\n\t\t\t}\n\t\t);\n\n\t\treturn {\n\t\t\tconversationId: response.conversationId,\n\t\t\tisTyping: response.isTyping,\n\t\t\tvisitorPreview: response.visitorPreview,\n\t\t\tsentAt: response.sentAt,\n\t\t};\n\t}\n\n\tasync sendMessage(\n\t\tparams: SendTimelineItemRequest\n\t): Promise<SendTimelineItemResponse> {\n\t\t// Get visitor ID from storage if we have the website ID\n\t\tconst visitorId = this.websiteId ? getVisitorId(this.websiteId) : undefined;\n\n\t\t// Add visitor ID header if available\n\t\tconst headers: Record<string, string> = {};\n\t\tif (visitorId) {\n\t\t\theaders[\"X-Visitor-Id\"] = visitorId;\n\t\t}\n\n\t\tconst response = await this.request<SendTimelineItemResponse>(\"/messages\", {\n\t\t\tmethod: \"POST\",\n\t\t\tbody: JSON.stringify(params),\n\t\t\theaders,\n\t\t});\n\n\t\treturn {\n\t\t\titem: response.item,\n\t\t};\n\t}\n\n\tasync getConversationTimelineItems(\n\t\tparams: GetConversationTimelineItemsRequest & { conversationId: string }\n\t): Promise<GetConversationTimelineItemsResponse> {\n\t\t// Get visitor ID from storage if we have the website ID\n\t\tconst visitorId = this.websiteId ? getVisitorId(this.websiteId) : undefined;\n\n\t\t// Create query parameters\n\t\tconst queryParams = new URLSearchParams();\n\n\t\tif (params.limit) {\n\t\t\tqueryParams.set(\"limit\", params.limit.toString());\n\t\t}\n\n\t\tif (params.cursor) {\n\t\t\tqueryParams.set(\"cursor\", params.cursor);\n\t\t}\n\n\t\t// Add visitor ID header if available\n\t\tconst headers: Record<string, string> = {};\n\t\tif (visitorId) {\n\t\t\theaders[\"X-Visitor-Id\"] = visitorId;\n\t\t}\n\n\t\tconst response = await this.request<GetConversationTimelineItemsResponse>(\n\t\t\t`/conversations/${params.conversationId}/timeline?${queryParams.toString()}`,\n\t\t\t{\n\t\t\t\theaders,\n\t\t\t}\n\t\t);\n\n\t\treturn {\n\t\t\titems: response.items,\n\t\t\tnextCursor: response.nextCursor,\n\t\t\thasNextPage: response.hasNextPage,\n\t\t};\n\t}\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"rest-client.js","names":["headers: Record<string, string>","body: CreateConversationRequestBody","body: MarkConversationSeenRequestBody","body: SetConversationTypingRequestBody"],"sources":["../src/rest-client.ts"],"sourcesContent":["import type { IdentifyContactResponse } from \"@cossistant/types/api/contact\";\nimport type {\n\tCreateConversationRequestBody,\n\tCreateConversationResponseBody,\n\tGetConversationRequest,\n\tGetConversationResponse,\n\tGetConversationSeenDataResponse,\n\tListConversationsRequest,\n\tListConversationsResponse,\n\tMarkConversationSeenRequestBody,\n\tMarkConversationSeenResponseBody,\n\tSetConversationTypingRequestBody,\n\tSetConversationTypingResponseBody,\n} from \"@cossistant/types/api/conversation\";\nimport type {\n\tGetConversationTimelineItemsRequest,\n\tGetConversationTimelineItemsResponse,\n\tSendTimelineItemRequest,\n\tSendTimelineItemResponse,\n} from \"@cossistant/types/api/timeline-item\";\nimport { logger } from \"./logger\";\nimport {\n\tCossistantAPIError,\n\ttype CossistantConfig,\n\ttype PublicWebsiteResponse,\n\ttype UpdateVisitorRequest,\n\ttype VisitorMetadata,\n\ttype VisitorResponse,\n} from \"./types\";\nimport { generateConversationId } from \"./utils\";\nimport { collectVisitorData } from \"./visitor-data\";\nimport {\n\tgetExistingVisitorId,\n\tgetVisitorId,\n\tsetVisitorId,\n} from \"./visitor-tracker\";\n\nexport class CossistantRestClient {\n\tprivate config: CossistantConfig;\n\tprivate baseHeaders: Record<string, string>;\n\tprivate publicKey: string;\n\tprivate websiteId: string | null = null;\n\tprivate visitorId: string | null = null;\n\tprivate visitorBlocked = false;\n\n\tconstructor(config: CossistantConfig) {\n\t\tthis.config = config;\n\n\t\t// Get public key from config or environment variables\n\t\tthis.publicKey =\n\t\t\tconfig.publicKey ||\n\t\t\t(typeof process !== \"undefined\"\n\t\t\t\t? process.env.NEXT_PUBLIC_COSSISTANT_API_KEY\n\t\t\t\t: undefined) ||\n\t\t\t(typeof process !== \"undefined\"\n\t\t\t\t? process.env.COSSISTANT_API_KEY\n\t\t\t\t: undefined) ||\n\t\t\t(typeof process !== \"undefined\"\n\t\t\t\t? process.env.NEXT_PUBLIC_COSSISTANT_KEY\n\t\t\t\t: undefined) ||\n\t\t\t\"\";\n\n\t\tif (!this.publicKey) {\n\t\t\tthrow new Error(\n\t\t\t\t\"Public key is required. Please provide it in the config or set NEXT_PUBLIC_COSSISTANT_API_KEY or COSSISTANT_API_KEY environment variable.\"\n\t\t\t);\n\t\t}\n\n\t\tthis.baseHeaders = {\n\t\t\t\"Content-Type\": \"application/json\",\n\t\t\t\"X-Public-Key\": this.publicKey,\n\t\t};\n\n\t\tif (config.userId) {\n\t\t\tthis.baseHeaders[\"X-User-ID\"] = config.userId;\n\t\t}\n\n\t\tif (config.organizationId) {\n\t\t\tthis.baseHeaders[\"X-Organization-ID\"] = config.organizationId;\n\t\t}\n\t}\n\n\tprivate normalizeVisitorResponse(payload: VisitorResponse): VisitorResponse {\n\t\tconst contact = payload.contact ? payload.contact : null;\n\t\treturn {\n\t\t\t...payload,\n\t\t\t// Ensure latitude and longitude are numbers or null\n\t\t\tlatitude:\n\t\t\t\ttypeof payload.latitude === \"string\"\n\t\t\t\t\t? Number.parseFloat(payload.latitude)\n\t\t\t\t\t: payload.latitude,\n\t\t\tlongitude:\n\t\t\t\ttypeof payload.longitude === \"string\"\n\t\t\t\t\t? Number.parseFloat(payload.longitude)\n\t\t\t\t\t: payload.longitude,\n\t\t\tcreatedAt: payload.createdAt,\n\t\t\tupdatedAt: payload.updatedAt,\n\t\t\tlastSeenAt: payload.lastSeenAt ? payload.lastSeenAt : null,\n\t\t\tblockedAt: payload.blockedAt ? payload.blockedAt : null,\n\t\t\tcontact: payload.contact ? payload.contact : null,\n\t\t};\n\t}\n\n\tprivate resolveVisitorId(): string {\n\t\tif (this.visitorId) {\n\t\t\treturn this.visitorId;\n\t\t}\n\n\t\tif (this.websiteId) {\n\t\t\tconst storedVisitorId = getVisitorId(this.websiteId);\n\t\t\tif (storedVisitorId) {\n\t\t\t\tthis.visitorId = storedVisitorId;\n\t\t\t\treturn storedVisitorId;\n\t\t\t}\n\t\t}\n\n\t\tthrow new Error(\"Visitor ID is required\");\n\t}\n\n\tprivate async syncVisitorSnapshot(visitorId: string): Promise<void> {\n\t\ttry {\n\t\t\tconst visitorData = await collectVisitorData();\n\t\t\tif (!visitorData) {\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tconst payload = Object.entries(visitorData).reduce<\n\t\t\t\tPartial<UpdateVisitorRequest>\n\t\t\t>((acc, [key, value]) => {\n\t\t\t\tif (value === null || value === undefined) {\n\t\t\t\t\treturn acc;\n\t\t\t\t}\n\t\t\t\t(acc as Record<string, unknown>)[key] = value;\n\t\t\t\treturn acc;\n\t\t\t}, {});\n\n\t\t\tif (Object.keys(payload).length === 0) {\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tawait this.request<VisitorResponse>(`/visitors/${visitorId}`, {\n\t\t\t\tmethod: \"PATCH\",\n\t\t\t\tbody: JSON.stringify(payload),\n\t\t\t\theaders: {\n\t\t\t\t\t\"X-Visitor-Id\": visitorId,\n\t\t\t\t},\n\t\t\t});\n\t\t} catch (error) {\n\t\t\tlogger.warn(\"Failed to sync visitor data\", error);\n\t\t}\n\t}\n\n\tprivate async request<T>(\n\t\tpath: string,\n\t\toptions: RequestInit = {}\n\t): Promise<T> {\n\t\tif (this.visitorBlocked) {\n\t\t\tconst method = (options.method ?? \"GET\").toUpperCase();\n\t\t\tconst [rawPath] = path.split(\"?\");\n\t\t\tconst normalizedPath = rawPath?.endsWith(\"/\")\n\t\t\t\t? rawPath.slice(0, -1)\n\t\t\t\t: rawPath;\n\t\t\tconst isWebsitesRoot = normalizedPath === \"/websites\";\n\t\t\tconst isSafeMethod = method === \"GET\" || method === \"HEAD\";\n\n\t\t\tif (!(isWebsitesRoot && isSafeMethod)) {\n\t\t\t\tthrow new CossistantAPIError({\n\t\t\t\t\tcode: \"VISITOR_BLOCKED\",\n\t\t\t\t\tmessage: \"Visitor is blocked and cannot perform this action.\",\n\t\t\t\t\tdetails: { path, method },\n\t\t\t\t});\n\t\t\t}\n\t\t}\n\n\t\tconst url = `${this.config.apiUrl}${path}`;\n\n\t\tconst response = await fetch(url, {\n\t\t\t...options,\n\t\t\theaders: {\n\t\t\t\t...this.baseHeaders,\n\t\t\t\t...options.headers,\n\t\t\t},\n\t\t});\n\n\t\tif (!response.ok) {\n\t\t\tconst errorData = await response.json().catch(() => ({}));\n\t\t\tconst statusCode = response.status;\n\t\t\tconst errorCode = errorData.code || `HTTP_${statusCode}`;\n\t\t\tconst serverMessage = errorData.message;\n\n\t\t\t// Determine if this is an authentication/authorization error\n\t\t\tconst isAuthError =\n\t\t\t\tstatusCode === 401 ||\n\t\t\t\tstatusCode === 403 ||\n\t\t\t\terrorCode === \"UNAUTHORIZED\" ||\n\t\t\t\terrorCode === \"FORBIDDEN\" ||\n\t\t\t\terrorCode === \"INVALID_API_KEY\" ||\n\t\t\t\terrorCode === \"API_KEY_EXPIRED\" ||\n\t\t\t\terrorCode === \"API_KEY_MISSING\" ||\n\t\t\t\terrorCode?.toUpperCase().includes(\"AUTH\") ||\n\t\t\t\terrorCode?.toUpperCase().includes(\"API_KEY\");\n\n\t\t\t// Use appropriate error message based on error type\n\t\t\tconst errorMessage = isAuthError\n\t\t\t\t? \"Your Cossistant public API key is invalid, expired, missing or not authorized to access this resource.\"\n\t\t\t\t: serverMessage || `Request failed with status ${statusCode}`;\n\n\t\t\t// Log with appropriate level based on error type\n\t\t\tif (isAuthError) {\n\t\t\t\tlogger.error(errorMessage, {\n\t\t\t\t\tdetails: errorData.details,\n\t\t\t\t\tpath,\n\t\t\t\t\tstatus: statusCode,\n\t\t\t\t\tcode: errorCode,\n\t\t\t\t});\n\t\t\t} else {\n\t\t\t\tlogger.error(\"API request failed\", {\n\t\t\t\t\tmessage: errorMessage,\n\t\t\t\t\tdetails: errorData.details,\n\t\t\t\t\tpath,\n\t\t\t\t\tstatus: statusCode,\n\t\t\t\t\tcode: errorCode,\n\t\t\t\t});\n\t\t\t}\n\n\t\t\tthrow new CossistantAPIError({\n\t\t\t\tcode: errorCode,\n\t\t\t\tmessage: errorMessage,\n\t\t\t\tdetails: errorData.details,\n\t\t\t});\n\t\t}\n\n\t\treturn response.json();\n\t}\n\n\tasync getWebsite(): Promise<PublicWebsiteResponse> {\n\t\t// Make the request with visitor ID if we have one stored\n\t\tconst headers: Record<string, string> = {};\n\n\t\t// First, check if we already know the website ID and have a visitor ID for it\n\t\tif (this.websiteId) {\n\t\t\tconst storedVisitorId = getVisitorId(this.websiteId);\n\t\t\tif (storedVisitorId) {\n\t\t\t\theaders[\"X-Visitor-Id\"] = storedVisitorId;\n\t\t\t}\n\t\t} else {\n\t\t\t// We don't know the website ID yet, but check if we have any existing visitor\n\t\t\t// This prevents creating duplicate visitors on page refresh\n\t\t\tconst existingVisitor = getExistingVisitorId(this.publicKey);\n\t\t\tif (existingVisitor) {\n\t\t\t\theaders[\"X-Visitor-Id\"] = existingVisitor.visitorId;\n\t\t\t\t// Pre-populate our local state\n\t\t\t\tthis.websiteId = existingVisitor.websiteId;\n\t\t\t\tthis.visitorId = existingVisitor.visitorId;\n\t\t\t}\n\t\t}\n\n\t\tconst response = await this.request<PublicWebsiteResponse>(\"/websites\", {\n\t\t\theaders,\n\t\t});\n\n\t\t// Store the website ID for future requests\n\t\tthis.websiteId = response.id;\n\n\t\t// Store the visitor ID if we got one\n\t\tthis.visitorBlocked = response.visitor?.isBlocked ?? false;\n\n\t\tif (response.visitor?.id) {\n\t\t\tif (this.visitorBlocked) {\n\t\t\t\tthis.visitorId = response.visitor.id;\n\t\t\t\tsetVisitorId(response.id, response.visitor.id);\n\t\t\t\treturn response;\n\t\t\t}\n\n\t\t\tthis.visitorId = response.visitor.id;\n\t\t\tsetVisitorId(response.id, response.visitor.id);\n\t\t\tthis.syncVisitorSnapshot(response.visitor.id);\n\t\t}\n\n\t\treturn response;\n\t}\n\n\t// Manually prime website and visitor context when the caller already has it\n\tsetWebsiteContext(websiteId: string, visitorId?: string): void {\n\t\tthis.websiteId = websiteId;\n\t\tif (visitorId) {\n\t\t\tthis.visitorId = visitorId;\n\t\t\tsetVisitorId(websiteId, visitorId);\n\t\t}\n\t}\n\n\tsetVisitorBlocked(isBlocked: boolean): void {\n\t\tthis.visitorBlocked = isBlocked;\n\t}\n\n\tgetCurrentWebsiteId(): string | null {\n\t\treturn this.websiteId;\n\t}\n\n\tgetCurrentVisitorId(): string | null {\n\t\tif (this.visitorId) {\n\t\t\treturn this.visitorId;\n\t\t}\n\n\t\tif (!this.websiteId) {\n\t\t\treturn null;\n\t\t}\n\n\t\treturn getVisitorId(this.websiteId) ?? null;\n\t}\n\n\tasync updateVisitorMetadata(\n\t\tmetadata: VisitorMetadata\n\t): Promise<VisitorResponse> {\n\t\tconst visitorId = this.resolveVisitorId();\n\t\tconst response = await this.request<VisitorResponse>(\n\t\t\t`/visitors/${visitorId}/metadata`,\n\t\t\t{\n\t\t\t\tmethod: \"PATCH\",\n\t\t\t\tbody: JSON.stringify({ metadata }),\n\t\t\t\theaders: {\n\t\t\t\t\t\"X-Visitor-Id\": visitorId,\n\t\t\t\t},\n\t\t\t}\n\t\t);\n\n\t\treturn this.normalizeVisitorResponse(response);\n\t}\n\n\t/**\n\t * Identify a visitor by creating or updating their contact information\n\t * This will link the visitor to a contact record that can be tracked across devices\n\t */\n\tasync identify(params: {\n\t\texternalId?: string;\n\t\temail?: string;\n\t\tname?: string;\n\t\timage?: string;\n\t\tmetadata?: Record<string, unknown>;\n\t\tcontactOrganizationId?: string;\n\t}): Promise<IdentifyContactResponse> {\n\t\tconst visitorId = this.resolveVisitorId();\n\n\t\tconst response = await this.request<IdentifyContactResponse>(\n\t\t\t\"/contacts/identify\",\n\t\t\t{\n\t\t\t\tmethod: \"POST\",\n\t\t\t\tbody: JSON.stringify({\n\t\t\t\t\tvisitorId,\n\t\t\t\t\t...params,\n\t\t\t\t}),\n\t\t\t\theaders: {\n\t\t\t\t\t\"X-Visitor-Id\": visitorId,\n\t\t\t\t},\n\t\t\t}\n\t\t);\n\n\t\treturn {\n\t\t\tcontact: {\n\t\t\t\t...response.contact,\n\t\t\t\t// Ensure metadata is properly typed\n\t\t\t\tmetadata:\n\t\t\t\t\ttypeof response.contact.metadata === \"string\"\n\t\t\t\t\t\t? JSON.parse(response.contact.metadata)\n\t\t\t\t\t\t: response.contact.metadata,\n\t\t\t\tcreatedAt: response.contact.createdAt,\n\t\t\t\tupdatedAt: response.contact.updatedAt,\n\t\t\t},\n\t\t\tvisitorId: response.visitorId,\n\t\t};\n\t}\n\n\t/**\n\t * Update metadata for the contact associated with the current visitor\n\t * Note: The visitor must be identified first via the identify() method\n\t */\n\tasync updateContactMetadata(\n\t\tmetadata: Record<string, unknown>\n\t): Promise<VisitorResponse> {\n\t\t// This still uses the visitor metadata endpoint for backward compatibility\n\t\t// The endpoint will internally update the contact metadata\n\t\treturn this.updateVisitorMetadata(metadata as VisitorMetadata);\n\t}\n\n\tasync createConversation(\n\t\tparams: Partial<CreateConversationRequestBody> = {}\n\t): Promise<CreateConversationResponseBody> {\n\t\tconst conversationId = params.conversationId || generateConversationId();\n\n\t\t// Get visitor ID from storage if we have the website ID, or use the provided one\n\t\tconst storedVisitorId = this.websiteId\n\t\t\t? getVisitorId(this.websiteId)\n\t\t\t: undefined;\n\t\tconst visitorId = params.visitorId || storedVisitorId;\n\n\t\tif (!visitorId) {\n\t\t\tthrow new Error(\"Visitor ID is required\");\n\t\t}\n\n\t\tconst body: CreateConversationRequestBody = {\n\t\t\tconversationId,\n\t\t\tvisitorId,\n\t\t\tdefaultTimelineItems: params.defaultTimelineItems || [],\n\t\t\tchannel: params.channel || \"widget\",\n\t\t};\n\n\t\t// Add visitor ID header if available\n\t\tconst headers: Record<string, string> = {};\n\t\tif (visitorId) {\n\t\t\theaders[\"X-Visitor-Id\"] = visitorId;\n\t\t}\n\n\t\tconst response = await this.request<CreateConversationResponseBody>(\n\t\t\t\"/conversations\",\n\t\t\t{\n\t\t\t\tmethod: \"POST\",\n\t\t\t\tbody: JSON.stringify(body),\n\t\t\t\theaders,\n\t\t\t}\n\t\t);\n\n\t\t// Convert date strings to Date objects\n\t\treturn {\n\t\t\tconversation: {\n\t\t\t\t...response.conversation,\n\t\t\t\tcreatedAt: response.conversation.createdAt,\n\t\t\t\tupdatedAt: response.conversation.updatedAt,\n\t\t\t\tdeletedAt: response.conversation.deletedAt ?? null,\n\t\t\t\tlastTimelineItem: response.conversation.lastTimelineItem,\n\t\t\t},\n\t\t\tinitialTimelineItems: response.initialTimelineItems,\n\t\t};\n\t}\n\n\tasync updateConfiguration(config: Partial<CossistantConfig>): Promise<void> {\n\t\tif (config.publicKey) {\n\t\t\tthis.publicKey = config.publicKey;\n\t\t\tthis.baseHeaders[\"X-Public-Key\"] = config.publicKey;\n\t\t}\n\n\t\tif (config.userId) {\n\t\t\tthis.baseHeaders[\"X-User-ID\"] = config.userId;\n\t\t} else if (config.userId === null) {\n\t\t\tconst { \"X-User-ID\": _, ...rest } = this.baseHeaders;\n\t\t\tthis.baseHeaders = rest;\n\t\t}\n\n\t\tif (config.organizationId) {\n\t\t\tthis.baseHeaders[\"X-Organization-ID\"] = config.organizationId;\n\t\t} else if (config.organizationId === null) {\n\t\t\tconst { \"X-Organization-ID\": _, ...rest } = this.baseHeaders;\n\t\t\tthis.baseHeaders = rest;\n\t\t}\n\n\t\tthis.config = { ...this.config, ...config };\n\t}\n\n\tasync listConversations(\n\t\tparams: Partial<ListConversationsRequest> = {}\n\t): Promise<ListConversationsResponse> {\n\t\t// Get visitor ID from storage if we have the website ID, or use the provided one\n\t\tconst storedVisitorId = this.websiteId\n\t\t\t? getVisitorId(this.websiteId)\n\t\t\t: undefined;\n\t\tconst visitorId = params.visitorId || storedVisitorId;\n\n\t\tif (!visitorId) {\n\t\t\tthrow new Error(\"Visitor ID is required\");\n\t\t}\n\n\t\t// Create query parameters\n\t\tconst queryParams = new URLSearchParams();\n\n\t\tif (visitorId) {\n\t\t\tqueryParams.set(\"visitorId\", visitorId);\n\t\t}\n\n\t\tif (params.page) {\n\t\t\tqueryParams.set(\"page\", params.page.toString());\n\t\t}\n\n\t\tif (params.limit) {\n\t\t\tqueryParams.set(\"limit\", params.limit.toString());\n\t\t}\n\n\t\tif (params.status) {\n\t\t\tqueryParams.set(\"status\", params.status);\n\t\t}\n\n\t\tif (params.orderBy) {\n\t\t\tqueryParams.set(\"orderBy\", params.orderBy);\n\t\t}\n\n\t\tif (params.order) {\n\t\t\tqueryParams.set(\"order\", params.order);\n\t\t}\n\n\t\t// Add visitor ID header if available\n\t\tconst headers: Record<string, string> = {};\n\t\tif (visitorId) {\n\t\t\theaders[\"X-Visitor-Id\"] = visitorId;\n\t\t}\n\n\t\tconst response = await this.request<ListConversationsResponse>(\n\t\t\t`/conversations?${queryParams.toString()}`,\n\t\t\t{\n\t\t\t\theaders,\n\t\t\t}\n\t\t);\n\n\t\t// Convert date strings to Date objects\n\t\treturn {\n\t\t\tconversations: response.conversations.map((conv) => ({\n\t\t\t\t...conv,\n\t\t\t\tcreatedAt: conv.createdAt,\n\t\t\t\tupdatedAt: conv.updatedAt,\n\t\t\t\tdeletedAt: conv.deletedAt ?? null,\n\t\t\t\tlastTimelineItem: conv.lastTimelineItem,\n\t\t\t})),\n\t\t\tpagination: response.pagination,\n\t\t};\n\t}\n\n\tasync getConversation(\n\t\tparams: GetConversationRequest\n\t): Promise<GetConversationResponse> {\n\t\t// Get visitor ID from storage if we have the website ID\n\t\tconst visitorId = this.websiteId ? getVisitorId(this.websiteId) : undefined;\n\n\t\t// Add visitor ID header if available\n\t\tconst headers: Record<string, string> = {};\n\t\tif (visitorId) {\n\t\t\theaders[\"X-Visitor-Id\"] = visitorId;\n\t\t}\n\n\t\tconst response = await this.request<GetConversationResponse>(\n\t\t\t`/conversations/${params.conversationId}`,\n\t\t\t{\n\t\t\t\theaders,\n\t\t\t}\n\t\t);\n\n\t\t// Convert date strings to Date objects\n\t\treturn {\n\t\t\tconversation: {\n\t\t\t\t...response.conversation,\n\t\t\t\tcreatedAt: response.conversation.createdAt,\n\t\t\t\tupdatedAt: response.conversation.updatedAt,\n\t\t\t\tdeletedAt: response.conversation.deletedAt ?? null,\n\t\t\t\tlastTimelineItem: response.conversation.lastTimelineItem,\n\t\t\t},\n\t\t};\n\t}\n\n\tasync markConversationSeen(\n\t\tparams: {\n\t\t\tconversationId: string;\n\t\t} & Partial<MarkConversationSeenRequestBody>\n\t): Promise<MarkConversationSeenResponseBody> {\n\t\tconst storedVisitorId = this.websiteId\n\t\t\t? getVisitorId(this.websiteId)\n\t\t\t: undefined;\n\t\tconst visitorId = params.visitorId || storedVisitorId;\n\n\t\tif (!visitorId) {\n\t\t\tthrow new Error(\"Visitor ID is required to mark a conversation as seen\");\n\t\t}\n\n\t\tconst headers: Record<string, string> = {};\n\t\tif (visitorId) {\n\t\t\theaders[\"X-Visitor-Id\"] = visitorId;\n\t\t}\n\n\t\tconst body: MarkConversationSeenRequestBody = {};\n\t\tif (params.visitorId) {\n\t\t\tbody.visitorId = params.visitorId;\n\t\t}\n\n\t\tconst response = await this.request<MarkConversationSeenResponseBody>(\n\t\t\t`/conversations/${params.conversationId}/seen`,\n\t\t\t{\n\t\t\t\tmethod: \"POST\",\n\t\t\t\tbody: JSON.stringify(body),\n\t\t\t\theaders,\n\t\t\t}\n\t\t);\n\n\t\treturn {\n\t\t\tconversationId: response.conversationId,\n\t\t\tlastSeenAt: response.lastSeenAt,\n\t\t};\n\t}\n\n\tasync getConversationSeenData(params: {\n\t\tconversationId: string;\n\t}): Promise<GetConversationSeenDataResponse> {\n\t\tconst response = await this.request<GetConversationSeenDataResponse>(\n\t\t\t`/conversations/${params.conversationId}/seen`,\n\t\t\t{\n\t\t\t\tmethod: \"GET\",\n\t\t\t}\n\t\t);\n\n\t\treturn {\n\t\t\tseenData: response.seenData.map((item) => ({\n\t\t\t\t...item,\n\t\t\t\tlastSeenAt: item.lastSeenAt,\n\t\t\t\tcreatedAt: item.createdAt,\n\t\t\t\tupdatedAt: item.updatedAt,\n\t\t\t\tdeletedAt: item.deletedAt ? item.deletedAt : null,\n\t\t\t})),\n\t\t};\n\t}\n\n\tasync setConversationTyping(params: {\n\t\tconversationId: string;\n\t\tisTyping: boolean;\n\t\tvisitorPreview?: string | null;\n\t\tvisitorId?: string;\n\t}): Promise<SetConversationTypingResponseBody> {\n\t\tconst storedVisitorId = this.websiteId\n\t\t\t? getVisitorId(this.websiteId)\n\t\t\t: undefined;\n\t\tconst visitorId = params.visitorId || storedVisitorId;\n\n\t\tif (!visitorId) {\n\t\t\tthrow new Error(\"Visitor ID is required to report typing state\");\n\t\t}\n\n\t\tconst headers: Record<string, string> = {};\n\t\tif (visitorId) {\n\t\t\theaders[\"X-Visitor-Id\"] = visitorId;\n\t\t}\n\n\t\tconst body: SetConversationTypingRequestBody = {\n\t\t\tisTyping: params.isTyping,\n\t\t};\n\n\t\tif (params.visitorId) {\n\t\t\tbody.visitorId = params.visitorId;\n\t\t}\n\n\t\tif (params.visitorPreview && params.isTyping) {\n\t\t\tbody.visitorPreview = params.visitorPreview.slice(0, 2000);\n\t\t}\n\n\t\tconst response = await this.request<SetConversationTypingResponseBody>(\n\t\t\t`/conversations/${params.conversationId}/typing`,\n\t\t\t{\n\t\t\t\tmethod: \"POST\",\n\t\t\t\tbody: JSON.stringify(body),\n\t\t\t\theaders,\n\t\t\t}\n\t\t);\n\n\t\treturn {\n\t\t\tconversationId: response.conversationId,\n\t\t\tisTyping: response.isTyping,\n\t\t\tvisitorPreview: response.visitorPreview,\n\t\t\tsentAt: response.sentAt,\n\t\t};\n\t}\n\n\tasync sendMessage(\n\t\tparams: SendTimelineItemRequest\n\t): Promise<SendTimelineItemResponse> {\n\t\t// Get visitor ID from storage if we have the website ID\n\t\tconst visitorId = this.websiteId ? getVisitorId(this.websiteId) : undefined;\n\n\t\t// Add visitor ID header if available\n\t\tconst headers: Record<string, string> = {};\n\t\tif (visitorId) {\n\t\t\theaders[\"X-Visitor-Id\"] = visitorId;\n\t\t}\n\n\t\tconst response = await this.request<SendTimelineItemResponse>(\"/messages\", {\n\t\t\tmethod: \"POST\",\n\t\t\tbody: JSON.stringify(params),\n\t\t\theaders,\n\t\t});\n\n\t\treturn {\n\t\t\titem: response.item,\n\t\t};\n\t}\n\n\tasync getConversationTimelineItems(\n\t\tparams: GetConversationTimelineItemsRequest & { conversationId: string }\n\t): Promise<GetConversationTimelineItemsResponse> {\n\t\t// Get visitor ID from storage if we have the website ID\n\t\tconst visitorId = this.websiteId ? getVisitorId(this.websiteId) : undefined;\n\n\t\t// Create query parameters\n\t\tconst queryParams = new URLSearchParams();\n\n\t\tif (params.limit) {\n\t\t\tqueryParams.set(\"limit\", params.limit.toString());\n\t\t}\n\n\t\tif (params.cursor) {\n\t\t\tqueryParams.set(\"cursor\", params.cursor);\n\t\t}\n\n\t\t// Add visitor ID header if available\n\t\tconst headers: Record<string, string> = {};\n\t\tif (visitorId) {\n\t\t\theaders[\"X-Visitor-Id\"] = visitorId;\n\t\t}\n\n\t\tconst response = await this.request<GetConversationTimelineItemsResponse>(\n\t\t\t`/conversations/${params.conversationId}/timeline?${queryParams.toString()}`,\n\t\t\t{\n\t\t\t\theaders,\n\t\t\t}\n\t\t);\n\n\t\treturn {\n\t\t\titems: response.items,\n\t\t\tnextCursor: response.nextCursor,\n\t\t\thasNextPage: response.hasNextPage,\n\t\t};\n\t}\n}\n"],"mappings":"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"}
|