@23blocks/angular 14.4.0 β 14.5.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/CHANGELOG.md +11 -0
- package/dist/fesm2022/23blocks-angular.mjs +326 -15
- package/dist/fesm2022/23blocks-angular.mjs.map +1 -1
- package/dist/index.d.ts +59 -4
- package/dist/index.d.ts.map +1 -1
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -1,3 +1,14 @@
|
|
|
1
|
+
## 14.5.0 (2026-03-14)
|
|
2
|
+
|
|
3
|
+
### π Features
|
|
4
|
+
|
|
5
|
+
- **@23blocks/angular:** integrate token lifecycle with AuthenticationService ([df3c6c3](https://github.com/23blocks-OS/frontend-sdk/commit/df3c6c3))
|
|
6
|
+
|
|
7
|
+
### β€οΈ Thank You
|
|
8
|
+
|
|
9
|
+
- Claude Opus 4.6
|
|
10
|
+
- Juan Pelaez
|
|
11
|
+
|
|
1
12
|
## 14.4.0 (2026-03-09)
|
|
2
13
|
|
|
3
14
|
### π Features
|
|
@@ -1,8 +1,9 @@
|
|
|
1
1
|
import * as i0 from '@angular/core';
|
|
2
2
|
import { InjectionToken, makeEnvironmentProviders, Optional, Inject, Injectable } from '@angular/core';
|
|
3
3
|
import { createHttpTransport } from '@23blocks/transport-http';
|
|
4
|
-
import {
|
|
4
|
+
import { BlockErrorException } from '@23blocks/contracts';
|
|
5
5
|
import { createAuthenticationBlock } from '@23blocks/block-authentication';
|
|
6
|
+
import { from, tap } from 'rxjs';
|
|
6
7
|
import { createSearchBlock } from '@23blocks/block-search';
|
|
7
8
|
import { createProductsBlock } from '@23blocks/block-products';
|
|
8
9
|
import { createCrmBlock } from '@23blocks/block-crm';
|
|
@@ -148,6 +149,10 @@ const WALLET_CONFIG = new InjectionToken('23blocks.wallet.config');
|
|
|
148
149
|
*/
|
|
149
150
|
const RAG_CONFIG = new InjectionToken('23blocks.rag.config');
|
|
150
151
|
|
|
152
|
+
/**
|
|
153
|
+
* Injection token for the token lifecycle manager
|
|
154
|
+
*/
|
|
155
|
+
const TOKEN_LIFECYCLE = new InjectionToken('23blocks.token-lifecycle');
|
|
151
156
|
/**
|
|
152
157
|
* Injection token for the token manager (internal use)
|
|
153
158
|
*/
|
|
@@ -287,6 +292,211 @@ function createTransportWithAuth(baseUrl, config, tokenManager) {
|
|
|
287
292
|
},
|
|
288
293
|
});
|
|
289
294
|
}
|
|
295
|
+
// βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
|
|
296
|
+
// Token Lifecycle Helpers
|
|
297
|
+
// βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
|
|
298
|
+
function decodeJwtExp(token) {
|
|
299
|
+
try {
|
|
300
|
+
const parts = token.split('.');
|
|
301
|
+
if (parts.length !== 3)
|
|
302
|
+
return null;
|
|
303
|
+
let payload = parts[1].replace(/-/g, '+').replace(/_/g, '/');
|
|
304
|
+
const pad = payload.length % 4;
|
|
305
|
+
if (pad)
|
|
306
|
+
payload += '='.repeat(4 - pad);
|
|
307
|
+
let decoded;
|
|
308
|
+
if (typeof atob === 'function') {
|
|
309
|
+
decoded = atob(payload);
|
|
310
|
+
}
|
|
311
|
+
else if (typeof Buffer !== 'undefined') {
|
|
312
|
+
decoded = Buffer.from(payload, 'base64').toString('utf-8');
|
|
313
|
+
}
|
|
314
|
+
else {
|
|
315
|
+
return null;
|
|
316
|
+
}
|
|
317
|
+
const parsed = JSON.parse(decoded);
|
|
318
|
+
return typeof parsed.exp === 'number' ? parsed.exp : null;
|
|
319
|
+
}
|
|
320
|
+
catch {
|
|
321
|
+
return null;
|
|
322
|
+
}
|
|
323
|
+
}
|
|
324
|
+
function isBrowserEnv() {
|
|
325
|
+
try {
|
|
326
|
+
return typeof window !== 'undefined'
|
|
327
|
+
&& typeof window.localStorage !== 'undefined'
|
|
328
|
+
&& typeof window.localStorage.getItem === 'function';
|
|
329
|
+
}
|
|
330
|
+
catch {
|
|
331
|
+
return false;
|
|
332
|
+
}
|
|
333
|
+
}
|
|
334
|
+
function createLifecycleManager(tokenManager, refreshFn, config = {}) {
|
|
335
|
+
const { refreshBufferSeconds = 120, enableVisibilityRefresh = true, enableProactiveRefresh = true, } = config;
|
|
336
|
+
const listeners = new Set();
|
|
337
|
+
let refreshTimer = null;
|
|
338
|
+
let refreshPromise = null;
|
|
339
|
+
let visibilityHandler = null;
|
|
340
|
+
let destroyed = false;
|
|
341
|
+
let running = false;
|
|
342
|
+
function notify(event) {
|
|
343
|
+
listeners.forEach((l) => { try {
|
|
344
|
+
l(event);
|
|
345
|
+
}
|
|
346
|
+
catch { } });
|
|
347
|
+
}
|
|
348
|
+
function clearTimer() {
|
|
349
|
+
if (refreshTimer !== null) {
|
|
350
|
+
clearTimeout(refreshTimer);
|
|
351
|
+
refreshTimer = null;
|
|
352
|
+
}
|
|
353
|
+
}
|
|
354
|
+
function scheduleRefresh() {
|
|
355
|
+
if (!enableProactiveRefresh || destroyed || !running)
|
|
356
|
+
return;
|
|
357
|
+
clearTimer();
|
|
358
|
+
const accessToken = tokenManager.getAccessToken();
|
|
359
|
+
if (!accessToken)
|
|
360
|
+
return;
|
|
361
|
+
const exp = decodeJwtExp(accessToken);
|
|
362
|
+
if (!exp)
|
|
363
|
+
return;
|
|
364
|
+
const refreshInSeconds = (exp - Math.floor(Date.now() / 1000)) - refreshBufferSeconds;
|
|
365
|
+
if (refreshInSeconds <= 0) {
|
|
366
|
+
refreshNow().catch(() => { });
|
|
367
|
+
return;
|
|
368
|
+
}
|
|
369
|
+
refreshTimer = setTimeout(() => {
|
|
370
|
+
if (!destroyed && running)
|
|
371
|
+
refreshNow().catch(() => { });
|
|
372
|
+
}, refreshInSeconds * 1000);
|
|
373
|
+
}
|
|
374
|
+
function handleVisibilityChange() {
|
|
375
|
+
if (destroyed || !running || typeof document === 'undefined')
|
|
376
|
+
return;
|
|
377
|
+
if (document.visibilityState === 'visible') {
|
|
378
|
+
const accessToken = tokenManager.getAccessToken();
|
|
379
|
+
if (!accessToken)
|
|
380
|
+
return;
|
|
381
|
+
const exp = decodeJwtExp(accessToken);
|
|
382
|
+
if (!exp) {
|
|
383
|
+
refreshNow().catch(() => { });
|
|
384
|
+
return;
|
|
385
|
+
}
|
|
386
|
+
const secondsUntilExpiry = exp - Math.floor(Date.now() / 1000);
|
|
387
|
+
if (secondsUntilExpiry <= refreshBufferSeconds) {
|
|
388
|
+
refreshNow().catch(() => { });
|
|
389
|
+
}
|
|
390
|
+
else {
|
|
391
|
+
scheduleRefresh();
|
|
392
|
+
}
|
|
393
|
+
}
|
|
394
|
+
}
|
|
395
|
+
async function refreshNow() {
|
|
396
|
+
if (destroyed)
|
|
397
|
+
throw new Error('[23blocks] Lifecycle destroyed');
|
|
398
|
+
if (refreshPromise)
|
|
399
|
+
return refreshPromise;
|
|
400
|
+
refreshPromise = (async () => {
|
|
401
|
+
try {
|
|
402
|
+
const rt = tokenManager.getRefreshToken();
|
|
403
|
+
if (!rt)
|
|
404
|
+
throw new Error('No refresh token');
|
|
405
|
+
const result = await refreshFn(rt);
|
|
406
|
+
tokenManager.setTokens(result.accessToken, result.refreshToken);
|
|
407
|
+
scheduleRefresh();
|
|
408
|
+
notify('TOKEN_REFRESHED');
|
|
409
|
+
return result.accessToken;
|
|
410
|
+
}
|
|
411
|
+
catch (error) {
|
|
412
|
+
clearTimer();
|
|
413
|
+
tokenManager.clearTokens();
|
|
414
|
+
running = false;
|
|
415
|
+
notify('SESSION_EXPIRED');
|
|
416
|
+
throw error;
|
|
417
|
+
}
|
|
418
|
+
finally {
|
|
419
|
+
refreshPromise = null;
|
|
420
|
+
}
|
|
421
|
+
})();
|
|
422
|
+
return refreshPromise;
|
|
423
|
+
}
|
|
424
|
+
return {
|
|
425
|
+
start() {
|
|
426
|
+
if (destroyed)
|
|
427
|
+
return;
|
|
428
|
+
running = true;
|
|
429
|
+
scheduleRefresh();
|
|
430
|
+
if (enableVisibilityRefresh && isBrowserEnv() && !visibilityHandler && typeof document !== 'undefined') {
|
|
431
|
+
visibilityHandler = handleVisibilityChange;
|
|
432
|
+
document.addEventListener('visibilitychange', visibilityHandler);
|
|
433
|
+
}
|
|
434
|
+
},
|
|
435
|
+
stop() {
|
|
436
|
+
running = false;
|
|
437
|
+
clearTimer();
|
|
438
|
+
refreshPromise = null;
|
|
439
|
+
},
|
|
440
|
+
onAuthStateChanged(listener) {
|
|
441
|
+
listeners.add(listener);
|
|
442
|
+
return () => { listeners.delete(listener); };
|
|
443
|
+
},
|
|
444
|
+
refreshNow,
|
|
445
|
+
destroy() {
|
|
446
|
+
destroyed = true;
|
|
447
|
+
running = false;
|
|
448
|
+
clearTimer();
|
|
449
|
+
refreshPromise = null;
|
|
450
|
+
if (visibilityHandler && typeof document !== 'undefined') {
|
|
451
|
+
document.removeEventListener('visibilitychange', visibilityHandler);
|
|
452
|
+
visibilityHandler = null;
|
|
453
|
+
}
|
|
454
|
+
listeners.clear();
|
|
455
|
+
},
|
|
456
|
+
};
|
|
457
|
+
}
|
|
458
|
+
function createRetryTransport(baseTransport, getLifecycle) {
|
|
459
|
+
async function withRetry(fn) {
|
|
460
|
+
try {
|
|
461
|
+
return await fn();
|
|
462
|
+
}
|
|
463
|
+
catch (error) {
|
|
464
|
+
if (error instanceof BlockErrorException && error.status === 401) {
|
|
465
|
+
const lc = getLifecycle();
|
|
466
|
+
if (lc) {
|
|
467
|
+
try {
|
|
468
|
+
await lc.refreshNow();
|
|
469
|
+
return await fn();
|
|
470
|
+
}
|
|
471
|
+
catch {
|
|
472
|
+
throw error;
|
|
473
|
+
}
|
|
474
|
+
}
|
|
475
|
+
}
|
|
476
|
+
throw error;
|
|
477
|
+
}
|
|
478
|
+
}
|
|
479
|
+
return {
|
|
480
|
+
get(path, options) {
|
|
481
|
+
return withRetry(() => baseTransport.get(path, options));
|
|
482
|
+
},
|
|
483
|
+
post(path, body, options) {
|
|
484
|
+
return withRetry(() => baseTransport.post(path, body, options));
|
|
485
|
+
},
|
|
486
|
+
patch(path, body, options) {
|
|
487
|
+
return withRetry(() => baseTransport.patch(path, body, options));
|
|
488
|
+
},
|
|
489
|
+
put(path, body, options) {
|
|
490
|
+
return withRetry(() => baseTransport.put(path, body, options));
|
|
491
|
+
},
|
|
492
|
+
delete(path, options) {
|
|
493
|
+
return withRetry(() => baseTransport.delete(path, options));
|
|
494
|
+
},
|
|
495
|
+
};
|
|
496
|
+
}
|
|
497
|
+
// βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
|
|
498
|
+
// Providers
|
|
499
|
+
// βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
|
|
290
500
|
/**
|
|
291
501
|
* Provide 23blocks services with simplified configuration.
|
|
292
502
|
*
|
|
@@ -335,15 +545,20 @@ function createTransportWithAuth(baseUrl, config, tokenManager) {
|
|
|
335
545
|
function provideBlocks23(config) {
|
|
336
546
|
// Block config for all services
|
|
337
547
|
const blockConfig = { apiKey: config.apiKey, tenantId: config.tenantId };
|
|
548
|
+
const lifecycleEnabled = config.authMode !== 'cookie' && config.tokenLifecycle !== false;
|
|
338
549
|
// Helper to create transport provider for a service URL
|
|
339
550
|
const createTransportProvider = (token, url) => ({
|
|
340
551
|
provide: token,
|
|
341
|
-
useFactory: (tokenManager) => {
|
|
552
|
+
useFactory: (tokenManager, lifecycle) => {
|
|
342
553
|
if (!url)
|
|
343
554
|
return null;
|
|
344
|
-
|
|
555
|
+
const base = createTransportWithAuth(url, config, tokenManager);
|
|
556
|
+
if (lifecycleEnabled && lifecycle) {
|
|
557
|
+
return createRetryTransport(base, () => lifecycle);
|
|
558
|
+
}
|
|
559
|
+
return base;
|
|
345
560
|
},
|
|
346
|
-
deps: [TOKEN_MANAGER],
|
|
561
|
+
deps: [TOKEN_MANAGER, TOKEN_LIFECYCLE],
|
|
347
562
|
});
|
|
348
563
|
const providers = [
|
|
349
564
|
// Store config for injection
|
|
@@ -356,7 +571,34 @@ function provideBlocks23(config) {
|
|
|
356
571
|
return createTokenManager(config.apiKey, storage, config.tenantId);
|
|
357
572
|
},
|
|
358
573
|
},
|
|
359
|
-
//
|
|
574
|
+
// Token lifecycle manager - uses a dedicated refresh transport (avoids circular retry)
|
|
575
|
+
{
|
|
576
|
+
provide: TOKEN_LIFECYCLE,
|
|
577
|
+
useFactory: (tokenManager) => {
|
|
578
|
+
if (!lifecycleEnabled || !config.urls.authentication)
|
|
579
|
+
return null;
|
|
580
|
+
// Dedicated transport for refresh calls β NOT wrapped with retry
|
|
581
|
+
const refreshTransport = createTransportWithAuth(config.urls.authentication, config, tokenManager);
|
|
582
|
+
const authBlock = createAuthenticationBlock(refreshTransport, blockConfig);
|
|
583
|
+
const refreshFn = async (refreshToken) => {
|
|
584
|
+
const response = await authBlock.auth.refreshToken({ refreshToken });
|
|
585
|
+
return {
|
|
586
|
+
accessToken: response.accessToken,
|
|
587
|
+
refreshToken: response.refreshToken,
|
|
588
|
+
expiresIn: response.expiresIn,
|
|
589
|
+
};
|
|
590
|
+
};
|
|
591
|
+
const lcConfig = typeof config.tokenLifecycle === 'object' ? config.tokenLifecycle : {};
|
|
592
|
+
const lc = createLifecycleManager(tokenManager, refreshFn, lcConfig);
|
|
593
|
+
// Auto-start if tokens exist (page reload)
|
|
594
|
+
if (tokenManager.getAccessToken() && tokenManager.getRefreshToken()) {
|
|
595
|
+
lc.start();
|
|
596
|
+
}
|
|
597
|
+
return lc;
|
|
598
|
+
},
|
|
599
|
+
deps: [TOKEN_MANAGER],
|
|
600
|
+
},
|
|
601
|
+
// Per-service transport factories (null if URL not configured, wrapped with retry if lifecycle enabled)
|
|
360
602
|
createTransportProvider(AUTHENTICATION_TRANSPORT, config.urls.authentication),
|
|
361
603
|
createTransportProvider(SEARCH_TRANSPORT, config.urls.search),
|
|
362
604
|
createTransportProvider(PRODUCTS_TRANSPORT, config.urls.products),
|
|
@@ -448,15 +690,20 @@ function provideBlocks23(config) {
|
|
|
448
690
|
function getBlocks23Providers(config) {
|
|
449
691
|
// Block config for all services
|
|
450
692
|
const blockConfig = { apiKey: config.apiKey, tenantId: config.tenantId };
|
|
693
|
+
const lifecycleEnabled = config.authMode !== 'cookie' && config.tokenLifecycle !== false;
|
|
451
694
|
// Helper to create transport provider for a service URL
|
|
452
695
|
const createTransportProvider = (token, url) => ({
|
|
453
696
|
provide: token,
|
|
454
|
-
useFactory: (tokenManager) => {
|
|
697
|
+
useFactory: (tokenManager, lifecycle) => {
|
|
455
698
|
if (!url)
|
|
456
699
|
return null;
|
|
457
|
-
|
|
700
|
+
const base = createTransportWithAuth(url, config, tokenManager);
|
|
701
|
+
if (lifecycleEnabled && lifecycle) {
|
|
702
|
+
return createRetryTransport(base, () => lifecycle);
|
|
703
|
+
}
|
|
704
|
+
return base;
|
|
458
705
|
},
|
|
459
|
-
deps: [TOKEN_MANAGER],
|
|
706
|
+
deps: [TOKEN_MANAGER, TOKEN_LIFECYCLE],
|
|
460
707
|
});
|
|
461
708
|
return [
|
|
462
709
|
// Store config for injection
|
|
@@ -469,7 +716,28 @@ function getBlocks23Providers(config) {
|
|
|
469
716
|
return createTokenManager(config.apiKey, storage, config.tenantId);
|
|
470
717
|
},
|
|
471
718
|
},
|
|
472
|
-
//
|
|
719
|
+
// Token lifecycle manager
|
|
720
|
+
{
|
|
721
|
+
provide: TOKEN_LIFECYCLE,
|
|
722
|
+
useFactory: (tokenManager) => {
|
|
723
|
+
if (!lifecycleEnabled || !config.urls.authentication)
|
|
724
|
+
return null;
|
|
725
|
+
const refreshTransport = createTransportWithAuth(config.urls.authentication, config, tokenManager);
|
|
726
|
+
const authBlock = createAuthenticationBlock(refreshTransport, blockConfig);
|
|
727
|
+
const refreshFn = async (refreshToken) => {
|
|
728
|
+
const response = await authBlock.auth.refreshToken({ refreshToken });
|
|
729
|
+
return { accessToken: response.accessToken, refreshToken: response.refreshToken, expiresIn: response.expiresIn };
|
|
730
|
+
};
|
|
731
|
+
const lcConfig = typeof config.tokenLifecycle === 'object' ? config.tokenLifecycle : {};
|
|
732
|
+
const lc = createLifecycleManager(tokenManager, refreshFn, lcConfig);
|
|
733
|
+
if (tokenManager.getAccessToken() && tokenManager.getRefreshToken()) {
|
|
734
|
+
lc.start();
|
|
735
|
+
}
|
|
736
|
+
return lc;
|
|
737
|
+
},
|
|
738
|
+
deps: [TOKEN_MANAGER],
|
|
739
|
+
},
|
|
740
|
+
// Per-service transport factories (null if URL not configured, wrapped with retry if lifecycle enabled)
|
|
473
741
|
createTransportProvider(AUTHENTICATION_TRANSPORT, config.urls.authentication),
|
|
474
742
|
createTransportProvider(SEARCH_TRANSPORT, config.urls.search),
|
|
475
743
|
createTransportProvider(PRODUCTS_TRANSPORT, config.urls.products),
|
|
@@ -729,11 +997,13 @@ class AuthenticationService {
|
|
|
729
997
|
block;
|
|
730
998
|
tokenManager;
|
|
731
999
|
simpleConfig;
|
|
732
|
-
|
|
1000
|
+
lifecycle;
|
|
1001
|
+
constructor(serviceTransport, legacyTransport, config, tokenManager, simpleConfig, lifecycle) {
|
|
733
1002
|
const transport = serviceTransport ?? legacyTransport;
|
|
734
1003
|
this.block = transport ? createAuthenticationBlock(transport, config) : null;
|
|
735
1004
|
this.tokenManager = tokenManager;
|
|
736
1005
|
this.simpleConfig = simpleConfig;
|
|
1006
|
+
this.lifecycle = lifecycle;
|
|
737
1007
|
}
|
|
738
1008
|
ensureConfigured() {
|
|
739
1009
|
if (!this.block) {
|
|
@@ -768,7 +1038,11 @@ class AuthenticationService {
|
|
|
768
1038
|
* ```
|
|
769
1039
|
*/
|
|
770
1040
|
signIn(request) {
|
|
771
|
-
return from(this.ensureConfigured().auth.signIn(request)).pipe(tap((response) =>
|
|
1041
|
+
return from(this.ensureConfigured().auth.signIn(request)).pipe(tap((response) => {
|
|
1042
|
+
this.storeTokens(response);
|
|
1043
|
+
if (response.accessToken)
|
|
1044
|
+
this.lifecycle?.start();
|
|
1045
|
+
}));
|
|
772
1046
|
}
|
|
773
1047
|
/**
|
|
774
1048
|
* Sign up a new user.
|
|
@@ -784,6 +1058,7 @@ class AuthenticationService {
|
|
|
784
1058
|
return from(this.ensureConfigured().auth.signUp(request)).pipe(tap((response) => {
|
|
785
1059
|
if (this.isTokenMode && this.tokenManager && response.accessToken) {
|
|
786
1060
|
this.tokenManager.setTokens(response.accessToken);
|
|
1061
|
+
this.lifecycle?.start();
|
|
787
1062
|
}
|
|
788
1063
|
}));
|
|
789
1064
|
}
|
|
@@ -795,6 +1070,7 @@ class AuthenticationService {
|
|
|
795
1070
|
*/
|
|
796
1071
|
signOut() {
|
|
797
1072
|
return from(this.ensureConfigured().auth.signOut()).pipe(tap(() => {
|
|
1073
|
+
this.lifecycle?.stop();
|
|
798
1074
|
if (this.isTokenMode && this.tokenManager) {
|
|
799
1075
|
this.tokenManager.clearTokens();
|
|
800
1076
|
}
|
|
@@ -819,7 +1095,11 @@ class AuthenticationService {
|
|
|
819
1095
|
* @returns Observable emitting SignInResponse with `user`, `accessToken`, optional `refreshToken`
|
|
820
1096
|
*/
|
|
821
1097
|
verifyMagicLink(request) {
|
|
822
|
-
return from(this.ensureConfigured().auth.verifyMagicLink(request)).pipe(tap((response) =>
|
|
1098
|
+
return from(this.ensureConfigured().auth.verifyMagicLink(request)).pipe(tap((response) => {
|
|
1099
|
+
this.storeTokens(response);
|
|
1100
|
+
if (response.accessToken)
|
|
1101
|
+
this.lifecycle?.start();
|
|
1102
|
+
}));
|
|
823
1103
|
}
|
|
824
1104
|
/**
|
|
825
1105
|
* Accept an invitation and create the user's account.
|
|
@@ -830,7 +1110,11 @@ class AuthenticationService {
|
|
|
830
1110
|
* optional `refreshToken`
|
|
831
1111
|
*/
|
|
832
1112
|
acceptInvitation(request) {
|
|
833
|
-
return from(this.ensureConfigured().auth.acceptInvitation(request)).pipe(tap((response) =>
|
|
1113
|
+
return from(this.ensureConfigured().auth.acceptInvitation(request)).pipe(tap((response) => {
|
|
1114
|
+
this.storeTokens(response);
|
|
1115
|
+
if (response.accessToken)
|
|
1116
|
+
this.lifecycle?.start();
|
|
1117
|
+
}));
|
|
834
1118
|
}
|
|
835
1119
|
/**
|
|
836
1120
|
* Sign in via Facebook OAuth.
|
|
@@ -935,6 +1219,28 @@ class AuthenticationService {
|
|
|
935
1219
|
return !!this.tokenManager.getAccessToken();
|
|
936
1220
|
}
|
|
937
1221
|
// βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
|
|
1222
|
+
// Token Lifecycle
|
|
1223
|
+
// βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
|
|
1224
|
+
/**
|
|
1225
|
+
* Subscribe to auth state changes (token refreshed, session expired, etc.).
|
|
1226
|
+
* Returns an unsubscribe function.
|
|
1227
|
+
* Only active when tokenLifecycle is enabled.
|
|
1228
|
+
*/
|
|
1229
|
+
onAuthStateChanged(listener) {
|
|
1230
|
+
return this.lifecycle?.onAuthStateChanged(listener) ?? (() => { });
|
|
1231
|
+
}
|
|
1232
|
+
/**
|
|
1233
|
+
* Force an immediate token refresh.
|
|
1234
|
+
* Returns the new access token. Throws if lifecycle is unavailable or refresh fails.
|
|
1235
|
+
*/
|
|
1236
|
+
refreshSession() {
|
|
1237
|
+
if (!this.lifecycle) {
|
|
1238
|
+
return Promise.reject(new Error('[23blocks] Token lifecycle is not available. ' +
|
|
1239
|
+
'Ensure authMode is "token" and tokenLifecycle is not disabled.'));
|
|
1240
|
+
}
|
|
1241
|
+
return this.lifecycle.refreshNow();
|
|
1242
|
+
}
|
|
1243
|
+
// βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
|
|
938
1244
|
// Delegated sub-services (Promise-based, auto-sync with block API)
|
|
939
1245
|
// βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
|
|
940
1246
|
/** Core auth operations (signIn, signUp, signOut, password reset link+OTP, magic links, invitations). Promise-based. */
|
|
@@ -999,7 +1305,7 @@ class AuthenticationService {
|
|
|
999
1305
|
get oidc() { return this.ensureConfigured().oidc; }
|
|
1000
1306
|
/** Direct access to the underlying AuthenticationBlock instance */
|
|
1001
1307
|
get authenticationBlock() { return this.ensureConfigured(); }
|
|
1002
|
-
static Ι΅fac = i0.Ι΅Ι΅ngDeclareFactory({ minVersion: "12.0.0", version: "20.3.16", ngImport: i0, type: AuthenticationService, deps: [{ token: AUTHENTICATION_TRANSPORT, optional: true }, { token: TRANSPORT, optional: true }, { token: AUTHENTICATION_CONFIG }, { token: TOKEN_MANAGER, optional: true }, { token: SIMPLE_CONFIG, optional: true }], target: i0.Ι΅Ι΅FactoryTarget.Injectable });
|
|
1308
|
+
static Ι΅fac = i0.Ι΅Ι΅ngDeclareFactory({ minVersion: "12.0.0", version: "20.3.16", ngImport: i0, type: AuthenticationService, deps: [{ token: AUTHENTICATION_TRANSPORT, optional: true }, { token: TRANSPORT, optional: true }, { token: AUTHENTICATION_CONFIG }, { token: TOKEN_MANAGER, optional: true }, { token: SIMPLE_CONFIG, optional: true }, { token: TOKEN_LIFECYCLE, optional: true }], target: i0.Ι΅Ι΅FactoryTarget.Injectable });
|
|
1003
1309
|
static Ι΅prov = i0.Ι΅Ι΅ngDeclareInjectable({ minVersion: "12.0.0", version: "20.3.16", ngImport: i0, type: AuthenticationService, providedIn: 'root' });
|
|
1004
1310
|
}
|
|
1005
1311
|
i0.Ι΅Ι΅ngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.16", ngImport: i0, type: AuthenticationService, decorators: [{
|
|
@@ -1028,6 +1334,11 @@ i0.Ι΅Ι΅ngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.16", ngImpo
|
|
|
1028
1334
|
}, {
|
|
1029
1335
|
type: Inject,
|
|
1030
1336
|
args: [SIMPLE_CONFIG]
|
|
1337
|
+
}] }, { type: undefined, decorators: [{
|
|
1338
|
+
type: Optional
|
|
1339
|
+
}, {
|
|
1340
|
+
type: Inject,
|
|
1341
|
+
args: [TOKEN_LIFECYCLE]
|
|
1031
1342
|
}] }] });
|
|
1032
1343
|
|
|
1033
1344
|
/**
|
|
@@ -2130,5 +2441,5 @@ i0.Ι΅Ι΅ngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.16", ngImpo
|
|
|
2130
2441
|
* Generated bundle index. Do not edit.
|
|
2131
2442
|
*/
|
|
2132
2443
|
|
|
2133
|
-
export { ASSETS_CONFIG, ASSETS_TRANSPORT, AUTHENTICATION_CONFIG, AUTHENTICATION_TRANSPORT, AssetsService, AuthenticationService, CAMPAIGNS_CONFIG, CAMPAIGNS_TRANSPORT, COMPANY_CONFIG, COMPANY_TRANSPORT, CONTENT_CONFIG, CONTENT_TRANSPORT, CONVERSATIONS_CONFIG, CONVERSATIONS_TRANSPORT, CRM_CONFIG, CRM_TRANSPORT, CampaignsService, CompanyService, ContentService, ConversationsService, CrmService, FILES_CONFIG, FILES_TRANSPORT, FORMS_CONFIG, FORMS_TRANSPORT, FilesService, FormsService, GEOLOCATION_CONFIG, GEOLOCATION_TRANSPORT, GeolocationService, JARVIS_CONFIG, JARVIS_TRANSPORT, JarvisService, ONBOARDING_CONFIG, ONBOARDING_TRANSPORT, OnboardingService, PRODUCTS_CONFIG, PRODUCTS_TRANSPORT, PROVIDER_CONFIG, ProductsService, RAG_CONFIG, RAG_TRANSPORT, REWARDS_CONFIG, REWARDS_TRANSPORT, RagService, RewardsService, SALES_CONFIG, SALES_TRANSPORT, SEARCH_CONFIG, SEARCH_TRANSPORT, SIMPLE_CONFIG, SalesService, SearchService, TOKEN_MANAGER, TRANSPORT, UNIVERSITY_CONFIG, UNIVERSITY_TRANSPORT, UniversityService, WALLET_CONFIG, WALLET_TRANSPORT, WalletService, get23BlocksProviders, getBlocks23Providers, provide23Blocks, provideBlocks23 };
|
|
2444
|
+
export { ASSETS_CONFIG, ASSETS_TRANSPORT, AUTHENTICATION_CONFIG, AUTHENTICATION_TRANSPORT, AssetsService, AuthenticationService, CAMPAIGNS_CONFIG, CAMPAIGNS_TRANSPORT, COMPANY_CONFIG, COMPANY_TRANSPORT, CONTENT_CONFIG, CONTENT_TRANSPORT, CONVERSATIONS_CONFIG, CONVERSATIONS_TRANSPORT, CRM_CONFIG, CRM_TRANSPORT, CampaignsService, CompanyService, ContentService, ConversationsService, CrmService, FILES_CONFIG, FILES_TRANSPORT, FORMS_CONFIG, FORMS_TRANSPORT, FilesService, FormsService, GEOLOCATION_CONFIG, GEOLOCATION_TRANSPORT, GeolocationService, JARVIS_CONFIG, JARVIS_TRANSPORT, JarvisService, ONBOARDING_CONFIG, ONBOARDING_TRANSPORT, OnboardingService, PRODUCTS_CONFIG, PRODUCTS_TRANSPORT, PROVIDER_CONFIG, ProductsService, RAG_CONFIG, RAG_TRANSPORT, REWARDS_CONFIG, REWARDS_TRANSPORT, RagService, RewardsService, SALES_CONFIG, SALES_TRANSPORT, SEARCH_CONFIG, SEARCH_TRANSPORT, SIMPLE_CONFIG, SalesService, SearchService, TOKEN_LIFECYCLE, TOKEN_MANAGER, TRANSPORT, UNIVERSITY_CONFIG, UNIVERSITY_TRANSPORT, UniversityService, WALLET_CONFIG, WALLET_TRANSPORT, WalletService, get23BlocksProviders, getBlocks23Providers, provide23Blocks, provideBlocks23 };
|
|
2134
2445
|
//# sourceMappingURL=23blocks-angular.mjs.map
|