@bounded-sh/core 0.0.115 → 0.0.116

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.
Files changed (28) hide show
  1. package/dist/{index-5TMFraRK.js → index-CjiaT9AT.js} +76 -8
  2. package/dist/index-CjiaT9AT.js.map +1 -0
  3. package/dist/{index-BilGFb3V.mjs → index-Db4lrwO6.mjs} +74 -9
  4. package/dist/index-Db4lrwO6.mjs.map +1 -0
  5. package/dist/index.d.ts +1 -0
  6. package/dist/index.js +4 -1
  7. package/dist/index.js.map +1 -1
  8. package/dist/index.mjs +1 -1
  9. package/dist/{realtime-store-Bc71mTWr.mjs → realtime-store-CNs5zURZ.mjs} +2 -2
  10. package/dist/{realtime-store-Bc71mTWr.mjs.map → realtime-store-CNs5zURZ.mjs.map} +1 -1
  11. package/dist/{realtime-store-BiChlioj.js → realtime-store-IPPwUhJc.js} +2 -2
  12. package/dist/{realtime-store-BiChlioj.js.map → realtime-store-IPPwUhJc.js.map} +1 -1
  13. package/dist/{solana-message-BNGEBst_.mjs → solana-message-BO6Dtgbv.mjs} +2 -2
  14. package/dist/{solana-message-BNGEBst_.mjs.map → solana-message-BO6Dtgbv.mjs.map} +1 -1
  15. package/dist/{solana-message-BVwD6WVm.js → solana-message-CXuLc7NX.js} +2 -2
  16. package/dist/{solana-message-BVwD6WVm.js.map → solana-message-CXuLc7NX.js.map} +1 -1
  17. package/dist/{solana-operations-B3u6Arbf.js → solana-operations-CghJe0_7.js} +3 -3
  18. package/dist/{solana-operations-B3u6Arbf.js.map → solana-operations-CghJe0_7.js.map} +1 -1
  19. package/dist/{solana-operations-BLbRO1rE.mjs → solana-operations-DDt4CzRR.mjs} +3 -3
  20. package/dist/{solana-operations-BLbRO1rE.mjs.map → solana-operations-DDt4CzRR.mjs.map} +1 -1
  21. package/dist/{solana-v1-operations-BxTmxUMN.js → solana-v1-operations-BY2DTfbR.js} +3 -3
  22. package/dist/{solana-v1-operations-BxTmxUMN.js.map → solana-v1-operations-BY2DTfbR.js.map} +1 -1
  23. package/dist/{solana-v1-operations-b1rmLBUP.mjs → solana-v1-operations-TH-HUzbT.mjs} +3 -3
  24. package/dist/{solana-v1-operations-b1rmLBUP.mjs.map → solana-v1-operations-TH-HUzbT.mjs.map} +1 -1
  25. package/dist/utils/session-signal.d.ts +7 -0
  26. package/package.json +2 -2
  27. package/dist/index-5TMFraRK.js.map +0 -1
  28. package/dist/index-BilGFb3V.mjs.map +0 -1
@@ -824,6 +824,63 @@ function notifySessionCleared() {
824
824
  }
825
825
  }
826
826
 
