mirror of
https://github.com/DSpace/dspace-angular.git
synced 2025-10-07 01:54:15 +00:00
93219: Move APP_INITIALIZER logic into InitService
This commit is contained in:
@@ -7,13 +7,9 @@ import { BrowserModule } from '@angular/platform-browser';
|
||||
import { NgbModule } from '@ng-bootstrap/ng-bootstrap';
|
||||
import { EffectsModule } from '@ngrx/effects';
|
||||
import { RouterStateSerializer, StoreRouterConnectingModule } from '@ngrx/router-store';
|
||||
import { MetaReducer, Store, StoreModule, USER_PROVIDED_META_REDUCERS } from '@ngrx/store';
|
||||
import { MetaReducer, StoreModule, USER_PROVIDED_META_REDUCERS } from '@ngrx/store';
|
||||
import { StoreDevtoolsModule } from '@ngrx/store-devtools';
|
||||
import {
|
||||
DYNAMIC_ERROR_MESSAGES_MATCHER,
|
||||
DYNAMIC_MATCHER_PROVIDERS,
|
||||
DynamicErrorMessagesMatcher
|
||||
} from '@ng-dynamic-forms/core';
|
||||
import { DYNAMIC_ERROR_MESSAGES_MATCHER, DYNAMIC_MATCHER_PROVIDERS, DynamicErrorMessagesMatcher } from '@ng-dynamic-forms/core';
|
||||
import { TranslateModule } from '@ngx-translate/core';
|
||||
import { ScrollToModule } from '@nicky-lenaers/ngx-scroll-to';
|
||||
import { AppRoutingModule } from './app-routing.module';
|
||||
@@ -21,7 +17,6 @@ import { AppComponent } from './app.component';
|
||||
import { appEffects } from './app.effects';
|
||||
import { appMetaReducers, debugMetaReducers } from './app.metareducers';
|
||||
import { appReducers, AppState, storeModuleConfig } from './app.reducer';
|
||||
import { CheckAuthenticationTokenAction } from './core/auth/auth.actions';
|
||||
import { CoreModule } from './core/core.module';
|
||||
import { ClientCookieService } from './core/services/client-cookie.service';
|
||||
import { NavbarModule } from './navbar/navbar.module';
|
||||
@@ -36,6 +31,7 @@ import { EagerThemesModule } from '../themes/eager-themes.module';
|
||||
|
||||
import { APP_CONFIG, AppConfig } from '../config/app-config.interface';
|
||||
import { RootModule } from './root.module';
|
||||
import { InitService } from './init.service';
|
||||
|
||||
export function getConfig() {
|
||||
return environment;
|
||||
@@ -82,6 +78,12 @@ IMPORTS.push(
|
||||
);
|
||||
|
||||
const PROVIDERS = [
|
||||
{
|
||||
provide: APP_INITIALIZER,
|
||||
useFactory: (initService: InitService) => initService.init(),
|
||||
deps: [ InitService ],
|
||||
multi: true,
|
||||
},
|
||||
{
|
||||
provide: APP_CONFIG,
|
||||
useFactory: getConfig
|
||||
@@ -101,15 +103,6 @@ const PROVIDERS = [
|
||||
useClass: DSpaceRouterStateSerializer
|
||||
},
|
||||
ClientCookieService,
|
||||
// Check the authentication token when the app initializes
|
||||
{
|
||||
provide: APP_INITIALIZER,
|
||||
useFactory: (store: Store<AppState>,) => {
|
||||
return () => store.dispatch(new CheckAuthenticationTokenAction());
|
||||
},
|
||||
deps: [Store],
|
||||
multi: true
|
||||
},
|
||||
// register AuthInterceptor as HttpInterceptor
|
||||
{
|
||||
provide: HTTP_INTERCEPTORS,
|
||||
|
63
src/app/init.service.ts
Normal file
63
src/app/init.service.ts
Normal file
@@ -0,0 +1,63 @@
|
||||
/**
|
||||
* The contents of this file are subject to the license and copyright
|
||||
* detailed in the LICENSE and NOTICE files at the root of the source
|
||||
* tree and available online at
|
||||
*
|
||||
* http://www.dspace.org/license/
|
||||
*/
|
||||
import { Store } from '@ngrx/store';
|
||||
import { AppState } from './app.reducer';
|
||||
import { CheckAuthenticationTokenAction } from './core/auth/auth.actions';
|
||||
import { CorrelationIdService } from './correlation-id/correlation-id.service';
|
||||
import { DSpaceTransferState } from '../modules/transfer-state/dspace-transfer-state.service';
|
||||
|
||||
/**
|
||||
* Performs the initialization of the app.
|
||||
*
|
||||
* Should have distinct extensions for server & browser for the specifics.
|
||||
* Should be provided in AppModule as follows
|
||||
* ```
|
||||
* {
|
||||
* provide: APP_INITIALIZER
|
||||
* useFactory: (initService: InitService) => initService.init(),
|
||||
* deps: [ InitService ],
|
||||
* multi: true,
|
||||
* }
|
||||
* ```
|
||||
*
|
||||
* In order to be injected in the common APP_INITIALIZER,
|
||||
* concrete subclasses should be provided in their respective app modules as
|
||||
* ```
|
||||
* { provide: InitService, useClass: SpecificInitService }
|
||||
* ```
|
||||
*/
|
||||
export abstract class InitService {
|
||||
protected constructor(
|
||||
protected store: Store<AppState>,
|
||||
protected correlationIdService: CorrelationIdService,
|
||||
protected dspaceTransferState: DSpaceTransferState,
|
||||
) {
|
||||
}
|
||||
|
||||
/**
|
||||
* Main initialization method, to be used as the APP_INITIALIZER factory.
|
||||
*
|
||||
* Note that the body of this method and the callback it returns are called
|
||||
* at different times.
|
||||
* This is important to take into account when other providers depend on the
|
||||
* initialization logic (e.g. APP_BASE_HREF)
|
||||
*/
|
||||
abstract init(): () => Promise<boolean>;
|
||||
|
||||
protected checkAuthenticationToken(): void {
|
||||
this.store.dispatch(new CheckAuthenticationTokenAction());
|
||||
}
|
||||
|
||||
protected initCorrelationId(): void {
|
||||
this.correlationIdService.initCorrelationId();
|
||||
}
|
||||
|
||||
protected async transferAppState(): Promise<unknown> {
|
||||
return this.dspaceTransferState.transfer();
|
||||
}
|
||||
}
|
@@ -1,5 +1,5 @@
|
||||
import { HttpClient, HttpClientModule } from '@angular/common/http';
|
||||
import { APP_INITIALIZER, NgModule } from '@angular/core';
|
||||
import { NgModule } from '@angular/core';
|
||||
import { BrowserModule, makeStateKey, TransferState } from '@angular/platform-browser';
|
||||
import { BrowserAnimationsModule } from '@angular/platform-browser/animations';
|
||||
import { REQUEST } from '@nguniversal/express-engine/tokens';
|
||||
@@ -13,7 +13,6 @@ import { AppComponent } from '../../app/app.component';
|
||||
|
||||
import { AppModule } from '../../app/app.module';
|
||||
import { DSpaceBrowserTransferStateModule } from '../transfer-state/dspace-browser-transfer-state.module';
|
||||
import { DSpaceTransferState } from '../transfer-state/dspace-transfer-state.service';
|
||||
import { ClientCookieService } from '../../app/core/services/client-cookie.service';
|
||||
import { CookieService } from '../../app/core/services/cookie.service';
|
||||
import { AuthService } from '../../app/core/auth/auth.service';
|
||||
@@ -23,21 +22,13 @@ import { StatisticsModule } from '../../app/statistics/statistics.module';
|
||||
import { BrowserKlaroService } from '../../app/shared/cookies/browser-klaro.service';
|
||||
import { KlaroService } from '../../app/shared/cookies/klaro.service';
|
||||
import { HardRedirectService } from '../../app/core/services/hard-redirect.service';
|
||||
import {
|
||||
BrowserHardRedirectService,
|
||||
locationProvider,
|
||||
LocationToken
|
||||
} from '../../app/core/services/browser-hard-redirect.service';
|
||||
import { BrowserHardRedirectService, locationProvider, LocationToken } from '../../app/core/services/browser-hard-redirect.service';
|
||||
import { LocaleService } from '../../app/core/locale/locale.service';
|
||||
import { GoogleAnalyticsService } from '../../app/statistics/google-analytics.service';
|
||||
import { AuthRequestService } from '../../app/core/auth/auth-request.service';
|
||||
import { BrowserAuthRequestService } from '../../app/core/auth/browser-auth-request.service';
|
||||
import { AppConfig, APP_CONFIG_STATE } from '../../config/app-config.interface';
|
||||
import { DefaultAppConfig } from '../../config/default-app-config';
|
||||
import { extendEnvironmentWithAppConfig } from '../../config/config.util';
|
||||
import { CorrelationIdService } from '../../app/correlation-id/correlation-id.service';
|
||||
|
||||
import { environment } from '../../environments/environment';
|
||||
import { InitService } from 'src/app/init.service';
|
||||
import { BrowserInitService } from './browser-init.service';
|
||||
|
||||
export const REQ_KEY = makeStateKey<string>('req');
|
||||
|
||||
@@ -73,25 +64,8 @@ export function getRequest(transferState: TransferState): any {
|
||||
],
|
||||
providers: [
|
||||
{
|
||||
provide: APP_INITIALIZER,
|
||||
useFactory: (
|
||||
transferState: TransferState,
|
||||
dspaceTransferState: DSpaceTransferState,
|
||||
correlationIdService: CorrelationIdService
|
||||
) => {
|
||||
if (transferState.hasKey<AppConfig>(APP_CONFIG_STATE)) {
|
||||
const appConfig = transferState.get<AppConfig>(APP_CONFIG_STATE, new DefaultAppConfig());
|
||||
// extend environment with app config for browser
|
||||
extendEnvironmentWithAppConfig(environment, appConfig);
|
||||
}
|
||||
return () =>
|
||||
dspaceTransferState.transfer().then((b: boolean) => {
|
||||
correlationIdService.initCorrelationId();
|
||||
return b;
|
||||
});
|
||||
},
|
||||
deps: [TransferState, DSpaceTransferState, CorrelationIdService],
|
||||
multi: true
|
||||
provide: InitService,
|
||||
useClass: BrowserInitService,
|
||||
},
|
||||
{
|
||||
provide: REQUEST,
|
||||
|
54
src/modules/app/browser-init.service.ts
Normal file
54
src/modules/app/browser-init.service.ts
Normal file
@@ -0,0 +1,54 @@
|
||||
/**
|
||||
* The contents of this file are subject to the license and copyright
|
||||
* detailed in the LICENSE and NOTICE files at the root of the source
|
||||
* tree and available online at
|
||||
*
|
||||
* http://www.dspace.org/license/
|
||||
*/
|
||||
import { InitService } from '../../app/init.service';
|
||||
import { Store } from '@ngrx/store';
|
||||
import { AppState } from '../../app/app.reducer';
|
||||
import { DSpaceTransferState } from '../transfer-state/dspace-transfer-state.service';
|
||||
import { TransferState } from '@angular/platform-browser';
|
||||
import { APP_CONFIG_STATE, AppConfig } from '../../config/app-config.interface';
|
||||
import { DefaultAppConfig } from '../../config/default-app-config';
|
||||
import { extendEnvironmentWithAppConfig } from '../../config/config.util';
|
||||
import { environment } from '../../environments/environment';
|
||||
import { CorrelationIdService } from '../../app/correlation-id/correlation-id.service';
|
||||
import { Injectable } from '@angular/core';
|
||||
|
||||
/**
|
||||
* Performs client-side initialization.
|
||||
*/
|
||||
@Injectable()
|
||||
export class BrowserInitService extends InitService {
|
||||
constructor(
|
||||
protected store: Store<AppState>,
|
||||
protected correlationIdService: CorrelationIdService,
|
||||
protected transferState: TransferState,
|
||||
protected dspaceTransferState: DSpaceTransferState,
|
||||
) {
|
||||
super(store, correlationIdService, dspaceTransferState);
|
||||
}
|
||||
|
||||
public init(): () => Promise<boolean> {
|
||||
// this method must be called before the callback because APP_BASE_HREF depends on it
|
||||
this.loadAppConfigFromSSR();
|
||||
|
||||
return async () => {
|
||||
await this.transferAppState();
|
||||
this.checkAuthenticationToken();
|
||||
this.initCorrelationId();
|
||||
|
||||
return true;
|
||||
};
|
||||
}
|
||||
|
||||
private loadAppConfigFromSSR(): void {
|
||||
if (this.transferState.hasKey<AppConfig>(APP_CONFIG_STATE)) {
|
||||
const appConfig = this.transferState.get<AppConfig>(APP_CONFIG_STATE, new DefaultAppConfig());
|
||||
// extend environment with app config for browser
|
||||
extendEnvironmentWithAppConfig(environment, appConfig);
|
||||
}
|
||||
}
|
||||
}
|
@@ -1,9 +1,8 @@
|
||||
import { HTTP_INTERCEPTORS } from '@angular/common/http';
|
||||
import { APP_INITIALIZER, NgModule } from '@angular/core';
|
||||
import { NgModule } from '@angular/core';
|
||||
import { BrowserModule, TransferState } from '@angular/platform-browser';
|
||||
import { NoopAnimationsModule } from '@angular/platform-browser/animations';
|
||||
import { ServerModule } from '@angular/platform-server';
|
||||
import { RouterModule } from '@angular/router';
|
||||
|
||||
import { TranslateLoader, TranslateModule } from '@ngx-translate/core';
|
||||
|
||||
@@ -14,7 +13,6 @@ import { AppComponent } from '../../app/app.component';
|
||||
|
||||
import { AppModule } from '../../app/app.module';
|
||||
import { DSpaceServerTransferStateModule } from '../transfer-state/dspace-server-transfer-state.module';
|
||||
import { DSpaceTransferState } from '../transfer-state/dspace-transfer-state.service';
|
||||
import { TranslateServerLoader } from '../../ngx-translate-loaders/translate-server.loader';
|
||||
import { CookieService } from '../../app/core/services/cookie.service';
|
||||
import { ServerCookieService } from '../../app/core/services/server-cookie.service';
|
||||
@@ -32,10 +30,8 @@ import { ServerHardRedirectService } from '../../app/core/services/server-hard-r
|
||||
import { Angulartics2Mock } from '../../app/shared/mocks/angulartics2.service.mock';
|
||||
import { AuthRequestService } from '../../app/core/auth/auth-request.service';
|
||||
import { ServerAuthRequestService } from '../../app/core/auth/server-auth-request.service';
|
||||
import { CorrelationIdService } from '../../app/correlation-id/correlation-id.service';
|
||||
import { AppConfig, APP_CONFIG_STATE } from '../../config/app-config.interface';
|
||||
|
||||
import { environment } from '../../environments/environment';
|
||||
import { InitService } from '../../app/init.service';
|
||||
import { ServerInitService } from './server-init.service';
|
||||
|
||||
export function createTranslateLoader(transferState: TransferState) {
|
||||
return new TranslateServerLoader(transferState, 'dist/server/assets/i18n/', '.json5');
|
||||
@@ -60,21 +56,9 @@ export function createTranslateLoader(transferState: TransferState) {
|
||||
AppModule
|
||||
],
|
||||
providers: [
|
||||
// Initialize app config and extend environment
|
||||
{
|
||||
provide: APP_INITIALIZER,
|
||||
useFactory: (
|
||||
transferState: TransferState,
|
||||
dspaceTransferState: DSpaceTransferState,
|
||||
correlationIdService: CorrelationIdService,
|
||||
) => {
|
||||
transferState.set<AppConfig>(APP_CONFIG_STATE, environment as AppConfig);
|
||||
dspaceTransferState.transfer();
|
||||
correlationIdService.initCorrelationId();
|
||||
return () => true;
|
||||
},
|
||||
deps: [TransferState, DSpaceTransferState, CorrelationIdService],
|
||||
multi: true
|
||||
provide: InitService,
|
||||
useClass: ServerInitService,
|
||||
},
|
||||
{
|
||||
provide: Angulartics2,
|
||||
|
46
src/modules/app/server-init.service.ts
Normal file
46
src/modules/app/server-init.service.ts
Normal file
@@ -0,0 +1,46 @@
|
||||
/**
|
||||
* The contents of this file are subject to the license and copyright
|
||||
* detailed in the LICENSE and NOTICE files at the root of the source
|
||||
* tree and available online at
|
||||
*
|
||||
* http://www.dspace.org/license/
|
||||
*/
|
||||
import { InitService } from '../../app/init.service';
|
||||
import { Store } from '@ngrx/store';
|
||||
import { AppState } from '../../app/app.reducer';
|
||||
import { TransferState } from '@angular/platform-browser';
|
||||
import { DSpaceTransferState } from '../transfer-state/dspace-transfer-state.service';
|
||||
import { CorrelationIdService } from '../../app/correlation-id/correlation-id.service';
|
||||
import { APP_CONFIG_STATE, AppConfig } from '../../config/app-config.interface';
|
||||
import { environment } from '../../environments/environment';
|
||||
import { Injectable } from '@angular/core';
|
||||
|
||||
/**
|
||||
* Performs server-side initialization.
|
||||
*/
|
||||
@Injectable()
|
||||
export class ServerInitService extends InitService {
|
||||
constructor(
|
||||
protected store: Store<AppState>,
|
||||
protected correlationIdService: CorrelationIdService,
|
||||
protected transferState: TransferState,
|
||||
protected dspaceTransferState: DSpaceTransferState,
|
||||
) {
|
||||
super(store, correlationIdService, dspaceTransferState);
|
||||
}
|
||||
|
||||
public init(): () => Promise<boolean> {
|
||||
return async () => {
|
||||
this.checkAuthenticationToken();
|
||||
this.saveAppConfigForCSR();
|
||||
this.transferAppState(); // todo: SSR breaks if we await this (why?)
|
||||
this.initCorrelationId();
|
||||
|
||||
return true;
|
||||
};
|
||||
}
|
||||
|
||||
private saveAppConfigForCSR(): void {
|
||||
this.transferState.set<AppConfig>(APP_CONFIG_STATE, environment as AppConfig);
|
||||
}
|
||||
}
|
Reference in New Issue
Block a user