From e6bd92598e095e1e9516f191591247518e6af286 Mon Sep 17 00:00:00 2001 From: Yuval Lotem Date: Mon, 7 Aug 2023 16:01:07 +0300 Subject: [PATCH 1/3] FR-13012-support-angular-16-signals --- .../frontegg-app.observables.ts | 50 ++++ .../frontegg-app.service.ts | 66 +---- .../frontegg-app.signals.ts | 33 +++ .../src/lib/frontegg-app.service/index.ts | 1 + .../frontegg-auth.observables.ts | 118 +++++++++ .../frontegg-auth.service.ts | 235 +++++------------- .../frontegg-auth.signals.ts | 93 +++++++ .../src/lib/frontegg-auth.service/index.ts | 1 + projects/frontegg-app/src/lib/v16/consts.ts | 1 + projects/frontegg-app/src/lib/v16/index.ts | 1 + .../frontegg-app/src/lib/v16/isAngular16.ts | 4 + projects/frontegg-app/src/lib/v16/signals.ts | 22 ++ 12 files changed, 397 insertions(+), 228 deletions(-) create mode 100644 projects/frontegg-app/src/lib/frontegg-app.service/frontegg-app.observables.ts rename projects/frontegg-app/src/lib/{ => frontegg-app.service}/frontegg-app.service.ts (66%) create mode 100644 projects/frontegg-app/src/lib/frontegg-app.service/frontegg-app.signals.ts create mode 100644 projects/frontegg-app/src/lib/frontegg-app.service/index.ts create mode 100644 projects/frontegg-app/src/lib/frontegg-auth.service/frontegg-auth.observables.ts rename projects/frontegg-app/src/lib/{ => frontegg-auth.service}/frontegg-auth.service.ts (78%) create mode 100644 projects/frontegg-app/src/lib/frontegg-auth.service/frontegg-auth.signals.ts create mode 100644 projects/frontegg-app/src/lib/frontegg-auth.service/index.ts create mode 100644 projects/frontegg-app/src/lib/v16/consts.ts create mode 100644 projects/frontegg-app/src/lib/v16/index.ts create mode 100644 projects/frontegg-app/src/lib/v16/isAngular16.ts create mode 100644 projects/frontegg-app/src/lib/v16/signals.ts diff --git a/projects/frontegg-app/src/lib/frontegg-app.service/frontegg-app.observables.ts b/projects/frontegg-app/src/lib/frontegg-app.service/frontegg-app.observables.ts new file mode 100644 index 00000000..d0e702ce --- /dev/null +++ b/projects/frontegg-app/src/lib/frontegg-app.service/frontegg-app.observables.ts @@ -0,0 +1,50 @@ +import { FronteggState } from '@frontegg/redux-store'; +import { BehaviorSubject, Observable } from 'rxjs'; + +export class FronteggAppObservables { + isLoadingSubject = new BehaviorSubject(true); + isAuthenticatedSubject = new BehaviorSubject(false); + stateSubject = new BehaviorSubject({} as FronteggState); + authStateSubject = new BehaviorSubject({ + isLoading: true, + isAuthenticated: false, + } as FronteggState['auth']); + auditsStateSubject = new BehaviorSubject({} as FronteggState['audits']); + connectivityStateSubject = new BehaviorSubject({} as FronteggState['connectivity']); + subscriptionsStateSubject = new BehaviorSubject({} as FronteggState['subscriptions']); + vendorStateSubject = new BehaviorSubject({} as FronteggState['vendor']); + + + get state$(): Observable { + return this.stateSubject.asObservable(); + } + + get authState$(): Observable { + return this.authStateSubject.asObservable(); + } + + get auditsState$(): Observable { + return this.auditsStateSubject.asObservable(); + } + + get connectivityState$(): Observable { + return this.connectivityStateSubject.asObservable(); + } + + get subscriptionsState$(): Observable { + return this.subscriptionsStateSubject.asObservable(); + } + + get vendorState$(): Observable { + return this.vendorStateSubject.asObservable(); + } + + get isLoading$(): Observable { + return this.isLoadingSubject.asObservable(); + }; + + get isAuthenticated$(): Observable { + return this.isAuthenticatedSubject.asObservable(); + }; + +} diff --git a/projects/frontegg-app/src/lib/frontegg-app.service.ts b/projects/frontegg-app/src/lib/frontegg-app.service/frontegg-app.service.ts similarity index 66% rename from projects/frontegg-app/src/lib/frontegg-app.service.ts rename to projects/frontegg-app/src/lib/frontegg-app.service/frontegg-app.service.ts index 0318d54f..473da254 100644 --- a/projects/frontegg-app/src/lib/frontegg-app.service.ts +++ b/projects/frontegg-app/src/lib/frontegg-app.service/frontegg-app.service.ts @@ -1,14 +1,14 @@ import { Inject, Injectable, NgZone } from '@angular/core'; +import angularCoreVersion from '@angular/core/package.json'; import { Route, Router } from '@angular/router'; import { FronteggApp, initialize } from '@frontegg/js'; -import { AuthPageRoutes,FronteggState, isAuthRoute } from '@frontegg/redux-store'; +import { AuthPageRoutes, FronteggState, isAuthRoute } from '@frontegg/redux-store'; +import { ContextHolder, FronteggFrameworks, RedirectOptions } from '@frontegg/rest-api'; import { FronteggAppOptions, FronteggCheckoutDialogOptions } from '@frontegg/types'; -import { BehaviorSubject, Observable } from 'rxjs'; -import { FronteggLoadGuard } from './guards/frontegg-load.guard'; -import { ContextHolder, RedirectOptions, FronteggFrameworks } from '@frontegg/rest-api'; -import { FronteggComponent } from './frontegg.component'; -import sdkVersion from '../sdkVersion'; -import angularCoreVersion from '@angular/core/package.json'; +import sdkVersion from '../../sdkVersion'; +import { FronteggComponent } from '../frontegg.component'; +import { FronteggLoadGuard } from '../guards/frontegg-load.guard'; +import { FronteggAppSignals } from './frontegg-app.signals'; export class FronteggAppOptionsClass implements FronteggAppOptions { contextOptions: FronteggAppOptions['contextOptions'] = { @@ -19,55 +19,11 @@ export class FronteggAppOptionsClass implements FronteggAppOptions { @Injectable({ providedIn: 'root', }) -export class FronteggAppService { +export class FronteggAppService extends FronteggAppSignals { fronteggApp: FronteggApp; - private isLoadingSubject = new BehaviorSubject(true); - private isAuthenticatedSubject = new BehaviorSubject(false); - private stateSubject = new BehaviorSubject({} as FronteggState); - private authStateSubject = new BehaviorSubject({ - isLoading: true, - isAuthenticated: false, - } as FronteggState['auth']); - private auditsStateSubject = new BehaviorSubject({} as FronteggState['audits']); - private connectivityStateSubject = new BehaviorSubject({} as FronteggState['connectivity']); - private subscriptionsStateSubject = new BehaviorSubject({} as FronteggState['subscriptions']); - private vendorStateSubject = new BehaviorSubject({} as FronteggState['vendor']); - - - get state$(): Observable { - return this.stateSubject.asObservable(); - } - - get authState$(): Observable { - return this.authStateSubject.asObservable(); - } - - get auditsState$(): Observable { - return this.auditsStateSubject.asObservable(); - } - - get connectivityState$(): Observable { - return this.connectivityStateSubject.asObservable(); - } - - get subscriptionsState$(): Observable { - return this.subscriptionsStateSubject.asObservable(); - } - - get vendorState$(): Observable { - return this.vendorStateSubject.asObservable(); - } - - get isLoading$(): Observable { - return this.isLoadingSubject.asObservable(); - }; - - get isAuthenticated$(): Observable { - return this.isAuthenticatedSubject.asObservable(); - }; - constructor(@Inject(FronteggAppOptionsClass) private config: FronteggAppOptions, public router: Router, private ngZone: NgZone) { + super(); if (!this.config) { throw Error('Need to pass config: FronteggConfigOptions in FronteggAppModule.forRoot(config)'); } @@ -118,8 +74,8 @@ export class FronteggAppService { ...this.mapAuthComponents, { path: '', - canActivate: [ FronteggLoadGuard ], - children: [ ...this.router.config ], + canActivate: [FronteggLoadGuard], + children: [...this.router.config], }, ]); const initialFronteggState = this.fronteggApp.store.getState() as FronteggState; diff --git a/projects/frontegg-app/src/lib/frontegg-app.service/frontegg-app.signals.ts b/projects/frontegg-app/src/lib/frontegg-app.service/frontegg-app.signals.ts new file mode 100644 index 00000000..98f9fb02 --- /dev/null +++ b/projects/frontegg-app/src/lib/frontegg-app.service/frontegg-app.signals.ts @@ -0,0 +1,33 @@ +import { FronteggState } from '@frontegg/redux-store'; +import { Signal, toSignal } from '../v16'; +import { FronteggAppObservables } from './frontegg-app.observables'; + +export class FronteggAppSignals extends FronteggAppObservables { + get authStateSignal(): Signal { + return toSignal(this.authState$); + } + + get auditsStateSignal(): Signal { + return toSignal(this.auditsState$); + } + + get connectivityStateSignal(): Signal { + return toSignal(this.connectivityState$); + } + + get subscriptionsStateSignal(): Signal { + return toSignal(this.subscriptionsState$); + } + + get vendorStateSignal(): Signal { + return toSignal(this.vendorState$); + } + + get isLoadingSignal(): Signal { + return toSignal(this.isLoading$); + } + + get isAuthenticatedSignal(): Signal { + return toSignal(this.isAuthenticated$); + } +} diff --git a/projects/frontegg-app/src/lib/frontegg-app.service/index.ts b/projects/frontegg-app/src/lib/frontegg-app.service/index.ts new file mode 100644 index 00000000..a496d6b1 --- /dev/null +++ b/projects/frontegg-app/src/lib/frontegg-app.service/index.ts @@ -0,0 +1 @@ +export * from './frontegg-app.service' \ No newline at end of file diff --git a/projects/frontegg-app/src/lib/frontegg-auth.service/frontegg-auth.observables.ts b/projects/frontegg-app/src/lib/frontegg-auth.service/frontegg-auth.observables.ts new file mode 100644 index 00000000..13d86df2 --- /dev/null +++ b/projects/frontegg-app/src/lib/frontegg-auth.service/frontegg-auth.observables.ts @@ -0,0 +1,118 @@ +import { + AuthState +} from '@frontegg/redux-store'; +import { BehaviorSubject, Observable } from 'rxjs'; + +export class FronteggAuthObservables { + authStateSubject = new BehaviorSubject({ isAuthenticated: false, isLoading: true } as AuthState); + acceptInvitationStateSubject = new BehaviorSubject({} as AuthState['acceptInvitationState']); + accountSettingsStateSubject = new BehaviorSubject({} as AuthState['accountSettingsState']); + activateStateSubject = new BehaviorSubject({} as AuthState['activateState']); + apiTokensStateSubject = new BehaviorSubject({} as AuthState['apiTokensState']); + forgotPasswordStateSubject = new BehaviorSubject({} as AuthState['forgotPasswordState']); + loginStateSubject = new BehaviorSubject({} as AuthState['loginState']); + mfaStateSubject = new BehaviorSubject({} as AuthState['mfaState']); + profileStateSubject = new BehaviorSubject({} as AuthState['profileState']); + rolesStateSubject = new BehaviorSubject({} as AuthState['rolesState']); + routesSubject = new BehaviorSubject({} as AuthState['routes']); + securityPolicyStateSubject = new BehaviorSubject({} as AuthState['securityPolicyState']); + signUpStateSubject = new BehaviorSubject({} as AuthState['signUpState']); + socialLoginStateSubject = new BehaviorSubject({} as AuthState['socialLoginState']); + ssoStateSubject = new BehaviorSubject({} as AuthState['ssoState']); + teamStateSubject = new BehaviorSubject({} as AuthState['teamState']); + tenantsStateSubject = new BehaviorSubject({} as AuthState['tenantsState']); + userSubject = new BehaviorSubject({} as AuthState['user']); + isAuthenticatedSubject = new BehaviorSubject(false); + isLoadingSubject = new BehaviorSubject(true); + isSSOAuthSubject = new BehaviorSubject(false); + ssoACSSubject = new BehaviorSubject(''); + + get authState$(): Observable { + return this.authStateSubject.asObservable(); + } + + get acceptInvitationState$(): Observable { + return this.acceptInvitationStateSubject.asObservable(); + } + + get accountSettingsState$(): Observable { + return this.accountSettingsStateSubject.asObservable(); + } + + get activateState$(): Observable { + return this.activateStateSubject.asObservable(); + } + + get apiTokensState$(): Observable { + return this.apiTokensStateSubject.asObservable(); + } + + get forgotPasswordState$(): Observable { + return this.forgotPasswordStateSubject.asObservable(); + } + + get loginState$(): Observable { + return this.loginStateSubject.asObservable(); + } + + get mfaState$(): Observable { + return this.mfaStateSubject.asObservable(); + } + + get profileState$(): Observable { + return this.profileStateSubject.asObservable(); + } + + get rolesState$(): Observable { + return this.rolesStateSubject.asObservable(); + } + + get routesState$(): Observable { + return this.routesSubject.asObservable(); + } + + get securityPolicyState$(): Observable { + return this.securityPolicyStateSubject.asObservable(); + } + + get signUpState$(): Observable { + return this.signUpStateSubject.asObservable(); + } + + get socialLoginState$(): Observable { + return this.socialLoginStateSubject.asObservable(); + } + + get ssoState$(): Observable { + return this.ssoStateSubject.asObservable(); + } + + get teamState$(): Observable { + return this.teamStateSubject.asObservable(); + } + + get tenantsState$(): Observable { + return this.tenantsStateSubject.asObservable(); + } + + get user$(): Observable { + return this.userSubject.asObservable(); + } + + get isAuthenticated$(): Observable { + return this.isAuthenticatedSubject.asObservable(); + } + + get isLoading$(): Observable { + return this.isLoadingSubject.asObservable(); + } + + get isSSOAuth$(): Observable { + return this.isSSOAuthSubject.asObservable(); + } + + get ssoACS$(): Observable { + return this.ssoACSSubject.asObservable(); + } + +} diff --git a/projects/frontegg-app/src/lib/frontegg-auth.service.ts b/projects/frontegg-app/src/lib/frontegg-auth.service/frontegg-auth.service.ts similarity index 78% rename from projects/frontegg-app/src/lib/frontegg-auth.service.ts rename to projects/frontegg-app/src/lib/frontegg-auth.service/frontegg-auth.service.ts index 7688ae83..398f3e79 100644 --- a/projects/frontegg-app/src/lib/frontegg-auth.service.ts +++ b/projects/frontegg-app/src/lib/frontegg-auth.service/frontegg-auth.service.ts @@ -1,91 +1,91 @@ import { Injectable } from '@angular/core'; -import { BehaviorSubject } from 'rxjs'; -import { FronteggAppService } from './frontegg-app.service'; -import FastDeepEqual from 'fast-deep-equal'; +import { Router } from '@angular/router'; +import type { ActivateAccountState, FronteggState, SocialLoginState } from '@frontegg/redux-store'; import { - RolesState, - TenantsState, + AcceptInvitationState, AccountSettingsState, - SaveSecurityPolicyPasswordHistoryPayload, - SaveSecurityPolicyLockoutPayload, - SaveSecurityPolicyMfaPayload, - PasswordPolicyState, - PasswordHistoryPolicyState, - MfaPolicyState, - CaptchaPolicyState, - LockoutPolicyState, - PublicPolicyState, - GlobalPolicyState, - SecurityPolicyState, - AddUserApiTokenPayload, + ActivateAccountStrategyState, AddTenantApiTokenPayload, + AddUserApiTokenPayload, + ApiStateIndicator, ApiTokenType, ApiTokensState, - ApiStateIndicator, - ISetDeleteUserDialog, + AuthState, + CaptchaPolicyState, + CreateSamlGroupPayload, + DeleteSamlGroupPayload, + ForgotPasswordState, + GlobalPolicyState, ISetAddUserDialog, + ISetDeleteUserDialog, LoadRolesAndPermissionsPayload, - TeamState, - TeamStateIndicator, + LockoutPolicyState, + LoginState, MFAState, - SaveSSOConfigurationPayload, - SSOState, + MfaPolicyState, + PasswordHistoryPolicyState, + PasswordPolicyState, ProfileState, - SaveSSOConfigurationFilePayload, - UpdateSSOAuthorizationRolesPayload, - DeleteSamlGroupPayload, - CreateSamlGroupPayload, + PublicPolicyState, + RolesState, + SSOState, SaveProfilePayload, + SaveSSOConfigurationFilePayload, + SaveSSOConfigurationPayload, + SaveSecurityPolicyLockoutPayload, + SaveSecurityPolicyMfaPayload, + SaveSecurityPolicyPasswordHistoryPayload, + SecurityPolicyState, SignUpState, - ForgotPasswordState, - AcceptInvitationState, - AuthState, + TeamState, + TeamStateIndicator, + TenantsState, + UpdateSSOAuthorizationRolesPayload, User, authStoreName, - LoginState, - ActivateAccountStrategyState, } from '@frontegg/redux-store'; import { + IAcceptInvitation, + IActivateAccount, + IAddRole, + IAddUser, + IAttachPermissionsToRole, + IChangePassword, + IDeleteRole, + IDeleteUser, + IDisableMfa, + IForgotPassword, + IGetActivateAccountStrategy, + IGetActivateAccountStrategyResponse, + IGetUserPasswordConfig, + ILoadUsers, ILogin, + ILoginViaSocialLogin, ILoginWithMfa, + IOidcPostLogin, IPostLogin, IPreLogin, IRecoverMFAToken, - IActivateAccount, - ILoginViaSocialLogin, - ISetSocialLoginError, IResendActivationEmail, - IGetActivateAccountStrategy, - IGetActivateAccountStrategyResponse, - IAcceptInvitation, - IForgotPassword, - IResetPassword, - IGetUserPasswordConfig, - ISignUpUser, - IChangePassword, - IOidcPostLogin, - IVerifyMfa, - IDisableMfa, - ILoadUsers, - ITeamUser, - IAddUser, - IUpdateUser, - IDeleteUser, IResendActivationLink, + IResendInvitationLink, + IResetPassword, + IRole, + IRolePermission, + ISetSocialLoginError, ISettingsResponse, + ISignUpUser, ISwitchTenant, + ITeamUser, ITenantsResponse, - IAddRole, - IRole, IUpdateRole, - IDeleteRole, - IAttachPermissionsToRole, - IResendInvitationLink, - IRolePermission, + IUpdateUser, + IVerifyMfa, } from '@frontegg/rest-api'; -import type { FronteggState, ActivateAccountState, SocialLoginState } from '@frontegg/redux-store'; -import { Observable } from 'rxjs'; -import { Router } from '@angular/router'; +import FastDeepEqual from 'fast-deep-equal'; +import { BehaviorSubject } from 'rxjs'; +import { FronteggAppService } from '../frontegg-app.service'; +import { FronteggAuthSignals } from './frontegg-auth.signals'; interface AuthSubStates { field: Partial; @@ -103,129 +103,18 @@ export type WithSilentLoad = T & { @Injectable({ providedIn: 'root', }) -export class FronteggAuthService { - private authStateSubject = new BehaviorSubject({ isAuthenticated: false, isLoading: true } as AuthState); - private acceptInvitationStateSubject = new BehaviorSubject({} as AuthState['acceptInvitationState']); - private accountSettingsStateSubject = new BehaviorSubject({} as AuthState['accountSettingsState']); - private activateStateSubject = new BehaviorSubject({} as AuthState['activateState']); - private apiTokensStateSubject = new BehaviorSubject({} as AuthState['apiTokensState']); - private forgotPasswordStateSubject = new BehaviorSubject({} as AuthState['forgotPasswordState']); - private loginStateSubject = new BehaviorSubject({} as AuthState['loginState']); - private mfaStateSubject = new BehaviorSubject({} as AuthState['mfaState']); - private profileStateSubject = new BehaviorSubject({} as AuthState['profileState']); - private rolesStateSubject = new BehaviorSubject({} as AuthState['rolesState']); - private routesSubject = new BehaviorSubject({} as AuthState['routes']); - private securityPolicyStateSubject = new BehaviorSubject({} as AuthState['securityPolicyState']); - private signUpStateSubject = new BehaviorSubject({} as AuthState['signUpState']); - private socialLoginStateSubject = new BehaviorSubject({} as AuthState['socialLoginState']); - private ssoStateSubject = new BehaviorSubject({} as AuthState['ssoState']); - private teamStateSubject = new BehaviorSubject({} as AuthState['teamState']); - private tenantsStateSubject = new BehaviorSubject({} as AuthState['tenantsState']); - private userSubject = new BehaviorSubject({} as AuthState['user']); - private isAuthenticatedSubject = new BehaviorSubject(false); - private isLoadingSubject = new BehaviorSubject(true); - private isSSOAuthSubject = new BehaviorSubject(false); - private ssoACSSubject = new BehaviorSubject(''); - - - get authState$(): Observable { - return this.authStateSubject.asObservable(); - } - - get acceptInvitationState$(): Observable { - return this.acceptInvitationStateSubject.asObservable(); - } - - get accountSettingsState$(): Observable { - return this.accountSettingsStateSubject.asObservable(); - } - - get activateState$(): Observable { - return this.activateStateSubject.asObservable(); - } - - get apiTokensState$(): Observable { - return this.apiTokensStateSubject.asObservable(); - } - - get forgotPasswordState$(): Observable { - return this.forgotPasswordStateSubject.asObservable(); - } - - get loginState$(): Observable { - return this.loginStateSubject.asObservable(); - } - - get mfaState$(): Observable { - return this.mfaStateSubject.asObservable(); - } - - get profileState$(): Observable { - return this.profileStateSubject.asObservable(); - } - - get rolesState$(): Observable { - return this.rolesStateSubject.asObservable(); - } - - get routesState$(): Observable { - return this.routesSubject.asObservable(); - } - - get securityPolicyState$(): Observable { - return this.securityPolicyStateSubject.asObservable(); - } - - get signUpState$(): Observable { - return this.signUpStateSubject.asObservable(); - } - - get socialLoginState$(): Observable { - return this.socialLoginStateSubject.asObservable(); - } - - get ssoState$(): Observable { - return this.ssoStateSubject.asObservable(); - } - - get teamState$(): Observable { - return this.teamStateSubject.asObservable(); - } - - get tenantsState$(): Observable { - return this.tenantsStateSubject.asObservable(); - } - - get user$(): Observable { - return this.userSubject.asObservable(); - } +export class FronteggAuthService extends FronteggAuthSignals { get user(): AuthState['user'] { return this.fronteggAppService.fronteggApp.store.getState().auth.user; } - - get isAuthenticated$(): Observable { - return this.isAuthenticatedSubject.asObservable(); - } - get isAuthenticated(): AuthState['isAuthenticated'] { return this.fronteggAppService.fronteggApp.store.getState().auth.isAuthenticated; } - get isLoading$(): Observable { - return this.isLoadingSubject.asObservable(); - } - - get isSSOAuth$(): Observable { - return this.isSSOAuthSubject.asObservable(); - } - - get ssoACS$(): Observable { - return this.ssoACSSubject.asObservable(); - } - constructor(private fronteggAppService: FronteggAppService, private router: Router) { + super(); const authSubStates: AuthSubStates[] = [ { field: 'acceptInvitationState', subject: this.acceptInvitationStateSubject }, { field: 'accountSettingsState', subject: this.accountSettingsStateSubject }, diff --git a/projects/frontegg-app/src/lib/frontegg-auth.service/frontegg-auth.signals.ts b/projects/frontegg-app/src/lib/frontegg-auth.service/frontegg-auth.signals.ts new file mode 100644 index 00000000..8e3d7e05 --- /dev/null +++ b/projects/frontegg-app/src/lib/frontegg-auth.service/frontegg-auth.signals.ts @@ -0,0 +1,93 @@ +import { + AuthState +} from '@frontegg/redux-store'; +import { Signal, toSignal } from '../v16'; +import { FronteggAuthObservables } from './frontegg-auth.observables'; + +export class FronteggAuthSignals extends FronteggAuthObservables { + get authStateSignal(): Signal { + return toSignal(this.authState$); + } + + get accountSettingsStateSignal(): Signal { + return toSignal(this.accountSettingsState$); + } + + get activateStateSignal(): Signal { + return toSignal(this.activateState$); + } + + get apiTokensStateSignal(): Signal { + return toSignal(this.apiTokensState$); + } + + get forgotPasswordStateSignal(): Signal { + return toSignal(this.forgotPasswordState$); + } + + get loginStateSignal(): Signal { + return toSignal(this.loginState$); + } + + get mfaStateSignal(): Signal { + return toSignal(this.mfaState$); + } + + get profileStateSignal(): Signal { + return toSignal(this.profileState$); + } + + get rolesStateSignal(): Signal { + return toSignal(this.rolesState$); + } + + get routesStateSignal(): Signal { + return toSignal(this.routesState$); + } + + get securityPolicyStateSignal(): Signal { + return toSignal(this.securityPolicyState$); + } + + get signUpStateSignal(): Signal { + return toSignal(this.signUpState$); + } + + get socialLoginStateSignal(): Signal { + return toSignal(this.socialLoginState$); + } + + get ssoStateSignal(): Signal { + return toSignal(this.ssoState$); + } + + get teamStateSignal(): Signal { + return toSignal(this.teamState$); + } + + get tenantsStateSignal(): Signal { + return toSignal(this.tenantsState$); + } + + + get userSignal(): Signal { + return toSignal(this.user$); + } + + get isAuthenticatedSignal(): Signal { + return toSignal(this.isAuthenticated$); + } + + get isLoadingSignal(): Signal { + return toSignal(this.isLoading$); + } + + get isSSOAuthSignal(): Signal { + return toSignal(this.isSSOAuth$); + } + + get ssoACSSignal(): Signal { + return toSignal(this.ssoACS$); + } + +} diff --git a/projects/frontegg-app/src/lib/frontegg-auth.service/index.ts b/projects/frontegg-app/src/lib/frontegg-auth.service/index.ts new file mode 100644 index 00000000..87c1d541 --- /dev/null +++ b/projects/frontegg-app/src/lib/frontegg-auth.service/index.ts @@ -0,0 +1 @@ +export * from './frontegg-auth.service' \ No newline at end of file diff --git a/projects/frontegg-app/src/lib/v16/consts.ts b/projects/frontegg-app/src/lib/v16/consts.ts new file mode 100644 index 00000000..b70c31d0 --- /dev/null +++ b/projects/frontegg-app/src/lib/v16/consts.ts @@ -0,0 +1 @@ +export const SIGNALS_ERROR_MESSAGE = 'Signals only supported from angular version 16, in order to use frontegg signals please upgrade your angular version to 16 or higher'; \ No newline at end of file diff --git a/projects/frontegg-app/src/lib/v16/index.ts b/projects/frontegg-app/src/lib/v16/index.ts new file mode 100644 index 00000000..36e9e262 --- /dev/null +++ b/projects/frontegg-app/src/lib/v16/index.ts @@ -0,0 +1 @@ +export * from './signals' \ No newline at end of file diff --git a/projects/frontegg-app/src/lib/v16/isAngular16.ts b/projects/frontegg-app/src/lib/v16/isAngular16.ts new file mode 100644 index 00000000..ede2c111 --- /dev/null +++ b/projects/frontegg-app/src/lib/v16/isAngular16.ts @@ -0,0 +1,4 @@ +import angularCoreVersion from '@angular/core/package.json'; + +const major = Number(angularCoreVersion?.version?.split('.')?.[0] ?? 0); +export const isAngular16 = major >= 16; diff --git a/projects/frontegg-app/src/lib/v16/signals.ts b/projects/frontegg-app/src/lib/v16/signals.ts new file mode 100644 index 00000000..424b08ca --- /dev/null +++ b/projects/frontegg-app/src/lib/v16/signals.ts @@ -0,0 +1,22 @@ +/** @ts-ignore **/ +import { Signal } from '@angular/core'; +import { SIGNALS_ERROR_MESSAGE } from './consts'; +import { isAngular16 } from './isAngular16'; + +let toSignal = (observable: any) => { + if (!isAngular16) { + throw new Error(SIGNALS_ERROR_MESSAGE) + } + +} + +if (isAngular16) { + //This is a workaround to prevent build error + const importPath = isAngular16 ? '@angular/core/rxjs-interop' : '@angular/core' + import(importPath) + .then(({ toSignal: angularToSignal }) => { + toSignal = angularToSignal; + }).catch(() => { }); +} + +export { toSignal, Signal } \ No newline at end of file From c13f6961a2ec83bd5e21154b406e6425ef05ebcb Mon Sep 17 00:00:00 2001 From: Yuval Lotem Date: Mon, 7 Aug 2023 17:33:33 +0300 Subject: [PATCH 2/3] update readme with signal exampels --- README.md | 33 ++++++++++++++++++++++++++++++++- projects/frontegg-app/README.md | 33 ++++++++++++++++++++++++++++++++- 2 files changed, 64 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index dc2e4398..03b0d5c7 100644 --- a/README.md +++ b/README.md @@ -238,5 +238,36 @@ export class AppComponent implements OnInit { } } ``` +### 6. Using signals -6. Enjoy! +In order to use frontegg signals you will have to call it from the frontegg services and assign them to the component state + +``` +import { Component, OnInit, Signal } from '@angular/core'; +import { FronteggAppService, FronteggAuthService, AuthState } from '@frontegg/angular'; +@Component({ + selector: 'app-home', + templateUrl: './home.component.html', + styleUrls: ['./home.component.scss'], +}) +export class AppComponent implements OnInit { + user: Signal + authenticated: Signal + constructor(private fronteggAppService: FronteggAppService, + private fronteggAuthService: FronteggAuthService, + private router: Router) { + this.user = this.fronteggAuthService.userSignal + this.authenticated = this.fronteggAppService.isAuthenticatedSignal + } +} +``` + +Then access it from the html component file +``` +
+

Authenticated: {{authenticated()}}

+

Authenticated as: {{user()?.name}}

+
+``` + +7. Enjoy! diff --git a/projects/frontegg-app/README.md b/projects/frontegg-app/README.md index 8c3c15f0..1ba81061 100644 --- a/projects/frontegg-app/README.md +++ b/projects/frontegg-app/README.md @@ -197,5 +197,36 @@ export class AppComponent implements OnInit { } } ``` +### 6. Using signals -6. Enjoy! +In order to use frontegg signals you will have to call it from the frontegg services and assign them to the component state + +``` +import { Component, OnInit, Signal } from '@angular/core'; +import { FronteggAppService, FronteggAuthService, AuthState } from '@frontegg/angular'; +@Component({ + selector: 'app-home', + templateUrl: './home.component.html', + styleUrls: ['./home.component.scss'], +}) +export class AppComponent implements OnInit { + user: Signal + authenticated: Signal + constructor(private fronteggAppService: FronteggAppService, + private fronteggAuthService: FronteggAuthService, + private router: Router) { + this.user = this.fronteggAuthService.userSignal + this.authenticated = this.fronteggAppService.isAuthenticatedSignal + } +} +``` + +Then access it from the html component file +``` +
+

Authenticated: {{authenticated()}}

+

Authenticated as: {{user()?.name}}

+
+``` + +7. Enjoy! \ No newline at end of file From 4836410de79e777c30f750c8e50fe47f9275ad4c Mon Sep 17 00:00:00 2001 From: Yuval Lotem Date: Mon, 7 Aug 2023 17:37:51 +0300 Subject: [PATCH 3/3] import Signal as type and add justification for ts-ignore --- projects/frontegg-app/src/lib/v16/signals.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/projects/frontegg-app/src/lib/v16/signals.ts b/projects/frontegg-app/src/lib/v16/signals.ts index 424b08ca..c49f75df 100644 --- a/projects/frontegg-app/src/lib/v16/signals.ts +++ b/projects/frontegg-app/src/lib/v16/signals.ts @@ -1,5 +1,5 @@ -/** @ts-ignore **/ -import { Signal } from '@angular/core'; +/** @ts-ignore Signal is not exported from angular/core before version 16 **/ +import type { Signal } from '@angular/core'; import { SIGNALS_ERROR_MESSAGE } from './consts'; import { isAngular16 } from './isAngular16';