@opencx/widget 2.2.0 → 2.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +30 -105
- package/dist/basic.cjs +3 -3
- package/dist/basic.cjs.map +1 -1
- package/dist/basic.js +10 -9
- package/dist/basic.js.map +1 -1
- package/dist/core/client/api.d.ts +21 -7
- package/dist/core/client/chat.d.ts +62 -0
- package/dist/core/client/chat.test.d.ts +1 -0
- package/dist/core/client/client.d.ts +6 -36
- package/dist/core/client/config.d.ts +35 -0
- package/dist/core/client/config.test.d.ts +1 -0
- package/dist/core/client/contact.d.ts +32 -0
- package/dist/core/client/contact.test.d.ts +1 -0
- package/dist/core/client/index.d.ts +3 -1
- package/dist/core/index.d.ts +6 -1
- package/dist/core/platform/index.d.ts +1 -10
- package/dist/core/types/index.d.ts +24 -2
- package/dist/core/types/pub-sub.d.ts +19 -82
- package/dist/core/types/schemas-v2.d.ts +687 -0
- package/dist/core/utils/create-fetch.d.ts +24 -0
- package/dist/index-B7LNpE9i.cjs +18 -0
- package/dist/index-B7LNpE9i.cjs.map +1 -0
- package/dist/{index-XkXeMM77.js → index-BQfnx4Er.js} +1182 -1310
- package/dist/index-BQfnx4Er.js.map +1 -0
- package/dist/index.cjs +1 -1
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +376 -370
- package/dist/index.js.map +1 -1
- package/dist/react-bindings/context/ChatContext.d.ts +130 -0
- package/dist/react-bindings/hooks/useContact.d.ts +9 -0
- package/dist/react-bindings/hooks/usePubsub.d.ts +3 -0
- package/dist/react-bindings/hooks/useSendMessage.d.ts +6 -0
- package/dist/react-bindings/index.d.ts +3 -0
- package/dist/react-lib/hooks/useAbstractChat.d.ts +42 -45
- package/dist/react-lib/hooks/useAxiosInstance.d.ts +37 -0
- package/dist/react-lib/hooks/useUploadFiles.d.ts +1 -1
- package/dist/react-lib/providers/ChatProvider.d.ts +54 -46
- package/dist/react-lib/types/index.d.ts +1 -0
- package/dist/react.cjs +1 -1
- package/dist/react.cjs.map +1 -1
- package/dist/react.js +2 -2
- package/dist/react.js.map +1 -1
- package/dist/schemas-BBAV6Sd_.js +122 -0
- package/dist/schemas-BBAV6Sd_.js.map +1 -0
- package/dist/schemas-wky4fpbc.cjs +2 -0
- package/dist/schemas-wky4fpbc.cjs.map +1 -0
- package/dist/src/components/dialog.d.ts +2 -2
- package/dist/style.css +1 -1
- package/dist-embed/script.js +106 -106
- package/dist-embed/script.js.map +1 -1
- package/package.json +1 -3
- package/dist/core/managers/chathistory-manager.d.ts +0 -61
- package/dist/core/managers/session-manager.d.ts +0 -35
- package/dist/core/transport/http.transport.d.ts +0 -17
- package/dist/core/transport/transport.d.ts +0 -25
- package/dist/core/types/transport.d.ts +0 -31
- package/dist/history-to-widget-messages-CP0hKjhv.js +0 -195
- package/dist/history-to-widget-messages-CP0hKjhv.js.map +0 -1
- package/dist/history-to-widget-messages-CdbZolRN.cjs +0 -2
- package/dist/history-to-widget-messages-CdbZolRN.cjs.map +0 -1
- package/dist/index-XkXeMM77.js.map +0 -1
- package/dist/index-xb7Pg6AD.cjs +0 -18
- package/dist/index-xb7Pg6AD.cjs.map +0 -1
- package/dist/react-lib/hooks/handle-socket-messages.d.ts +0 -27
- package/dist/react-lib/hooks/socket.d.ts +0 -11
- package/dist/react-lib/hooks/socketState.d.ts +0 -2
- package/dist/react-lib/hooks/useBaseClient.d.ts +0 -2
- package/dist/react-lib/providers/ClientProvider.d.ts +0 -7
package/dist/index.cjs
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
"use strict";var
|
|
1
|
+
"use strict";var T=Object.defineProperty;var O=t=>{throw TypeError(t)};var I=(t,e,r)=>e in t?T(t,e,{enumerable:!0,configurable:!0,writable:!0,value:r}):t[e]=r;var y=(t,e,r)=>I(t,typeof e!="symbol"?e+"":e,r),C=(t,e,r)=>e.has(t)||O("Cannot "+r);var d=(t,e,r)=>(C(t,e,"read from private field"),r?r.call(t):e.get(t)),b=(t,e,r)=>e.has(t)?O("Cannot add the same private member more than once"):e instanceof WeakSet?e.add(t):e.set(t,r),E=(t,e,r,s)=>(C(t,e,"write to private field"),s?s.call(t,r):e.set(t,r),r);Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const h=require("./schemas-wky4fpbc.cjs");var g;class f{constructor(e){y(this,"subscribers",new Set);b(this,g);y(this,"initialState");E(this,g,e),this.initialState=e}subscribe(e){return this.subscribers.add(e),()=>{this.subscribers.delete(e)}}getState(){return d(this,g)}setState(e){d(this,g)!==e&&(E(this,g,e),this.subscribers.forEach(r=>r(e)))}setStatePartial(e){const r={...d(this,g),...e};this.setState(r)}clear(){this.subscribers.clear()}reset(){this.setState(this.initialState)}getSnapshot(){return d(this,g)}get state(){return d(this,g)}}g=new WeakMap;function U(t){return new f(t)}const v=1e4,A=5e3;function k(t){var e,r,s;return t.sender.kind==="user"?{id:t.publicId||h.genId(),type:"FROM_USER",content:t.content.text||"",deliveredAt:((e=t.sentAt)==null?void 0:e.toISOString())||null,attachments:t.attachments||void 0,timestamp:(r=t.sentAt)==null?void 0:r.toISOString()}:{id:t.publicId||h.genId(),type:"FROM_BOT",component:t.type,data:{text:t.content.text},timestamp:(s=t.sentAt)==null?void 0:s.toISOString(),attachments:t.attachments||void 0}}function M(t,e,r){const s=[];return s.push(setInterval(async()=>{const n=e.getState();if(n!=null&&n.id)try{const a=await t.getSession(n.id);a&&e.setState(a)}catch(a){console.error("Error polling session:",a)}},v)),s.push(setInterval(async()=>{const n=e.getState();if(n!=null&&n.id)try{const a=await t.getSessionHistory(n.id);if(a){const l=a.map(k);r.setStatePartial({messages:l,lastUpdated:Date.now()})}}catch(a){console.error("Error polling messages:",a)}},A)),()=>s.forEach(clearInterval)}function D(t){const e=new f({lastUpdated:null,messages:[],keyboard:null}),r=new f(null);let s=null;async function n(){const o=await t.api.createSession();return r.setState(o),s||(s=M(t.api,r,e)),o}async function a(){var i;const o=r.getState();if(o!=null&&o.id)try{s&&(s(),s=null),r.setState(null),e.setState({lastUpdated:null,messages:[],keyboard:null}),(i=t.onSessionDestroy)==null||i.call(t)}catch(u){throw console.error("Error clearing session:",u),u}}function l(){s&&(s(),s=null),e.setState({lastUpdated:null,messages:[],keyboard:null}),r.setState(null),e.clear(),r.clear()}return{chatState:e,sessionState:r,sendMessage:async o=>{const i=r.getState();if(!(i!=null&&i.id))throw new Error("No active session");const u={...o,session_id:i.id};try{e.setStatePartial({messages:[...e.getState().messages,{id:o.id||h.genId(),type:"FROM_USER",content:o.content.text,deliveredAt:new Date().toISOString(),attachments:o.attachments,timestamp:new Date().toISOString()}]}),await t.api.handleMessage(u)}catch(S){throw console.error("Error sending message:",S),S}},createSession:n,clearSession:a,cleanup:l}}function F(t){var l;const e=`${t.botToken}:contact:${(l=t.user)==null?void 0:l.external_id}`;let r=null;if(t.platform.storage){const c=t.platform.storage.getItem(e);if(c)try{r=JSON.parse(c)}catch(o){console.error("Error parsing stored contact:",o)}}const s=new f(r);t.platform.storage&&s.subscribe(c=>{var o,i;c?(o=t.platform.storage)==null||o.setItem(e,JSON.stringify(c)):(i=t.platform.storage)==null||i.removeItem(e)});function n(){const c=s.getState();return!(c!=null&&c.id)&&t.collectUserData?{should:!0,reason:"No contact id and collectUserData is true"}:{should:!1}}function a(){s.clear(),s.setState(null)}return{shouldCollectData:n,cleanup:a,contactState:s}}function N(t={}){const e=[],r=[],s=[],n=async(a,l={})=>{let c={...t,...l,headers:{...t.headers,...l.headers}};try{for(const S of e)c=await S(c);const o=c.params?"?"+new URLSearchParams(c.params).toString():"",i=c.baseURL?`${c.baseURL}${a}${o}`.replace(/([^:]\/)\/+/g,"$1"):`${a}${o}`;let u=await fetch(i,c);for(const S of r)u=await S(u);return u}catch(o){let i=o;for(const u of s)i=await u(i);throw i}};return n.interceptors={request:{use:a=>(e.push(a),e.length-1),eject:a=>{e.splice(a,1)}},response:{use:(a,l)=>(r.push(a),l&&s.push(l),r.length-1),eject:a=>{r.splice(a,1),s.splice(a,1)}}},n}var m;class ${constructor(e){b(this,m);this.options=e;const r=this.options.coreOptions.user,s={claim:"",value:""};r!=null&&r.email?(s.claim="email",s.value=r.email):r!=null&&r.phone&&(s.claim="phone",s.value=r.phone);const n={"X-Bot-Token":this.options.token,"X-Consumer-Id":`${s.claim}:${s.value}`};this.options.coreOptions.contactToken&&(n.Authorization=`Bearer ${this.options.coreOptions.contactToken}`),E(this,m,N({baseURL:`${this.options.apiUrl}/widget/v2`,headers:n}))}async me(){return(await d(this,m).call(this,"/me")).json()}async widgetPrelude(){return(await d(this,m).call(this,"/prelude")).json()}async handleMessage(e){return(await d(this,m).call(this,"/chat/send",{method:"POST",body:JSON.stringify(e)})).json()}async getSessionHistory(e,r){const s=new URLSearchParams({lastMessageTimestamp:r||""}),n=`/session/history/${e}?${s.toString()}`;return(await d(this,m).call(this,n,{method:"GET"})).json()}async createSession(){return(await d(this,m).call(this,"/create-session",{method:"POST"})).json()}async getSession(e){return(await d(this,m).call(this,`/session/${e}`,{method:"GET"})).json()}async createContact(e){return(await d(this,m).call(this,"/contact/upsert",{method:"POST",body:JSON.stringify(e)})).json()}}m=new WeakMap;class p extends Error{constructor(e){super(e),this.name="OpenCXError"}}class x extends p{constructor(e="Connection failed"){super(e),this.name="ConnectionError"}}class L extends p{constructor(e="Authentication failed"){super(e),this.name="AuthenticationError"}}class P extends p{constructor(e="Session error occurred"){super(e),this.name="SessionError"}}class _ extends P{constructor(e="Session not defined"){super(e),this.name="SessionNotDefinedError"}}class R extends p{constructor(e="Transport error occurred"){super(e),this.name="TransportError"}}class j extends p{constructor(e="File upload failed"){super(e),this.name="FileUploadError"}}function q(){return{env:{platform:typeof window<"u"?"browser":"server"},date:{now:()=>Date.now(),toISOString:e=>new Date(e).toISOString()}}}const H={messageArrived:"https://cloud.opencopilot.so/sfx/notification3.mp3"},w={headerStyle:"basic",primaryColor:"hsl(211,65%,59%)",triggerOffset:"20px"};function B(t){var r,s,n,a,l,c,o,i,u,S;const e={...t,apiUrl:t.apiUrl??"https://api-v2.opencopilot.so/backend",socketUrl:t.socketUrl??"https://api-v2.opencopilot.so",transport:t.transport??"socket",pollingInterval:t.pollingInterval??3e3,headers:{...t.headers??{},"X-Bot-Token":t.token},queryParams:t.queryParams??{},pathParams:t.pathParams??{},bot:{name:((r=t.bot)==null?void 0:r.name)??"Bot",avatarUrl:(s=t.bot)==null?void 0:s.avatarUrl,id:((n=t.bot)==null?void 0:n.id)??null,is_ai:((a=t.bot)==null?void 0:a.is_ai)??!0},contactToken:t.contactToken,debug:t.debug??!1,language:t.language??"en",user:t.user??{},soundEffectFiles:{messageArrived:((l=t.soundEffectFiles)==null?void 0:l.messageArrived)??H.messageArrived},theme:{headerStyle:((c=t.theme)==null?void 0:c.headerStyle)??w.headerStyle,primaryColor:((o=t.theme)==null?void 0:o.primaryColor)??w.primaryColor,triggerOffset:((i=t.theme)==null?void 0:i.triggerOffset)??w.triggerOffset},settings:{persistSession:((u=t.settings)==null?void 0:u.persistSession)??!1,useSoundEffects:((S=t.settings)==null?void 0:S.useSoundEffects)??!1}};return{getConfig:()=>e,getApiConfig:()=>({apiUrl:e.apiUrl,token:e.token,headers:e.headers,queryParams:e.queryParams,pathParams:e.pathParams}),getBotConfig:()=>e.bot,getThemeConfig:()=>e.theme,getSettings:()=>e.settings,getSoundEffects:()=>e.soundEffectFiles,getUser:()=>e.user,getLanguage:()=>e.language,getDebugMode:()=>e.debug}}exports.AIClosureType=h.AIClosureType;exports.MessageTypeEnum=h.MessageTypeEnum;exports.SentimentEnum=h.SentimentEnum;exports.SessionChannel=h.SessionChannel;exports.SessionStatus=h.SessionStatus;exports.chatAttachmentSchema=h.chatAttachmentSchema;exports.chatHistoryMessageSchema=h.chatHistoryMessageSchema;exports.chatSessionSchema=h.chatSessionSchema;exports.consumerSchema=h.consumerSchema;exports.structuredSocketMessageSchema=h.structuredSocketMessageSchema;exports.ApiCaller=$;exports.AuthenticationError=L;exports.ConnectionError=x;exports.FileUploadError=j;exports.OpenCXError=p;exports.PubSub=f;exports.SessionError=P;exports.SessionNotDefinedError=_;exports.TransportError=R;exports.createChat=D;exports.createConfig=B;exports.createContact=F;exports.createDefaultPlatform=q;exports.createPubSub=U;
|
|
2
2
|
//# sourceMappingURL=index.cjs.map
|
package/dist/index.cjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.cjs","sources":["../core/types/pub-sub.ts","../core/client/api.ts","../core/managers/session-manager.ts","../core/platform/index.ts","../core/transport/transport.ts","../core/transport/http.transport.ts","../core/client/client.ts","../core/errors/index.ts"],"sourcesContent":["/**\n * Base interface for event maps. All event maps must extend this.\n * @example\n * ```typescript\n * interface MyEvents extends EventMap {\n * \"my:event\": string\n * \"my:other:event\": { data: number }\n * }\n * ```\n */\nexport interface EventMap {\n [key: string]: any;\n}\n\n/**\n * Event subscriber function type\n */\nexport type Subscriber<T> = (data: T) => void;\n\n/**\n * Generic PubSub class that can be typed with specific event maps.\n * Each component should create its own instance with its specific events.\n *\n * @example\n * ```typescript\n * interface MyEvents extends EventMap {\n * \"my:event\": string\n * }\n *\n * const pubSub = new PubSub<MyEvents>();\n *\n * pubSub.subscribe(\"my:event\", (data) => {\n * console.log(data.toUpperCase()); // Type-safe: data is string\n * });\n * ```\n */\nexport class PubSub<T extends EventMap> {\n private subscribers: Map<keyof T, Set<Subscriber<any>>> = new Map();\n\n /**\n * Subscribe to an event\n * @param event Event name to subscribe to\n * @param callback Function to call when event is published\n * @returns Unsubscribe function\n */\n subscribe<K extends keyof T>(\n event: K,\n callback: Subscriber<T[K]>,\n ): () => void {\n if (!this.subscribers.has(event)) {\n this.subscribers.set(event, new Set());\n }\n this.subscribers.get(event)!.add(callback);\n\n return () => {\n const subs = this.subscribers.get(event);\n if (subs) {\n subs.delete(callback);\n if (subs.size === 0) {\n this.subscribers.delete(event);\n }\n }\n };\n }\n\n /**\n * Publish an event with data\n * @param event Event name to publish\n * @param data Data to send with the event\n */\n publish<K extends keyof T>(event: K, data: T[K]): void {\n const callbacks = this.subscribers.get(event);\n if (callbacks) {\n callbacks.forEach((callback) => callback(data));\n }\n }\n\n /**\n * Clear all subscriptions\n */\n clear(): void {\n this.subscribers.clear();\n }\n}\n\n/**\n * Abstract base class for components that need subscription management.\n * Provides common functionality for managing subscriptions and cleanup.\n *\n * @example\n * ```typescript\n * class MyComponent extends Subscribable {\n * constructor() {\n * super();\n * // Add unsubscribers\n * this.addUnsubscriber(() => {\n * console.log('Cleanup');\n * });\n * }\n *\n * protected cleanup(): void {\n * // Component-specific cleanup\n * }\n * }\n * ```\n */\nexport abstract class Subscribable {\n protected unsubscribers: (() => void)[] = [];\n\n /**\n * Add an unsubscribe function to be called during cleanup\n */\n protected addUnsubscriber(unsubscribe: () => void) {\n this.unsubscribers.push(unsubscribe);\n }\n\n /**\n * Dispose of all subscriptions and perform cleanup\n */\n public dispose() {\n this.unsubscribers.forEach((unsubscribe) => unsubscribe());\n this.unsubscribers = [];\n this.cleanup();\n }\n\n /**\n * Component-specific cleanup logic\n */\n protected abstract cleanup(): void;\n}\n\n/**\n * Helper function to create a strongly typed PubSub instance\n */\nexport function createPubSub<T extends EventMap>(): PubSub<T> {\n return new PubSub<T>();\n}\n","import { ChatSessionType } from \"../types/schemas\";\nimport { MessageData } from \"../types/transport\";\n\nexport interface ApiCallerOptions {\n apiUrl: string;\n token: string;\n}\n\nexport class ApiCaller {\n constructor(private readonly options: ApiCallerOptions) {}\n\n async createSession(): Promise<ChatSessionType> {\n const response = await fetch(`${this.options.apiUrl}/sessions`, {\n method: \"POST\",\n headers: {\n Authorization: `Bearer ${this.options.token}`,\n \"Content-Type\": \"application/json\",\n },\n });\n\n if (!response.ok) {\n throw new Error(\"Failed to create session\");\n }\n\n return response.json();\n }\n\n async fetchSession(sessionId: string): Promise<ChatSessionType> {\n const response = await fetch(\n `${this.options.apiUrl}/sessions/${sessionId}`,\n {\n headers: {\n Authorization: `Bearer ${this.options.token}`,\n },\n },\n );\n\n if (!response.ok) {\n throw new Error(\"Failed to fetch session\");\n }\n\n return response.json();\n }\n\n async ping(): Promise<void> {\n const response = await fetch(`${this.options.apiUrl}/ping`, {\n headers: {\n Authorization: `Bearer ${this.options.token}`,\n },\n });\n\n if (!response.ok) {\n throw new Error(\"Failed to ping API\");\n }\n }\n\n async getMessages(sessionId?: string): Promise<MessageData[]> {\n const url = sessionId\n ? `${this.options.apiUrl}/messages/${sessionId}`\n : `${this.options.apiUrl}/messages`;\n\n const response = await fetch(url, {\n headers: {\n Authorization: `Bearer ${this.options.token}`,\n },\n });\n\n if (!response.ok) {\n throw new Error(\"Failed to fetch messages\");\n }\n\n return response.json();\n }\n\n async sendMessage(message: MessageData): Promise<void> {\n const response = await fetch(`${this.options.apiUrl}/messages`, {\n method: \"POST\",\n headers: {\n Authorization: `Bearer ${this.options.token}`,\n \"Content-Type\": \"application/json\",\n },\n body: JSON.stringify(message),\n });\n\n if (!response.ok) {\n throw new Error(\"Failed to send message\");\n }\n }\n}\n","import { EventMap, PubSub } from \"../types/pub-sub\";\nimport {\n AIClosureType,\n SessionStatus,\n ChatSessionType,\n} from \"../types/schemas\";\nimport { ApiCaller } from \"../client/api\";\n\nexport type ChatSessionWithStatus = ChatSessionType & {\n isSessionClosed: boolean;\n isAssignedToAi: boolean;\n isAssignedToHuman: boolean;\n isPendingHuman: boolean;\n};\n\n/**\n * Events emitted by the SessionManager\n */\ninterface SessionEvents extends EventMap {\n \"session:updated\": ChatSessionType;\n \"session:created\": ChatSessionType;\n \"session:closed\": { sessionId: string };\n \"session:error\": { error: Error };\n}\n\nexport class SessionManager extends PubSub<SessionEvents> {\n #currentSession: ChatSessionType | null = null;\n\n constructor(\n private readonly httpClient: ApiCaller,\n initialSession?: ChatSessionType,\n ) {\n super();\n if (initialSession) {\n this.setSession(initialSession);\n }\n }\n\n get currentSession(): ChatSessionWithStatus | null {\n if (!this.#currentSession) {\n return null;\n }\n return {\n ...this.#currentSession,\n isSessionClosed: this.#currentSession.status !== SessionStatus.OPEN,\n isAssignedToAi: this.#currentSession.assignee_id === 555,\n isAssignedToHuman: this.#currentSession.assignee_id !== 555,\n isPendingHuman:\n this.#currentSession.assignee_id === 555 &&\n this.#currentSession.ai_closure_type === AIClosureType.handed_off,\n };\n }\n\n setSession(session: ChatSessionType): void {\n this.#currentSession = session;\n this.publish(\"session:updated\", session);\n }\n\n clearSession = (): void => {\n if (this.#currentSession) {\n const sessionId = this.#currentSession.id;\n this.#currentSession = null;\n this.publish(\"session:closed\", { sessionId });\n }\n };\n\n async createSession(): Promise<ChatSessionType> {\n try {\n const session = await this.httpClient.createSession();\n this.setSession(session);\n this.publish(\"session:created\", session);\n return session;\n } catch (error) {\n this.publish(\"session:error\", { error: error as Error });\n throw error;\n }\n }\n\n async getOrCreateSession(): Promise<ChatSessionType> {\n const session = this.currentSession;\n if (!session) {\n return this.createSession();\n }\n return session;\n }\n\n async refreshSession(sessionId: string): Promise<ChatSessionType | null> {\n try {\n const session = await this.httpClient.fetchSession(sessionId);\n if (session) {\n this.setSession(session);\n return session;\n }\n } catch (error) {\n this.publish(\"session:error\", { error: error as Error });\n console.error(\"Failed to refresh session:\", error);\n }\n return null;\n }\n\n protected cleanup(): void {\n this.#currentSession = null;\n this.clear();\n }\n}\n","export interface Platform {\n storage?: Storage;\n env: {\n platform: string;\n };\n date: {\n now(): number;\n toISOString(date: number): string;\n };\n}\n\n// Default platform implementation\nexport class DefaultPlatform implements Platform {\n env = {\n platform: this.detectPlatform(),\n };\n\n date = {\n now: () => Date.now(),\n toISOString: (date: number) => new Date(date).toISOString(),\n };\n\n private detectPlatform() {\n // detect browser\n if (typeof window !== \"undefined\") {\n return \"browser\";\n }\n return \"server\";\n }\n}\n","import { MessageData, TransportOptions } from \"../types/transport\";\nimport { PubSub } from \"../types/pub-sub\";\n\nexport interface TransportEvents extends Record<string, any> {\n \"transport:message:received\": MessageData;\n \"transport:error\": { error: Error };\n \"transport:status\": { status: \"connected\" | \"disconnected\" };\n}\n\nexport interface TransportState {\n connected: boolean;\n}\n\nexport abstract class MessagingTransport extends PubSub<TransportEvents> {\n #state: TransportState = {\n connected: false,\n };\n\n constructor(protected readonly options: TransportOptions) {\n super();\n }\n\n abstract connect(): Promise<void>;\n abstract disconnect(): void;\n abstract sendMessage(message: MessageData): Promise<void>;\n\n protected setState(newState: Partial<TransportState>) {\n this.#state = { ...this.#state, ...newState };\n\n // Emit status change event if connected state changes\n if (\"connected\" in newState) {\n this.publish(\"transport:status\", {\n status: newState.connected ? \"connected\" : \"disconnected\",\n });\n }\n }\n\n isConnected(): boolean {\n return this.#state.connected;\n }\n\n getState(): TransportState {\n return { ...this.#state };\n }\n}\n","import { Platform, DefaultPlatform } from \"../platform\";\nimport { MessageData, TransportOptions } from \"../types/transport\";\nimport { MessagingTransport } from \"./transport\";\n\ninterface HttpTransportOptions extends TransportOptions {\n pollingInterval: number;\n}\n\nexport class HttpTransport extends MessagingTransport {\n private pollingInterval?: NodeJS.Timeout;\n\n constructor(\n private readonly httpOptions: HttpTransportOptions,\n private readonly platform: Platform = new DefaultPlatform(),\n ) {\n super(httpOptions);\n }\n\n async connect(): Promise<void> {\n this.setState({ connected: true });\n this.startPolling();\n }\n\n disconnect(): void {\n if (this.pollingInterval) {\n clearInterval(this.pollingInterval);\n }\n this.setState({ connected: false });\n }\n\n async sendMessage(message: MessageData): Promise<void> {\n if (!this.isConnected()) {\n const error = new Error(\"Transport not connected\");\n this.publish(\"transport:error\", { error });\n throw error;\n }\n\n try {\n await this.httpOptions.api.sendMessage(message);\n } catch (error) {\n this.publish(\"transport:error\", { error: error as Error });\n throw error;\n }\n }\n\n private startPolling(): void {\n if (this.pollingInterval) {\n clearInterval(this.pollingInterval);\n }\n\n this.pollingInterval = setInterval(async () => {\n if (!this.isConnected()) return;\n\n try {\n const session =\n await this.httpOptions.sessionManager.getOrCreateSession();\n const messages = await this.httpOptions.api.getMessages(session.id);\n\n messages.forEach((message) => {\n this.publish(\"transport:message:received\", message);\n });\n } catch (error) {\n this.publish(\"transport:error\", { error: error as Error });\n }\n }, this.httpOptions.pollingInterval);\n }\n}\n","import { CoreOptions } from \"../types\";\nimport { ApiCaller } from \"./api\";\nimport { PubSub, Subscribable } from \"../types/pub-sub\";\nimport { SessionManager } from \"../managers/session-manager\";\nimport { Platform, DefaultPlatform } from \"../platform\";\nimport { HttpTransport } from \"../transport/http.transport\";\nimport { MessagingTransport } from \"../transport/transport\";\nimport {\n MessageType,\n UserMessageType,\n BotMessageType,\n SendMessageInput,\n} from \"../types/messages\";\nimport { genId } from \"../utils/genId\";\nimport { MessageData } from \"../types/transport\";\nimport { mapChatHistoryToMessage } from \"../utils/history-to-widget-messages\";\n\ninterface ClientEvents {\n \"client:error\": Error;\n}\n\nexport class ApiClient extends Subscribable {\n private messagingTransport!: MessagingTransport;\n private readonly options: Required<CoreOptions>;\n private readonly api: ApiCaller;\n private readonly session: SessionManager;\n private readonly events = new PubSub<ClientEvents>();\n private messages: MessageType[] = [];\n private keyboard: string[] | null = null;\n private pollingInterval?: NodeJS.Timeout;\n private heartbeatInterval?: NodeJS.Timeout;\n\n constructor(\n options: CoreOptions,\n private readonly platform: Platform = new DefaultPlatform(),\n ) {\n super();\n this.options = {\n ...options,\n apiUrl: options.apiUrl ?? \"https://api-v2.opencopilot.so/backend\",\n socketUrl: options.socketUrl ?? \"https://api-v2.opencopilot.so\",\n transport: options.transport ?? \"socket\",\n pollingInterval: options.pollingInterval ?? 3000,\n headers: {\n \"X-Bot-Token\": options.token,\n ...options.headers,\n },\n queryParams: {},\n pathParams: {},\n bot: {},\n debug: false,\n language: \"en\",\n user: {},\n };\n\n this.api = new ApiCaller({\n apiUrl: this.options.apiUrl,\n token: this.options.token,\n });\n\n this.session = new SessionManager(this.api);\n\n // Initialize transport\n this.initializeTransport();\n\n // Start polling and heartbeat\n this.startMessagePolling();\n this.startHeartbeat();\n }\n\n private startMessagePolling() {\n if (this.pollingInterval) {\n clearInterval(this.pollingInterval);\n }\n\n this.pollingInterval = setInterval(async () => {\n const session = this.session.currentSession;\n if (!session) return;\n\n const lastMessage = this.messages[this.messages.length - 1];\n if (!lastMessage?.timestamp) return;\n\n try {\n const response = await this.api.getMessages(session.id);\n if (response && response.length > 0) {\n // Convert MessageData[] to ChatHistoryMessageType[]\n const historyMessages = response.map((msg) => ({\n message: msg.content.text,\n type: \"message\",\n publicId: msg.id,\n agent_avatar: null,\n agent_id: null,\n agent_name: null,\n created_at: msg.timestamp,\n from_user: false,\n handoff_happened_during_office_hours: false,\n session_id: msg.session_id,\n updated_at: null,\n attachments: msg.attachments,\n }));\n\n this.appendMessages(mapChatHistoryToMessage(historyMessages));\n }\n } catch (error) {\n console.error(\"Error polling messages:\", error);\n this.events.publish(\"client:error\", error as Error);\n }\n }, 20 * 1000);\n }\n\n private startHeartbeat() {\n if (this.heartbeatInterval) {\n clearInterval(this.heartbeatInterval);\n }\n\n const sendHeartbeat = async () => {\n const session = this.session.currentSession;\n if (!session) return;\n };\n\n sendHeartbeat();\n this.heartbeatInterval = setInterval(sendHeartbeat, 50 * 1000);\n }\n\n private appendMessages(messages: MessageType[]) {\n const newMessages = messages.filter(\n (msg) => !this.messages.some((m) => m.id === msg.id),\n );\n this.messages.push(...newMessages);\n }\n\n private handleIncomingMessage(message: MessageType): void {\n this.messages.push(message);\n this.refreshSession();\n }\n\n private async refreshSession() {\n const session = this.session.currentSession;\n if (session) {\n await this.session.getOrCreateSession();\n }\n }\n\n private initializeTransport() {\n const transportConfig = {\n api: this.api,\n sessionManager: this.session,\n coreOptions: this.options,\n };\n\n if (this.options.transport === \"http\") {\n this.messagingTransport = new HttpTransport(\n {\n ...transportConfig,\n pollingInterval: this.options.pollingInterval,\n },\n this.platform,\n );\n }\n }\n\n public async sendMessage({\n content,\n user,\n ...data\n }: SendMessageInput): Promise<void> {\n const session = await this.session.getOrCreateSession();\n const messageId = genId();\n\n const message: UserMessageType = {\n type: \"FROM_USER\",\n id: messageId,\n content: content.text,\n user,\n deliveredAt: null,\n attachments: data.attachments,\n };\n\n // Add to local messages\n this.messages.push(message);\n\n // Clear keyboard if exists\n if (this.keyboard) {\n this.setKeyboard(null);\n }\n\n // Send through transport\n await this.messagingTransport.sendMessage({\n id: messageId,\n content: { text: content.text },\n session_id: session.id,\n bot_token: this.options.token,\n headers: this.options.headers,\n pathParams: this.options.pathParams,\n queryParams: this.options.queryParams,\n user,\n language: data.language ?? this.options.language,\n attachments: data.attachments,\n timestamp: new Date().toISOString(),\n });\n }\n\n public setKeyboard(options: string[] | null): void {\n this.keyboard = options;\n }\n\n public handleKeyboardOption(option: string): void {\n this.sendMessage({\n content: { text: option },\n });\n this.setKeyboard(null);\n }\n\n public getMessages(): readonly MessageType[] {\n return this.messages;\n }\n\n public clearChat(): void {\n this.messages = [];\n this.keyboard = null;\n this.session.clearSession();\n }\n\n async connect(): Promise<void> {\n await this.messagingTransport.connect();\n }\n\n async disconnect(): Promise<void> {\n this.messagingTransport.disconnect();\n }\n\n setTransport(transport: MessagingTransport): void {\n this.messagingTransport.disconnect();\n this.messagingTransport = transport;\n this.connect();\n }\n\n get state() {\n return {\n connected: this.messagingTransport.isConnected(),\n session: this.session.currentSession,\n messages: this.messages,\n keyboard: this.keyboard,\n };\n }\n\n protected cleanup(): void {\n if (this.pollingInterval) {\n clearInterval(this.pollingInterval);\n }\n if (this.heartbeatInterval) {\n clearInterval(this.heartbeatInterval);\n }\n this.messagingTransport.disconnect();\n this.session.clear();\n this.events.clear();\n this.messages = [];\n this.keyboard = null;\n }\n}\n","export class OpenCXError extends Error {\n constructor(message: string) {\n super(message);\n this.name = \"OpenCXError\";\n }\n}\n\nexport class ConnectionError extends OpenCXError {\n constructor(message = \"Connection failed\") {\n super(message);\n this.name = \"ConnectionError\";\n }\n}\n\nexport class AuthenticationError extends OpenCXError {\n constructor(message = \"Authentication failed\") {\n super(message);\n this.name = \"AuthenticationError\";\n }\n}\n\nexport class SessionError extends OpenCXError {\n constructor(message = \"Session error occurred\") {\n super(message);\n this.name = \"SessionError\";\n }\n}\n\nexport class SessionNotDefinedError extends SessionError {\n constructor(message = \"Session not defined\") {\n super(message);\n this.name = \"SessionNotDefinedError\";\n }\n}\n\nexport class TransportError extends OpenCXError {\n constructor(message = \"Transport error occurred\") {\n super(message);\n this.name = \"TransportError\";\n }\n}\n\nexport class FileUploadError extends OpenCXError {\n constructor(message = \"File upload failed\") {\n super(message);\n this.name = \"FileUploadError\";\n }\n}\n"],"names":["PubSub","__publicField","event","callback","subs","data","callbacks","Subscribable","unsubscribe","ApiCaller","options","response","sessionId","url","message","SessionManager","httpClient","initialSession","__privateAdd","_currentSession","__privateGet","__privateSet","SessionStatus","AIClosureType","session","error","DefaultPlatform","date","MessagingTransport","_state","newState","HttpTransport","httpOptions","platform","ApiClient","lastMessage","historyMessages","msg","mapChatHistoryToMessage","sendHeartbeat","messages","newMessages","m","transportConfig","content","user","messageId","genId","option","transport","OpenCXError","ConnectionError","AuthenticationError","SessionError","SessionNotDefinedError","TransportError","FileUploadError"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"index.cjs","sources":["../core/types/pub-sub.ts","../core/client/chat.ts","../core/client/contact.ts","../core/utils/create-fetch.ts","../core/client/api.ts","../core/errors/index.ts","../core/platform/index.ts","../core/client/config.ts"],"sourcesContent":["export type Subscriber<T> = (data: T) => void\r\n\r\nexport class PubSub<S> {\r\n private subscribers = new Set<Subscriber<S>>();\r\n #state: S;\r\n private initialState: S;\r\n\r\n constructor(state: S) {\r\n this.#state = state;\r\n this.initialState = state;\r\n }\r\n\r\n /**\r\n * Subscribe to state changes\r\n * @param callback Function to call when state changes\r\n * @returns Unsubscribe function\r\n */\r\n subscribe(callback: Subscriber<S>): () => void {\r\n this.subscribers.add(callback);\r\n\r\n return () => {\r\n this.subscribers.delete(callback);\r\n };\r\n }\r\n\r\n /**\r\n * Get the current state\r\n */\r\n getState(): S {\r\n return this.#state;\r\n }\r\n\r\n /**\r\n * Set the state and notify subscribers if the state changes\r\n * @param newState The new state to set\r\n */\r\n setState(newState: S): void {\r\n if (this.#state !== newState) {\r\n this.#state = newState;\r\n this.subscribers.forEach(callback => callback(newState));\r\n }\r\n }\r\n\r\n setStatePartial(_s: Partial<S>): void {\r\n const newState = { ...this.#state, ..._s };\r\n this.setState(newState);\r\n }\r\n\r\n /**\r\n * Clear all subscriptions\r\n */\r\n clear(): void {\r\n this.subscribers.clear();\r\n }\r\n\r\n reset(): void {\r\n this.setState(this.initialState);\r\n }\r\n\r\n getSnapshot(): S {\r\n return this.#state;\r\n }\r\n\r\n get state(): S {\r\n return this.#state;\r\n }\r\n}\r\n\r\nexport function createPubSub<S>(state: S): PubSub<S> {\r\n return new PubSub<S>(state);\r\n}","import { PubSub } from \"../types/pub-sub\";\r\nimport { MessageType, UserMessageType, SendMessageInput } from \"../types\";\r\nimport { ApiCaller } from \"./api\";\r\nimport { genId } from \"../utils/genId\";\r\nimport { WidgetHistorySchema, WidgetSessionSchema } from \"../types/schemas-v2\";\r\n\r\nconst SESSION_POLLING_INTERVAL = 10000; // every 10 seconds\r\nconst MESSAGE_POLLING_INTERVAL = 5000; // every 5 seconds\r\n\r\ntype ChatState = {\r\n lastUpdated: number | null;\r\n messages: MessageType[];\r\n keyboard: { options: string[] } | null;\r\n};\r\n\r\ntype ChatOptions = {\r\n api: ApiCaller;\r\n persistSession?: boolean;\r\n useSoundEffects?: boolean;\r\n onSessionDestroy?: () => void;\r\n};\r\n\r\n\r\nfunction mapHistoryToMessage(history: WidgetHistorySchema): MessageType {\r\n if (history.sender.kind === 'user') {\r\n return {\r\n id: history.publicId || genId(),\r\n type: \"FROM_USER\",\r\n content: history.content.text || \"\",\r\n deliveredAt: history.sentAt?.toISOString() || null,\r\n attachments: history.attachments || undefined,\r\n timestamp: history.sentAt?.toISOString()\r\n };\r\n }\r\n\r\n return {\r\n id: history.publicId || genId(),\r\n type: \"FROM_BOT\",\r\n component: history.type,\r\n data: {\r\n text: history.content.text\r\n },\r\n timestamp: history.sentAt?.toISOString(),\r\n attachments: history.attachments || undefined\r\n };\r\n}\r\n\r\nfunction startPolling(\r\n api: ApiCaller,\r\n sessionState: PubSub<WidgetSessionSchema | null>,\r\n state: PubSub<ChatState>\r\n) {\r\n const intervals: NodeJS.Timeout[] = [];\r\n\r\n // Poll session\r\n intervals.push(\r\n setInterval(async () => {\r\n const session = sessionState.getState();\r\n if (!session?.id) return;\r\n\r\n try {\r\n const response = await api.getSession(session.id);\r\n if (response) {\r\n sessionState.setState(response);\r\n }\r\n } catch (error) {\r\n console.error(\"Error polling session:\", error);\r\n }\r\n }, SESSION_POLLING_INTERVAL)\r\n );\r\n\r\n // Poll messages\r\n intervals.push(\r\n setInterval(async () => {\r\n const session = sessionState.getState();\r\n if (!session?.id) return;\r\n\r\n try {\r\n const response = await api.getSessionHistory(session.id);\r\n if (response) {\r\n const messages = response.map(mapHistoryToMessage);\r\n state.setStatePartial({\r\n messages,\r\n lastUpdated: Date.now()\r\n });\r\n }\r\n } catch (error) {\r\n console.error(\"Error polling messages:\", error);\r\n }\r\n }, MESSAGE_POLLING_INTERVAL)\r\n );\r\n\r\n return () => intervals.forEach(clearInterval);\r\n}\r\n\r\nexport function createChat(options: ChatOptions) {\r\n const state = new PubSub<ChatState>({\r\n lastUpdated: null,\r\n messages: [],\r\n keyboard: null\r\n });\r\n\r\n const sessionState = new PubSub<WidgetSessionSchema | null>(null);\r\n let stopPolling: (() => void) | null = null;\r\n\r\n async function createSession() {\r\n const session = await options.api.createSession();\r\n sessionState.setState(session);\r\n if (!stopPolling) {\r\n stopPolling = startPolling(options.api, sessionState, state);\r\n }\r\n return session;\r\n }\r\n\r\n async function clearSession() {\r\n const session = sessionState.getState();\r\n if (!session?.id) return;\r\n\r\n try {\r\n if (stopPolling) {\r\n stopPolling();\r\n stopPolling = null;\r\n }\r\n sessionState.setState(null);\r\n state.setState({\r\n lastUpdated: null,\r\n messages: [],\r\n keyboard: null\r\n });\r\n options.onSessionDestroy?.();\r\n } catch (error) {\r\n console.error(\"Error clearing session:\", error);\r\n throw error;\r\n }\r\n }\r\n\r\n function cleanup() {\r\n if (stopPolling) {\r\n stopPolling();\r\n stopPolling = null;\r\n }\r\n state.setState({\r\n lastUpdated: null,\r\n messages: [],\r\n keyboard: null\r\n });\r\n sessionState.setState(null);\r\n state.clear();\r\n sessionState.clear();\r\n }\r\n\r\n const sendMessage = async (input: {\r\n content: { text: string };\r\n attachments?: any[];\r\n id?: string;\r\n language?: string;\r\n user?: {\r\n external_id?: string;\r\n name?: string;\r\n email?: string;\r\n phone?: string;\r\n customData?: Record<string, string>;\r\n avatarUrl?: string;\r\n };\r\n }) => {\r\n const session = sessionState.getState();\r\n if (!session?.id) {\r\n throw new Error(\"No active session\");\r\n }\r\n\r\n const message: SendMessageInput = {\r\n ...input,\r\n session_id: session.id\r\n };\r\n\r\n try {\r\n // Add message to local state first\r\n state.setStatePartial({\r\n messages: [\r\n ...state.getState().messages,\r\n {\r\n id: input.id || genId(),\r\n type: \"FROM_USER\",\r\n content: input.content.text,\r\n deliveredAt: new Date().toISOString(),\r\n attachments: input.attachments,\r\n timestamp: new Date().toISOString()\r\n }\r\n ]\r\n });\r\n\r\n // Send message\r\n await options.api.handleMessage(message);\r\n } catch (error) {\r\n console.error(\"Error sending message:\", error);\r\n throw error;\r\n }\r\n };\r\n\r\n return {\r\n chatState: state,\r\n sessionState,\r\n sendMessage,\r\n createSession,\r\n clearSession,\r\n cleanup\r\n };\r\n} ","import { PubSub } from \"../types/pub-sub\";\r\nimport { ConsumerType } from \"../types\";\r\nimport { ApiCaller } from \"./api\";\r\nimport { Platform } from \"../platform\";\r\n\r\ntype ContactOptions = {\r\n api: ApiCaller;\r\n botToken: string;\r\n platform: Platform;\r\n collectUserData?: boolean;\r\n user?: {\r\n external_id?: string;\r\n name?: string;\r\n email?: string;\r\n phone?: string;\r\n customData?: Record<string, string>;\r\n avatarUrl?: string;\r\n };\r\n};\r\n\r\nexport function createContact(options: ContactOptions) {\r\n const storageKey = `${options.botToken}:contact:${options.user?.external_id}`;\r\n\r\n // Initialize state from storage if available\r\n let initialState: ConsumerType | null = null;\r\n if (options.platform.storage) {\r\n const stored = options.platform.storage.getItem(storageKey);\r\n if (stored) {\r\n try {\r\n initialState = JSON.parse(stored);\r\n } catch (e) {\r\n console.error(\"Error parsing stored contact:\", e);\r\n }\r\n }\r\n }\r\n\r\n const state = new PubSub<ConsumerType | null>(initialState);\r\n\r\n // Subscribe to state changes to persist\r\n if (options.platform.storage) {\r\n state.subscribe((contact) => {\r\n if (contact) {\r\n options.platform.storage?.setItem(storageKey, JSON.stringify(contact));\r\n } else {\r\n options.platform.storage?.removeItem(storageKey);\r\n }\r\n });\r\n }\r\n\r\n function shouldCollectData(): { should: boolean; reason?: string } {\r\n const contact = state.getState();\r\n\r\n if (!contact?.id && options.collectUserData) {\r\n return {\r\n should: true,\r\n reason: \"No contact id and collectUserData is true\"\r\n };\r\n }\r\n\r\n return {\r\n should: false\r\n };\r\n }\r\n\r\n function cleanup() {\r\n state.clear();\r\n state.setState(null);\r\n }\r\n\r\n return {\r\n shouldCollectData,\r\n cleanup,\r\n contactState: state,\r\n };\r\n} ","type RequestInterceptor = (config: RequestConfig) => RequestConfig | Promise<RequestConfig>;\r\ntype ResponseInterceptor = (response: Response) => Response | Promise<Response>;\r\ntype ErrorInterceptor = (error: any) => any;\r\n\r\ninterface RequestConfig extends RequestInit {\r\n baseURL?: string;\r\n headers?: HeadersInit;\r\n params?: Record<string, string>;\r\n}\r\n\r\nexport interface CustomFetch {\r\n (url: string, config?: RequestConfig): Promise<Response>;\r\n interceptors: {\r\n request: {\r\n use: (interceptor: RequestInterceptor) => number;\r\n eject: (id: number) => void;\r\n };\r\n response: {\r\n use: (interceptor: ResponseInterceptor, errorInterceptor?: ErrorInterceptor) => number;\r\n eject: (id: number) => void;\r\n };\r\n };\r\n}\r\n\r\nexport function createFetch(defaultConfig: RequestConfig = {}): CustomFetch {\r\n const requestInterceptors: RequestInterceptor[] = [];\r\n const responseInterceptors: ResponseInterceptor[] = [];\r\n const errorInterceptors: ErrorInterceptor[] = [];\r\n\r\n const customFetch: CustomFetch = async (url: string, config: RequestConfig = {}) => {\r\n // Merge configs\r\n let mergedConfig: RequestConfig = {\r\n ...defaultConfig,\r\n ...config,\r\n headers: {\r\n ...defaultConfig.headers,\r\n ...config.headers,\r\n },\r\n };\r\n\r\n try {\r\n // Apply request interceptors\r\n for (const interceptor of requestInterceptors) {\r\n mergedConfig = await interceptor(mergedConfig);\r\n }\r\n\r\n // Handle URL params\r\n const queryParams = mergedConfig.params\r\n ? '?' + new URLSearchParams(mergedConfig.params).toString()\r\n : '';\r\n\r\n // Construct full URL\r\n const fullUrl = mergedConfig.baseURL\r\n ? `${mergedConfig.baseURL}${url}${queryParams}`.replace(/([^:]\\/)\\/+/g, '$1')\r\n : `${url}${queryParams}`;\r\n\r\n // Make the fetch call\r\n let response = await fetch(fullUrl, mergedConfig);\r\n\r\n // Apply response interceptors\r\n for (const interceptor of responseInterceptors) {\r\n response = await interceptor(response);\r\n }\r\n\r\n return response;\r\n } catch (error) {\r\n // Apply error interceptors\r\n let processedError = error;\r\n for (const interceptor of errorInterceptors) {\r\n processedError = await interceptor(processedError);\r\n }\r\n throw processedError;\r\n }\r\n };\r\n\r\n // Add interceptors management\r\n customFetch.interceptors = {\r\n request: {\r\n use: (interceptor: RequestInterceptor) => {\r\n requestInterceptors.push(interceptor);\r\n return requestInterceptors.length - 1;\r\n },\r\n eject: (id: number) => {\r\n requestInterceptors.splice(id, 1);\r\n },\r\n },\r\n response: {\r\n use: (interceptor: ResponseInterceptor, errorInterceptor?: ErrorInterceptor) => {\r\n responseInterceptors.push(interceptor);\r\n if (errorInterceptor) {\r\n errorInterceptors.push(errorInterceptor);\r\n }\r\n return responseInterceptors.length - 1;\r\n },\r\n eject: (id: number) => {\r\n responseInterceptors.splice(id, 1);\r\n errorInterceptors.splice(id, 1);\r\n },\r\n },\r\n };\r\n\r\n return customFetch;\r\n}\r\n\r\n// Helper method to handle JSON responses\r\nexport async function handleJsonResponse<T>(response: Response): Promise<T> {\r\n if (!response.ok) {\r\n throw new Error(`HTTP error! status: ${response.status}`);\r\n }\r\n return response.json();\r\n}\r\n\r\n// Usage example:\r\n/*\r\nconst api = createFetch({\r\n baseURL: 'https://api.example.com',\r\n headers: {\r\n 'Content-Type': 'application/json',\r\n },\r\n});\r\n\r\n// Add request interceptor\r\napi.interceptors.request.use((config) => {\r\n config.headers = {\r\n ...config.headers,\r\n 'Authorization': `Bearer ${getToken()}`,\r\n };\r\n return config;\r\n});\r\n\r\n// Add response interceptor\r\napi.interceptors.response.use(\r\n async (response) => {\r\n if (!response.ok) {\r\n throw new Error(`HTTP error! status: ${response.status}`);\r\n }\r\n return response;\r\n },\r\n (error) => {\r\n console.error('Request failed:', error);\r\n throw error;\r\n }\r\n);\r\n*/\r\n","import { createFetch, CustomFetch } from \"../utils/create-fetch\";\r\nimport { HandleContactMessageOutputSchema, WidgetHistorySchema, WidgetPreludeSchema, WidgetSessionSchema } from \"../types/schemas-v2\";\r\nimport { CoreOptions, SendMessageInput, ConsumerType } from \"../types\";\r\n\r\nexport interface ApiCallerOptions {\r\n apiUrl: string;\r\n token: string;\r\n coreOptions: CoreOptions;\r\n}\r\n\r\nexport class ApiCaller {\r\n #fetch: CustomFetch\r\n constructor(private readonly options: ApiCallerOptions) {\r\n const user = this.options.coreOptions.user;\r\n const consumerHeader = {\r\n claim: '',\r\n value: ''\r\n }\r\n\r\n if (user?.email) {\r\n consumerHeader.claim = 'email';\r\n consumerHeader.value = user.email;\r\n }\r\n\r\n else if (user?.phone) {\r\n consumerHeader.claim = 'phone';\r\n consumerHeader.value = user.phone;\r\n }\r\n\r\n const headers: Record<string, string> = {\r\n 'X-Bot-Token': this.options.token,\r\n 'X-Consumer-Id': `${consumerHeader.claim}:${consumerHeader.value}`\r\n }\r\n\r\n // Only add Authorization header if contactToken exists\r\n if (this.options.coreOptions.contactToken) {\r\n headers['Authorization'] = `Bearer ${this.options.coreOptions.contactToken}`\r\n }\r\n\r\n this.#fetch = createFetch({\r\n baseURL: `${this.options.apiUrl}/widget/v2`,\r\n headers\r\n })\r\n }\r\n\r\n async me(): Promise<{\r\n contactId: string;\r\n contactName: string;\r\n }> {\r\n // GET /me\r\n const response = await this.#fetch('/me')\r\n return response.json()\r\n }\r\n\r\n async widgetPrelude(): Promise<WidgetPreludeSchema> {\r\n // GET /prelude\r\n const response = await this.#fetch('/prelude')\r\n return response.json()\r\n }\r\n\r\n async handleMessage(message: SendMessageInput): Promise<HandleContactMessageOutputSchema> {\r\n // POST /chat/send\r\n const response = await this.#fetch('/chat/send', {\r\n method: \"POST\",\r\n body: JSON.stringify(message)\r\n })\r\n return response.json()\r\n }\r\n\r\n async getSessionHistory(sessionId: string, lastMessageTimestamp?: string): Promise<WidgetHistorySchema[]> {\r\n // session/history/:sessionId\r\n const queryParams = new URLSearchParams({\r\n lastMessageTimestamp: lastMessageTimestamp || ''\r\n })\r\n\r\n const url = `/session/history/${sessionId}?${queryParams.toString()}`\r\n\r\n const response = await this.#fetch(url, {\r\n method: 'GET'\r\n })\r\n\r\n return response.json()\r\n }\r\n\r\n async createSession(): Promise<WidgetSessionSchema> {\r\n // POST /create-session\r\n const response = await this.#fetch('/create-session', {\r\n method: 'POST'\r\n })\r\n return response.json()\r\n }\r\n\r\n async getSession(sessionId: string): Promise<WidgetSessionSchema> {\r\n // GET /session/:sessionId\r\n const response = await this.#fetch(`/session/${sessionId}`, {\r\n method: 'GET'\r\n })\r\n return response.json()\r\n }\r\n\r\n async createContact(user: {\r\n external_id?: string;\r\n name?: string;\r\n email?: string;\r\n phone?: string;\r\n customData?: Record<string, string>;\r\n avatarUrl?: string;\r\n }): Promise<ConsumerType> {\r\n const response = await this.#fetch('/contact/upsert', {\r\n method: 'POST',\r\n body: JSON.stringify(user)\r\n });\r\n return response.json();\r\n }\r\n}\r\n","export class OpenCXError extends Error {\r\n constructor(message: string) {\r\n super(message);\r\n this.name = \"OpenCXError\";\r\n }\r\n}\r\n\r\nexport class ConnectionError extends OpenCXError {\r\n constructor(message = \"Connection failed\") {\r\n super(message);\r\n this.name = \"ConnectionError\";\r\n }\r\n}\r\n\r\nexport class AuthenticationError extends OpenCXError {\r\n constructor(message = \"Authentication failed\") {\r\n super(message);\r\n this.name = \"AuthenticationError\";\r\n }\r\n}\r\n\r\nexport class SessionError extends OpenCXError {\r\n constructor(message = \"Session error occurred\") {\r\n super(message);\r\n this.name = \"SessionError\";\r\n }\r\n}\r\n\r\nexport class SessionNotDefinedError extends SessionError {\r\n constructor(message = \"Session not defined\") {\r\n super(message);\r\n this.name = \"SessionNotDefinedError\";\r\n }\r\n}\r\n\r\nexport class TransportError extends OpenCXError {\r\n constructor(message = \"Transport error occurred\") {\r\n super(message);\r\n this.name = \"TransportError\";\r\n }\r\n}\r\n\r\nexport class FileUploadError extends OpenCXError {\r\n constructor(message = \"File upload failed\") {\r\n super(message);\r\n this.name = \"FileUploadError\";\r\n }\r\n}\r\n","export interface Platform {\r\n storage?: Storage;\r\n env: {\r\n platform: string;\r\n };\r\n date: {\r\n now(): number;\r\n toISOString(date: number): string;\r\n };\r\n}\r\n\r\nexport function createDefaultPlatform(): Platform {\r\n const detectPlatform = () => {\r\n // detect browser\r\n if (typeof window !== \"undefined\") {\r\n return \"browser\";\r\n }\r\n return \"server\";\r\n };\r\n\r\n return {\r\n env: {\r\n platform: detectPlatform()\r\n },\r\n date: {\r\n now: () => Date.now(),\r\n toISOString: (date: number) => new Date(date).toISOString()\r\n }\r\n };\r\n}\r\n","import { CoreOptions } from \"../types\";\r\n\r\nconst DEFAULT_SOUND_EFFECTS = {\r\n messageArrived: \"https://cloud.opencopilot.so/sfx/notification3.mp3\"\r\n};\r\n\r\nconst DEFAULT_THEME = {\r\n headerStyle: \"basic\" as const,\r\n primaryColor: \"hsl(211,65%,59%)\",\r\n triggerOffset: \"20px\"\r\n};\r\n\r\ntype NormalizedConfig = Required<Omit<CoreOptions, 'contactToken'>> & {\r\n contactToken: string | undefined | null;\r\n soundEffectFiles: {\r\n messageArrived: string;\r\n };\r\n theme: {\r\n headerStyle: \"compact\" | \"basic\";\r\n primaryColor: string;\r\n triggerOffset: string;\r\n };\r\n settings: {\r\n persistSession: boolean;\r\n useSoundEffects: boolean;\r\n };\r\n};\r\n\r\ntype ConfigInstance = {\r\n getConfig: () => NormalizedConfig;\r\n getApiConfig: () => {\r\n apiUrl: string;\r\n token: string;\r\n headers: Record<string, string>;\r\n queryParams: Record<string, string>;\r\n pathParams: Record<string, string>;\r\n };\r\n getBotConfig: () => NormalizedConfig['bot'];\r\n getThemeConfig: () => NormalizedConfig['theme'];\r\n getSettings: () => NormalizedConfig['settings'];\r\n getSoundEffects: () => NormalizedConfig['soundEffectFiles'];\r\n getUser: () => NormalizedConfig['user'];\r\n getLanguage: () => string;\r\n getDebugMode: () => boolean;\r\n};\r\n\r\nexport function createConfig(options: CoreOptions): ConfigInstance {\r\n const normalizedConfig: NormalizedConfig = {\r\n ...options,\r\n apiUrl: options.apiUrl ?? \"https://api-v2.opencopilot.so/backend\",\r\n socketUrl: options.socketUrl ?? \"https://api-v2.opencopilot.so\",\r\n transport: options.transport ?? 'socket',\r\n pollingInterval: options.pollingInterval ?? 3000,\r\n headers: {\r\n ...(options.headers ?? {}),\r\n \"X-Bot-Token\": options.token,\r\n },\r\n queryParams: options.queryParams ?? {},\r\n pathParams: options.pathParams ?? {},\r\n bot: {\r\n name: options.bot?.name ?? \"Bot\",\r\n avatarUrl: options.bot?.avatarUrl,\r\n id: options.bot?.id ?? null,\r\n is_ai: options.bot?.is_ai ?? true\r\n },\r\n contactToken: options.contactToken,\r\n debug: options.debug ?? false,\r\n language: options.language ?? \"en\",\r\n user: options.user ?? {},\r\n soundEffectFiles: {\r\n messageArrived: options.soundEffectFiles?.messageArrived ?? DEFAULT_SOUND_EFFECTS.messageArrived\r\n },\r\n theme: {\r\n headerStyle: options.theme?.headerStyle ?? DEFAULT_THEME.headerStyle,\r\n primaryColor: options.theme?.primaryColor ?? DEFAULT_THEME.primaryColor,\r\n triggerOffset: options.theme?.triggerOffset ?? DEFAULT_THEME.triggerOffset\r\n },\r\n settings: {\r\n persistSession: options.settings?.persistSession ?? false,\r\n useSoundEffects: options.settings?.useSoundEffects ?? false\r\n }\r\n };\r\n\r\n return {\r\n getConfig: () => normalizedConfig,\r\n getApiConfig: () => ({\r\n apiUrl: normalizedConfig.apiUrl,\r\n token: normalizedConfig.token,\r\n headers: normalizedConfig.headers,\r\n queryParams: normalizedConfig.queryParams,\r\n pathParams: normalizedConfig.pathParams\r\n }),\r\n getBotConfig: () => normalizedConfig.bot,\r\n getThemeConfig: () => normalizedConfig.theme,\r\n getSettings: () => normalizedConfig.settings,\r\n getSoundEffects: () => normalizedConfig.soundEffectFiles,\r\n getUser: () => normalizedConfig.user,\r\n getLanguage: () => normalizedConfig.language,\r\n getDebugMode: () => normalizedConfig.debug\r\n };\r\n} "],"names":["PubSub","state","__publicField","__privateAdd","_state","__privateSet","callback","__privateGet","newState","_s","createPubSub","SESSION_POLLING_INTERVAL","MESSAGE_POLLING_INTERVAL","mapHistoryToMessage","history","genId","_a","_b","_c","startPolling","api","sessionState","intervals","session","response","error","messages","createChat","options","stopPolling","createSession","clearSession","cleanup","input","message","createContact","storageKey","initialState","stored","e","contact","shouldCollectData","createFetch","defaultConfig","requestInterceptors","responseInterceptors","errorInterceptors","customFetch","url","config","mergedConfig","interceptor","queryParams","fullUrl","processedError","id","errorInterceptor","ApiCaller","_fetch","user","consumerHeader","headers","sessionId","lastMessageTimestamp","OpenCXError","ConnectionError","AuthenticationError","SessionError","SessionNotDefinedError","TransportError","FileUploadError","createDefaultPlatform","date","DEFAULT_SOUND_EFFECTS","DEFAULT_THEME","createConfig","normalizedConfig","_d","_e","_f","_g","_h","_i","_j"],"mappings":"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"}
|