@cstar.help/react 0.6.1 → 0.8.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 +9 -9
- package/dist/index.cjs +80 -23
- package/dist/index.d.cts +57 -24
- package/dist/index.d.ts +57 -24
- package/dist/index.js +116 -59
- package/package.json +2 -2
package/README.md
CHANGED
|
@@ -24,7 +24,7 @@ import { CStarChatProvider } from '@cstar.help/react';
|
|
|
24
24
|
|
|
25
25
|
function App() {
|
|
26
26
|
return (
|
|
27
|
-
<CStarChatProvider teamSlug="acme"
|
|
27
|
+
<CStarChatProvider teamSlug="acme">
|
|
28
28
|
<ChatWidget />
|
|
29
29
|
</CStarChatProvider>
|
|
30
30
|
);
|
|
@@ -47,24 +47,24 @@ function ChatWidget() {
|
|
|
47
47
|
}, []);
|
|
48
48
|
|
|
49
49
|
if (!isIdentified) return <p>Connecting...</p>;
|
|
50
|
-
return <
|
|
50
|
+
return <TicketList />;
|
|
51
51
|
}
|
|
52
52
|
```
|
|
53
53
|
|
|
54
|
-
###
|
|
54
|
+
### Tickets
|
|
55
55
|
|
|
56
56
|
```tsx
|
|
57
|
-
import {
|
|
57
|
+
import { useTickets } from '@cstar.help/react';
|
|
58
58
|
|
|
59
|
-
function
|
|
60
|
-
const {
|
|
59
|
+
function TicketList() {
|
|
60
|
+
const { tickets, isLoading, create, refresh, hasMore } = useTickets();
|
|
61
61
|
|
|
62
62
|
if (isLoading) return <Spinner />;
|
|
63
63
|
|
|
64
64
|
return (
|
|
65
65
|
<ul>
|
|
66
|
-
{
|
|
67
|
-
<li key={
|
|
66
|
+
{tickets.map((t) => (
|
|
67
|
+
<li key={t.id}>{t.subject}</li>
|
|
68
68
|
))}
|
|
69
69
|
</ul>
|
|
70
70
|
);
|
|
@@ -270,7 +270,7 @@ function CommunitySearch() {
|
|
|
270
270
|
| Hook | Returns | Description |
|
|
271
271
|
| ----------------------- | ---------------------------------------------------------------- | ---------------------------------------------------- |
|
|
272
272
|
| `useChat()` | `{ identify, disconnect, isIdentified, isRealtimeReady, error }` | Identity verification and connection state |
|
|
273
|
-
| `
|
|
273
|
+
| `useTickets()` | `{ tickets, isLoading, error, hasMore, refresh, create }` | List and create tickets |
|
|
274
274
|
| `useMessages(ticketId)` | `{ messages, isLoading, error, send, refresh }` | Messages with real-time updates and optimistic send |
|
|
275
275
|
| `useTyping(ticketId)` | `{ typingAgents, sendTyping }` | Agent typing indicators with auto-clear (4s timeout) |
|
|
276
276
|
|
package/dist/index.cjs
CHANGED
|
@@ -39,7 +39,6 @@ __export(src_exports, {
|
|
|
39
39
|
useChatClient: () => useChatClient,
|
|
40
40
|
useCommunityClient: () => useCommunityClient,
|
|
41
41
|
useCommunitySearch: () => useCommunitySearch,
|
|
42
|
-
useConversations: () => useConversations,
|
|
43
42
|
useDashboardClient: () => useDashboardClient,
|
|
44
43
|
useGameActivity: () => useGameActivity,
|
|
45
44
|
useLeaderboard: () => useLeaderboard,
|
|
@@ -48,6 +47,7 @@ __export(src_exports, {
|
|
|
48
47
|
usePlayerStats: () => usePlayerStats,
|
|
49
48
|
usePost: () => usePost,
|
|
50
49
|
usePosts: () => usePosts,
|
|
50
|
+
useTickets: () => useTickets,
|
|
51
51
|
useTopics: () => useTopics,
|
|
52
52
|
useTyping: () => useTyping
|
|
53
53
|
});
|
|
@@ -102,19 +102,26 @@ function CStarChatProvider({ children, ...config }) {
|
|
|
102
102
|
var import_react3 = require("react");
|
|
103
103
|
function useChat() {
|
|
104
104
|
const client = useChatClient();
|
|
105
|
-
const [
|
|
105
|
+
const [isAuthenticated, setIsAuthenticated] = (0, import_react3.useState)(false);
|
|
106
|
+
const [authMode, setAuthMode] = (0, import_react3.useState)(() => client.getAuthMode());
|
|
106
107
|
const [isRealtimeReady, setIsRealtimeReady] = (0, import_react3.useState)(false);
|
|
107
108
|
const [error, setError] = (0, import_react3.useState)(null);
|
|
109
|
+
(0, import_react3.useEffect)(() => {
|
|
110
|
+
const current = client.getAuthMode();
|
|
111
|
+
if (current !== authMode) setAuthMode(current);
|
|
112
|
+
}, [client, authMode]);
|
|
113
|
+
const wireRealtime = (0, import_react3.useCallback)(() => {
|
|
114
|
+
client.waitForRealtime().then(() => setIsRealtimeReady(true)).catch(() => {
|
|
115
|
+
});
|
|
116
|
+
}, [client]);
|
|
108
117
|
const identify = (0, import_react3.useCallback)(
|
|
109
118
|
async (customer, signature) => {
|
|
110
119
|
setError(null);
|
|
111
120
|
try {
|
|
112
121
|
const result = await client.identify(customer, signature);
|
|
113
|
-
|
|
114
|
-
client.
|
|
115
|
-
|
|
116
|
-
}).catch(() => {
|
|
117
|
-
});
|
|
122
|
+
setIsAuthenticated(true);
|
|
123
|
+
setAuthMode(client.getAuthMode());
|
|
124
|
+
wireRealtime();
|
|
118
125
|
return result;
|
|
119
126
|
} catch (err) {
|
|
120
127
|
const e = err instanceof Error ? err : new Error(String(err));
|
|
@@ -122,22 +129,66 @@ function useChat() {
|
|
|
122
129
|
throw e;
|
|
123
130
|
}
|
|
124
131
|
},
|
|
125
|
-
[client]
|
|
132
|
+
[client, wireRealtime]
|
|
133
|
+
);
|
|
134
|
+
const loginWithCredentials = (0, import_react3.useCallback)(
|
|
135
|
+
async (params) => {
|
|
136
|
+
setError(null);
|
|
137
|
+
try {
|
|
138
|
+
const result = await client.loginWithCredentials(params);
|
|
139
|
+
setIsAuthenticated(true);
|
|
140
|
+
setAuthMode(client.getAuthMode());
|
|
141
|
+
wireRealtime();
|
|
142
|
+
return result;
|
|
143
|
+
} catch (err) {
|
|
144
|
+
const e = err instanceof Error ? err : new Error(String(err));
|
|
145
|
+
setError(e);
|
|
146
|
+
throw e;
|
|
147
|
+
}
|
|
148
|
+
},
|
|
149
|
+
[client, wireRealtime]
|
|
150
|
+
);
|
|
151
|
+
const loginWithSession = (0, import_react3.useCallback)(
|
|
152
|
+
async (params) => {
|
|
153
|
+
setError(null);
|
|
154
|
+
try {
|
|
155
|
+
await client.loginWithSession(params);
|
|
156
|
+
setIsAuthenticated(true);
|
|
157
|
+
setAuthMode(client.getAuthMode());
|
|
158
|
+
wireRealtime();
|
|
159
|
+
} catch (err) {
|
|
160
|
+
const e = err instanceof Error ? err : new Error(String(err));
|
|
161
|
+
setError(e);
|
|
162
|
+
throw e;
|
|
163
|
+
}
|
|
164
|
+
},
|
|
165
|
+
[client, wireRealtime]
|
|
126
166
|
);
|
|
127
167
|
const disconnect = (0, import_react3.useCallback)(() => {
|
|
128
168
|
client.disconnect();
|
|
129
|
-
|
|
169
|
+
setIsAuthenticated(false);
|
|
170
|
+
setAuthMode(null);
|
|
130
171
|
setIsRealtimeReady(false);
|
|
131
172
|
setError(null);
|
|
132
173
|
}, [client]);
|
|
133
|
-
return {
|
|
174
|
+
return {
|
|
175
|
+
identify,
|
|
176
|
+
loginWithCredentials,
|
|
177
|
+
loginWithSession,
|
|
178
|
+
disconnect,
|
|
179
|
+
isIdentified: isAuthenticated,
|
|
180
|
+
isAuthenticated,
|
|
181
|
+
authMode,
|
|
182
|
+
isRealtimeReady,
|
|
183
|
+
error
|
|
184
|
+
};
|
|
134
185
|
}
|
|
135
186
|
|
|
136
|
-
// src/chat/
|
|
187
|
+
// src/chat/useTickets.ts
|
|
137
188
|
var import_react4 = require("react");
|
|
138
|
-
function
|
|
189
|
+
function useTickets() {
|
|
139
190
|
const client = useChatClient();
|
|
140
|
-
const [
|
|
191
|
+
const [tickets, setTickets] = (0, import_react4.useState)([]);
|
|
141
192
|
const [isLoading, setIsLoading] = (0, import_react4.useState)(true);
|
|
142
193
|
const [error, setError] = (0, import_react4.useState)(null);
|
|
143
194
|
const [hasMore, setHasMore] = (0, import_react4.useState)(false);
|
|
@@ -146,9 +197,9 @@ function useConversations() {
|
|
|
146
197
|
setIsLoading(true);
|
|
147
198
|
setError(null);
|
|
148
199
|
try {
|
|
149
|
-
const result = await client.
|
|
200
|
+
const result = await client.tickets.list();
|
|
150
201
|
if (mountedRef.current) {
|
|
151
|
-
|
|
202
|
+
setTickets(result.tickets);
|
|
152
203
|
setHasMore(result.hasMore);
|
|
153
204
|
}
|
|
154
205
|
} catch (err) {
|
|
@@ -170,15 +221,15 @@ function useConversations() {
|
|
|
170
221
|
}, [refresh]);
|
|
171
222
|
const create = (0, import_react4.useCallback)(
|
|
172
223
|
async (params) => {
|
|
173
|
-
const
|
|
224
|
+
const ticket = await client.tickets.create(params);
|
|
174
225
|
if (mountedRef.current) {
|
|
175
|
-
|
|
226
|
+
setTickets((prev) => [ticket, ...prev]);
|
|
176
227
|
}
|
|
177
|
-
return
|
|
228
|
+
return ticket;
|
|
178
229
|
},
|
|
179
230
|
[client]
|
|
180
231
|
);
|
|
181
|
-
return {
|
|
232
|
+
return { tickets, isLoading, error, hasMore, refresh, create };
|
|
182
233
|
}
|
|
183
234
|
|
|
184
235
|
// src/chat/useMessages.ts
|
|
@@ -241,7 +292,7 @@ function useMessages(ticketId) {
|
|
|
241
292
|
}, [client, ticketId, refresh]);
|
|
242
293
|
const send = (0, import_react5.useCallback)(
|
|
243
294
|
async (content) => {
|
|
244
|
-
if (!ticketId) throw new Error("No
|
|
295
|
+
if (!ticketId) throw new Error("No ticket selected");
|
|
245
296
|
const optimistic = {
|
|
246
297
|
id: `optimistic-${Date.now()}`,
|
|
247
298
|
content,
|
|
@@ -679,10 +730,15 @@ var import_react17 = require("react");
|
|
|
679
730
|
var import_jsx_runtime4 = require("react/jsx-runtime");
|
|
680
731
|
var CStarDashboardContext = (0, import_react17.createContext)(null);
|
|
681
732
|
function CStarDashboardProvider({ client, children }) {
|
|
733
|
+
if (!client) {
|
|
734
|
+
throw new Error(
|
|
735
|
+
"CStarDashboardProvider requires a `client` prop. Build it server-side with `new CStarClient({ apiKey: process.env.CSTAR_API_KEY, teamId })` and pass via SSR. See https://cstar.help/developers/sdk/react#dashboard"
|
|
736
|
+
);
|
|
737
|
+
}
|
|
682
738
|
const contextValue = (0, import_react17.useRef)({ client }).current;
|
|
683
739
|
(0, import_react17.useEffect)(() => {
|
|
684
740
|
return () => {
|
|
685
|
-
client
|
|
741
|
+
client?.realtime?.disconnect?.();
|
|
686
742
|
};
|
|
687
743
|
}, [client]);
|
|
688
744
|
return /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(CStarDashboardContext.Provider, { value: contextValue, children });
|
|
@@ -754,7 +810,8 @@ function resolveMutation(client, path) {
|
|
|
754
810
|
const methodName = parts[1];
|
|
755
811
|
const resource = client[resourceName];
|
|
756
812
|
if (!resource || typeof resource !== "object") return null;
|
|
757
|
-
const
|
|
813
|
+
const lookupName = methodName === "delete" ? "del" : methodName;
|
|
814
|
+
const method = resource[lookupName];
|
|
758
815
|
if (typeof method !== "function") return null;
|
|
759
816
|
if (methodName === "update") {
|
|
760
817
|
return (params) => {
|
|
@@ -982,7 +1039,6 @@ function useGameActivity() {
|
|
|
982
1039
|
useChatClient,
|
|
983
1040
|
useCommunityClient,
|
|
984
1041
|
useCommunitySearch,
|
|
985
|
-
useConversations,
|
|
986
1042
|
useDashboardClient,
|
|
987
1043
|
useGameActivity,
|
|
988
1044
|
useLeaderboard,
|
|
@@ -991,6 +1047,7 @@ function useGameActivity() {
|
|
|
991
1047
|
usePlayerStats,
|
|
992
1048
|
usePost,
|
|
993
1049
|
usePosts,
|
|
1050
|
+
useTickets,
|
|
994
1051
|
useTopics,
|
|
995
1052
|
useTyping
|
|
996
1053
|
});
|
package/dist/index.d.cts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import * as react from 'react';
|
|
2
2
|
import react__default, { ReactNode } from 'react';
|
|
3
|
-
import { ChatClient, ChatConfig, IdentifyParams, IdentifyResult,
|
|
4
|
-
export { ChatConfig,
|
|
3
|
+
import { ChatClient, ChatConfig, IdentifyParams, IdentifyResult, LoginWithCredentialsParams, LoginWithCredentialsResult, LoginWithSessionParams, ChatAuthMode, Ticket, TicketCreateParams, Message } from '@cstar.help/js/chat';
|
|
4
|
+
export { ChatConfig, IdentifyParams, IdentifyResult, Message, Ticket, TicketCreateParams, TicketListResponse, TypingPayload } from '@cstar.help/js/chat';
|
|
5
5
|
import { LibraryClient, LibraryConfig, Category, LibraryArticle, LibraryArticleListParams } from '@cstar.help/js/library';
|
|
6
6
|
export { Category, LibraryArticle, LibraryArticleListParams, LibraryConfig, LibrarySearchParams, LibrarySearchResult } from '@cstar.help/js/library';
|
|
7
7
|
import { CommunityClient, CommunityConfig, CommunityTopic, CommunityPost, CommunityPostListParams, CommunityPostDetail, CommunitySearchResult } from '@cstar.help/js/community';
|
|
@@ -36,7 +36,7 @@ interface CStarChatProviderProps extends ChatConfig {
|
|
|
36
36
|
* Creates the client on mount and disconnects on unmount.
|
|
37
37
|
*
|
|
38
38
|
* ```tsx
|
|
39
|
-
* <CStarChatProvider teamSlug="acme"
|
|
39
|
+
* <CStarChatProvider teamSlug="acme">
|
|
40
40
|
* <ChatWidget />
|
|
41
41
|
* </CStarChatProvider>
|
|
42
42
|
* ```
|
|
@@ -46,66 +46,99 @@ declare function CStarChatProvider({ children, ...config }: CStarChatProviderPro
|
|
|
46
46
|
interface UseChatReturn {
|
|
47
47
|
/** Identify a customer with HMAC signature. */
|
|
48
48
|
identify: (customer: IdentifyParams, signature: string) => Promise<IdentifyResult>;
|
|
49
|
+
/**
|
|
50
|
+
* Log in with cStar's hosted password auth (no separate auth backend
|
|
51
|
+
* required). Updates `isAuthenticated` and `authMode` to `'session'`.
|
|
52
|
+
*/
|
|
53
|
+
loginWithCredentials: (params: LoginWithCredentialsParams) => Promise<LoginWithCredentialsResult>;
|
|
54
|
+
/**
|
|
55
|
+
* Use an existing Supabase access token (e.g. forwarded from your own
|
|
56
|
+
* auth). Updates `isAuthenticated` and `authMode` to `'session'`.
|
|
57
|
+
*/
|
|
58
|
+
loginWithSession: (params: LoginWithSessionParams) => Promise<void>;
|
|
49
59
|
/** Disconnect the client and clean up all subscriptions. */
|
|
50
60
|
disconnect: () => void;
|
|
51
|
-
/**
|
|
61
|
+
/**
|
|
62
|
+
* `true` once the client has authenticated through any of the four modes
|
|
63
|
+
* (HMAC `identify`, credentials login, session login, or anonymous). Use
|
|
64
|
+
* this for "is the customer signed in?" branches.
|
|
65
|
+
*
|
|
66
|
+
* @deprecated since 0.8.0 — use `isAuthenticated`. Kept as an alias.
|
|
67
|
+
*/
|
|
52
68
|
isIdentified: boolean;
|
|
53
|
-
/**
|
|
69
|
+
/** Same as `isIdentified` — kept under the more accurate name. */
|
|
70
|
+
isAuthenticated: boolean;
|
|
71
|
+
/**
|
|
72
|
+
* The auth mode the underlying ChatClient is using right now. `null`
|
|
73
|
+
* before any auth call has resolved (or after `disconnect()`).
|
|
74
|
+
*/
|
|
75
|
+
authMode: ChatAuthMode | null;
|
|
76
|
+
/** Whether the real-time connection is ready. */
|
|
54
77
|
isRealtimeReady: boolean;
|
|
55
|
-
/** The last error from
|
|
78
|
+
/** The last error from any auth call, or null. */
|
|
56
79
|
error: Error | null;
|
|
57
80
|
}
|
|
58
81
|
/**
|
|
59
|
-
* Core chat hook — manages identity verification
|
|
82
|
+
* Core chat hook — manages identity verification (any of four auth modes)
|
|
83
|
+
* and realtime readiness. Closes F-041 / F-044: previously the hook only
|
|
84
|
+
* tracked HMAC `identify()` and ignored `loginWithCredentials` /
|
|
85
|
+
* `loginWithSession`, leaving consumer UI stuck on the unauthenticated
|
|
86
|
+
* branch even after a successful session login.
|
|
60
87
|
*
|
|
61
88
|
* ```tsx
|
|
62
|
-
* const { identify,
|
|
89
|
+
* const { identify, loginWithCredentials, isAuthenticated, authMode } = useChat();
|
|
63
90
|
*
|
|
64
91
|
* await identify(
|
|
65
92
|
* { externalId: 'usr_123', email: 'jane@co.com', timestamp: Date.now() / 1000 },
|
|
66
93
|
* hmacSignature
|
|
67
94
|
* );
|
|
95
|
+
* // OR
|
|
96
|
+
* await loginWithCredentials({ email: 'jane@co.com', password: 'hunter2' });
|
|
97
|
+
*
|
|
98
|
+
* if (isAuthenticated && authMode === 'session') {
|
|
99
|
+
* // show "Sign out" button
|
|
100
|
+
* }
|
|
68
101
|
* ```
|
|
69
102
|
*/
|
|
70
103
|
declare function useChat(): UseChatReturn;
|
|
71
104
|
|
|
72
|
-
interface
|
|
73
|
-
/** List of
|
|
74
|
-
|
|
105
|
+
interface UseTicketsReturn {
|
|
106
|
+
/** List of tickets for the identified customer. */
|
|
107
|
+
tickets: Ticket[];
|
|
75
108
|
/** Whether the initial fetch is in progress. */
|
|
76
109
|
isLoading: boolean;
|
|
77
110
|
/** The last error, or null. */
|
|
78
111
|
error: Error | null;
|
|
79
|
-
/** Whether there are more
|
|
112
|
+
/** Whether there are more tickets to load. */
|
|
80
113
|
hasMore: boolean;
|
|
81
|
-
/** Re-fetch the
|
|
114
|
+
/** Re-fetch the ticket list. */
|
|
82
115
|
refresh: () => Promise<void>;
|
|
83
|
-
/** Create a new
|
|
84
|
-
create: (params:
|
|
116
|
+
/** Create a new ticket. */
|
|
117
|
+
create: (params: TicketCreateParams) => Promise<Ticket>;
|
|
85
118
|
}
|
|
86
119
|
/**
|
|
87
|
-
* Manage the customer's
|
|
120
|
+
* Manage the customer's ticket list.
|
|
88
121
|
*
|
|
89
122
|
* ```tsx
|
|
90
|
-
* const {
|
|
123
|
+
* const { tickets, isLoading, create, refresh } = useTickets();
|
|
91
124
|
* ```
|
|
92
125
|
*/
|
|
93
|
-
declare function
|
|
126
|
+
declare function useTickets(): UseTicketsReturn;
|
|
94
127
|
|
|
95
128
|
interface UseMessagesReturn {
|
|
96
|
-
/** Messages
|
|
97
|
-
messages:
|
|
129
|
+
/** Messages on the ticket, oldest first. */
|
|
130
|
+
messages: Message[];
|
|
98
131
|
/** Whether the initial fetch is in progress. */
|
|
99
132
|
isLoading: boolean;
|
|
100
133
|
/** The last error, or null. */
|
|
101
134
|
error: Error | null;
|
|
102
135
|
/** Send a message. Optimistically appended, replaced with server response. */
|
|
103
|
-
send: (content: string) => Promise<
|
|
136
|
+
send: (content: string) => Promise<Message>;
|
|
104
137
|
/** Re-fetch messages from the API. */
|
|
105
138
|
refresh: () => Promise<void>;
|
|
106
139
|
}
|
|
107
140
|
/**
|
|
108
|
-
* Manage messages for a single
|
|
141
|
+
* Manage messages for a single ticket with automatic real-time updates.
|
|
109
142
|
*
|
|
110
143
|
* ```tsx
|
|
111
144
|
* const { messages, isLoading, send } = useMessages(ticketId);
|
|
@@ -125,7 +158,7 @@ interface UseTypingReturn {
|
|
|
125
158
|
sendTyping: (isTyping: boolean) => Promise<void>;
|
|
126
159
|
}
|
|
127
160
|
/**
|
|
128
|
-
* Track agent typing indicators for a
|
|
161
|
+
* Track agent typing indicators for a ticket.
|
|
129
162
|
*
|
|
130
163
|
* ```tsx
|
|
131
164
|
* const { typingAgents, sendTyping } = useTyping(ticketId);
|
|
@@ -477,4 +510,4 @@ interface UseGameActivityReturn {
|
|
|
477
510
|
*/
|
|
478
511
|
declare function useGameActivity(): UseGameActivityReturn;
|
|
479
512
|
|
|
480
|
-
export { CStarChatContext, CStarChatProvider, type CStarChatProviderProps, CStarCommunityContext, CStarCommunityProvider, type CStarCommunityProviderProps, CStarDashboardProvider, type CStarDashboardProviderProps, CStarLibraryContext, CStarLibraryProvider, type CStarLibraryProviderProps, type TypingAgent, type UseArticleReturn, type UseArticleSearchReturn, type UseArticlesReturn, type UseBossBattleReturn, type UseCStarEventsReturn, type UseCStarMutationReturn, type UseCStarQueryReturn, type UseCategoriesReturn, type UseChatReturn, type UseCommunitySearchReturn, type
|
|
513
|
+
export { CStarChatContext, CStarChatProvider, type CStarChatProviderProps, CStarCommunityContext, CStarCommunityProvider, type CStarCommunityProviderProps, CStarDashboardProvider, type CStarDashboardProviderProps, CStarLibraryContext, CStarLibraryProvider, type CStarLibraryProviderProps, type TypingAgent, type UseArticleReturn, type UseArticleSearchReturn, type UseArticlesReturn, type UseBossBattleReturn, type UseCStarEventsReturn, type UseCStarMutationReturn, type UseCStarQueryReturn, type UseCategoriesReturn, type UseChatReturn, type UseCommunitySearchReturn, type UseGameActivityReturn, type UseLeaderboardReturn, type UseMessagesReturn, type UsePlayerStatsReturn, type UsePostReturn, type UsePostsReturn, type UseTicketsReturn, type UseTopicsReturn, type UseTypingReturn, useArticle, useArticleSearch, useArticles, useBossBattle, useCStarEvents, useCStarMutation, useCStarQuery, useCategories, useChat, useChatClient, useCommunityClient, useCommunitySearch, useDashboardClient, useGameActivity, useLeaderboard, useLibraryClient, useMessages, usePlayerStats, usePost, usePosts, useTickets, useTopics, useTyping };
|
package/dist/index.d.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import * as react from 'react';
|
|
2
2
|
import react__default, { ReactNode } from 'react';
|
|
3
|
-
import { ChatClient, ChatConfig, IdentifyParams, IdentifyResult,
|
|
4
|
-
export { ChatConfig,
|
|
3
|
+
import { ChatClient, ChatConfig, IdentifyParams, IdentifyResult, LoginWithCredentialsParams, LoginWithCredentialsResult, LoginWithSessionParams, ChatAuthMode, Ticket, TicketCreateParams, Message } from '@cstar.help/js/chat';
|
|
4
|
+
export { ChatConfig, IdentifyParams, IdentifyResult, Message, Ticket, TicketCreateParams, TicketListResponse, TypingPayload } from '@cstar.help/js/chat';
|
|
5
5
|
import { LibraryClient, LibraryConfig, Category, LibraryArticle, LibraryArticleListParams } from '@cstar.help/js/library';
|
|
6
6
|
export { Category, LibraryArticle, LibraryArticleListParams, LibraryConfig, LibrarySearchParams, LibrarySearchResult } from '@cstar.help/js/library';
|
|
7
7
|
import { CommunityClient, CommunityConfig, CommunityTopic, CommunityPost, CommunityPostListParams, CommunityPostDetail, CommunitySearchResult } from '@cstar.help/js/community';
|
|
@@ -36,7 +36,7 @@ interface CStarChatProviderProps extends ChatConfig {
|
|
|
36
36
|
* Creates the client on mount and disconnects on unmount.
|
|
37
37
|
*
|
|
38
38
|
* ```tsx
|
|
39
|
-
* <CStarChatProvider teamSlug="acme"
|
|
39
|
+
* <CStarChatProvider teamSlug="acme">
|
|
40
40
|
* <ChatWidget />
|
|
41
41
|
* </CStarChatProvider>
|
|
42
42
|
* ```
|
|
@@ -46,66 +46,99 @@ declare function CStarChatProvider({ children, ...config }: CStarChatProviderPro
|
|
|
46
46
|
interface UseChatReturn {
|
|
47
47
|
/** Identify a customer with HMAC signature. */
|
|
48
48
|
identify: (customer: IdentifyParams, signature: string) => Promise<IdentifyResult>;
|
|
49
|
+
/**
|
|
50
|
+
* Log in with cStar's hosted password auth (no separate auth backend
|
|
51
|
+
* required). Updates `isAuthenticated` and `authMode` to `'session'`.
|
|
52
|
+
*/
|
|
53
|
+
loginWithCredentials: (params: LoginWithCredentialsParams) => Promise<LoginWithCredentialsResult>;
|
|
54
|
+
/**
|
|
55
|
+
* Use an existing Supabase access token (e.g. forwarded from your own
|
|
56
|
+
* auth). Updates `isAuthenticated` and `authMode` to `'session'`.
|
|
57
|
+
*/
|
|
58
|
+
loginWithSession: (params: LoginWithSessionParams) => Promise<void>;
|
|
49
59
|
/** Disconnect the client and clean up all subscriptions. */
|
|
50
60
|
disconnect: () => void;
|
|
51
|
-
/**
|
|
61
|
+
/**
|
|
62
|
+
* `true` once the client has authenticated through any of the four modes
|
|
63
|
+
* (HMAC `identify`, credentials login, session login, or anonymous). Use
|
|
64
|
+
* this for "is the customer signed in?" branches.
|
|
65
|
+
*
|
|
66
|
+
* @deprecated since 0.8.0 — use `isAuthenticated`. Kept as an alias.
|
|
67
|
+
*/
|
|
52
68
|
isIdentified: boolean;
|
|
53
|
-
/**
|
|
69
|
+
/** Same as `isIdentified` — kept under the more accurate name. */
|
|
70
|
+
isAuthenticated: boolean;
|
|
71
|
+
/**
|
|
72
|
+
* The auth mode the underlying ChatClient is using right now. `null`
|
|
73
|
+
* before any auth call has resolved (or after `disconnect()`).
|
|
74
|
+
*/
|
|
75
|
+
authMode: ChatAuthMode | null;
|
|
76
|
+
/** Whether the real-time connection is ready. */
|
|
54
77
|
isRealtimeReady: boolean;
|
|
55
|
-
/** The last error from
|
|
78
|
+
/** The last error from any auth call, or null. */
|
|
56
79
|
error: Error | null;
|
|
57
80
|
}
|
|
58
81
|
/**
|
|
59
|
-
* Core chat hook — manages identity verification
|
|
82
|
+
* Core chat hook — manages identity verification (any of four auth modes)
|
|
83
|
+
* and realtime readiness. Closes F-041 / F-044: previously the hook only
|
|
84
|
+
* tracked HMAC `identify()` and ignored `loginWithCredentials` /
|
|
85
|
+
* `loginWithSession`, leaving consumer UI stuck on the unauthenticated
|
|
86
|
+
* branch even after a successful session login.
|
|
60
87
|
*
|
|
61
88
|
* ```tsx
|
|
62
|
-
* const { identify,
|
|
89
|
+
* const { identify, loginWithCredentials, isAuthenticated, authMode } = useChat();
|
|
63
90
|
*
|
|
64
91
|
* await identify(
|
|
65
92
|
* { externalId: 'usr_123', email: 'jane@co.com', timestamp: Date.now() / 1000 },
|
|
66
93
|
* hmacSignature
|
|
67
94
|
* );
|
|
95
|
+
* // OR
|
|
96
|
+
* await loginWithCredentials({ email: 'jane@co.com', password: 'hunter2' });
|
|
97
|
+
*
|
|
98
|
+
* if (isAuthenticated && authMode === 'session') {
|
|
99
|
+
* // show "Sign out" button
|
|
100
|
+
* }
|
|
68
101
|
* ```
|
|
69
102
|
*/
|
|
70
103
|
declare function useChat(): UseChatReturn;
|
|
71
104
|
|
|
72
|
-
interface
|
|
73
|
-
/** List of
|
|
74
|
-
|
|
105
|
+
interface UseTicketsReturn {
|
|
106
|
+
/** List of tickets for the identified customer. */
|
|
107
|
+
tickets: Ticket[];
|
|
75
108
|
/** Whether the initial fetch is in progress. */
|
|
76
109
|
isLoading: boolean;
|
|
77
110
|
/** The last error, or null. */
|
|
78
111
|
error: Error | null;
|
|
79
|
-
/** Whether there are more
|
|
112
|
+
/** Whether there are more tickets to load. */
|
|
80
113
|
hasMore: boolean;
|
|
81
|
-
/** Re-fetch the
|
|
114
|
+
/** Re-fetch the ticket list. */
|
|
82
115
|
refresh: () => Promise<void>;
|
|
83
|
-
/** Create a new
|
|
84
|
-
create: (params:
|
|
116
|
+
/** Create a new ticket. */
|
|
117
|
+
create: (params: TicketCreateParams) => Promise<Ticket>;
|
|
85
118
|
}
|
|
86
119
|
/**
|
|
87
|
-
* Manage the customer's
|
|
120
|
+
* Manage the customer's ticket list.
|
|
88
121
|
*
|
|
89
122
|
* ```tsx
|
|
90
|
-
* const {
|
|
123
|
+
* const { tickets, isLoading, create, refresh } = useTickets();
|
|
91
124
|
* ```
|
|
92
125
|
*/
|
|
93
|
-
declare function
|
|
126
|
+
declare function useTickets(): UseTicketsReturn;
|
|
94
127
|
|
|
95
128
|
interface UseMessagesReturn {
|
|
96
|
-
/** Messages
|
|
97
|
-
messages:
|
|
129
|
+
/** Messages on the ticket, oldest first. */
|
|
130
|
+
messages: Message[];
|
|
98
131
|
/** Whether the initial fetch is in progress. */
|
|
99
132
|
isLoading: boolean;
|
|
100
133
|
/** The last error, or null. */
|
|
101
134
|
error: Error | null;
|
|
102
135
|
/** Send a message. Optimistically appended, replaced with server response. */
|
|
103
|
-
send: (content: string) => Promise<
|
|
136
|
+
send: (content: string) => Promise<Message>;
|
|
104
137
|
/** Re-fetch messages from the API. */
|
|
105
138
|
refresh: () => Promise<void>;
|
|
106
139
|
}
|
|
107
140
|
/**
|
|
108
|
-
* Manage messages for a single
|
|
141
|
+
* Manage messages for a single ticket with automatic real-time updates.
|
|
109
142
|
*
|
|
110
143
|
* ```tsx
|
|
111
144
|
* const { messages, isLoading, send } = useMessages(ticketId);
|
|
@@ -125,7 +158,7 @@ interface UseTypingReturn {
|
|
|
125
158
|
sendTyping: (isTyping: boolean) => Promise<void>;
|
|
126
159
|
}
|
|
127
160
|
/**
|
|
128
|
-
* Track agent typing indicators for a
|
|
161
|
+
* Track agent typing indicators for a ticket.
|
|
129
162
|
*
|
|
130
163
|
* ```tsx
|
|
131
164
|
* const { typingAgents, sendTyping } = useTyping(ticketId);
|
|
@@ -477,4 +510,4 @@ interface UseGameActivityReturn {
|
|
|
477
510
|
*/
|
|
478
511
|
declare function useGameActivity(): UseGameActivityReturn;
|
|
479
512
|
|
|
480
|
-
export { CStarChatContext, CStarChatProvider, type CStarChatProviderProps, CStarCommunityContext, CStarCommunityProvider, type CStarCommunityProviderProps, CStarDashboardProvider, type CStarDashboardProviderProps, CStarLibraryContext, CStarLibraryProvider, type CStarLibraryProviderProps, type TypingAgent, type UseArticleReturn, type UseArticleSearchReturn, type UseArticlesReturn, type UseBossBattleReturn, type UseCStarEventsReturn, type UseCStarMutationReturn, type UseCStarQueryReturn, type UseCategoriesReturn, type UseChatReturn, type UseCommunitySearchReturn, type
|
|
513
|
+
export { CStarChatContext, CStarChatProvider, type CStarChatProviderProps, CStarCommunityContext, CStarCommunityProvider, type CStarCommunityProviderProps, CStarDashboardProvider, type CStarDashboardProviderProps, CStarLibraryContext, CStarLibraryProvider, type CStarLibraryProviderProps, type TypingAgent, type UseArticleReturn, type UseArticleSearchReturn, type UseArticlesReturn, type UseBossBattleReturn, type UseCStarEventsReturn, type UseCStarMutationReturn, type UseCStarQueryReturn, type UseCategoriesReturn, type UseChatReturn, type UseCommunitySearchReturn, type UseGameActivityReturn, type UseLeaderboardReturn, type UseMessagesReturn, type UsePlayerStatsReturn, type UsePostReturn, type UsePostsReturn, type UseTicketsReturn, type UseTopicsReturn, type UseTypingReturn, useArticle, useArticleSearch, useArticles, useBossBattle, useCStarEvents, useCStarMutation, useCStarQuery, useCategories, useChat, useChatClient, useCommunityClient, useCommunitySearch, useDashboardClient, useGameActivity, useLeaderboard, useLibraryClient, useMessages, usePlayerStats, usePost, usePosts, useTickets, useTopics, useTyping };
|
package/dist/index.js
CHANGED
|
@@ -44,22 +44,29 @@ function CStarChatProvider({ children, ...config }) {
|
|
|
44
44
|
}
|
|
45
45
|
|
|
46
46
|
// src/chat/useChat.ts
|
|
47
|
-
import { useState, useCallback } from "react";
|
|
47
|
+
import { useState, useCallback, useEffect as useEffect2 } from "react";
|
|
48
48
|
function useChat() {
|
|
49
49
|
const client = useChatClient();
|
|
50
|
-
const [
|
|
50
|
+
const [isAuthenticated, setIsAuthenticated] = useState(false);
|
|
51
|
+
const [authMode, setAuthMode] = useState(() => client.getAuthMode());
|
|
51
52
|
const [isRealtimeReady, setIsRealtimeReady] = useState(false);
|
|
52
53
|
const [error, setError] = useState(null);
|
|
54
|
+
useEffect2(() => {
|
|
55
|
+
const current = client.getAuthMode();
|
|
56
|
+
if (current !== authMode) setAuthMode(current);
|
|
57
|
+
}, [client, authMode]);
|
|
58
|
+
const wireRealtime = useCallback(() => {
|
|
59
|
+
client.waitForRealtime().then(() => setIsRealtimeReady(true)).catch(() => {
|
|
60
|
+
});
|
|
61
|
+
}, [client]);
|
|
53
62
|
const identify = useCallback(
|
|
54
63
|
async (customer, signature) => {
|
|
55
64
|
setError(null);
|
|
56
65
|
try {
|
|
57
66
|
const result = await client.identify(customer, signature);
|
|
58
|
-
|
|
59
|
-
client.
|
|
60
|
-
|
|
61
|
-
}).catch(() => {
|
|
62
|
-
});
|
|
67
|
+
setIsAuthenticated(true);
|
|
68
|
+
setAuthMode(client.getAuthMode());
|
|
69
|
+
wireRealtime();
|
|
63
70
|
return result;
|
|
64
71
|
} catch (err) {
|
|
65
72
|
const e = err instanceof Error ? err : new Error(String(err));
|
|
@@ -67,22 +74,66 @@ function useChat() {
|
|
|
67
74
|
throw e;
|
|
68
75
|
}
|
|
69
76
|
},
|
|
70
|
-
[client]
|
|
77
|
+
[client, wireRealtime]
|
|
78
|
+
);
|
|
79
|
+
const loginWithCredentials = useCallback(
|
|
80
|
+
async (params) => {
|
|
81
|
+
setError(null);
|
|
82
|
+
try {
|
|
83
|
+
const result = await client.loginWithCredentials(params);
|
|
84
|
+
setIsAuthenticated(true);
|
|
85
|
+
setAuthMode(client.getAuthMode());
|
|
86
|
+
wireRealtime();
|
|
87
|
+
return result;
|
|
88
|
+
} catch (err) {
|
|
89
|
+
const e = err instanceof Error ? err : new Error(String(err));
|
|
90
|
+
setError(e);
|
|
91
|
+
throw e;
|
|
92
|
+
}
|
|
93
|
+
},
|
|
94
|
+
[client, wireRealtime]
|
|
95
|
+
);
|
|
96
|
+
const loginWithSession = useCallback(
|
|
97
|
+
async (params) => {
|
|
98
|
+
setError(null);
|
|
99
|
+
try {
|
|
100
|
+
await client.loginWithSession(params);
|
|
101
|
+
setIsAuthenticated(true);
|
|
102
|
+
setAuthMode(client.getAuthMode());
|
|
103
|
+
wireRealtime();
|
|
104
|
+
} catch (err) {
|
|
105
|
+
const e = err instanceof Error ? err : new Error(String(err));
|
|
106
|
+
setError(e);
|
|
107
|
+
throw e;
|
|
108
|
+
}
|
|
109
|
+
},
|
|
110
|
+
[client, wireRealtime]
|
|
71
111
|
);
|
|
72
112
|
const disconnect = useCallback(() => {
|
|
73
113
|
client.disconnect();
|
|
74
|
-
|
|
114
|
+
setIsAuthenticated(false);
|
|
115
|
+
setAuthMode(null);
|
|
75
116
|
setIsRealtimeReady(false);
|
|
76
117
|
setError(null);
|
|
77
118
|
}, [client]);
|
|
78
|
-
return {
|
|
119
|
+
return {
|
|
120
|
+
identify,
|
|
121
|
+
loginWithCredentials,
|
|
122
|
+
loginWithSession,
|
|
123
|
+
disconnect,
|
|
124
|
+
isIdentified: isAuthenticated,
|
|
125
|
+
isAuthenticated,
|
|
126
|
+
authMode,
|
|
127
|
+
isRealtimeReady,
|
|
128
|
+
error
|
|
129
|
+
};
|
|
79
130
|
}
|
|
80
131
|
|
|
81
|
-
// src/chat/
|
|
82
|
-
import { useState as useState2, useEffect as
|
|
83
|
-
function
|
|
132
|
+
// src/chat/useTickets.ts
|
|
133
|
+
import { useState as useState2, useEffect as useEffect3, useCallback as useCallback2, useRef as useRef2 } from "react";
|
|
134
|
+
function useTickets() {
|
|
84
135
|
const client = useChatClient();
|
|
85
|
-
const [
|
|
136
|
+
const [tickets, setTickets] = useState2([]);
|
|
86
137
|
const [isLoading, setIsLoading] = useState2(true);
|
|
87
138
|
const [error, setError] = useState2(null);
|
|
88
139
|
const [hasMore, setHasMore] = useState2(false);
|
|
@@ -91,9 +142,9 @@ function useConversations() {
|
|
|
91
142
|
setIsLoading(true);
|
|
92
143
|
setError(null);
|
|
93
144
|
try {
|
|
94
|
-
const result = await client.
|
|
145
|
+
const result = await client.tickets.list();
|
|
95
146
|
if (mountedRef.current) {
|
|
96
|
-
|
|
147
|
+
setTickets(result.tickets);
|
|
97
148
|
setHasMore(result.hasMore);
|
|
98
149
|
}
|
|
99
150
|
} catch (err) {
|
|
@@ -106,7 +157,7 @@ function useConversations() {
|
|
|
106
157
|
}
|
|
107
158
|
}
|
|
108
159
|
}, [client]);
|
|
109
|
-
|
|
160
|
+
useEffect3(() => {
|
|
110
161
|
mountedRef.current = true;
|
|
111
162
|
refresh();
|
|
112
163
|
return () => {
|
|
@@ -115,19 +166,19 @@ function useConversations() {
|
|
|
115
166
|
}, [refresh]);
|
|
116
167
|
const create = useCallback2(
|
|
117
168
|
async (params) => {
|
|
118
|
-
const
|
|
169
|
+
const ticket = await client.tickets.create(params);
|
|
119
170
|
if (mountedRef.current) {
|
|
120
|
-
|
|
171
|
+
setTickets((prev) => [ticket, ...prev]);
|
|
121
172
|
}
|
|
122
|
-
return
|
|
173
|
+
return ticket;
|
|
123
174
|
},
|
|
124
175
|
[client]
|
|
125
176
|
);
|
|
126
|
-
return {
|
|
177
|
+
return { tickets, isLoading, error, hasMore, refresh, create };
|
|
127
178
|
}
|
|
128
179
|
|
|
129
180
|
// src/chat/useMessages.ts
|
|
130
|
-
import { useState as useState3, useEffect as
|
|
181
|
+
import { useState as useState3, useEffect as useEffect4, useCallback as useCallback3, useRef as useRef3 } from "react";
|
|
131
182
|
function useMessages(ticketId) {
|
|
132
183
|
const client = useChatClient();
|
|
133
184
|
const [messages, setMessages] = useState3([]);
|
|
@@ -155,7 +206,7 @@ function useMessages(ticketId) {
|
|
|
155
206
|
}
|
|
156
207
|
}
|
|
157
208
|
}, [client, ticketId]);
|
|
158
|
-
|
|
209
|
+
useEffect4(() => {
|
|
159
210
|
mountedRef.current = true;
|
|
160
211
|
if (!ticketId) {
|
|
161
212
|
setMessages([]);
|
|
@@ -186,7 +237,7 @@ function useMessages(ticketId) {
|
|
|
186
237
|
}, [client, ticketId, refresh]);
|
|
187
238
|
const send = useCallback3(
|
|
188
239
|
async (content) => {
|
|
189
|
-
if (!ticketId) throw new Error("No
|
|
240
|
+
if (!ticketId) throw new Error("No ticket selected");
|
|
190
241
|
const optimistic = {
|
|
191
242
|
id: `optimistic-${Date.now()}`,
|
|
192
243
|
content,
|
|
@@ -213,14 +264,14 @@ function useMessages(ticketId) {
|
|
|
213
264
|
}
|
|
214
265
|
|
|
215
266
|
// src/chat/useTyping.ts
|
|
216
|
-
import { useState as useState4, useEffect as
|
|
267
|
+
import { useState as useState4, useEffect as useEffect5, useCallback as useCallback4, useRef as useRef4 } from "react";
|
|
217
268
|
var TYPING_TIMEOUT = 4e3;
|
|
218
269
|
function useTyping(ticketId) {
|
|
219
270
|
const client = useChatClient();
|
|
220
271
|
const [typingAgents, setTypingAgents] = useState4([]);
|
|
221
272
|
const timersRef = useRef4(/* @__PURE__ */ new Map());
|
|
222
273
|
const mountedRef = useRef4(true);
|
|
223
|
-
|
|
274
|
+
useEffect5(() => {
|
|
224
275
|
mountedRef.current = true;
|
|
225
276
|
if (!ticketId) {
|
|
226
277
|
setTypingAgents([]);
|
|
@@ -280,7 +331,7 @@ function CStarLibraryProvider({ children, ...config }) {
|
|
|
280
331
|
}
|
|
281
332
|
|
|
282
333
|
// src/library/useCategories.ts
|
|
283
|
-
import { useState as useState5, useEffect as
|
|
334
|
+
import { useState as useState5, useEffect as useEffect6, useCallback as useCallback5, useRef as useRef6 } from "react";
|
|
284
335
|
function useCategories() {
|
|
285
336
|
const client = useLibraryClient();
|
|
286
337
|
const [categories, setCategories] = useState5([]);
|
|
@@ -305,7 +356,7 @@ function useCategories() {
|
|
|
305
356
|
}
|
|
306
357
|
}
|
|
307
358
|
}, [client]);
|
|
308
|
-
|
|
359
|
+
useEffect6(() => {
|
|
309
360
|
mountedRef.current = true;
|
|
310
361
|
refresh();
|
|
311
362
|
return () => {
|
|
@@ -316,7 +367,7 @@ function useCategories() {
|
|
|
316
367
|
}
|
|
317
368
|
|
|
318
369
|
// src/library/useArticles.ts
|
|
319
|
-
import { useState as useState6, useEffect as
|
|
370
|
+
import { useState as useState6, useEffect as useEffect7, useCallback as useCallback6, useRef as useRef7 } from "react";
|
|
320
371
|
function useArticles(params) {
|
|
321
372
|
const client = useLibraryClient();
|
|
322
373
|
const [articles, setArticles] = useState6([]);
|
|
@@ -344,7 +395,7 @@ function useArticles(params) {
|
|
|
344
395
|
}
|
|
345
396
|
}
|
|
346
397
|
}, [client, categorySlug, limit, offset]);
|
|
347
|
-
|
|
398
|
+
useEffect7(() => {
|
|
348
399
|
mountedRef.current = true;
|
|
349
400
|
refresh();
|
|
350
401
|
return () => {
|
|
@@ -355,7 +406,7 @@ function useArticles(params) {
|
|
|
355
406
|
}
|
|
356
407
|
|
|
357
408
|
// src/library/useArticle.ts
|
|
358
|
-
import { useState as useState7, useEffect as
|
|
409
|
+
import { useState as useState7, useEffect as useEffect8, useCallback as useCallback7, useRef as useRef8 } from "react";
|
|
359
410
|
function useArticle(slug) {
|
|
360
411
|
const client = useLibraryClient();
|
|
361
412
|
const [article, setArticle] = useState7(null);
|
|
@@ -388,7 +439,7 @@ function useArticle(slug) {
|
|
|
388
439
|
} catch {
|
|
389
440
|
}
|
|
390
441
|
}, [client, slug]);
|
|
391
|
-
|
|
442
|
+
useEffect8(() => {
|
|
392
443
|
mountedRef.current = true;
|
|
393
444
|
if (!slug) {
|
|
394
445
|
setArticle(null);
|
|
@@ -404,7 +455,7 @@ function useArticle(slug) {
|
|
|
404
455
|
}
|
|
405
456
|
|
|
406
457
|
// src/library/useArticleSearch.ts
|
|
407
|
-
import { useState as useState8, useEffect as
|
|
458
|
+
import { useState as useState8, useEffect as useEffect9, useRef as useRef9 } from "react";
|
|
408
459
|
var DEBOUNCE_MS = 300;
|
|
409
460
|
function useArticleSearch(query) {
|
|
410
461
|
const client = useLibraryClient();
|
|
@@ -413,7 +464,7 @@ function useArticleSearch(query) {
|
|
|
413
464
|
const [isLoading, setIsLoading] = useState8(false);
|
|
414
465
|
const [error, setError] = useState8(null);
|
|
415
466
|
const mountedRef = useRef9(true);
|
|
416
|
-
|
|
467
|
+
useEffect9(() => {
|
|
417
468
|
mountedRef.current = true;
|
|
418
469
|
const trimmed = query.trim();
|
|
419
470
|
if (!trimmed) {
|
|
@@ -463,7 +514,7 @@ function CStarCommunityProvider({ children, ...config }) {
|
|
|
463
514
|
}
|
|
464
515
|
|
|
465
516
|
// src/community/useTopics.ts
|
|
466
|
-
import { useState as useState9, useEffect as
|
|
517
|
+
import { useState as useState9, useEffect as useEffect10, useCallback as useCallback8, useRef as useRef11 } from "react";
|
|
467
518
|
function useTopics() {
|
|
468
519
|
const client = useCommunityClient();
|
|
469
520
|
const [topics, setTopics] = useState9([]);
|
|
@@ -488,7 +539,7 @@ function useTopics() {
|
|
|
488
539
|
}
|
|
489
540
|
}
|
|
490
541
|
}, [client]);
|
|
491
|
-
|
|
542
|
+
useEffect10(() => {
|
|
492
543
|
mountedRef.current = true;
|
|
493
544
|
refresh();
|
|
494
545
|
return () => {
|
|
@@ -499,7 +550,7 @@ function useTopics() {
|
|
|
499
550
|
}
|
|
500
551
|
|
|
501
552
|
// src/community/usePosts.ts
|
|
502
|
-
import { useState as useState10, useEffect as
|
|
553
|
+
import { useState as useState10, useEffect as useEffect11, useCallback as useCallback9, useRef as useRef12 } from "react";
|
|
503
554
|
function usePosts(params) {
|
|
504
555
|
const client = useCommunityClient();
|
|
505
556
|
const [posts, setPosts] = useState10([]);
|
|
@@ -531,7 +582,7 @@ function usePosts(params) {
|
|
|
531
582
|
}
|
|
532
583
|
}
|
|
533
584
|
}, [client, topicSlug, status, sort, limit, offset]);
|
|
534
|
-
|
|
585
|
+
useEffect11(() => {
|
|
535
586
|
mountedRef.current = true;
|
|
536
587
|
refresh();
|
|
537
588
|
return () => {
|
|
@@ -542,7 +593,7 @@ function usePosts(params) {
|
|
|
542
593
|
}
|
|
543
594
|
|
|
544
595
|
// src/community/usePost.ts
|
|
545
|
-
import { useState as useState11, useEffect as
|
|
596
|
+
import { useState as useState11, useEffect as useEffect12, useCallback as useCallback10, useRef as useRef13 } from "react";
|
|
546
597
|
function usePost(slug) {
|
|
547
598
|
const client = useCommunityClient();
|
|
548
599
|
const [data, setData] = useState11(null);
|
|
@@ -567,7 +618,7 @@ function usePost(slug) {
|
|
|
567
618
|
}
|
|
568
619
|
}
|
|
569
620
|
}, [client, slug]);
|
|
570
|
-
|
|
621
|
+
useEffect12(() => {
|
|
571
622
|
mountedRef.current = true;
|
|
572
623
|
refresh();
|
|
573
624
|
return () => {
|
|
@@ -578,14 +629,14 @@ function usePost(slug) {
|
|
|
578
629
|
}
|
|
579
630
|
|
|
580
631
|
// src/community/useCommunitySearch.ts
|
|
581
|
-
import { useState as useState12, useEffect as
|
|
632
|
+
import { useState as useState12, useEffect as useEffect13, useCallback as useCallback11, useRef as useRef14 } from "react";
|
|
582
633
|
function useCommunitySearch() {
|
|
583
634
|
const client = useCommunityClient();
|
|
584
635
|
const [results, setResults] = useState12(null);
|
|
585
636
|
const [isLoading, setIsLoading] = useState12(false);
|
|
586
637
|
const [error, setError] = useState12(null);
|
|
587
638
|
const mountedRef = useRef14(true);
|
|
588
|
-
|
|
639
|
+
useEffect13(() => {
|
|
589
640
|
mountedRef.current = true;
|
|
590
641
|
return () => {
|
|
591
642
|
mountedRef.current = false;
|
|
@@ -620,14 +671,19 @@ function useCommunitySearch() {
|
|
|
620
671
|
}
|
|
621
672
|
|
|
622
673
|
// src/dashboard/CStarDashboardProvider.tsx
|
|
623
|
-
import { createContext as createContext2, useContext as useContext2, useEffect as
|
|
674
|
+
import { createContext as createContext2, useContext as useContext2, useEffect as useEffect14, useRef as useRef15 } from "react";
|
|
624
675
|
import { jsx as jsx4 } from "react/jsx-runtime";
|
|
625
676
|
var CStarDashboardContext = createContext2(null);
|
|
626
677
|
function CStarDashboardProvider({ client, children }) {
|
|
678
|
+
if (!client) {
|
|
679
|
+
throw new Error(
|
|
680
|
+
"CStarDashboardProvider requires a `client` prop. Build it server-side with `new CStarClient({ apiKey: process.env.CSTAR_API_KEY, teamId })` and pass via SSR. See https://cstar.help/developers/sdk/react#dashboard"
|
|
681
|
+
);
|
|
682
|
+
}
|
|
627
683
|
const contextValue = useRef15({ client }).current;
|
|
628
|
-
|
|
684
|
+
useEffect14(() => {
|
|
629
685
|
return () => {
|
|
630
|
-
client
|
|
686
|
+
client?.realtime?.disconnect?.();
|
|
631
687
|
};
|
|
632
688
|
}, [client]);
|
|
633
689
|
return /* @__PURE__ */ jsx4(CStarDashboardContext.Provider, { value: contextValue, children });
|
|
@@ -641,7 +697,7 @@ function useDashboardClient() {
|
|
|
641
697
|
}
|
|
642
698
|
|
|
643
699
|
// src/dashboard/useCStarQuery.ts
|
|
644
|
-
import { useState as useState13, useEffect as
|
|
700
|
+
import { useState as useState13, useEffect as useEffect15, useRef as useRef16, useCallback as useCallback12 } from "react";
|
|
645
701
|
function resolveResource(client, path) {
|
|
646
702
|
const parts = path.split(".");
|
|
647
703
|
if (parts.length < 2 || parts[1] !== "list") return null;
|
|
@@ -659,7 +715,7 @@ function useCStarQuery(resource, params) {
|
|
|
659
715
|
const [error, setError] = useState13(null);
|
|
660
716
|
const subscriptionRef = useRef16(null);
|
|
661
717
|
const paramsKey = params ? JSON.stringify(params) : "";
|
|
662
|
-
|
|
718
|
+
useEffect15(() => {
|
|
663
719
|
const resolved = resolveResource(client, resource);
|
|
664
720
|
if (!resolved) {
|
|
665
721
|
setError(new Error(`Invalid resource path: ${resource}. Expected format: 'tickets.list'`));
|
|
@@ -699,7 +755,8 @@ function resolveMutation(client, path) {
|
|
|
699
755
|
const methodName = parts[1];
|
|
700
756
|
const resource = client[resourceName];
|
|
701
757
|
if (!resource || typeof resource !== "object") return null;
|
|
702
|
-
const
|
|
758
|
+
const lookupName = methodName === "delete" ? "del" : methodName;
|
|
759
|
+
const method = resource[lookupName];
|
|
703
760
|
if (typeof method !== "function") return null;
|
|
704
761
|
if (methodName === "update") {
|
|
705
762
|
return (params) => {
|
|
@@ -745,14 +802,14 @@ function useCStarMutation(resource) {
|
|
|
745
802
|
}
|
|
746
803
|
|
|
747
804
|
// src/dashboard/useCStarEvents.ts
|
|
748
|
-
import { useState as useState15, useEffect as
|
|
805
|
+
import { useState as useState15, useEffect as useEffect16 } from "react";
|
|
749
806
|
var MAX_EVENTS = 100;
|
|
750
807
|
function useCStarEvents(types) {
|
|
751
808
|
const client = useDashboardClient();
|
|
752
809
|
const [events, setEvents] = useState15([]);
|
|
753
810
|
const [connected, setConnected] = useState15(false);
|
|
754
811
|
const typesKey = types ? types.join(",") : "";
|
|
755
|
-
|
|
812
|
+
useEffect16(() => {
|
|
756
813
|
const realtime = client.realtime;
|
|
757
814
|
const handler = (event) => {
|
|
758
815
|
if (types && types.length > 0) {
|
|
@@ -784,14 +841,14 @@ function useCStarEvents(types) {
|
|
|
784
841
|
}
|
|
785
842
|
|
|
786
843
|
// src/dashboard/useBossBattle.ts
|
|
787
|
-
import { useState as useState16, useEffect as
|
|
844
|
+
import { useState as useState16, useEffect as useEffect17, useRef as useRef17, useCallback as useCallback14 } from "react";
|
|
788
845
|
function useBossBattle() {
|
|
789
846
|
const client = useDashboardClient();
|
|
790
847
|
const [boss, setBoss] = useState16(null);
|
|
791
848
|
const [loading, setLoading] = useState16(true);
|
|
792
849
|
const [error, setError] = useState16(null);
|
|
793
850
|
const subRef = useRef17(null);
|
|
794
|
-
|
|
851
|
+
useEffect17(() => {
|
|
795
852
|
const sub = client.game.subscribeBoss(client.realtime);
|
|
796
853
|
subRef.current = sub;
|
|
797
854
|
sub.on("change", (data) => {
|
|
@@ -815,14 +872,14 @@ function useBossBattle() {
|
|
|
815
872
|
}
|
|
816
873
|
|
|
817
874
|
// src/dashboard/usePlayerStats.ts
|
|
818
|
-
import { useState as useState17, useEffect as
|
|
875
|
+
import { useState as useState17, useEffect as useEffect18, useRef as useRef18, useCallback as useCallback15 } from "react";
|
|
819
876
|
function usePlayerStats(memberId) {
|
|
820
877
|
const client = useDashboardClient();
|
|
821
878
|
const [player, setPlayer] = useState17(null);
|
|
822
879
|
const [loading, setLoading] = useState17(true);
|
|
823
880
|
const [error, setError] = useState17(null);
|
|
824
881
|
const subRef = useRef18(null);
|
|
825
|
-
|
|
882
|
+
useEffect18(() => {
|
|
826
883
|
const sub = client.game.subscribePlayer(client.realtime, memberId);
|
|
827
884
|
subRef.current = sub;
|
|
828
885
|
sub.on("change", (data) => {
|
|
@@ -846,14 +903,14 @@ function usePlayerStats(memberId) {
|
|
|
846
903
|
}
|
|
847
904
|
|
|
848
905
|
// src/dashboard/useLeaderboard.ts
|
|
849
|
-
import { useState as useState18, useEffect as
|
|
906
|
+
import { useState as useState18, useEffect as useEffect19, useRef as useRef19, useCallback as useCallback16 } from "react";
|
|
850
907
|
function useLeaderboard(period) {
|
|
851
908
|
const client = useDashboardClient();
|
|
852
909
|
const [entries, setEntries] = useState18([]);
|
|
853
910
|
const [loading, setLoading] = useState18(true);
|
|
854
911
|
const [error, setError] = useState18(null);
|
|
855
912
|
const subRef = useRef19(null);
|
|
856
|
-
|
|
913
|
+
useEffect19(() => {
|
|
857
914
|
const sub = client.game.subscribeLeaderboard(client.realtime, period ? { period } : void 0);
|
|
858
915
|
subRef.current = sub;
|
|
859
916
|
sub.on("change", (data) => {
|
|
@@ -877,14 +934,14 @@ function useLeaderboard(period) {
|
|
|
877
934
|
}
|
|
878
935
|
|
|
879
936
|
// src/dashboard/useGameActivity.ts
|
|
880
|
-
import { useState as useState19, useEffect as
|
|
937
|
+
import { useState as useState19, useEffect as useEffect20, useRef as useRef20, useCallback as useCallback17 } from "react";
|
|
881
938
|
function useGameActivity() {
|
|
882
939
|
const client = useDashboardClient();
|
|
883
940
|
const [events, setEvents] = useState19([]);
|
|
884
941
|
const [loading, setLoading] = useState19(true);
|
|
885
942
|
const [error, setError] = useState19(null);
|
|
886
943
|
const subRef = useRef20(null);
|
|
887
|
-
|
|
944
|
+
useEffect20(() => {
|
|
888
945
|
const sub = client.game.subscribeActivity(client.realtime);
|
|
889
946
|
subRef.current = sub;
|
|
890
947
|
sub.on("change", (data) => {
|
|
@@ -926,7 +983,6 @@ export {
|
|
|
926
983
|
useChatClient,
|
|
927
984
|
useCommunityClient,
|
|
928
985
|
useCommunitySearch,
|
|
929
|
-
useConversations,
|
|
930
986
|
useDashboardClient,
|
|
931
987
|
useGameActivity,
|
|
932
988
|
useLeaderboard,
|
|
@@ -935,6 +991,7 @@ export {
|
|
|
935
991
|
usePlayerStats,
|
|
936
992
|
usePost,
|
|
937
993
|
usePosts,
|
|
994
|
+
useTickets,
|
|
938
995
|
useTopics,
|
|
939
996
|
useTyping
|
|
940
997
|
};
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@cstar.help/react",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.8.0",
|
|
4
4
|
"description": "React hooks for the cStar customer support platform",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./dist/index.cjs",
|
|
@@ -30,7 +30,7 @@
|
|
|
30
30
|
},
|
|
31
31
|
"peerDependencies": {
|
|
32
32
|
"react": ">=18.0.0",
|
|
33
|
-
"@cstar.help/js": ">=0.
|
|
33
|
+
"@cstar.help/js": ">=0.11.0"
|
|
34
34
|
},
|
|
35
35
|
"devDependencies": {
|
|
36
36
|
"react": "^18.3.1",
|