@23blocks/react 14.4.0 → 14.5.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/CHANGELOG.md
CHANGED
|
@@ -1,3 +1,30 @@
|
|
|
1
|
+
## 14.5.1 (2026-03-14)
|
|
2
|
+
|
|
3
|
+
### 🩹 Fixes
|
|
4
|
+
|
|
5
|
+
- **@23blocks/react:** add managed verifyMagicLink/acceptInvitation and stabilize memo deps ([ee811ee](https://github.com/23blocks-OS/frontend-sdk/commit/ee811ee))
|
|
6
|
+
- **@23blocks/react:** fix lifecycle circular retry, late-subscriber, and signUp ([31b18a9](https://github.com/23blocks-OS/frontend-sdk/commit/31b18a9))
|
|
7
|
+
|
|
8
|
+
### 📖 Documentation
|
|
9
|
+
|
|
10
|
+
- update llms.txt and JSDoc for token lifecycle across all packages ([74d8319](https://github.com/23blocks-OS/frontend-sdk/commit/74d8319))
|
|
11
|
+
|
|
12
|
+
### ❤️ Thank You
|
|
13
|
+
|
|
14
|
+
- Claude Opus 4.6
|
|
15
|
+
- Juan Pelaez
|
|
16
|
+
|
|
17
|
+
## 14.5.0 (2026-03-14)
|
|
18
|
+
|
|
19
|
+
### 🚀 Features
|
|
20
|
+
|
|
21
|
+
- **@23blocks/react:** integrate token lifecycle in Provider ([71aee53](https://github.com/23blocks-OS/frontend-sdk/commit/71aee53))
|
|
22
|
+
|
|
23
|
+
### ❤️ Thank You
|
|
24
|
+
|
|
25
|
+
- Claude Opus 4.6
|
|
26
|
+
- Juan Pelaez
|
|
27
|
+
|
|
1
28
|
## 14.4.0 (2026-03-09)
|
|
2
29
|
|
|
3
30
|
### 🚀 Features
|
package/dist/index.esm.js
CHANGED
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
import { _ } from '@swc/helpers/_/_extends';
|
|
2
2
|
import { jsx } from 'react/jsx-runtime';
|
|
3
|
-
import { useState, useRef, useMemo, useCallback, createContext, useContext
|
|
3
|
+
import { useState, useRef, useMemo, useCallback, useEffect, createContext, useContext } from 'react';
|
|
4
4
|
import { createHttpTransport } from '@23blocks/transport-http';
|
|
5
|
+
import { BlockErrorException } from '@23blocks/contracts';
|
|
5
6
|
import { createAuthenticationBlock } from '@23blocks/block-authentication';
|
|
6
7
|
import { createSearchBlock } from '@23blocks/block-search';
|
|
7
8
|
import { createProductsBlock } from '@23blocks/block-products';
|
|
@@ -187,6 +188,186 @@ let MemoryStorage = class MemoryStorage {
|
|
|
187
188
|
};
|
|
188
189
|
}
|
|
189
190
|
// ─────────────────────────────────────────────────────────────────────────────
|
|
191
|
+
// Token Lifecycle Helpers
|
|
192
|
+
// CANONICAL SOURCE: packages/sdk/src/lib/token-lifecycle.ts
|
|
193
|
+
// These are inlined here to avoid adding @23blocks/sdk as a dependency
|
|
194
|
+
// (which would change ng-packagr and consumer dependency requirements).
|
|
195
|
+
// When fixing bugs, update all three copies: sdk, react, angular.
|
|
196
|
+
// ─────────────────────────────────────────────────────────────────────────────
|
|
197
|
+
function decodeJwtExp(token) {
|
|
198
|
+
try {
|
|
199
|
+
const parts = token.split('.');
|
|
200
|
+
if (parts.length !== 3) return null;
|
|
201
|
+
let payload = parts[1].replace(/-/g, '+').replace(/_/g, '/');
|
|
202
|
+
const pad = payload.length % 4;
|
|
203
|
+
if (pad) payload += '='.repeat(4 - pad);
|
|
204
|
+
let decoded;
|
|
205
|
+
if (typeof atob === 'function') {
|
|
206
|
+
decoded = atob(payload);
|
|
207
|
+
} else if (typeof Buffer !== 'undefined') {
|
|
208
|
+
decoded = Buffer.from(payload, 'base64').toString('utf-8');
|
|
209
|
+
} else {
|
|
210
|
+
return null;
|
|
211
|
+
}
|
|
212
|
+
const parsed = JSON.parse(decoded);
|
|
213
|
+
return typeof parsed.exp === 'number' ? parsed.exp : null;
|
|
214
|
+
} catch (e) {
|
|
215
|
+
return null;
|
|
216
|
+
}
|
|
217
|
+
}
|
|
218
|
+
function isBrowserEnv() {
|
|
219
|
+
try {
|
|
220
|
+
return typeof window !== 'undefined' && typeof window.localStorage !== 'undefined' && typeof window.localStorage.getItem === 'function';
|
|
221
|
+
} catch (e) {
|
|
222
|
+
return false;
|
|
223
|
+
}
|
|
224
|
+
}
|
|
225
|
+
function createLifecycleManager(tokenManager, refreshFn, config = {}) {
|
|
226
|
+
const { refreshBufferSeconds = 120, enableVisibilityRefresh = true, enableProactiveRefresh = true } = config;
|
|
227
|
+
const listeners = new Set();
|
|
228
|
+
let refreshTimer = null;
|
|
229
|
+
let refreshPromise = null;
|
|
230
|
+
let visibilityHandler = null;
|
|
231
|
+
let destroyed = false;
|
|
232
|
+
let running = false;
|
|
233
|
+
function notify(event) {
|
|
234
|
+
listeners.forEach((l)=>{
|
|
235
|
+
try {
|
|
236
|
+
l(event);
|
|
237
|
+
} catch (e) {}
|
|
238
|
+
});
|
|
239
|
+
}
|
|
240
|
+
function clearTimer() {
|
|
241
|
+
if (refreshTimer !== null) {
|
|
242
|
+
clearTimeout(refreshTimer);
|
|
243
|
+
refreshTimer = null;
|
|
244
|
+
}
|
|
245
|
+
}
|
|
246
|
+
function scheduleRefresh() {
|
|
247
|
+
if (!enableProactiveRefresh || destroyed || !running) return;
|
|
248
|
+
clearTimer();
|
|
249
|
+
const accessToken = tokenManager.getAccessToken();
|
|
250
|
+
if (!accessToken) return;
|
|
251
|
+
const exp = decodeJwtExp(accessToken);
|
|
252
|
+
if (!exp) return;
|
|
253
|
+
const refreshInSeconds = exp - Math.floor(Date.now() / 1000) - refreshBufferSeconds;
|
|
254
|
+
if (refreshInSeconds <= 0) {
|
|
255
|
+
refreshNow().catch(()=>{});
|
|
256
|
+
return;
|
|
257
|
+
}
|
|
258
|
+
refreshTimer = setTimeout(()=>{
|
|
259
|
+
if (!destroyed && running) refreshNow().catch(()=>{});
|
|
260
|
+
}, refreshInSeconds * 1000);
|
|
261
|
+
}
|
|
262
|
+
function handleVisibilityChange() {
|
|
263
|
+
if (destroyed || !running || typeof document === 'undefined') return;
|
|
264
|
+
if (document.visibilityState === 'visible') {
|
|
265
|
+
const accessToken = tokenManager.getAccessToken();
|
|
266
|
+
if (!accessToken) return;
|
|
267
|
+
const exp = decodeJwtExp(accessToken);
|
|
268
|
+
if (!exp) {
|
|
269
|
+
refreshNow().catch(()=>{});
|
|
270
|
+
return;
|
|
271
|
+
}
|
|
272
|
+
const secondsUntilExpiry = exp - Math.floor(Date.now() / 1000);
|
|
273
|
+
if (secondsUntilExpiry <= refreshBufferSeconds) {
|
|
274
|
+
refreshNow().catch(()=>{});
|
|
275
|
+
} else {
|
|
276
|
+
scheduleRefresh();
|
|
277
|
+
}
|
|
278
|
+
}
|
|
279
|
+
}
|
|
280
|
+
async function refreshNow() {
|
|
281
|
+
if (destroyed) throw new Error('[23blocks] Lifecycle destroyed');
|
|
282
|
+
if (refreshPromise) return refreshPromise;
|
|
283
|
+
refreshPromise = (async ()=>{
|
|
284
|
+
try {
|
|
285
|
+
const rt = tokenManager.getRefreshToken();
|
|
286
|
+
if (!rt) throw new Error('No refresh token');
|
|
287
|
+
const result = await refreshFn(rt);
|
|
288
|
+
// Guard: don't store tokens if lifecycle was stopped/destroyed during the async call
|
|
289
|
+
if (!running || destroyed) return result.accessToken;
|
|
290
|
+
tokenManager.setTokens(result.accessToken, result.refreshToken);
|
|
291
|
+
scheduleRefresh();
|
|
292
|
+
notify('TOKEN_REFRESHED');
|
|
293
|
+
return result.accessToken;
|
|
294
|
+
} catch (error) {
|
|
295
|
+
clearTimer();
|
|
296
|
+
tokenManager.clearTokens();
|
|
297
|
+
running = false;
|
|
298
|
+
notify('SESSION_EXPIRED');
|
|
299
|
+
throw error;
|
|
300
|
+
} finally{
|
|
301
|
+
refreshPromise = null;
|
|
302
|
+
}
|
|
303
|
+
})();
|
|
304
|
+
return refreshPromise;
|
|
305
|
+
}
|
|
306
|
+
return {
|
|
307
|
+
start () {
|
|
308
|
+
if (destroyed) return;
|
|
309
|
+
running = true;
|
|
310
|
+
scheduleRefresh();
|
|
311
|
+
if (enableVisibilityRefresh && isBrowserEnv() && !visibilityHandler && typeof document !== 'undefined') {
|
|
312
|
+
visibilityHandler = handleVisibilityChange;
|
|
313
|
+
document.addEventListener('visibilitychange', visibilityHandler);
|
|
314
|
+
}
|
|
315
|
+
notify('SIGNED_IN');
|
|
316
|
+
},
|
|
317
|
+
stop () {
|
|
318
|
+
running = false;
|
|
319
|
+
clearTimer();
|
|
320
|
+
refreshPromise = null;
|
|
321
|
+
notify('SIGNED_OUT');
|
|
322
|
+
},
|
|
323
|
+
onAuthStateChanged (listener) {
|
|
324
|
+
listeners.add(listener);
|
|
325
|
+
return ()=>{
|
|
326
|
+
listeners.delete(listener);
|
|
327
|
+
};
|
|
328
|
+
},
|
|
329
|
+
refreshNow,
|
|
330
|
+
destroy () {
|
|
331
|
+
destroyed = true;
|
|
332
|
+
running = false;
|
|
333
|
+
clearTimer();
|
|
334
|
+
refreshPromise = null;
|
|
335
|
+
if (visibilityHandler && typeof document !== 'undefined') {
|
|
336
|
+
document.removeEventListener('visibilitychange', visibilityHandler);
|
|
337
|
+
visibilityHandler = null;
|
|
338
|
+
}
|
|
339
|
+
listeners.clear();
|
|
340
|
+
}
|
|
341
|
+
};
|
|
342
|
+
}
|
|
343
|
+
function createRetryTransport(baseTransport, getLifecycle) {
|
|
344
|
+
async function withRetry(fn) {
|
|
345
|
+
try {
|
|
346
|
+
return await fn();
|
|
347
|
+
} catch (error) {
|
|
348
|
+
if (error instanceof BlockErrorException && error.status === 401) {
|
|
349
|
+
const lc = getLifecycle();
|
|
350
|
+
if (lc) {
|
|
351
|
+
try {
|
|
352
|
+
await lc.refreshNow();
|
|
353
|
+
return await fn();
|
|
354
|
+
} catch (e) {
|
|
355
|
+
throw error;
|
|
356
|
+
}
|
|
357
|
+
}
|
|
358
|
+
}
|
|
359
|
+
throw error;
|
|
360
|
+
}
|
|
361
|
+
}
|
|
362
|
+
return {
|
|
363
|
+
get: (path, options)=>withRetry(()=>baseTransport.get(path, options)),
|
|
364
|
+
post: (path, body, options)=>withRetry(()=>baseTransport.post(path, body, options)),
|
|
365
|
+
patch: (path, body, options)=>withRetry(()=>baseTransport.patch(path, body, options)),
|
|
366
|
+
put: (path, body, options)=>withRetry(()=>baseTransport.put(path, body, options)),
|
|
367
|
+
delete: (path, options)=>withRetry(()=>baseTransport.delete(path, options))
|
|
368
|
+
};
|
|
369
|
+
}
|
|
370
|
+
// ─────────────────────────────────────────────────────────────────────────────
|
|
190
371
|
// Context
|
|
191
372
|
// ─────────────────────────────────────────────────────────────────────────────
|
|
192
373
|
const Blocks23Context = /*#__PURE__*/ createContext(null);
|
|
@@ -280,10 +461,22 @@ const Blocks23Context = /*#__PURE__*/ createContext(null);
|
|
|
280
461
|
* <App />
|
|
281
462
|
* </Provider>
|
|
282
463
|
* ```
|
|
283
|
-
*/ function Provider({ children, urls, apiKey, tenantId, authMode = 'token', storage = 'localStorage', customStorage, headers: staticHeaders = {}, timeout }) {
|
|
464
|
+
*/ function Provider({ children, urls, apiKey, tenantId, authMode = 'token', storage = 'localStorage', customStorage, headers: staticHeaders = {}, timeout, tokenLifecycle: lifecycleConfig = {} }) {
|
|
284
465
|
// Track if async storage has loaded tokens
|
|
285
466
|
const [isReady, setIsReady] = useState(!customStorage);
|
|
286
467
|
const tokenManagerRef = useRef(null);
|
|
468
|
+
const lifecycleRef = useRef(null);
|
|
469
|
+
// Buffer listeners registered before lifecycle is initialized
|
|
470
|
+
const pendingListenersRef = useRef(new Set());
|
|
471
|
+
const lifecycleEnabled = authMode === 'token' && lifecycleConfig !== false;
|
|
472
|
+
// Stabilize object props to prevent cascading memo invalidation
|
|
473
|
+
// when consumers pass inline objects (e.g., headers={{}} or tokenLifecycle={{}})
|
|
474
|
+
const headersJson = JSON.stringify(staticHeaders);
|
|
475
|
+
const headersRef = useRef(staticHeaders);
|
|
476
|
+
headersRef.current = staticHeaders;
|
|
477
|
+
const lifecycleConfigJson = typeof lifecycleConfig === 'object' ? JSON.stringify(lifecycleConfig) : String(lifecycleConfig);
|
|
478
|
+
const lifecycleConfigRef = useRef(lifecycleConfig);
|
|
479
|
+
lifecycleConfigRef.current = lifecycleConfig;
|
|
287
480
|
// Create token manager (memoized) with scoped storage keys
|
|
288
481
|
const tokenManager = useMemo(()=>{
|
|
289
482
|
if (authMode !== 'token') {
|
|
@@ -309,14 +502,14 @@ const Blocks23Context = /*#__PURE__*/ createContext(null);
|
|
|
309
502
|
tenantId,
|
|
310
503
|
customStorage
|
|
311
504
|
]);
|
|
312
|
-
// Factory to create transport for a specific service URL
|
|
313
|
-
const
|
|
505
|
+
// Factory to create base transport for a specific service URL
|
|
506
|
+
const createBaseTransport = useCallback((baseUrl)=>{
|
|
314
507
|
return createHttpTransport({
|
|
315
508
|
baseUrl,
|
|
316
509
|
timeout,
|
|
317
510
|
credentials: authMode === 'cookie' ? 'include' : undefined,
|
|
318
511
|
headers: ()=>{
|
|
319
|
-
const headers = _({},
|
|
512
|
+
const headers = _({}, headersRef.current, {
|
|
320
513
|
'x-api-key': apiKey
|
|
321
514
|
});
|
|
322
515
|
if (tenantId) {
|
|
@@ -331,13 +524,25 @@ const Blocks23Context = /*#__PURE__*/ createContext(null);
|
|
|
331
524
|
return headers;
|
|
332
525
|
}
|
|
333
526
|
});
|
|
527
|
+
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
334
528
|
}, [
|
|
335
529
|
apiKey,
|
|
336
530
|
tenantId,
|
|
337
531
|
authMode,
|
|
338
|
-
|
|
532
|
+
headersJson,
|
|
339
533
|
timeout
|
|
340
534
|
]);
|
|
535
|
+
// Factory to create transport with optional 401 retry
|
|
536
|
+
const createServiceTransport = useCallback((baseUrl)=>{
|
|
537
|
+
const base = createBaseTransport(baseUrl);
|
|
538
|
+
if (lifecycleEnabled) {
|
|
539
|
+
return createRetryTransport(base, ()=>lifecycleRef.current);
|
|
540
|
+
}
|
|
541
|
+
return base;
|
|
542
|
+
}, [
|
|
543
|
+
createBaseTransport,
|
|
544
|
+
lifecycleEnabled
|
|
545
|
+
]);
|
|
341
546
|
// Create blocks (memoized) - each with its own transport (no fallback)
|
|
342
547
|
const blockConfig = useMemo(()=>({
|
|
343
548
|
apiKey,
|
|
@@ -527,6 +732,50 @@ const Blocks23Context = /*#__PURE__*/ createContext(null);
|
|
|
527
732
|
urls.university,
|
|
528
733
|
blockConfig
|
|
529
734
|
]);
|
|
735
|
+
// Create and manage lifecycle manager
|
|
736
|
+
useEffect(()=>{
|
|
737
|
+
if (!lifecycleEnabled || !tokenManager || !urls.authentication) {
|
|
738
|
+
lifecycleRef.current = null;
|
|
739
|
+
return;
|
|
740
|
+
}
|
|
741
|
+
// Dedicated transport for refresh calls — NOT wrapped with retry to avoid circular 401 handling
|
|
742
|
+
const refreshTransport = createBaseTransport(urls.authentication);
|
|
743
|
+
const refreshAuthBlock = createAuthenticationBlock(refreshTransport, blockConfig);
|
|
744
|
+
const refreshFn = async (refreshToken)=>{
|
|
745
|
+
const response = await refreshAuthBlock.auth.refreshToken({
|
|
746
|
+
refreshToken
|
|
747
|
+
});
|
|
748
|
+
return {
|
|
749
|
+
accessToken: response.accessToken,
|
|
750
|
+
refreshToken: response.refreshToken,
|
|
751
|
+
expiresIn: response.expiresIn
|
|
752
|
+
};
|
|
753
|
+
};
|
|
754
|
+
const lcConfig = typeof lifecycleConfigRef.current === 'object' ? lifecycleConfigRef.current : {};
|
|
755
|
+
const lc = createLifecycleManager(tokenManager, refreshFn, lcConfig);
|
|
756
|
+
lifecycleRef.current = lc;
|
|
757
|
+
// Replay any listeners that were registered before lifecycle was ready
|
|
758
|
+
pendingListenersRef.current.forEach((listener)=>{
|
|
759
|
+
lc.onAuthStateChanged(listener);
|
|
760
|
+
});
|
|
761
|
+
pendingListenersRef.current.clear();
|
|
762
|
+
// Auto-start if tokens already exist (page reload)
|
|
763
|
+
if (tokenManager.getAccessToken() && tokenManager.getRefreshToken()) {
|
|
764
|
+
lc.start();
|
|
765
|
+
}
|
|
766
|
+
return ()=>{
|
|
767
|
+
lc.destroy();
|
|
768
|
+
lifecycleRef.current = null;
|
|
769
|
+
};
|
|
770
|
+
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
771
|
+
}, [
|
|
772
|
+
lifecycleEnabled,
|
|
773
|
+
tokenManager,
|
|
774
|
+
createBaseTransport,
|
|
775
|
+
blockConfig,
|
|
776
|
+
urls.authentication,
|
|
777
|
+
lifecycleConfigJson
|
|
778
|
+
]);
|
|
530
779
|
// Check if authentication is configured for auth methods
|
|
531
780
|
const isAuthConfigured = !!urls.authentication;
|
|
532
781
|
// Auth methods with automatic token management
|
|
@@ -536,7 +785,9 @@ const Blocks23Context = /*#__PURE__*/ createContext(null);
|
|
|
536
785
|
}
|
|
537
786
|
const response = await authentication.auth.signIn(request);
|
|
538
787
|
if (authMode === 'token' && tokenManager && response.accessToken) {
|
|
788
|
+
var _lifecycleRef_current;
|
|
539
789
|
tokenManager.setTokens(response.accessToken, response.refreshToken);
|
|
790
|
+
(_lifecycleRef_current = lifecycleRef.current) == null ? void 0 : _lifecycleRef_current.start();
|
|
540
791
|
}
|
|
541
792
|
return response;
|
|
542
793
|
}, [
|
|
@@ -551,7 +802,9 @@ const Blocks23Context = /*#__PURE__*/ createContext(null);
|
|
|
551
802
|
}
|
|
552
803
|
const response = await authentication.auth.signUp(request);
|
|
553
804
|
if (authMode === 'token' && tokenManager && response.accessToken) {
|
|
805
|
+
var _lifecycleRef_current;
|
|
554
806
|
tokenManager.setTokens(response.accessToken);
|
|
807
|
+
(_lifecycleRef_current = lifecycleRef.current) == null ? void 0 : _lifecycleRef_current.start();
|
|
555
808
|
}
|
|
556
809
|
return response;
|
|
557
810
|
}, [
|
|
@@ -561,9 +814,11 @@ const Blocks23Context = /*#__PURE__*/ createContext(null);
|
|
|
561
814
|
isAuthConfigured
|
|
562
815
|
]);
|
|
563
816
|
const signOut = useCallback(async ()=>{
|
|
817
|
+
var _lifecycleRef_current;
|
|
564
818
|
if (!isAuthConfigured) {
|
|
565
819
|
throw new Error('[23blocks] Cannot call signOut: The authentication service URL is not configured. ' + "Add 'urls.authentication' to your Provider configuration.");
|
|
566
820
|
}
|
|
821
|
+
(_lifecycleRef_current = lifecycleRef.current) == null ? void 0 : _lifecycleRef_current.stop();
|
|
567
822
|
await authentication.auth.signOut();
|
|
568
823
|
if (authMode === 'token' && tokenManager) {
|
|
569
824
|
tokenManager.clearTokens();
|
|
@@ -574,6 +829,40 @@ const Blocks23Context = /*#__PURE__*/ createContext(null);
|
|
|
574
829
|
tokenManager,
|
|
575
830
|
isAuthConfigured
|
|
576
831
|
]);
|
|
832
|
+
const verifyMagicLink = useCallback(async (request)=>{
|
|
833
|
+
if (!isAuthConfigured) {
|
|
834
|
+
throw new Error('[23blocks] Cannot call verifyMagicLink: The authentication service URL is not configured. ' + "Add 'urls.authentication' to your Provider configuration.");
|
|
835
|
+
}
|
|
836
|
+
const response = await authentication.auth.verifyMagicLink(request);
|
|
837
|
+
if (authMode === 'token' && tokenManager && response.accessToken) {
|
|
838
|
+
var _lifecycleRef_current;
|
|
839
|
+
tokenManager.setTokens(response.accessToken, response.refreshToken);
|
|
840
|
+
(_lifecycleRef_current = lifecycleRef.current) == null ? void 0 : _lifecycleRef_current.start();
|
|
841
|
+
}
|
|
842
|
+
return response;
|
|
843
|
+
}, [
|
|
844
|
+
authentication,
|
|
845
|
+
authMode,
|
|
846
|
+
tokenManager,
|
|
847
|
+
isAuthConfigured
|
|
848
|
+
]);
|
|
849
|
+
const acceptInvitation = useCallback(async (request)=>{
|
|
850
|
+
if (!isAuthConfigured) {
|
|
851
|
+
throw new Error('[23blocks] Cannot call acceptInvitation: The authentication service URL is not configured. ' + "Add 'urls.authentication' to your Provider configuration.");
|
|
852
|
+
}
|
|
853
|
+
const response = await authentication.auth.acceptInvitation(request);
|
|
854
|
+
if (authMode === 'token' && tokenManager && response.accessToken) {
|
|
855
|
+
var _lifecycleRef_current;
|
|
856
|
+
tokenManager.setTokens(response.accessToken, response.refreshToken);
|
|
857
|
+
(_lifecycleRef_current = lifecycleRef.current) == null ? void 0 : _lifecycleRef_current.start();
|
|
858
|
+
}
|
|
859
|
+
return response;
|
|
860
|
+
}, [
|
|
861
|
+
authentication,
|
|
862
|
+
authMode,
|
|
863
|
+
tokenManager,
|
|
864
|
+
isAuthConfigured
|
|
865
|
+
]);
|
|
577
866
|
// Token utilities
|
|
578
867
|
const getAccessToken = useCallback(()=>{
|
|
579
868
|
var _tokenManager_getAccessToken;
|
|
@@ -608,6 +897,24 @@ const Blocks23Context = /*#__PURE__*/ createContext(null);
|
|
|
608
897
|
}, [
|
|
609
898
|
tokenManager
|
|
610
899
|
]);
|
|
900
|
+
const onAuthStateChanged = useCallback((listener)=>{
|
|
901
|
+
const lc = lifecycleRef.current;
|
|
902
|
+
if (lc) {
|
|
903
|
+
return lc.onAuthStateChanged(listener);
|
|
904
|
+
}
|
|
905
|
+
// Lifecycle not ready yet — buffer the listener for replay when it initializes
|
|
906
|
+
pendingListenersRef.current.add(listener);
|
|
907
|
+
return ()=>{
|
|
908
|
+
pendingListenersRef.current.delete(listener);
|
|
909
|
+
};
|
|
910
|
+
}, []);
|
|
911
|
+
const refreshSession = useCallback(async ()=>{
|
|
912
|
+
const lc = lifecycleRef.current;
|
|
913
|
+
if (!lc) {
|
|
914
|
+
throw new Error('[23blocks] Token lifecycle is not available. ' + 'Ensure authMode is "token" and tokenLifecycle is not disabled.');
|
|
915
|
+
}
|
|
916
|
+
return lc.refreshNow();
|
|
917
|
+
}, []);
|
|
611
918
|
const value = useMemo(()=>({
|
|
612
919
|
// Blocks
|
|
613
920
|
authentication,
|
|
@@ -632,6 +939,8 @@ const Blocks23Context = /*#__PURE__*/ createContext(null);
|
|
|
632
939
|
signIn,
|
|
633
940
|
signUp,
|
|
634
941
|
signOut,
|
|
942
|
+
verifyMagicLink,
|
|
943
|
+
acceptInvitation,
|
|
635
944
|
// Token utilities
|
|
636
945
|
getAccessToken,
|
|
637
946
|
getRefreshToken,
|
|
@@ -639,6 +948,9 @@ const Blocks23Context = /*#__PURE__*/ createContext(null);
|
|
|
639
948
|
clearTokens,
|
|
640
949
|
isAuthenticated,
|
|
641
950
|
onStorageChange,
|
|
951
|
+
// Lifecycle
|
|
952
|
+
onAuthStateChanged,
|
|
953
|
+
refreshSession,
|
|
642
954
|
// Config
|
|
643
955
|
authMode,
|
|
644
956
|
isReady
|
|
@@ -664,12 +976,16 @@ const Blocks23Context = /*#__PURE__*/ createContext(null);
|
|
|
664
976
|
signIn,
|
|
665
977
|
signUp,
|
|
666
978
|
signOut,
|
|
979
|
+
verifyMagicLink,
|
|
980
|
+
acceptInvitation,
|
|
667
981
|
getAccessToken,
|
|
668
982
|
getRefreshToken,
|
|
669
983
|
setTokens,
|
|
670
984
|
clearTokens,
|
|
671
985
|
isAuthenticated,
|
|
672
986
|
onStorageChange,
|
|
987
|
+
onAuthStateChanged,
|
|
988
|
+
refreshSession,
|
|
673
989
|
authMode,
|
|
674
990
|
isReady
|
|
675
991
|
]);
|
|
@@ -776,12 +1092,12 @@ const Blocks23Context = /*#__PURE__*/ createContext(null);
|
|
|
776
1092
|
updatePassword: (...args)=>getAuth().updatePassword(...args),
|
|
777
1093
|
// Token refresh
|
|
778
1094
|
refreshToken: (...args)=>getAuth().refreshToken(...args),
|
|
779
|
-
// Magic link (passwordless)
|
|
1095
|
+
// Magic link (passwordless) — verifyMagicLink uses managed wrapper with token storage
|
|
780
1096
|
requestMagicLink: (...args)=>getAuth().requestMagicLink(...args),
|
|
781
|
-
verifyMagicLink:
|
|
782
|
-
// Invitations
|
|
1097
|
+
verifyMagicLink: context.verifyMagicLink,
|
|
1098
|
+
// Invitations — acceptInvitation uses managed wrapper with token storage
|
|
783
1099
|
sendInvitation: (...args)=>getAuth().sendInvitation(...args),
|
|
784
|
-
acceptInvitation:
|
|
1100
|
+
acceptInvitation: context.acceptInvitation,
|
|
785
1101
|
resendInvitation: (...args)=>getAuth().resendInvitation(...args),
|
|
786
1102
|
// Email confirmation
|
|
787
1103
|
confirmEmail: (...args)=>getAuth().confirmEmail(...args),
|
|
@@ -795,6 +1111,9 @@ const Blocks23Context = /*#__PURE__*/ createContext(null);
|
|
|
795
1111
|
// Token validation
|
|
796
1112
|
validateToken: ()=>getAuth().validateToken(),
|
|
797
1113
|
getCurrentUser: ()=>getAuth().getCurrentUser(),
|
|
1114
|
+
// Token lifecycle
|
|
1115
|
+
onAuthStateChanged: context.onAuthStateChanged,
|
|
1116
|
+
refreshSession: context.refreshSession,
|
|
798
1117
|
// Full block access for advanced usage
|
|
799
1118
|
authentication: context.authentication
|
|
800
1119
|
};
|
package/dist/src/lib/index.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
export { Provider, useClient, useAuth, useUser, type ProviderProps, type ClientContext, type ServiceUrls, type AuthMode, type StorageType, type TokenManager, type AsyncStorageInterface, type UseUserReturn, SimpleBlocks23Provider, useSimpleBlocks23, useSimpleAuth, type SimpleBlocks23ProviderProps, type SimpleBlocks23Context, } from './simple-provider.js';
|
|
1
|
+
export { Provider, useClient, useAuth, useUser, type ProviderProps, type ClientContext, type ServiceUrls, type AuthMode, type StorageType, type TokenManager, type AsyncStorageInterface, type UseUserReturn, type AuthStateEvent, type AuthStateListener, type TokenLifecycleConfig, SimpleBlocks23Provider, useSimpleBlocks23, useSimpleAuth, type SimpleBlocks23ProviderProps, type SimpleBlocks23Context, } from './simple-provider.js';
|
|
2
2
|
export { Blocks23Provider, use23Blocks, useAuthenticationBlock, useSearchBlock, useProductsBlock, useCrmBlock, useContentBlock, useGeolocationBlock, useConversationsBlock, useFilesBlock, useFormsBlock, useAssetsBlock, useCampaignsBlock, useCompanyBlock, useRewardsBlock, useSalesBlock, useWalletBlock, useJarvisBlock, useOnboardingBlock, useUniversityBlock, type Blocks23ProviderProps, type Blocks23Context, } from './context.js';
|
|
3
3
|
export { useUsers, type UseUsersReturn, type UseUsersState, type UseUsersActions, useMfa, type UseMfaReturn, type UseMfaState, type UseMfaActions, useOAuth, type UseOAuthReturn, type UseOAuthState, type UseOAuthActions, useAvatars, type UseAvatarsReturn, type UseAvatarsState, type UseAvatarsActions, useTenants, type UseTenantsReturn, type UseTenantsState, type UseTenantsActions, useSearch, useFavorites, type UseSearchReturn, type UseSearchState, type UseSearchActions, type UseFavoritesReturn, type UseFavoritesState, type UseFavoritesActions, useContentSeries, type UseContentSeriesReturn, type UseContentSeriesState, type UseContentSeriesActions, } from './hooks/index.js';
|
|
4
4
|
//# sourceMappingURL=index.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/lib/index.ts"],"names":[],"mappings":"AAGA,OAAO,EAEL,QAAQ,EACR,SAAS,EACT,OAAO,EACP,OAAO,EACP,KAAK,aAAa,EAClB,KAAK,aAAa,EAClB,KAAK,WAAW,EAChB,KAAK,QAAQ,EACb,KAAK,WAAW,EAChB,KAAK,YAAY,EACjB,KAAK,qBAAqB,EAC1B,KAAK,aAAa,
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/lib/index.ts"],"names":[],"mappings":"AAGA,OAAO,EAEL,QAAQ,EACR,SAAS,EACT,OAAO,EACP,OAAO,EACP,KAAK,aAAa,EAClB,KAAK,aAAa,EAClB,KAAK,WAAW,EAChB,KAAK,QAAQ,EACb,KAAK,WAAW,EAChB,KAAK,YAAY,EACjB,KAAK,qBAAqB,EAC1B,KAAK,aAAa,EAClB,KAAK,cAAc,EACnB,KAAK,iBAAiB,EACtB,KAAK,oBAAoB,EAGzB,sBAAsB,EACtB,iBAAiB,EACjB,aAAa,EACb,KAAK,2BAA2B,EAChC,KAAK,qBAAqB,GAC3B,MAAM,sBAAsB,CAAC;AAM9B,OAAO,EACL,gBAAgB,EAChB,WAAW,EACX,sBAAsB,EACtB,cAAc,EACd,gBAAgB,EAChB,WAAW,EACX,eAAe,EACf,mBAAmB,EACnB,qBAAqB,EACrB,aAAa,EACb,aAAa,EACb,cAAc,EACd,iBAAiB,EACjB,eAAe,EACf,eAAe,EACf,aAAa,EACb,cAAc,EACd,cAAc,EACd,kBAAkB,EAClB,kBAAkB,EAClB,KAAK,qBAAqB,EAC1B,KAAK,eAAe,GACrB,MAAM,cAAc,CAAC;AAGtB,OAAO,EAEL,QAAQ,EACR,KAAK,cAAc,EACnB,KAAK,aAAa,EAClB,KAAK,eAAe,EAGpB,MAAM,EACN,KAAK,YAAY,EACjB,KAAK,WAAW,EAChB,KAAK,aAAa,EAGlB,QAAQ,EACR,KAAK,cAAc,EACnB,KAAK,aAAa,EAClB,KAAK,eAAe,EAGpB,UAAU,EACV,KAAK,gBAAgB,EACrB,KAAK,eAAe,EACpB,KAAK,iBAAiB,EAGtB,UAAU,EACV,KAAK,gBAAgB,EACrB,KAAK,eAAe,EACpB,KAAK,iBAAiB,EAGtB,SAAS,EACT,YAAY,EACZ,KAAK,eAAe,EACpB,KAAK,cAAc,EACnB,KAAK,gBAAgB,EACrB,KAAK,kBAAkB,EACvB,KAAK,iBAAiB,EACtB,KAAK,mBAAmB,EAGxB,gBAAgB,EAChB,KAAK,sBAAsB,EAC3B,KAAK,qBAAqB,EAC1B,KAAK,uBAAuB,GAC7B,MAAM,kBAAkB,CAAC"}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { type ReactNode } from 'react';
|
|
2
|
-
import { type AuthenticationBlock, type SignInRequest, type SignInResponse, type SignUpRequest, type SignUpResponse, type User, type UpdateProfileRequest } from '@23blocks/block-authentication';
|
|
2
|
+
import { type AuthenticationBlock, type SignInRequest, type SignInResponse, type SignUpRequest, type SignUpResponse, type MagicLinkVerifyRequest, type AcceptInvitationRequest, type User, type UpdateProfileRequest } from '@23blocks/block-authentication';
|
|
3
3
|
import { type SearchBlock } from '@23blocks/block-search';
|
|
4
4
|
import { type ProductsBlock } from '@23blocks/block-products';
|
|
5
5
|
import { type CrmBlock } from '@23blocks/block-crm';
|
|
@@ -90,6 +90,25 @@ export interface ServiceUrls {
|
|
|
90
90
|
/** University (LMS) service URL */
|
|
91
91
|
university?: string;
|
|
92
92
|
}
|
|
93
|
+
/**
|
|
94
|
+
* Auth state change events emitted by the token lifecycle manager
|
|
95
|
+
*/
|
|
96
|
+
export type AuthStateEvent = 'SIGNED_IN' | 'SIGNED_OUT' | 'TOKEN_REFRESHED' | 'SESSION_EXPIRED';
|
|
97
|
+
/**
|
|
98
|
+
* Callback invoked when auth state changes
|
|
99
|
+
*/
|
|
100
|
+
export type AuthStateListener = (event: AuthStateEvent) => void;
|
|
101
|
+
/**
|
|
102
|
+
* Configuration for automatic token lifecycle management
|
|
103
|
+
*/
|
|
104
|
+
export interface TokenLifecycleConfig {
|
|
105
|
+
/** Seconds before token expiry to trigger a proactive refresh. @default 120 */
|
|
106
|
+
refreshBufferSeconds?: number;
|
|
107
|
+
/** Refresh token when tab becomes visible. @default true */
|
|
108
|
+
enableVisibilityRefresh?: boolean;
|
|
109
|
+
/** Schedule proactive refresh based on JWT `exp` claim. @default true */
|
|
110
|
+
enableProactiveRefresh?: boolean;
|
|
111
|
+
}
|
|
93
112
|
/**
|
|
94
113
|
* Provider props
|
|
95
114
|
*/
|
|
@@ -181,6 +200,16 @@ export interface ProviderProps {
|
|
|
181
200
|
* @default 30000
|
|
182
201
|
*/
|
|
183
202
|
timeout?: number;
|
|
203
|
+
/**
|
|
204
|
+
* Token lifecycle configuration for automatic refresh and 401 retry.
|
|
205
|
+
* - Pass an object to customize (e.g., `{ refreshBufferSeconds: 60 }`)
|
|
206
|
+
* - Pass `false` to disable entirely
|
|
207
|
+
* - Omit or pass `{}` to use defaults (enabled with 120s buffer)
|
|
208
|
+
*
|
|
209
|
+
* Only applies in token mode. Ignored in cookie mode.
|
|
210
|
+
* @default {} (enabled with defaults)
|
|
211
|
+
*/
|
|
212
|
+
tokenLifecycle?: TokenLifecycleConfig | false;
|
|
184
213
|
}
|
|
185
214
|
/**
|
|
186
215
|
* Context value providing access to all 23blocks services
|
|
@@ -207,6 +236,10 @@ export interface ClientContext {
|
|
|
207
236
|
signIn: (request: SignInRequest) => Promise<SignInResponse>;
|
|
208
237
|
signUp: (request: SignUpRequest) => Promise<SignUpResponse>;
|
|
209
238
|
signOut: () => Promise<void>;
|
|
239
|
+
/** Verify magic link and store tokens. Starts lifecycle for proactive refresh. */
|
|
240
|
+
verifyMagicLink: (request: MagicLinkVerifyRequest) => Promise<SignInResponse>;
|
|
241
|
+
/** Accept invitation and store tokens. Starts lifecycle for proactive refresh. */
|
|
242
|
+
acceptInvitation: (request: AcceptInvitationRequest) => Promise<SignInResponse>;
|
|
210
243
|
getAccessToken: () => string | null;
|
|
211
244
|
getRefreshToken: () => string | null;
|
|
212
245
|
setTokens: (accessToken: string, refreshToken?: string) => void;
|
|
@@ -217,6 +250,16 @@ export interface ClientContext {
|
|
|
217
250
|
* Returns an unsubscribe function.
|
|
218
251
|
*/
|
|
219
252
|
onStorageChange: (callback: () => void) => () => void;
|
|
253
|
+
/**
|
|
254
|
+
* Subscribe to auth state changes (token refreshed, session expired, etc.).
|
|
255
|
+
* Returns an unsubscribe function.
|
|
256
|
+
*/
|
|
257
|
+
onAuthStateChanged: (listener: AuthStateListener) => () => void;
|
|
258
|
+
/**
|
|
259
|
+
* Force an immediate token refresh.
|
|
260
|
+
* Returns the new access token on success.
|
|
261
|
+
*/
|
|
262
|
+
refreshSession: () => Promise<string>;
|
|
220
263
|
authMode: AuthMode;
|
|
221
264
|
/**
|
|
222
265
|
* Whether the provider has finished loading tokens from async storage.
|
|
@@ -304,7 +347,7 @@ export interface ClientContext {
|
|
|
304
347
|
* </Provider>
|
|
305
348
|
* ```
|
|
306
349
|
*/
|
|
307
|
-
export declare function Provider({ children, urls, apiKey, tenantId, authMode, storage, customStorage, headers: staticHeaders, timeout, }: ProviderProps): import("react/jsx-runtime").JSX.Element;
|
|
350
|
+
export declare function Provider({ children, urls, apiKey, tenantId, authMode, storage, customStorage, headers: staticHeaders, timeout, tokenLifecycle: lifecycleConfig, }: ProviderProps): import("react/jsx-runtime").JSX.Element;
|
|
308
351
|
/**
|
|
309
352
|
* Hook to access all 23blocks services.
|
|
310
353
|
*
|
|
@@ -389,9 +432,9 @@ export declare function useAuth(): {
|
|
|
389
432
|
updatePassword: (request: import("@23blocks/block-authentication").PasswordUpdateRequest) => Promise<void>;
|
|
390
433
|
refreshToken: (request: import("@23blocks/block-authentication").RefreshTokenRequest) => Promise<import("@23blocks/block-authentication").RefreshTokenResponse>;
|
|
391
434
|
requestMagicLink: (request: import("@23blocks/block-authentication").MagicLinkRequest) => Promise<void>;
|
|
392
|
-
verifyMagicLink: (request:
|
|
435
|
+
verifyMagicLink: (request: MagicLinkVerifyRequest) => Promise<SignInResponse>;
|
|
393
436
|
sendInvitation: (request: import("@23blocks/block-authentication").InvitationRequest) => Promise<void>;
|
|
394
|
-
acceptInvitation: (request:
|
|
437
|
+
acceptInvitation: (request: AcceptInvitationRequest) => Promise<SignInResponse>;
|
|
395
438
|
resendInvitation: (request: import("@23blocks/block-authentication").ResendInvitationRequest) => Promise<User>;
|
|
396
439
|
confirmEmail: (token: string) => Promise<User>;
|
|
397
440
|
resendConfirmation: (request: import("@23blocks/block-authentication").ResendConfirmationRequest) => Promise<void>;
|
|
@@ -401,6 +444,8 @@ export declare function useAuth(): {
|
|
|
401
444
|
completeAccountRecovery: (request: import("@23blocks/block-authentication").CompleteRecoveryRequest) => Promise<User>;
|
|
402
445
|
validateToken: () => Promise<import("@23blocks/block-authentication").TokenValidationResponse>;
|
|
403
446
|
getCurrentUser: () => Promise<User>;
|
|
447
|
+
onAuthStateChanged: (listener: AuthStateListener) => () => void;
|
|
448
|
+
refreshSession: () => Promise<string>;
|
|
404
449
|
authentication: AuthenticationBlock;
|
|
405
450
|
};
|
|
406
451
|
/**
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"simple-provider.d.ts","sourceRoot":"","sources":["../../../src/lib/simple-provider.tsx"],"names":[],"mappings":"AAAA,OAAO,EAAgF,KAAK,SAAS,EAAE,MAAM,OAAO,CAAC;
|
|
1
|
+
{"version":3,"file":"simple-provider.d.ts","sourceRoot":"","sources":["../../../src/lib/simple-provider.tsx"],"names":[],"mappings":"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"}
|