@ai4b-team/fsaos-gateway-sdk 3.40.0 → 3.41.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/iife/ui.js CHANGED
@@ -1,3 +1,3 @@
1
- /* @fsaos/ui v2.0.0 — FSAOS UI Primitives — 2026-10-15T09:44:35.224Z */
1
+ /* @fsaos/ui v2.0.0 — FSAOS UI Primitives — 2026-10-26T00:58:56.236Z */
2
2
  "use strict";var __FSAOS_UI__=(()=>{var m=Object.create;var r=Object.defineProperty;var g=Object.getOwnPropertyDescriptor;var u=Object.getOwnPropertyNames;var f=Object.getPrototypeOf,h=Object.prototype.hasOwnProperty;var y=(e,i)=>()=>(i||e((i={exports:{}}).exports,i),i.exports),N=(e,i)=>{for(var a in i)r(e,a,{get:i[a],enumerable:!0})},s=(e,i,a,l)=>{if(i&&typeof i=="object"||typeof i=="function")for(let t of u(i))!h.call(e,t)&&t!==a&&r(e,t,{get:()=>i[t],enumerable:!(l=g(i,t))||l.enumerable});return e};var x=(e,i,a)=>(a=e!=null?m(f(e)):{},s(i||!e||!e.__esModule?r(a,"default",{value:e,enumerable:!0}):a,e)),b=e=>s(r({},"__esModule",{value:!0}),e);var d=y((V,c)=>{c.exports=React});var P={};N(P,{Badge:()=>z,Breadcrumbs:()=>A,Button:()=>D,Card:()=>w,DataView:()=>R,Detail:()=>_,Empty:()=>I,FilePreview:()=>O,Form:()=>F,Grid:()=>k,Image:()=>G,Link:()=>E,Page:()=>v,Router:()=>T,Sidebar:()=>S,Spinner:()=>B,Stack:()=>C,Table:()=>j,Tabs:()=>W,Video:()=>H});var n=x(d(),1);function o(){return(typeof window<"u"&&window.__FSAOS_CONFIG__||{}).edgeBaseUrl||""}function v(e){return(0,n.createElement)("div",{style:{minHeight:"100vh",display:"flex",flexDirection:"column"},className:e.className||""},e.children)}function C(e){let i=e.direction||"vertical";return(0,n.createElement)("div",{style:{display:"flex",flexDirection:i==="horizontal"?"row":"column",gap:e.gap||"0.5rem",padding:e.padding||"0",alignItems:e.align||"stretch",justifyContent:e.justify||"flex-start",flex:e.flex||"initial"},className:e.className||""},e.children)}function k(e){return(0,n.createElement)("div",{style:{display:"grid",gridTemplateColumns:"repeat("+(e.columns||3)+", 1fr)",gap:e.gap||"1rem",padding:e.padding||"0"},className:e.className||""},e.children)}function S(e){return(0,n.createElement)("div",{style:{display:"flex",flexDirection:"row",minHeight:"100vh"},className:e.className||""},e.children)}function w(e){return(0,n.createElement)("div",{style:{border:"1px solid var(--color-border, #e5e7eb)",borderRadius:"var(--border-radius, 0.5rem)",padding:e.padding||"1rem",background:"var(--color-surface, #fff)"},className:e.className||"",onClick:e.onClick},e.children)}function z(e){return(0,n.createElement)("span",{style:{display:"inline-flex",alignItems:"center",padding:"0.125rem 0.5rem",fontSize:"0.75rem",fontWeight:"500",borderRadius:"9999px",background:e.color||"#e5e7eb",color:e.textColor||"#374151"},className:e.className||""},e.children||e.label)}function B(e){let i=e.size||"1.5rem";return(0,n.createElement)("div",{style:{width:i,height:i,border:"2px solid #e5e7eb",borderTopColor:"var(--color-primary, #3b82f6)",borderRadius:"50%",animation:"fsaos-spin 0.6s linear infinite"}})}function D(e){return(0,n.createElement)("button",{style:{display:"inline-flex",alignItems:"center",justifyContent:"center",padding:"0.5rem 1rem",fontSize:"0.875rem",fontWeight:"500",borderRadius:"var(--border-radius, 0.375rem)",border:e.variant==="outline"?"1px solid var(--color-border, #d1d5db)":"none",background:e.variant==="outline"||e.variant==="ghost"?"transparent":"var(--color-primary, #3b82f6)",color:e.variant==="outline"||e.variant==="ghost"?"var(--color-text, #1a1a1a)":"#fff",cursor:e.disabled?"not-allowed":"pointer",opacity:e.disabled?"0.5":"1",gap:"0.5rem"},className:e.className||"",onClick:e.onClick,disabled:e.disabled},e.children||e.label)}function I(e){return(0,n.createElement)("div",{style:{display:"flex",flexDirection:"column",alignItems:"center",justifyContent:"center",padding:"3rem",color:"var(--color-text-secondary, #6b7280)",textAlign:"center"}},e.icon?(0,n.createElement)("div",{style:{fontSize:"2rem",marginBottom:"0.5rem"}},e.icon):null,(0,n.createElement)("div",{style:{fontWeight:500,marginBottom:"0.25rem"}},e.title||e.message||e.children||"No items"),e.description?(0,n.createElement)("div",{style:{fontSize:"0.875rem",opacity:.7}},e.description):null)}function R(e){return(0,n.createElement)("div",{className:e.className||""},e.children)}function j(e){return(0,n.createElement)("table",{className:e.className||""},e.children)}function F(e){return(0,n.createElement)("form",{className:e.className||"",onSubmit:e.onSubmit},e.children)}function _(e){return(0,n.createElement)("div",{className:e.className||""},e.children)}function T(e){return(0,n.createElement)("div",null,e.children)}function E(e){return(0,n.createElement)("a",{href:e.href||e.to,className:e.className||"",onClick:e.onClick},e.children)}function W(e){return(0,n.createElement)("div",{className:e.className||""},e.children)}function A(e){return(0,n.createElement)("nav",{className:e.className||""},e.children)}function G(e){return(0,n.createElement)("img",{src:e.src||(e.path?o()+e.path:""),alt:e.alt||"",className:e.className||"",style:e.style})}function H(e){return(0,n.createElement)("video",{src:e.src||(e.path?o()+e.path:""),controls:!0,className:e.className||""})}function O(e){return(0,n.createElement)("div",{className:e.className||""},e.children||"File preview")}return b(P);})();