827
+ // Same-tab session change signal.
828
+ //
829
+ // A page can run more than one copy of the SDK: the app's own bundle and the hosted widget
830
+ // bounded-router injects (which bundles its own, pinned copy). They share one session record in
831
+ // localStorage, keyed by issuer and app id, but the browser fires `storage` events only in OTHER
832
+ // tabs, so a copy that signs in never tells the other copy in the same tab. Until a reload, the
833
+ // app stayed signed out after a widget sign-in and the widget stayed signed out after an app
834
+ // sign-in (observed on staging, 2026-10-07).
835
+ //
836
+ // This announces "the record changed" on a BroadcastChannel, which reaches every other channel
837
+ // on the origin, same tab included, and never the announcing instance itself. The message is a
838
+ // nudge, not an authority: it carries no token and no identity, and a listener only re-reads the
839
+ // record through its ordinary restore path. Nothing signs in or out because of the message alone.
840
+ const SESSION_SIGNAL_CHANNEL = "bounded.session";
841
+ let channel;
842
+ function openChannel() {
843
+ var _a;
844
+ if (channel !== undefined)
845
+ return channel;
846
+ try {
847
+ channel = typeof BroadcastChannel === "function" ? new BroadcastChannel(SESSION_SIGNAL_CHANNEL) : null;
848
+ // Node's BroadcastChannel holds the event loop open until closed; a Node consumer (tests,
849
+ // tarobase-server) must not hang on exit because of a nudge channel. Browsers have no unref.
850
+ (_a = channel === null || channel === void 0 ? void 0 : channel.unref) === null || _a === void 0 ? void 0 : _a.call(channel);
851
+ }
852
+ catch (_b) {
853
+ channel = null;
854
+ }
855
+ return channel;
856
+ }
857
+ /** Tell the other SDK copies on this origin that the session record under `key` changed. */
858
+ function announceSessionChange(key) {
859
+ const ch = openChannel();
860
+ if (!ch)
861
+ return;
862
+ try {
863
+ ch.postMessage({ type: "session-changed", key });
864
+ }
865
+ catch (_a) {
866
+ // A closed or unavailable channel loses the nudge; the record itself is unaffected.
867
+ }
868
+ }
869
+ /** Run `listener` when another SDK copy announces a session change. Returns the unsubscribe. */
870
+ function onSessionChange(listener) {
871
+ const ch = openChannel();
872
+ if (!ch)
873
+ return () => { };
874
+ const handler = (event) => {
875
+ const data = event.data;
876
+ if (!data || data.type !== "session-changed" || typeof data.key !== "string")
877
+ return;
878
+ listener(data.key);
879
+ };
880
+ ch.addEventListener("message", handler);
881
+ return () => ch.removeEventListener("message", handler);
882
+ }
883
+
827
884
  /**
828
885
  * The one protocol every session-storage mutation goes through.
829
886
  *
@@ -1020,6 +1077,7 @@ class WebSessionManager {
1020
1077
  }
1021
1078
  static writeRaw(sessionObj) {
1022
1079
  localStorage.setItem(this.BOUNDED_SESSION_STORAGE_KEY, JSON.stringify(sessionObj));
1080
+ announceSessionChange(this.BOUNDED_SESSION_STORAGE_KEY);
1023
1081
  }
1024
1082
  /**
1025
1083
  * Read the session, stamping a `sessionGeneration` if it predates them.
@@ -1116,6 +1174,7 @@ class WebSessionManager {
1116
1174
  idToken,
1117
1175
  refreshToken, appId: currentAppId, sessionGeneration: generation }, (sessionIssuer ? { issuer: sessionIssuer } : {}))));
1118
1176
  });
1177
+ announceSessionChange(storageKey);
1119
1178
  // Adoption can fail after persistence (for example, logout while the
1120
1179
  // provider is loading). Remove only this incomplete login, even if the
1121
1180
  // caller has since switched app configuration or another tab signed in.
@@ -1127,6 +1186,8 @@ class WebSessionManager {
1127
1186
  localStorage.removeItem(storageKey);
1128
1187
  return true;
1129
1188
  });
1189
+ if (removed)
1190
+ announceSessionChange(storageKey);
1130
1191
  if (removed)
1131
1192
  notifySessionCleared();
1132
1193
  };
@@ -1256,8 +1317,10 @@ class WebSessionManager {
1256
1317
  });
1257
1318
  // Only announce a clear that actually happened, so a no-op cannot sign out
1258
1319
  // a UI that was already signed out.
1259
- if (removed)
1320
+ if (removed) {
1260
1321
  notifySessionCleared();
1322
+ announceSessionChange(key);
1323
+ }
1261
1324
  }
1262
1325
  /**
1263
1326
  * Remove the session only if it is still the one identified by `generation`.
@@ -1282,8 +1345,10 @@ class WebSessionManager {
1282
1345
  localStorage.removeItem(this.BOUNDED_SESSION_STORAGE_KEY);
1283
1346
  return true;
1284
1347
  });
1285
- if (removed)
1348
+ if (removed) {
1286
1349
  notifySessionCleared();
1350
+ announceSessionChange(this.BOUNDED_SESSION_STORAGE_KEY);
1351
+ }
1287
1352
  }
1288
1353
  /* ------------------------------------------------------------------ */
1289
1354
  /* IS-AUTH */
