ajaxter-chat 3.0.1 → 3.0.4

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.
@@ -1,3 +1,7 @@
1
1
  import { LocalEnvConfig, RemoteChatData } from '../types';
2
- export declare function loadLocalConfig(): LocalEnvConfig;
2
+ /**
3
+ * Loads remote widget config once via GET. Uses query params `key` and `widget` so the
4
+ * server can validate the request without custom headers (avoids CORS preflight failures).
5
+ */
3
6
  export declare function fetchRemoteChatData(apiKey: string, widgetId: string): Promise<RemoteChatData>;
7
+ export declare function loadLocalConfig(): LocalEnvConfig;
@@ -1,4 +1,9 @@
1
- const REMOTE_URL = 'https://window.mscorpres.com/TEST/chatData.json';
1
+ /**
2
+ * Default JSON endpoint. Override with `REACT_APP_CHAT_CONFIG_URL` / `NEXT_PUBLIC_CHAT_CONFIG_URL`.
3
+ * If the remote host does not send CORS headers, set this to a same-origin path (e.g. `/api/chat-config`)
4
+ * and proxy the JSON from your server — see `examples/next-app-router-chat-proxy.ts`.
5
+ */
6
+ const DEFAULT_CHAT_DATA_BASE = 'https://window.mscorpres.com/TEST/chatData.json';
2
7
  const DEMO_API_KEY = 'demo1234';
3
8
  const DEMO_WIDGET_ID = 'demo';
4
9
  function getEnv(key) {
@@ -8,23 +13,33 @@ function getEnv(key) {
8
13
  }
9
14
  return undefined;
10
15
  }
