@hosty-sdk/app 0.27.23 → 0.27.24

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 (2) hide show
  1. package/dist/react.js +15 -5
  2. package/package.json +1 -1
package/dist/react.js CHANGED
@@ -208,24 +208,34 @@ export function useAppIdentity({ probePath = "/api/auth/identity", appCodePath =
208
208
  const onSessionRef = useRef(onSession);
209
209
  useEffect(() => { onSessionRef.current = onSession; }, [onSession]);
210
210
  const continuity = activity?.continuity;
211
+ const continuityCoreOrigin = activity?.openUrl ? new URL(activity.openUrl).origin : null;
211
212
  const continuityActor = session?.userId;
212
213
  useEffect(() => {
213
- if (!continuity || !activity?.openUrl || !continuityActor)
214
+ if (!continuity || !continuityCoreOrigin || !continuityActor)
214
215
  return;
215
- return configureAppContinuity({ coreOrigin: new URL(activity.openUrl).origin, authority: continuity,
216
+ return configureAppContinuity({ coreOrigin: continuityCoreOrigin, authority: continuity,
216
217
  probe: async () => {
217
218
  const next = await refreshRef.current();
218
219
  return next?.status === "active" && next.userId === continuityActor
219
220
  && (!next.hosty || (next.hosty.version === 1 && next.hosty.setup === "ready"));
220
221
  } });
221
- }, [continuity?.grantId, activity?.openUrl, continuityActor]);
222
+ }, [continuity?.grantId, continuityCoreOrigin, continuityActor]);
222
223
  useEffect(() => {
223
224
  let cancelled = false;
224
225
  let probeSequence = 0;
225
226
  const controller = new AbortController();
226
227
  if (initialGrantPresent.current === null)
227
228
  initialGrantPresent.current = restoreAppGrant();
228
- async function probeAndRecover() {
229
+ let pendingProbe = null;
230
+ // Focus, continuity maintenance and setup review can request the same identity at once.
231
+ // Share its result: a superseded successful probe must not look like an access outage.
232
+ function probeAndRecover() {
233
+ if (pendingProbe)
234
+ return pendingProbe;
235
+ pendingProbe = runProbeAndRecover().finally(() => { pendingProbe = null; });
236
+ return pendingProbe;
237
+ }
238
+ async function runProbeAndRecover() {
229
239
  const sequence = ++probeSequence;
230
240
  // Dedicated controller + setTimeout instead of AbortSignal.any/timeout, which are not
231
241
  // available in every browser (a synchronous throw here would stop the bridge from
@@ -274,7 +284,7 @@ export function useAppIdentity({ probePath = "/api/auth/identity", appCodePath =
274
284
  }
275
285
  if (revision !== appGrantRevision()) {
276
286
  initialGrantPresent.current ||= restoreAppGrant();
277
- return probeAndRecover();
287
+ return runProbeAndRecover();
278
288
  }
279
289
  forgetRejectedAppGrant(rejectionCode, revision);
280
290
  if (openUrl && protocol)
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@hosty-sdk/app",
3
- "version": "0.27.23",
3
+ "version": "0.27.24",
4
4
  "description": "Hosty app auth: session state machine, recovery bridge, Core revalidation, and the embedder responder.",
5
5
  "license": "AGPL-3.0-only",
6
6
  "type": "module",