azirid-react 0.10.2 → 0.10.4

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/README.md CHANGED
@@ -376,6 +376,8 @@ import { useBootstrap } from 'azirid-react'
376
376
  const { bootstrap, isBootstrapping } = useBootstrap()
377
377
  ```
378
378
 
379
+ > **Note:** The automatic bootstrap uses request deduplication — if React 18 Strict Mode (or any other scenario) triggers multiple bootstrap calls, only **one HTTP request** is made and all callers await the same promise. This prevents token rotation conflicts that would otherwise invalidate the session on page reload in development mode. Hooks like `usePayphoneCheckout` and `<PayphoneCallback>` wait for bootstrap to complete before making authenticated requests.
380
+
379
381
  ### `useRefresh`
380
382
 
381
383
  Manually refresh the access token.
@@ -1297,7 +1299,7 @@ function createAccessClient(
1297
1299
  | `publishableKey` | `string` | — | Publishable key (e.g. `pk_live_...`) |
1298
1300
  | `tenantId` | `string` | — | Tenant ID for multi-tenant apps |
1299
1301
  | `fetchOptions` | `Record<string, string>` | — | Extra headers to send with every request |
1300
- | `autoBootstrap` | `boolean` | `true` | Auto-restore session on mount |
1302
+ | `autoBootstrap` | `boolean` | `true` | Auto-restore session on mount. Runs once (safe in React 18 Strict Mode) |
1301
1303
  | `refreshInterval` | `number` | `50000` | Token refresh interval in ms. `0` to disable |
1302
1304
  | `sessionSyncUrl` | `string \| false` | auto | URL for session cookie sync. Auto-activates in dev mode. Pass `false` to disable |
1303
1305
  | `onAuthStateChange`| `() => void` | — | Called after login, signup, or logout. **In Next.js, pass `router.refresh()`** to sync server actions with updated cookies |
package/dist/index.cjs CHANGED
@@ -165,6 +165,7 @@ function createAccessClient(config, appContext) {
165
165
  let refreshToken = ssGet(storageKeyRt);
166
166
  let csrfToken = ssGet(storageKeyCsrf);
167
167
  let refreshPromise = null;
168
+ let bootstrapPromise = null;
168
169
  let channel = null;
169
170
  try {
170
171
  if (typeof BroadcastChannel !== "undefined") {
@@ -264,6 +265,13 @@ function createAccessClient(config, appContext) {
264
265
  });
265
266
  return refreshPromise;
266
267
  }
268
+ function deduplicatedBootstrap() {
269
+ if (bootstrapPromise) return bootstrapPromise;
270
+ bootstrapPromise = request("POST", paths.bootstrap).finally(() => {
271
+ bootstrapPromise = null;
272
+ });
273
+ return bootstrapPromise;
274
+ }
267
275
  async function request(method, path, body) {
268
276
  const headers = {
269
277
  "Content-Type": "application/json",
@@ -365,7 +373,8 @@ function createAccessClient(config, appContext) {
365
373
  getRefreshToken,
366
374
  setCsrfToken,
367
375
  getCsrfToken,
368
- refreshSession: (opts) => refreshTokens(opts)
376
+ refreshSession: (opts) => refreshTokens(opts),
377
+ bootstrapSession: () => deduplicatedBootstrap()
369
378
  };
370
379
  }
371
380
 
@@ -775,7 +784,7 @@ function AziridProviderInner({
775
784
  async function bootstrap() {
776
785
  setIsBootstrapping(true);
777
786
  try {
778
- const response = await client.post(client.paths.bootstrap);
787
+ const response = await client.bootstrapSession();
779
788
  if (cancelled) return;
780
789
  if (response.branding) {
781
790
  setBranding(response.branding);
@@ -4349,7 +4358,7 @@ function usePasswordToggle() {
4349
4358
  }
4350
4359
 
4351
4360
  // src/index.ts
4352
- var SDK_VERSION = "0.10.2";
4361
+ var SDK_VERSION = "0.10.4";
4353
4362
 
4354
4363
  exports.AuthForm = AuthForm;
4355
4364
  exports.AziridProvider = AziridProvider;