@anakin824/prdg-chat-ui 0.1.0 → 0.2.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/dist/index.d.mts CHANGED
@@ -134,10 +134,16 @@ type ChatProviderProps = {
134
134
  apiUrl: string;
135
135
  /** Current bearer token (HDS JWT in integrated mode, prdg-chat JWT in standalone). */
136
136
  token: string;
137
- /** prdg-chat user UUID — identifies the current user for own-message display, mentions, etc. */
138
- userId: string;
139
- /** Internal prdg-chat tenant UUID (JWT / API). */
140
- tenantId: string;
137
+ /**
138
+ * prdg-chat user UUID — identifies the current user for own-message display, mentions, etc.
139
+ * When omitted, ChatProvider calls GET /me with the supplied token to resolve it automatically.
140
+ */
141
+ userId?: string;
142
+ /**
143
+ * Internal prdg-chat tenant UUID (JWT / API).
144
+ * When omitted, resolved automatically via GET /me.
145
+ */
146
+ tenantId?: string;
141
147
  /**
142
148
  * Conduitly `tenant_id` for NATS (`chat.{conduitly_tenant_id}.user.*`). Set via `conduitly_tenant_id` in dev.json or `NEXT_PUBLIC_CONDUITLY_TENANT_ID`; do not rely on internal prdg-chat tenant UUID.
143
149
  */
@@ -165,7 +171,7 @@ type ChatProviderProps = {
165
171
  natsToken?: string;
166
172
  children: ReactNode;
167
173
  };
168
- declare function ChatProvider({ apiUrl, token, userId, tenantId, conduitlyTenantId, theme, pollIntervalMs, onUnreadChange: _onUnreadChange, onTokenRefresh, callEnabled, natsWsUrl, natsToken, children, }: ChatProviderProps): react.JSX.Element;
174
+ declare function ChatProvider({ apiUrl, token, userId: userIdProp, tenantId: tenantIdProp, conduitlyTenantId: conduitlyTenantIdProp, theme, pollIntervalMs, onUnreadChange: _onUnreadChange, onTokenRefresh, callEnabled, natsWsUrl, natsToken, children, }: ChatProviderProps): react.JSX.Element | null;
169
175
 
170
176
  type ListConversationsRes = {
171
177
  items: Conversation[];
@@ -210,6 +216,9 @@ declare class ChatAPI {
210
216
  onAuthError?: (() => Promise<string | null>) | undefined);
211
217
  private headers;
212
218
  private json;
219
+ getMe(): Promise<AppUser & {
220
+ conduitly_tenant_id?: string;
221
+ }>;
213
222
  listConversations(cursor?: string, limit?: number): Promise<ListConversationsRes>;
214
223
  listMessages(conversationId: string, cursor?: string, limit?: number): Promise<ListMessagesRes>;
215
224
  findOrCreateDirect(peerUserId: string): Promise<Conversation>;
package/dist/index.d.ts CHANGED
@@ -134,10 +134,16 @@ type ChatProviderProps = {
134
134
  apiUrl: string;
135
135
  /** Current bearer token (HDS JWT in integrated mode, prdg-chat JWT in standalone). */
136
136
  token: string;
137
- /** prdg-chat user UUID — identifies the current user for own-message display, mentions, etc. */
138
- userId: string;
139
- /** Internal prdg-chat tenant UUID (JWT / API). */
140
- tenantId: string;
137
+ /**
138
+ * prdg-chat user UUID — identifies the current user for own-message display, mentions, etc.
139
+ * When omitted, ChatProvider calls GET /me with the supplied token to resolve it automatically.
140
+ */
141
+ userId?: string;
142
+ /**
143
+ * Internal prdg-chat tenant UUID (JWT / API).
144
+ * When omitted, resolved automatically via GET /me.
145
+ */
146
+ tenantId?: string;
141
147
  /**
142
148
  * Conduitly `tenant_id` for NATS (`chat.{conduitly_tenant_id}.user.*`). Set via `conduitly_tenant_id` in dev.json or `NEXT_PUBLIC_CONDUITLY_TENANT_ID`; do not rely on internal prdg-chat tenant UUID.
143
149
  */
@@ -165,7 +171,7 @@ type ChatProviderProps = {
165
171
  natsToken?: string;
166
172
  children: ReactNode;
167
173
  };
168
- declare function ChatProvider({ apiUrl, token, userId, tenantId, conduitlyTenantId, theme, pollIntervalMs, onUnreadChange: _onUnreadChange, onTokenRefresh, callEnabled, natsWsUrl, natsToken, children, }: ChatProviderProps): react.JSX.Element;
174
+ declare function ChatProvider({ apiUrl, token, userId: userIdProp, tenantId: tenantIdProp, conduitlyTenantId: conduitlyTenantIdProp, theme, pollIntervalMs, onUnreadChange: _onUnreadChange, onTokenRefresh, callEnabled, natsWsUrl, natsToken, children, }: ChatProviderProps): react.JSX.Element | null;
169
175
 
170
176
  type ListConversationsRes = {
171
177
  items: Conversation[];
@@ -210,6 +216,9 @@ declare class ChatAPI {
210
216
  onAuthError?: (() => Promise<string | null>) | undefined);
211
217
  private headers;
212
218
  private json;
219
+ getMe(): Promise<AppUser & {
220
+ conduitly_tenant_id?: string;
221
+ }>;
213
222
  listConversations(cursor?: string, limit?: number): Promise<ListConversationsRes>;
214
223
  listMessages(conversationId: string, cursor?: string, limit?: number): Promise<ListMessagesRes>;
215
224
  findOrCreateDirect(peerUserId: string): Promise<Conversation>;
package/dist/index.js CHANGED
@@ -51,6 +51,9 @@ var ChatAPI = class {
51
51
  }
52
52
  return res.json();
53
53
  }
54
+ getMe() {
55
+ return this.json("/me");
56
+ }
54
57
  listConversations(cursor, limit = 50) {
55
58
  const q = new URLSearchParams();
56
59
  if (cursor) q.set("cursor", cursor);
@@ -324,9 +327,9 @@ var defaultTheme = {
324
327
  function ChatProvider({
325
328
  apiUrl,
326
329
  token,
327
- userId,
328
- tenantId,
329
- conduitlyTenantId,
330
+ userId: userIdProp,
331
+ tenantId: tenantIdProp,
332
+ conduitlyTenantId: conduitlyTenantIdProp,
330
333
  theme,
331
334
  pollIntervalMs = 3e4,
332
335
  onUnreadChange: _onUnreadChange,
@@ -358,6 +361,35 @@ function ChatProvider({
358
361
  () => new ChatAPI(apiUrl.replace(/\/$/, ""), () => tokenRef.current, handleAuthError),
359
362
  [apiUrl, handleAuthError]
360
363
  );
364
+ const [resolvedUserId, setResolvedUserId] = react.useState(userIdProp ?? null);
365
+ const [resolvedTenantId, setResolvedTenantId] = react.useState(tenantIdProp ?? null);
366
+ const [resolvedConduitlyTenantId, setResolvedConduitlyTenantId] = react.useState(
367
+ conduitlyTenantIdProp
368
+ );
369
+ const [meError, setMeError] = react.useState(null);
370
+ react.useEffect(() => {
371
+ setMeError(null);
372
+ if (userIdProp) setResolvedUserId(userIdProp);
373
+ if (tenantIdProp) setResolvedTenantId(tenantIdProp);
374
+ if (conduitlyTenantIdProp) setResolvedConduitlyTenantId(conduitlyTenantIdProp);
375
+ if (userIdProp && tenantIdProp) return;
376
+ let cancelled = false;
377
+ api.getMe().then((me) => {
378
+ if (cancelled) return;
379
+ if (!userIdProp) setResolvedUserId(me.id);
380
+ if (!tenantIdProp) setResolvedTenantId(me.tenant_id);
381
+ if (!conduitlyTenantIdProp && me.conduitly_tenant_id) {
382
+ setResolvedConduitlyTenantId(me.conduitly_tenant_id);
383
+ }
384
+ }).catch((err) => {
385
+ if (!cancelled) setMeError(err instanceof Error ? err.message : String(err));
386
+ });
387
+ return () => {
388
+ cancelled = true;
389
+ };
390
+ }, [api, token, userIdProp, tenantIdProp, conduitlyTenantIdProp]);
391
+ const userId = resolvedUserId ?? "";
392
+ const tenantId = resolvedTenantId ?? "";
361
393
  const mergedTheme = react.useMemo(() => ({ ...defaultTheme, ...theme }), [theme]);
362
394
  const styleTag = react.useMemo(() => {
363
395
  const t = mergedTheme;
@@ -379,7 +411,7 @@ function ChatProvider({
379
411
  const natsUrl = natsWsUrl?.trim() ?? "";
380
412
  const wsConnected = Boolean(natsUrl) && natsConnected;
381
413
  const natsTenantId = react.useMemo(() => {
382
- const c = conduitlyTenantId?.trim();
414
+ const c = resolvedConduitlyTenantId?.trim();
383
415
  if (c) return c;
384
416
  if (process.env.NODE_ENV === "development" && natsUrl) {
385
417
  console.warn(
@@ -387,7 +419,7 @@ function ChatProvider({
387
419
  );
388
420
  }
389
421
  return tenantId.trim();
390
- }, [conduitlyTenantId, tenantId, natsUrl]);
422
+ }, [resolvedConduitlyTenantId, tenantId, natsUrl]);
391
423
  const typingByConversation = react.useMemo(() => ({}), []);
392
424
  const sendTyping = react.useCallback((_conversationId) => {
393
425
  }, []);
@@ -443,6 +475,12 @@ function ChatProvider({
443
475
  flexDirection: "column",
444
476
  boxSizing: "border-box"
445
477
  };
478
+ if (!resolvedUserId || !resolvedTenantId) {
479
+ if (meError) {
480
+ return /* @__PURE__ */ React.createElement("div", { style: { padding: 16, fontFamily: "system-ui, sans-serif", color: "#b91c1c", fontSize: 13 } }, "Chat failed to load: ", meError);
481
+ }
482
+ return null;
483
+ }
446
484
  return /* @__PURE__ */ React.createElement(reactQuery.QueryClientProvider, { client: queryClient }, /* @__PURE__ */ React.createElement(ChatContext.Provider, { value }, /* @__PURE__ */ React.createElement("div", { style: layoutStyle }, natsUrl ? /* @__PURE__ */ React.createElement(ChatNatsBridge, { natsWsUrl: natsUrl, natsToken, onConnectedChange: setNatsConnected }) : null, /* @__PURE__ */ React.createElement("style", { dangerouslySetInnerHTML: { __html: styleTag } }), /* @__PURE__ */ React.createElement("div", { "data-chat-root": true, style: { ...layoutStyle, flex: 1 } }, children))));
447
485
  }
448
486
  function useChatActions() {