@axiom-lattice/react-sdk 2.1.91 → 2.1.93

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
@@ -726,6 +726,8 @@ interface PersonalAssistantInfo {
726
726
  assistantId: string;
727
727
  projectId: string;
728
728
  workspaceId: string;
729
+ /** tenantId for debugging cross-tenant leakage */
730
+ tenantId?: string | null;
729
731
  }
730
732
  interface AuthContextValue {
731
733
  user: User | null;
package/dist/index.d.ts CHANGED
@@ -726,6 +726,8 @@ interface PersonalAssistantInfo {
726
726
  assistantId: string;
727
727
  projectId: string;
728
728
  workspaceId: string;
729
+ /** tenantId for debugging cross-tenant leakage */
730
+ tenantId?: string | null;
729
731
  }
730
732
  interface AuthContextValue {
731
733
  user: User | null;
package/dist/index.js CHANGED
@@ -164,18 +164,24 @@ var AuthProvider = ({
164
164
  const [personalAssistant, setPersonalAssistant] = (0, import_react.useState)(null);
165
165
  const [isLoading, setIsLoading] = (0, import_react.useState)(false);
166
166
  const [error, setError] = (0, import_react.useState)(null);
167
+ const getPAKey = (tenantId) => tenantId ? `lattice_personal_assistant_${tenantId}` : "lattice_personal_assistant";
168
+ const currentTenantRef = (0, import_react.useRef)(currentTenant);
169
+ currentTenantRef.current = currentTenant;
167
170
  (0, import_react.useEffect)(() => {
168
171
  const storedUser = sessionStorage.getItem("lattice_user");
169
172
  const storedTenants = sessionStorage.getItem("lattice_tenants");
170
173
  const storedCurrentTenant = sessionStorage.getItem("lattice_current_tenant");
171
- const storedPA = sessionStorage.getItem("lattice_personal_assistant");
172
174
  if (storedUser) {
173
175
  try {
174
176
  const userData = JSON.parse(storedUser);
175
177
  setUser(userData);
176
178
  if (storedTenants) setTenants(JSON.parse(storedTenants));
177
- if (storedCurrentTenant) setCurrentTenant(JSON.parse(storedCurrentTenant));
178
- if (storedPA) setPersonalAssistant(JSON.parse(storedPA));
179
+ if (storedCurrentTenant) {
180
+ const ct = JSON.parse(storedCurrentTenant);
181
+ setCurrentTenant(ct);
182
+ const storedPA = sessionStorage.getItem(getPAKey(ct.id));
183
+ if (storedPA) setPersonalAssistant(JSON.parse(storedPA));
184
+ }
179
185
  } catch {
180
186
  sessionStorage.removeItem("lattice_user");
181
187
  sessionStorage.removeItem("lattice_tenants");
@@ -281,13 +287,18 @@ var AuthProvider = ({
281
287
  }
282
288
  const result = await response.json();
283
289
  const tenantData = result.data.tenant;
290
+ const oldTenantId = currentTenantRef.current?.id;
291
+ if (oldTenantId) {
292
+ sessionStorage.removeItem(getPAKey(oldTenantId));
293
+ }
284
294
  setCurrentTenant(tenantData);
285
295
  sessionStorage.setItem("lattice_current_tenant", JSON.stringify(tenantData));
286
296
  setPersonalAssistant(result.data.personalAssistant || null);
287
297
  if (result.data.personalAssistant) {
288
- sessionStorage.setItem("lattice_personal_assistant", JSON.stringify(result.data.personalAssistant));
298
+ const paWithTenant = { ...result.data.personalAssistant, tenantId: tenantData.id };
299
+ sessionStorage.setItem(getPAKey(tenantData.id), JSON.stringify(paWithTenant));
289
300
  } else {
290
- sessionStorage.removeItem("lattice_personal_assistant");
301
+ sessionStorage.removeItem(getPAKey(tenantData.id));
291
302
  }
292
303
  if (result.data.token) {
293
304
  sessionStorage.setItem("lattice_token", result.data.token);
@@ -411,9 +422,14 @@ var AuthProvider = ({
411
422
  }, [baseURL]);
412
423
  const wrappedSetPersonalAssistant = (0, import_react.useCallback)((info) => {
413
424
  setPersonalAssistant(info);
425
+ const tenantId = currentTenantRef.current?.id;
414
426
  if (info) {
415
- sessionStorage.setItem("lattice_personal_assistant", JSON.stringify(info));
427
+ const paWithTenant = { ...info, tenantId: tenantId || info.tenantId };
428
+ sessionStorage.setItem(getPAKey(tenantId), JSON.stringify(paWithTenant));
416
429
  } else {
430
+ if (tenantId) {
431
+ sessionStorage.removeItem(getPAKey(tenantId));
432
+ }
417
433
  sessionStorage.removeItem("lattice_personal_assistant");
418
434
  }
419
435
  }, []);
@@ -30892,25 +30908,30 @@ var PersonalAssistantChannelModal = ({
30892
30908
  const [qrLoading, setQrLoading] = (0, import_react101.useState)(false);
30893
30909
  const [qrCodeUrl, setQrCodeUrl] = (0, import_react101.useState)(null);
30894
30910
  const [qrStatus, setQrStatus] = (0, import_react101.useState)("idle");
30911
+ const [qrCountdown, setQrCountdown] = (0, import_react101.useState)(0);
30895
30912
  const qrCodeRef = (0, import_react101.useRef)(null);
30896
- const qrPollRef = (0, import_react101.useRef)(null);
30897
- const clearQrPoll = (0, import_react101.useCallback)(() => {
30898
- if (qrPollRef.current) {
30899
- clearInterval(qrPollRef.current);
30900
- qrPollRef.current = null;
30913
+ const qrCountdownRef = (0, import_react101.useRef)(null);
30914
+ const clearQrCountdown = (0, import_react101.useCallback)(() => {
30915
+ if (qrCountdownRef.current) {
30916
+ clearInterval(qrCountdownRef.current);
30917
+ qrCountdownRef.current = null;
30901
30918
  }
30902
30919
  }, []);
30903
30920
  const resetQrState = (0, import_react101.useCallback)(() => {
30904
- clearQrPoll();
30921
+ clearQrCountdown();
30905
30922
  setQrLoading(false);
30906
30923
  setQrCodeUrl(null);
30907
30924
  setQrStatus("idle");
30925
+ setQrCountdown(0);
30908
30926
  qrCodeRef.current = null;
30909
- }, [clearQrPoll]);
30927
+ }, [clearQrCountdown]);
30928
+ const QR_EXPIRY_SECONDS = 300;
30910
30929
  const fetchQrCode = (0, import_react101.useCallback)(async () => {
30911
30930
  setQrLoading(true);
30912
30931
  setQrStatus("loading");
30913
30932
  setQrCodeUrl(null);
30933
+ clearQrCountdown();
30934
+ setQrCountdown(0);
30914
30935
  try {
30915
30936
  const res = await get(
30916
30937
  "/api/channels/wechat/setup/qrcode"
@@ -30919,32 +30940,17 @@ var PersonalAssistantChannelModal = ({
30919
30940
  qrCodeRef.current = res.data.qrcode;
30920
30941
  setQrCodeUrl(res.data.qrcodeImgUrl);
30921
30942
  setQrStatus("wait");
30922
- clearQrPoll();
30923
- qrPollRef.current = setInterval(async () => {
30924
- try {
30925
- const statusRes = await get(`/api/channels/wechat/setup/status?qrcode=${encodeURIComponent(qrCodeRef.current)}`);
30926
- if (statusRes.success && statusRes.data) {
30927
- const s = statusRes.data.status;
30928
- if (s === "confirmed" && statusRes.data.botToken) {
30929
- setQrStatus("confirmed");
30930
- clearQrPoll();
30931
- form.setFieldsValue({
30932
- botToken: statusRes.data.botToken,
30933
- uin: statusRes.data.uin
30934
- });
30935
- import_antd90.message.success("WeChat login confirmed!");
30936
- } else if (s === "expired") {
30937
- setQrStatus("expired");
30938
- clearQrPoll();
30939
- } else if (s === "scaned") {
30940
- setQrStatus("scaned");
30941
- } else if (s === "wait") {
30942
- setQrStatus("wait");
30943
- }
30943
+ setQrCountdown(QR_EXPIRY_SECONDS);
30944
+ qrCountdownRef.current = setInterval(() => {
30945
+ setQrCountdown((prev) => {
30946
+ if (prev <= 1) {
30947
+ clearQrCountdown();
30948
+ setQrStatus("expired");
30949
+ return 0;
30944
30950
  }
30945
- } catch {
30946
- }
30947
- }, 2e3);
30951
+ return prev - 1;
30952
+ });
30953
+ }, 1e3);
30948
30954
  } else {
30949
30955
  setQrStatus("error");
30950
30956
  import_antd90.message.error("Failed to get QR code");
@@ -30955,10 +30961,36 @@ var PersonalAssistantChannelModal = ({
30955
30961
  } finally {
30956
30962
  setQrLoading(false);
30957
30963
  }
30958
- }, [get, clearQrPoll, form]);
30964
+ }, [get, clearQrCountdown]);
30965
+ const checkQrStatus = (0, import_react101.useCallback)(async () => {
30966
+ if (!qrCodeRef.current) return;
30967
+ try {
30968
+ const statusRes = await get(`/api/channels/wechat/setup/status?qrcode=${encodeURIComponent(qrCodeRef.current)}`);
30969
+ if (statusRes.success && statusRes.data) {
30970
+ const s = statusRes.data.status;
30971
+ if (s === "confirmed" && statusRes.data.botToken) {
30972
+ setQrStatus("confirmed");
30973
+ clearQrCountdown();
30974
+ form.setFieldsValue({
30975
+ botToken: statusRes.data.botToken,
30976
+ uin: statusRes.data.uin
30977
+ });
30978
+ import_antd90.message.success("WeChat login confirmed!");
30979
+ } else if (s === "expired") {
30980
+ setQrStatus("expired");
30981
+ clearQrCountdown();
30982
+ setQrCountdown(0);
30983
+ } else if (s === "scaned") {
30984
+ setQrStatus("scaned");
30985
+ }
30986
+ }
30987
+ } catch {
30988
+ import_antd90.message.error("Failed to check QR status");
30989
+ }
30990
+ }, [get, clearQrCountdown, form]);
30959
30991
  (0, import_react101.useEffect)(() => {
30960
30992
  return () => {
30961
- if (qrPollRef.current) clearInterval(qrPollRef.current);
30993
+ if (qrCountdownRef.current) clearInterval(qrCountdownRef.current);
30962
30994
  };
30963
30995
  }, []);
30964
30996
  const loadInstallations = (0, import_react101.useCallback)(async () => {
@@ -31336,7 +31368,7 @@ var PersonalAssistantChannelModal = ({
31336
31368
  /* @__PURE__ */ (0, import_jsx_runtime118.jsx)(import_antd90.Spin, {}),
31337
31369
  /* @__PURE__ */ (0, import_jsx_runtime118.jsx)(Text48, { type: "secondary", style: { display: "block", marginTop: 8, fontSize: 12 }, children: "Generating QR code..." })
31338
31370
  ] }),
31339
- (qrStatus === "wait" || qrStatus === "scaned") && qrCodeUrl && /* @__PURE__ */ (0, import_jsx_runtime118.jsxs)("div", { children: [
31371
+ (qrStatus === "wait" || qrStatus === "scaned") && qrCodeUrl && /* @__PURE__ */ (0, import_jsx_runtime118.jsxs)("div", { style: { display: "flex", flexDirection: "column", alignItems: "center" }, children: [
31340
31372
  /* @__PURE__ */ (0, import_jsx_runtime118.jsx)(import_antd90.QRCode, { value: qrCodeUrl, size: 180 }),
31341
31373
  /* @__PURE__ */ (0, import_jsx_runtime118.jsx)(
31342
31374
  Text48,
@@ -31351,7 +31383,16 @@ var PersonalAssistantChannelModal = ({
31351
31383
  children: qrStatus === "scaned" ? "Scanned! Confirm on your phone..." : "Scan with WeChat"
31352
31384
  }
31353
31385
  ),
31354
- /* @__PURE__ */ (0, import_jsx_runtime118.jsx)(Text48, { type: "secondary", style: { fontSize: 11, marginTop: 4, display: "block" }, children: "QR expires in 5 minutes" })
31386
+ /* @__PURE__ */ (0, import_jsx_runtime118.jsx)(Text48, { type: "secondary", style: { fontSize: 11, marginTop: 4, display: "block" }, children: qrCountdown > 0 ? `Expires in ${Math.floor(qrCountdown / 60)}:${String(qrCountdown % 60).padStart(2, "0")}` : "QR code expired" }),
31387
+ /* @__PURE__ */ (0, import_jsx_runtime118.jsx)(
31388
+ import_antd90.Button,
31389
+ {
31390
+ size: "small",
31391
+ style: { marginTop: 8 },
31392
+ onClick: checkQrStatus,
31393
+ children: "Refresh Status"
31394
+ }
31395
+ )
31355
31396
  ] }),
31356
31397
  qrStatus === "confirmed" && /* @__PURE__ */ (0, import_jsx_runtime118.jsxs)("div", { style: { padding: "12px 0" }, children: [
31357
31398
  /* @__PURE__ */ (0, import_jsx_runtime118.jsx)(Text48, { strong: true, style: { fontSize: 14, color: "var(--color-success, #22c55e)", display: "block" }, children: "Login confirmed!" }),
@@ -31599,7 +31640,7 @@ var PERSONALITY_MAP = {
31599
31640
  var PersonalAssistantPage = () => {
31600
31641
  const { styles } = useStyles20();
31601
31642
  const { get, post, del } = useApi();
31602
- const { personalAssistant, setPersonalAssistant } = useAuth();
31643
+ const { personalAssistant, setPersonalAssistant, currentTenant } = useAuth();
31603
31644
  const auth = useAuthOptional();
31604
31645
  const userName = auth?.user?.name || auth?.user?.email?.split("@")[0];
31605
31646
  const [creating, setCreating] = (0, import_react102.useState)(false);
@@ -31626,7 +31667,7 @@ var PersonalAssistantPage = () => {
31626
31667
  import_antd91.message.error(b.message);
31627
31668
  return;
31628
31669
  }
31629
- const info = { assistantId: b.data.id, projectId: b.data.projectId, workspaceId: b.data.workspaceId || "default" };
31670
+ const info = { assistantId: b.data.id, projectId: b.data.projectId, workspaceId: b.data.workspaceId || "default", tenantId: currentTenant?.id };
31630
31671
  setPersonalAssistant(info);
31631
31672
  import_antd91.message.success("Done!");
31632
31673
  } catch {