11
- export function loadLocalConfig() {
12
- var _a, _b;
13
- return {
14
- apiKey: (_a = getEnv('CHAT_API_KEY')) !== null && _a !== void 0 ? _a : DEMO_API_KEY,
15
- widgetId: (_b = getEnv('CHAT_WIDGET_ID')) !== null && _b !== void 0 ? _b : DEMO_WIDGET_ID,
16
- };
16
+ function getChatDataBaseUrl() {
17
+ var _a;
18
+ return ((_a = getEnv('CHAT_CONFIG_URL')) === null || _a === void 0 ? void 0 : _a.trim()) || DEFAULT_CHAT_DATA_BASE;
17
19
  }
20
+ /**
21
+ * Loads remote widget config once via GET. Uses query params `key` and `widget` so the
22
+ * server can validate the request without custom headers (avoids CORS preflight failures).
23
+ */
18
24
  export async function fetchRemoteChatData(apiKey, widgetId) {
19
- const url = REMOTE_URL;
20
- const res = await fetch(url, {
21
- headers: {
22
- 'X-Chat-Api-Key': apiKey,
23
- 'X-Chat-Widget-Id': widgetId,
24
- 'Content-Type': 'application/json',
25
- },
25
+ const base = getChatDataBaseUrl();
26
+ const url = new URL(base, typeof window !== 'undefined' ? window.location.origin : 'https://localhost');
27
+ url.searchParams.set('key', apiKey);
28
+ url.searchParams.set('widget', widgetId);
29
+ const res = await fetch(url.toString(), {
30
+ method: 'GET',
31
+ credentials: 'omit',
32
+ mode: 'cors',
33
+ headers: { Accept: 'application/json' },
26
34
  });
27
35
  if (!res.ok)
28
36
  throw new Error(`Failed to load chat config: ${res.status}`);
29
37
  return res.json();
30
38
  }
39
+ export function loadLocalConfig() {
40
+ var _a, _b;
41
+ return {
42
+ apiKey: (_a = getEnv('CHAT_API_KEY')) !== null && _a !== void 0 ? _a : DEMO_API_KEY,
43
+ widgetId: (_b = getEnv('CHAT_WIDGET_ID')) !== null && _b !== void 0 ? _b : DEMO_WIDGET_ID,
44
+ };
45
+ }
@@ -10,12 +10,16 @@ export function useRemoteConfig(apiKey, widgetId) {
10
10
  fetchRemoteChatData(apiKey, widgetId)
11
11
  .then(d => { if (!cancelled) {
12
12
  setData(d);
13
+ setError(null);
13
14
  setLoading(false);
14
15
  } })
15
- .catch(e => { if (!cancelled) {
16
- setError(e.message);
17
- setLoading(false);
18
- } });
16
+ .catch(e => {
17
+ if (!cancelled) {
18
+ const msg = e instanceof Error ? e.message : String(e);
19
+ setError(msg || 'Network error while loading configuration');
20
+ setLoading(false);
21
+ }
22
+ });
19
23
  return () => { cancelled = true; };
20
24
  }, [apiKey, widgetId]);
21
25
  return { data, loading, error };
@@ -1,8 +1,8 @@
1
1
  import { CallSession, ChatUser } from '../types';
2
2
  export declare function useWebRTC(): {
3
3
  session: CallSession;
4
- localVideoRef: import("react").RefObject<HTMLVideoElement | null>;
5
- remoteVideoRef: import("react").RefObject<HTMLVideoElement | null>;
4
+ localVideoRef: import("react").MutableRefObject<HTMLVideoElement | null>;
5
+ remoteVideoRef: import("react").MutableRefObject<HTMLVideoElement | null>;
6
6
  startCall: (peer: ChatUser, withVideo?: boolean) => Promise<void>;
7
7
  acceptCall: (offer: RTCSessionDescriptionInit, peer: ChatUser, withVideo?: boolean) => Promise<void>;
8
8
  endCall: () => void;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "ajaxter-chat",
3
- "version": "3.0.1",
3
+ "version": "3.0.4",
4
4
  "description": "Drawer-based chat widget with support chat, tickets, WebRTC calling, voice messages, block list, and transcript download.",
5
5
  "main": "dist/index.js",
6
6
  "types": "dist/index.d.ts",
@@ -38,12 +38,12 @@ export const CallScreen: React.FC<CallScreenProps> = ({
38
38
  position:'relative', overflow:'hidden',
39
39
  }}>
40
40
  {/* Remote video (background) */}
41
- <video ref={remoteVideoRef} autoPlay playsInline
41
+ <video ref={remoteVideoRef as React.Ref<HTMLVideoElement>} autoPlay playsInline
42
42
  style={{ position:'absolute', inset:0, width:'100%', height:'100%', objectFit:'cover', opacity: session.state==='connected'?1:0 }}
43
43
  />
44
44
 
45
45
  {/* Local video (PiP) */}
46
- <video ref={localVideoRef} autoPlay playsInline muted
46
+ <video ref={localVideoRef as React.Ref<HTMLVideoElement>} autoPlay playsInline muted
47
47
  style={{
48
48
  position:'absolute', bottom:120, right:14,
49
49
  width:90, height:120, borderRadius:10,
@@ -1,6 +1,11 @@
1
1
  import { LocalEnvConfig, RemoteChatData } from '../types';
2
2
 
3
- const REMOTE_URL = 'https://window.mscorpres.com/TEST/chatData.json';
3
+ /**
4
+ * Default JSON endpoint. Override with `REACT_APP_CHAT_CONFIG_URL` / `NEXT_PUBLIC_CHAT_CONFIG_URL`.
5
+ * If the remote host does not send CORS headers, set this to a same-origin path (e.g. `/api/chat-config`)
6
+ * and proxy the JSON from your server — see `examples/next-app-router-chat-proxy.ts`.
7
+ */
8
+ const DEFAULT_CHAT_DATA_BASE = 'https://window.mscorpres.com/TEST/chatData.json';
4
9
  const DEMO_API_KEY = 'demo1234';
5
10
  const DEMO_WIDGET_ID = 'demo';
6
11
 
@@ -16,25 +21,36 @@ function getEnv(key: string): string | undefined {
16
21
  return undefined;
17
22
  }
18
23
 
19
- export function loadLocalConfig(): LocalEnvConfig {
20
- return {
21
- apiKey: getEnv('CHAT_API_KEY') ?? DEMO_API_KEY,
22
- widgetId: getEnv('CHAT_WIDGET_ID') ?? DEMO_WIDGET_ID,
23
- };
24
+ function getChatDataBaseUrl(): string {
25
+ return getEnv('CHAT_CONFIG_URL')?.trim() || DEFAULT_CHAT_DATA_BASE;
24
26
  }
25
27
 
28
+ /**
29
+ * Loads remote widget config once via GET. Uses query params `key` and `widget` so the
30
+ * server can validate the request without custom headers (avoids CORS preflight failures).
31
+ */
26
32
  export async function fetchRemoteChatData(
27
33
  apiKey: string,
28
34
  widgetId: string
29
35
  ): Promise<RemoteChatData> {
30
- const url = REMOTE_URL;
31
- const res = await fetch(url, {
32
- headers: {
33
- 'X-Chat-Api-Key': apiKey,
34
- 'X-Chat-Widget-Id': widgetId,
35
- 'Content-Type': 'application/json',
36
- },
36
+ const base = getChatDataBaseUrl();
37
+ const url = new URL(base, typeof window !== 'undefined' ? window.location.origin : 'https://localhost');
38
+ url.searchParams.set('key', apiKey);
39
+ url.searchParams.set('widget', widgetId);
40
+
41
+ const res = await fetch(url.toString(), {
42
+ method: 'GET',
43
+ credentials: 'omit',
44
+ mode: 'cors',
45
+ headers: { Accept: 'application/json' },
37
46
  });
38
47
  if (!res.ok) throw new Error(`Failed to load chat config: ${res.status}`);
39
48
  return res.json() as Promise<RemoteChatData>;
40
49
  }
50
+
51
+ export function loadLocalConfig(): LocalEnvConfig {
52
+ return {
53
+ apiKey: getEnv('CHAT_API_KEY') ?? DEMO_API_KEY,
54
+ widgetId: getEnv('CHAT_WIDGET_ID') ?? DEMO_WIDGET_ID,
55
+ };
56
+ }
@@ -11,8 +11,14 @@ export function useRemoteConfig(apiKey: string, widgetId: string) {
11
11
  let cancelled = false;
12
12
  setLoading(true);
13
13
  fetchRemoteChatData(apiKey, widgetId)
14
- .then(d => { if (!cancelled) { setData(d); setLoading(false); } })
15
- .catch(e => { if (!cancelled) { setError(e.message); setLoading(false); } });
14
+ .then(d => { if (!cancelled) { setData(d); setError(null); setLoading(false); } })
15
+ .catch(e => {
16
+ if (!cancelled) {
17
+ const msg = e instanceof Error ? e.message : String(e);
18
+ setError(msg || 'Network error while loading configuration');
19
+ setLoading(false);
20
+ }
21
+ });
16
22
  return () => { cancelled = true; };
17
23
  }, [apiKey, widgetId]);
18
24