3
3
  //# sourceMappingURL=ui.js.map
package/dist/index.cjs CHANGED
@@ -433,9 +433,30 @@ function commitMountSelection(mounts, anchor) {
433
433
  var sessionEntry = null;
434
434
  var sessionPromise = null;
435
435
  var sessionGeneration = 0;
436
+ var sessionListeners = /* @__PURE__ */ new Set();
437
+ var sessionVersion = 0;
438
+ function notifySessionListeners() {
439
+ sessionVersion++;
440
+ sessionListeners.forEach((listener) => {
441
+ try {
442
+ listener();
443
+ } catch (e) {
444
+ console.warn("[SDK] Session listener error:", e);
445
+ }
446
+ });
447
+ }
436
448
  function getSessionGeneration() {
437
449
  return sessionGeneration;
438
450
  }
451
+ function getSessionVersion() {
452
+ return sessionVersion;
453
+ }
454
+ function subscribeSession(listener) {
455
+ sessionListeners.add(listener);
456
+ return () => {
457
+ sessionListeners.delete(listener);
458
+ };
459
+ }
439
460
  async function initSession() {
440
461
  if (sessionEntry) return sessionEntry;
441
462
  if (sessionPromise) return sessionPromise;
@@ -469,6 +490,7 @@ async function initSession() {
469
490
  // resolver has no principal and omits the field entirely.
470
491
  principal_id: entry.principal_id || null
471
492
  };
493
+ notifySessionListeners();
472
494
  return sessionEntry;
473
495
  })().catch((error) => {
474
496
  if (generation === sessionGeneration) sessionPromise = null;
@@ -487,6 +509,7 @@ function clearSession() {
487
509
  currentAnchorRef = null;
488
510
  homeAnchor = null;
489
511
  mountSet = [];
512
+ notifySessionListeners();
490
513
  }
491
514
  var cleanupRegistry = [];
492
515
  function registerCleanup(fn) {
@@ -3174,14 +3197,50 @@ function useScope() {
3174
3197
  return { data, loading, error };
3175
3198
  }
3176
3199
  var EMPTY_ACCOUNTS = [];
3200
+ function embedTokenConfigured() {
3201
+ if (typeof window === "undefined") return false;
3202
+ const token = window.__FSAOS_CONFIG__?.embedToken;
3203
+ return typeof token === "function" || typeof token === "string" && token.length > 0;
3204
+ }
3205
+ function groupSwitcherAccounts(accountMemberships) {
3206
+ return accountMemberships.filter((account) => account.placement === "switcher_entry").map((account) => ({
3207
+ account,
3208
+ mountables: accountMemberships.filter((candidate) => candidate.placement !== "switcher_entry" && candidate.subordinateTo === account.accountId)
3209
+ }));
3210
+ }
3177
3211
  function useAccounts() {
3178
3212
  const { user } = useAuth();
3213
+ const sessionVersion2 = React.useSyncExternalStore(subscribeSession, getSessionVersion, getSessionVersion);
3214
+ const principalId = getSessionEntry()?.principal_id ?? null;
3179
3215
  const autoSelectedRef = React.useRef(null);
3180
3216
  const [mountError, setMountError] = React.useState(null);
3217
+ const [sessionError, setSessionError] = React.useState(null);
3218
+ React.useEffect(() => {
3219
+ if (principalId) {
3220
+ setSessionError(null);
3221
+ return;
3222
+ }
3223
+ if (!user?.id && !embedTokenConfigured()) {
3224
+ setSessionError(null);
3225
+ return;
3226
+ }
3227
+ let cancelled = false;
3228
+ initSession().then((entry) => {
3229
+ if (cancelled) return;
3230
+ if (!entry.principal_id) {
3231
+ setSessionError(new Error("Memberships require an authenticated principal"));
3232
+ }
3233
+ }).catch((err) => {
3234
+ if (!cancelled) setSessionError(err instanceof Error ? err : new Error(String(err)));
3235
+ });
3236
+ return () => {
3237
+ cancelled = true;
3238
+ };
3239
+ }, [principalId, user?.id, sessionVersion2]);
3181
3240
  const query = reactQuery.useQuery({
3182
- queryKey: vfsKeys.memberships(user?.id ?? "anonymous"),
3241
+ queryKey: vfsKeys.memberships(principalId ?? "anonymous"),
3183
3242
  queryFn: fetchMemberships,
3184
- enabled: !!user?.id,
3243
+ enabled: !!principalId,
3185
3244
  staleTime: 1e3 * 60 * 2
3186
3245
  });
3187
3246
  const allMemberships = query.data ?? EMPTY_ACCOUNTS;
@@ -3200,12 +3259,16 @@ function useAccounts() {
3200
3259
  if (!ref) return null;
3201
3260
  return allMemberships.find((a) => a.accountId === ref.id) ?? null;
3202
3261
  }, [anchorVersion2, allMemberships]);
3262
+ const switcherAccounts = React.useMemo(
3263
+ () => groupSwitcherAccounts(accountMemberships),
3264
+ [accountMemberships]
3265
+ );
3203
3266
  React.useEffect(() => {
3204
- if (!user?.id) {
3267
+ if (!principalId) {
3205
3268
  autoSelectedRef.current = null;
3206
3269
  return;
3207
3270
  }
3208
- if (autoSelectedRef.current === user.id) return;
3271
+ if (autoSelectedRef.current === principalId) return;
3209
3272
  setMountError(null);
3210
3273
  if (electionCandidates.length === 1) {
3211
3274
  const only = electionCandidates[0];
@@ -3217,11 +3280,11 @@ function useAccounts() {
3217
3280
  return m ? membershipToMountRef(m) : null;
3218
3281
  }).catch(setMountError);
3219
3282
  }
3220
- autoSelectedRef.current = user.id;
3283
+ autoSelectedRef.current = principalId;
3221
3284
  } else if (electionCandidates.length > 1) {
3222
- autoSelectedRef.current = user.id;
3285
+ autoSelectedRef.current = principalId;
3223
3286
  }
3224
- }, [user?.id, electionCandidates, allMemberships]);
3287
+ }, [principalId, electionCandidates, allMemberships]);
3225
3288
  const switchAccount = React.useCallback(async (accountPath) => {
3226
3289
  const m = allMemberships.find((a) => a.path === accountPath);
3227
3290
  if (!m) throw new Error("Account membership is unavailable");
@@ -3244,15 +3307,17 @@ function useAccounts() {
3244
3307
  if (!m) throw new Error("Scope membership is unavailable");
3245
3308
  await mount(membershipToMountRef(m));
3246
3309
  }, [allMemberships]);
3310
+ const awaitingPrincipal = (!!user?.id || embedTokenConfigured()) && !principalId && !sessionError;
3247
3311
  return {
3248
3312
  accounts: electionCandidates,
3313
+ switcherAccounts,
3249
3314
  allMemberships,
3250
3315
  currentAccount,
3251
3316
  mountedScope: null,
3252
3317
  switchAccount,
3253
3318
  mountScope,
3254
- loading: query.isLoading,
3255
- error: query.error ?? mountError
3319
+ loading: awaitingPrincipal || query.isLoading,
3320
+ error: sessionError ?? query.error ?? mountError
3256
3321
  };
3257
3322
  }
3258
3323
  function useMounts() {