@enterprisestandard/react 0.0.10 → 0.0.11-beta.20260318.1
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.ts +20 -2
- package/dist/index.js +1 -1
- package/package.json +2 -2
package/dist/index.d.ts
CHANGED
|
@@ -30,6 +30,24 @@ declare function logout(logoutUrl: string): Promise<{
|
|
|
30
30
|
success: boolean;
|
|
31
31
|
error?: string;
|
|
32
32
|
}>;
|
|
33
|
+
import { TenantRoutingStrategy } from "@enterprisestandard/core";
|
|
34
|
+
type TenantUrls = {
|
|
35
|
+
ui: (restPath?: string) => string;
|
|
36
|
+
api: (restPath?: string) => string;
|
|
37
|
+
};
|
|
38
|
+
type TenantContextValue = {
|
|
39
|
+
tenantId: string;
|
|
40
|
+
strategy: TenantRoutingStrategy;
|
|
41
|
+
urls: TenantUrls;
|
|
42
|
+
};
|
|
43
|
+
type TenantProviderProps = {
|
|
44
|
+
tenantId: string;
|
|
45
|
+
strategy?: TenantRoutingStrategy;
|
|
46
|
+
children: React.ReactNode;
|
|
47
|
+
};
|
|
48
|
+
declare function createTenantUrls(tenantId: string, strategy?: TenantRoutingStrategy): TenantUrls;
|
|
49
|
+
declare function TenantProvider({ tenantId, strategy, children }: TenantProviderProps): React.ReactNode;
|
|
50
|
+
declare function useTenant(): TenantContextValue;
|
|
33
51
|
import { User as User2 } from "@enterprisestandard/core";
|
|
34
52
|
type SessionInfo = {
|
|
35
53
|
clientId: string;
|
|
@@ -49,7 +67,7 @@ declare function useSessions(options?: UseSessionsOptions): {
|
|
|
49
67
|
sessions: SessionInfo[];
|
|
50
68
|
isLoading: boolean;
|
|
51
69
|
refresh: () => Promise<void>;
|
|
52
|
-
switchSession: (clientId: string) => Promise<void>;
|
|
70
|
+
switchSession: (clientId: string, redirectTo?: string) => Promise<void>;
|
|
53
71
|
};
|
|
54
72
|
declare function useActiveUser(sessionsUrl?: string): {
|
|
55
73
|
user: User2 | null;
|
|
@@ -69,4 +87,4 @@ type TenantSwitcherProps = {
|
|
|
69
87
|
onLogin?: (clientId: string) => void;
|
|
70
88
|
};
|
|
71
89
|
declare function TenantSwitcher({ activeSession, sessions, onSwitch, availableTenants, onLogin }: TenantSwitcherProps): React.ReactNode;
|
|
72
|
-
export { useUser, useSessions, useActiveUser, logout, getUser, TenantSwitcher, SignedOut, SignedIn, SignInLoading, SessionInfo, SSOProvider };
|
|
90
|
+
export { useUser, useTenant, useSessions, useActiveUser, logout, getUser, createTenantUrls, TenantSwitcher, TenantProvider, SignedOut, SignedIn, SignInLoading, SessionInfo, SSOProvider };
|
package/dist/index.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
export*from"@enterprisestandard/core";import{createContext as
|
|
1
|
+
export*from"@enterprisestandard/core";import{createContext as k,useCallback as I,useContext as q,useEffect as A,useState as g}from"react";import{jsx as G}from"react/jsx-runtime";var C=k(void 0),B=/^[a-zA-Z0-9._-]{1,1024}$/;function H(n){if(!n.trim())throw Error("SSOProvider storageKey must be a non-empty string.");if(!B.test(n))throw Error("SSOProvider storageKey must be 1-1024 characters and contain only letters, numbers, dots, underscores, and hyphens.")}var O=(n)=>{if(n===void 0||n==="")return"es.sso.user";return H(n),n};function x(n,t){if(typeof window>"u")return null;try{let e=(n==="local"?localStorage:sessionStorage).getItem(t);if(!e)return null;let s=JSON.parse(e);if(s.sso?.expires)s.sso.expires=new Date(s.sso.expires);return s}catch(i){return console.error("Error loading user from storage:",i),null}}async function E(n){try{let t=await fetch(n);if(t.status===401)return null;if(!t.ok)throw Error(`Failed to fetch user: ${t.status} ${t.statusText}`);let i=await t.json();if(i.sso?.expires&&typeof i.sso.expires==="string")i.sso.expires=new Date(i.sso.expires);return i}catch(t){return console.error("Error fetching user from URL:",t),null}}function L({storageKey:n,userUrl:t,storage:i="memory",disableListener:e=!1,children:s}){let[o,d]=g(null),[f,v]=g(!!t),p=O(n),h=I(()=>{if(i==="memory")return null;return x(i,p)},[i,p]),l=I((c)=>{if(i==="memory"||typeof window>"u")return;try{let r=i==="local"?localStorage:sessionStorage;if(c===null)r.removeItem(p);else r.setItem(p,JSON.stringify(c))}catch(r){console.error("Error saving user to storage:",r)}},[i,p]),u=I((c)=>{d(c),l(c)},[l]),a=I(async()=>{if(!t)return;v(!0);try{let c=await E(t);d(c),l(c)}finally{v(!1)}},[t,l]);A(()=>{let c=h();if(c)d(c);if(t)a();else v(!1)},[h,t,a]),A(()=>{if(e||i==="memory")return;let c=(P)=>{if(P.key!==p)return;if(P.newValue===null)d(null);else try{let T=JSON.parse(P.newValue);if(T.sso?.expires)T.sso.expires=new Date(T.sso.expires);d(T)}catch(T){console.error("Error parsing user from storage event:",T)}},r=()=>{d(null)};return window.addEventListener("storage",c),window.addEventListener("es-sso-logout",r),()=>{window.removeEventListener("storage",c),window.removeEventListener("es-sso-logout",r)}},[e,i,p]);let y={user:o,setUser:u,isLoading:f};return G(C.Provider,{value:y,children:s})}function N(){let n=q(C);if(n===void 0)throw Error("useUser must be used within a SSOProvider");return n}async function Q(n,t){let i=O(t),e=x("local",i);if(e)return e;let s=x("session",i);if(s)return s;if(n){let o=await E(n);if(o)return o}return}async function Z(n){try{let t=await fetch(n,{headers:{Accept:"application/json"}});if(!t.ok)return{success:!1,error:`HTTP ${t.status}`};let i=await t.json();if(!i.success)return{success:!1,error:i.message||"Logout failed"};if(typeof window<"u")localStorage.removeItem("es.sso.user"),sessionStorage.removeItem("es.sso.user"),window.dispatchEvent(new CustomEvent("es-sso-logout"));return{success:!0}}catch(t){return{success:!1,error:t instanceof Error?t.message:"Network error"}}}import{jsx as D,Fragment as X}from"react/jsx-runtime";function Y({complete:n=!1,children:t}){let{isLoading:i}=N();if(i&&!n)return D(X,{children:t});return null}import{jsx as U,Fragment as j}from"react/jsx-runtime";function F({children:n}){let{user:t}=N();if(t)return U(j,{children:n});return null}import{jsx as tn,Fragment as nn}from"react/jsx-runtime";function K({children:n}){let{user:t,isLoading:i}=N();if(t||i)return null;return tn(nn,{children:n})}import{buildTenantPath as W,DEFAULT_TENANT_API_NAMESPACE as on,DEFAULT_TENANT_UI_NAMESPACE as en,normalizeTenantRoutingStrategy as _}from"@enterprisestandard/core";import{createContext as sn,useContext as cn,useMemo as pn}from"react";import{jsx as un}from"react/jsx-runtime";var z=sn(null);function M(n,t){let i=_(t);if(i.type==="jwt"){let o=i.ui?.segments??[],d=i.api?.segments??["api"];return{ui:(f="/")=>$(o,f),api:(f="/")=>$(d,f)}}let e=i.ui??en,s=i.api??on;return{ui:(o="/")=>W(n,o,e),api:(o="/")=>W(n,o,s)}}function $(n,t="/"){let i=n.join("/"),e=t.trim().replace(/^\/+/,"");if(!i&&!e)return"/";if(!i)return`/${e}`;if(!e)return`/${i}`;return`/${i}/${e}`}function dn({tenantId:n,strategy:t,children:i}){let e=pn(()=>{let s=_(t);return{tenantId:n,strategy:s,urls:M(n,s)}},[t,n]);return un(z.Provider,{value:e,children:i})}function ln(){let n=cn(z);if(!n)throw Error("useTenant() must be used within a TenantProvider");return n}import{jsx as m,jsxs as w,Fragment as mn}from"react/jsx-runtime";function S(n){if(!n)return"Unknown user";return n.name??n.email??n.id??"Unknown user"}function b(n){return n.tenantName??n.companyName??n.tenantId??n.clientId}function an({activeSession:n,sessions:t,onSwitch:i,availableTenants:e=[],onLogin:s}){return w("details",{className:"relative inline-block text-left",children:[w("summary",{className:"cursor-pointer select-none rounded-md border px-3 py-2 text-sm",children:[S(n?.user)," · ",n?b(n):"No active session"]}),w("div",{className:"absolute left-0 mt-2 w-64 rounded-md border bg-white p-3 text-sm shadow",children:[m("div",{className:"mb-2 text-gray-500 text-xs uppercase",children:"Active"}),m("div",{className:"mb-4",children:n?w("div",{className:"rounded-md border px-2 py-1",children:[b(n)," · ",S(n.user)]}):m("div",{className:"text-gray-500",children:"No active session"})}),m("div",{className:"mb-2 text-gray-500 text-xs uppercase",children:"Sessions"}),w("div",{className:"space-y-2",children:[t.length===0&&m("div",{className:"text-gray-500",children:"No sessions"}),t.map((o)=>w("button",{type:"button",className:"w-full rounded-md border px-2 py-1 text-left hover:bg-gray-50",onClick:()=>i(o.clientId),children:[b(o)," · ",S(o.user)]},o.clientId))]}),e.length>0&&w(mn,{children:[m("div",{className:"mt-4 mb-2 text-gray-500 text-xs uppercase",children:"Login to another tenant"}),m("div",{className:"space-y-2",children:e.map((o)=>m("button",{type:"button",className:"w-full rounded-md border px-2 py-1 text-left hover:bg-gray-50",onClick:()=>s?.(o.clientId),children:o.tenantName??o.companyName??o.tenantId??o.clientId},o.clientId))})]})]})]})}import{useCallback as V,useEffect as fn,useState as R}from"react";function J(n={}){let t=n.sessionsUrl??"/api/sessions",i=n.switchUrl??"/api/sessions/switch",[e,s]=R([]),[o,d]=R(null),[f,v]=R(!0),p=V(async()=>{v(!0);try{let l=await fetch(t);if(!l.ok){s([]),d(null);return}let u=await l.json();s(u.sessions??[]);let a=u.sessions?.find((y)=>y.clientId===u.activeSession)??null;d(a)}finally{v(!1)}},[t]),h=V(async(l,u)=>{let a=await fetch(i,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({clientId:l,redirectTo:u})});if(a.redirected&&typeof window<"u"){window.location.assign(a.url);return}if(!a.ok){if(typeof window<"u")window.location.assign(`/api/auth/login?clientId=${l}`);return}if(await p(),u&&typeof window<"u")window.location.assign(u)},[p,i]);return fn(()=>{p()},[p]),{activeSession:o,sessions:e,isLoading:f,refresh:p,switchSession:h}}function rn(n){let{activeSession:t,isLoading:i}=J({sessionsUrl:n});return{user:t?.user??null,isLoading:i}}export{N as useUser,ln as useTenant,J as useSessions,rn as useActiveUser,Z as logout,Q as getUser,M as createTenantUrls,an as TenantSwitcher,dn as TenantProvider,K as SignedOut,F as SignedIn,Y as SignInLoading,L as SSOProvider};
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@enterprisestandard/react",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.11-beta.20260318.1",
|
|
4
4
|
"description": "Enterprise Standard React Components",
|
|
5
5
|
"private": false,
|
|
6
6
|
"author": "enterprisestandard",
|
|
@@ -22,7 +22,7 @@
|
|
|
22
22
|
"./package.json": "./package.json"
|
|
23
23
|
},
|
|
24
24
|
"dependencies": {
|
|
25
|
-
"@enterprisestandard/core": "
|
|
25
|
+
"@enterprisestandard/core": "0.0.11-beta.20260318.1"
|
|
26
26
|
},
|
|
27
27
|
"peerDependencies": {
|
|
28
28
|
"react": "^18.0.0 || ^19.0.0",
|