@@ -4240,7 +4305,7 @@ class ServerSessionManager {
4240
4305
  const sessionConfig = (_a = this.sessionConfig) !== null && _a !== void 0 ? _a : undefined;
4241
4306
  /* fetch nonce from auth API (bound to the snapshotted app+issuer) */
4242
4307
  const nonce = await genAuthNonce(sessionConfig);
4243
- const { genSolanaMessage } = await import('./solana-message-BNGEBst_.mjs');
4308
+ const { genSolanaMessage } = await import('./solana-message-BO6Dtgbv.mjs');
4244
4309
  const message = await genSolanaMessage(address, nonce, sessionConfig === null || sessionConfig === void 0 ? void 0 : sessionConfig.appId);
4245
4310
  /* sign the message */
4246
4311
  const sigBytes = nacl.sign.detached(new TextEncoder().encode(message), kp.secretKey);
@@ -7599,7 +7664,7 @@ async function doReconnectWithNewAuth() {
7599
7664
  console.warn('[WS v2] Failed to clear HTTP read cache on auth change:', error);
7600
7665
  }
7601
7666
  try {
7602
- const { reconnectRealtimeStoreWithNewAuth } = await import('./realtime-store-Bc71mTWr.mjs');
7667
+ const { reconnectRealtimeStoreWithNewAuth } = await import('./realtime-store-CNs5zURZ.mjs');
7603
7668
  await reconnectRealtimeStoreWithNewAuth();
7604
7669
  }
7605
7670
  catch (error) {
@@ -9099,7 +9164,7 @@ async function setMany(many, options) {
9099
9164
  if (typeof curTx.serializedTransaction !== 'string' || typeof curTx.poofnetIntentId !== 'string') {
9100
9165
  throw new Error('Unsupported 202 transaction shape: a poofnet write needs serializedTransaction and poofnetIntentId');
9101
9166
  }
9102
- const { signPoofnetTransaction, buildExpectedWriteIntent } = await import('./solana-operations-BLbRO1rE.mjs');
9167
+ const { signPoofnetTransaction, buildExpectedWriteIntent } = await import('./solana-operations-DDt4CzRR.mjs');
9103
9168
  const signedTransaction = await signPoofnetTransaction(curTx.serializedTransaction, authProvider, options, buildExpectedWriteIntent(documents));
9104
9169
  // Signing-only, exactly as on a real chain: signed and NOT committed.
9105
9170
  if ((options === null || options === void 0 ? void 0 : options.shouldSubmitTx) === false) {
@@ -9137,7 +9202,7 @@ async function setMany(many, options) {
9137
9202
  'Nothing was signed or submitted.');
9138
9203
  }
9139
9204
  const solanaChain = workerChain;
9140
- const { handlePreBuiltTransaction, buildExpectedWriteIntent } = await import('./solana-operations-BLbRO1rE.mjs');
9205
+ const { handlePreBuiltTransaction, buildExpectedWriteIntent } = await import('./solana-operations-DDt4CzRR.mjs');
9141
9206
  // OA-0001: derive the expected intent from OUR OWN request (the one
9142
9207
  // ground truth a tampered builder response cannot change) so the
9143
9208
  // validator can reject any transaction whose operation semantics
@@ -10981,7 +11046,7 @@ function toMillis(seconds) {
10981
11046
 
10982
11047
  /** SIWS message creation is async already, so its onchain module can be lazy. */
10983
11048
  async function genSolanaMessage(address, nonce) {
10984
- const implementation = await import('./solana-message-BNGEBst_.mjs');
11049
+ const implementation = await import('./solana-message-BO6Dtgbv.mjs');
10985
11050
  return implementation.genSolanaMessage(address, nonce);
10986
11051
  }
10987
11052
 
@@ -11530,5 +11595,5 @@ function defineLiveModule(mod) {
11530
11595
  return mod;
11531
11596
  }
11532
11597
 
11533
- export { RATE_LIMIT_EVENT_NAME as $, isWriteNotApplied as A, writeNotAppliedPhase as B, subscribe as C, closeAllSubscriptions as D, clearCache as E, getCachedData as F, reconnectWithNewAuth as G, createClient as H, InsufficientBalanceError as I, exchangeAppToken as J, clearAppTokenCache as K, createAppTokenAuthHeaders as L, AppTokenExchangeError as M, setWithVenueGrant as N, resolveVenueRpcUrl as O, subscribeQuery as P, closeAllQuerySubscriptions as Q, canonicalizeArgs as R, ScopedClientReadOnlyError as S, canonicalizeResult as T, DEFAULT_QUERY_POLL_INTERVAL_MS as U, MIN_QUERY_POLL_INTERVAL_MS as V, BoundedDeclineError as W, deriveDecline as X, dispatchDeclineEvent as Y, DECLINE_EVENT_NAME as Z, dispatchRateLimitEvent as _, getWebhookKeysUrl as a, hasActiveConnection as a0, increment as a1, serverTimestamp as a2, now as a3, toSeconds as a4, toMillis as a5, getIdToken as a6, deriveUserIdentityFromIdToken as a7, getSessionGeneration as a8, WebSessionManager as a9, invoke as aA, FunctionInvokeError as aB, live as aC, intent as aD, status as aE, subscribeView as aF, LiveIntentError as aG, withEffects as aH, isEffectResult as aI, defineLiveModule as aJ, EFFECT_INTENT_ADDRESS as aK, ReactNativeSessionManager as aa, getActiveSessionManager as ab, onSessionCleared as ac, SessionEnvironmentError as ad, UNSUPPORTED_ENVIRONMENT_CODE as ae, AUTH_CHANGED_CODE as af, AUTH_EXPIRED_CODE as ag, isAuthExpiredError as ah, getFreshAuthToken as ai, ServerSessionManager as aj, createSessionWithSignature as ak, refreshSession as al, revokeSession as am, signSessionCreateMessage as an, genAuthNonce as ao, genSolanaMessage as ap, createSolanaSignInRequest as aq, createSolanaSignInMessageText as ar, genSolanaSignInRequest as as, genSolanaSignInMessage as at, browserSignInDomain as au, SOLANA_SIGN_IN_STATEMENT as av, genSiweMessage as aw, normalizeEvmAddress as ax, toLowerEvmAddress as ay, functions as az, bufferExports as b, getConfiguredAppId as c, get as d, getMany as e, docId as f, getConfig as g, setMany as h, init as i, setFile as j, getFiles as k, search as l, markWriteNotApplied as m, runQueryMany as n, runExpression as o, runExpressionMany as p, queryAggregate as q, runQuery as r, set as s, signMessage as t, signTransaction as u, signAndSubmitTransaction as v, count as w, aggregate as x, reconcileSetResult as y, waitForSetResult as z };
11534
- //# sourceMappingURL=index-BilGFb3V.mjs.map
11598
+ export { RATE_LIMIT_EVENT_NAME as $, isWriteNotApplied as A, writeNotAppliedPhase as B, subscribe as C, closeAllSubscriptions as D, clearCache as E, getCachedData as F, reconnectWithNewAuth as G, createClient as H, InsufficientBalanceError as I, exchangeAppToken as J, clearAppTokenCache as K, createAppTokenAuthHeaders as L, AppTokenExchangeError as M, setWithVenueGrant as N, resolveVenueRpcUrl as O, subscribeQuery as P, closeAllQuerySubscriptions as Q, canonicalizeArgs as R, ScopedClientReadOnlyError as S, canonicalizeResult as T, DEFAULT_QUERY_POLL_INTERVAL_MS as U, MIN_QUERY_POLL_INTERVAL_MS as V, BoundedDeclineError as W, deriveDecline as X, dispatchDeclineEvent as Y, DECLINE_EVENT_NAME as Z, dispatchRateLimitEvent as _, getWebhookKeysUrl as a, hasActiveConnection as a0, increment as a1, serverTimestamp as a2, now as a3, toSeconds as a4, toMillis as a5, getIdToken as a6, deriveUserIdentityFromIdToken as a7, getSessionGeneration as a8, WebSessionManager as a9, normalizeEvmAddress as aA, toLowerEvmAddress as aB, functions as aC, invoke as aD, FunctionInvokeError as aE, live as aF, intent as aG, status as aH, subscribeView as aI, LiveIntentError as aJ, withEffects as aK, isEffectResult as aL, defineLiveModule as aM, EFFECT_INTENT_ADDRESS as aN, ReactNativeSessionManager as aa, getActiveSessionManager as ab, onSessionCleared as ac, announceSessionChange as ad, onSessionChange as ae, SESSION_SIGNAL_CHANNEL as af, SessionEnvironmentError as ag, UNSUPPORTED_ENVIRONMENT_CODE as ah, AUTH_CHANGED_CODE as ai, AUTH_EXPIRED_CODE as aj, isAuthExpiredError as ak, getFreshAuthToken as al, ServerSessionManager as am, createSessionWithSignature as an, refreshSession as ao, revokeSession as ap, signSessionCreateMessage as aq, genAuthNonce as ar, genSolanaMessage as as, createSolanaSignInRequest as at, createSolanaSignInMessageText as au, genSolanaSignInRequest as av, genSolanaSignInMessage as aw, browserSignInDomain as ax, SOLANA_SIGN_IN_STATEMENT as ay, genSiweMessage as az, bufferExports as b, getConfiguredAppId as c, get as d, getMany as e, docId as f, getConfig as g, setMany as h, init as i, setFile as j, getFiles as k, search as l, markWriteNotApplied as m, runQueryMany as n, runExpression as o, runExpressionMany as p, queryAggregate as q, runQuery as r, set as s, signMessage as t, signTransaction as u, signAndSubmitTransaction as v, count as w, aggregate as x, reconcileSetResult as y, waitForSetResult as z };
11599
+ //# sourceMappingURL=index-Db4lrwO6.mjs.map