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 { NgbModule } from '@ng-bootstrap/ng-bootstrap';
|
||||||
import { EffectsModule } from '@ngrx/effects';
|
import { EffectsModule } from '@ngrx/effects';
|
||||||
import { RouterStateSerializer, StoreRouterConnectingModule } from '@ngrx/router-store';
|
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 { StoreDevtoolsModule } from '@ngrx/store-devtools';
|
||||||
import {
|
import { DYNAMIC_ERROR_MESSAGES_MATCHER, DYNAMIC_MATCHER_PROVIDERS, DynamicErrorMessagesMatcher } from '@ng-dynamic-forms/core';
|
||||||
DYNAMIC_ERROR_MESSAGES_MATCHER,
|
|
||||||
DYNAMIC_MATCHER_PROVIDERS,
|
|
||||||
DynamicErrorMessagesMatcher
|
|
||||||
} from '@ng-dynamic-forms/core';
|
|
||||||
import { TranslateModule } from '@ngx-translate/core';
|
import { TranslateModule } from '@ngx-translate/core';
|
||||||
import { ScrollToModule } from '@nicky-lenaers/ngx-scroll-to';
|
import { ScrollToModule } from '@nicky-lenaers/ngx-scroll-to';
|
||||||
import { AppRoutingModule } from './app-routing.module';
|
import { AppRoutingModule } from './app-routing.module';
|
||||||
@@ -21,7 +17,6 @@ import { AppComponent } from './app.component';
|
|||||||
import { appEffects } from './app.effects';
|
import { appEffects } from './app.effects';
|
||||||
import { appMetaReducers, debugMetaReducers } from './app.metareducers';
|
import { appMetaReducers, debugMetaReducers } from './app.metareducers';
|
||||||
import { appReducers, AppState, storeModuleConfig } from './app.reducer';
|
import { appReducers, AppState, storeModuleConfig } from './app.reducer';
|
||||||
import { CheckAuthenticationTokenAction } from './core/auth/auth.actions';
|
|
||||||
import { CoreModule } from './core/core.module';
|
import { CoreModule } from './core/core.module';
|
||||||
import { ClientCookieService } from './core/services/client-cookie.service';
|
import { ClientCookieService } from './core/services/client-cookie.service';
|
||||||
import { NavbarModule } from './navbar/navbar.module';
|
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 { APP_CONFIG, AppConfig } from '../config/app-config.interface';
|
||||||
import { RootModule } from './root.module';
|
import { RootModule } from './root.module';
|
||||||
|
import { InitService } from './init.service';
|
||||||
|
|
||||||
export function getConfig() {
|
export function getConfig() {
|
||||||
return environment;
|
return environment;
|
||||||
@@ -82,6 +78,12 @@ IMPORTS.push(
|
|||||||
);
|
);
|
||||||
|
|
||||||
const PROVIDERS = [
|
const PROVIDERS = [
|
||||||
|
{
|
||||||
|
provide: APP_INITIALIZER,
|
||||||
|
useFactory: (initService: InitService) => initService.init(),
|
||||||
|
deps: [ InitService ],
|
||||||
|
multi: true,
|
||||||
|
},
|
||||||
{
|
{
|
||||||
provide: APP_CONFIG,
|
provide: APP_CONFIG,
|
||||||
useFactory: getConfig
|
useFactory: getConfig
|
||||||
@@ -101,15 +103,6 @@ const PROVIDERS = [
|
|||||||
useClass: DSpaceRouterStateSerializer
|
useClass: DSpaceRouterStateSerializer
|
||||||
},
|
},
|
||||||
ClientCookieService,
|
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
|
// register AuthInterceptor as HttpInterceptor
|
||||||
{
|
{
|
||||||
provide: HTTP_INTERCEPTORS,
|
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 { 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 { BrowserModule, makeStateKey, TransferState } from '@angular/platform-browser';
|
||||||
import { BrowserAnimationsModule } from '@angular/platform-browser/animations';
|
import { BrowserAnimationsModule } from '@angular/platform-browser/animations';
|
||||||
import { REQUEST } from '@nguniversal/express-engine/tokens';
|
import { REQUEST } from '@nguniversal/express-engine/tokens';
|
||||||
@@ -13,7 +13,6 @@ import { AppComponent } from '../../app/app.component';
|
|||||||
|
|
||||||
import { AppModule } from '../../app/app.module';
|
import { AppModule } from '../../app/app.module';
|
||||||
import { DSpaceBrowserTransferStateModule } from '../transfer-state/dspace-browser-transfer-state.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 { ClientCookieService } from '../../app/core/services/client-cookie.service';
|
||||||
import { CookieService } from '../../app/core/services/cookie.service';
|
import { CookieService } from '../../app/core/services/cookie.service';
|
||||||
import { AuthService } from '../../app/core/auth/auth.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 { BrowserKlaroService } from '../../app/shared/cookies/browser-klaro.service';
|
||||||
import { KlaroService } from '../../app/shared/cookies/klaro.service';
|
import { KlaroService } from '../../app/shared/cookies/klaro.service';
|
||||||
import { HardRedirectService } from '../../app/core/services/hard-redirect.service';
|
import { HardRedirectService } from '../../app/core/services/hard-redirect.service';
|
||||||
import {
|
import { BrowserHardRedirectService, locationProvider, LocationToken } from '../../app/core/services/browser-hard-redirect.service';
|
||||||
BrowserHardRedirectService,
|
|
||||||
locationProvider,
|
|
||||||
LocationToken
|
|
||||||
} from '../../app/core/services/browser-hard-redirect.service';
|
|
||||||
import { LocaleService } from '../../app/core/locale/locale.service';
|
import { LocaleService } from '../../app/core/locale/locale.service';
|
||||||
import { GoogleAnalyticsService } from '../../app/statistics/google-analytics.service';
|
import { GoogleAnalyticsService } from '../../app/statistics/google-analytics.service';
|
||||||
import { AuthRequestService } from '../../app/core/auth/auth-request.service';
|
import { AuthRequestService } from '../../app/core/auth/auth-request.service';
|
||||||
import { BrowserAuthRequestService } from '../../app/core/auth/browser-auth-request.service';
|
import { BrowserAuthRequestService } from '../../app/core/auth/browser-auth-request.service';
|
||||||
import { AppConfig, APP_CONFIG_STATE } from '../../config/app-config.interface';
|
import { InitService } from 'src/app/init.service';
|
||||||
import { DefaultAppConfig } from '../../config/default-app-config';
|
import { BrowserInitService } from './browser-init.service';
|
||||||
import { extendEnvironmentWithAppConfig } from '../../config/config.util';
|
|
||||||
import { CorrelationIdService } from '../../app/correlation-id/correlation-id.service';
|
|
||||||
|
|
||||||
import { environment } from '../../environments/environment';
|
|
||||||
|
|
||||||
export const REQ_KEY = makeStateKey<string>('req');
|
export const REQ_KEY = makeStateKey<string>('req');
|
||||||
|
|
||||||
@@ -73,25 +64,8 @@ export function getRequest(transferState: TransferState): any {
|
|||||||
],
|
],
|
||||||
providers: [
|
providers: [
|
||||||
{
|
{
|
||||||
provide: APP_INITIALIZER,
|
provide: InitService,
|
||||||
useFactory: (
|
useClass: BrowserInitService,
|
||||||
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: REQUEST,
|
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 { 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 { BrowserModule, TransferState } from '@angular/platform-browser';
|
||||||
import { NoopAnimationsModule } from '@angular/platform-browser/animations';
|
import { NoopAnimationsModule } from '@angular/platform-browser/animations';
|
||||||
import { ServerModule } from '@angular/platform-server';
|
import { ServerModule } from '@angular/platform-server';
|
||||||
import { RouterModule } from '@angular/router';
|
|
||||||
|
|
||||||
import { TranslateLoader, TranslateModule } from '@ngx-translate/core';
|
import { TranslateLoader, TranslateModule } from '@ngx-translate/core';
|
||||||
|
|
||||||
@@ -14,7 +13,6 @@ import { AppComponent } from '../../app/app.component';
|
|||||||
|
|
||||||
import { AppModule } from '../../app/app.module';
|
import { AppModule } from '../../app/app.module';
|
||||||
import { DSpaceServerTransferStateModule } from '../transfer-state/dspace-server-transfer-state.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 { TranslateServerLoader } from '../../ngx-translate-loaders/translate-server.loader';
|
||||||
import { CookieService } from '../../app/core/services/cookie.service';
|
import { CookieService } from '../../app/core/services/cookie.service';
|
||||||
import { ServerCookieService } from '../../app/core/services/server-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 { Angulartics2Mock } from '../../app/shared/mocks/angulartics2.service.mock';
|
||||||
import { AuthRequestService } from '../../app/core/auth/auth-request.service';
|
import { AuthRequestService } from '../../app/core/auth/auth-request.service';
|
||||||
import { ServerAuthRequestService } from '../../app/core/auth/server-auth-request.service';
|
import { ServerAuthRequestService } from '../../app/core/auth/server-auth-request.service';
|
||||||
import { CorrelationIdService } from '../../app/correlation-id/correlation-id.service';
|
import { InitService } from '../../app/init.service';
|
||||||
import { AppConfig, APP_CONFIG_STATE } from '../../config/app-config.interface';
|
import { ServerInitService } from './server-init.service';
|
||||||
|
|
||||||
import { environment } from '../../environments/environment';
|
|
||||||
|
|
||||||
export function createTranslateLoader(transferState: TransferState) {
|
export function createTranslateLoader(transferState: TransferState) {
|
||||||
return new TranslateServerLoader(transferState, 'dist/server/assets/i18n/', '.json5');
|
return new TranslateServerLoader(transferState, 'dist/server/assets/i18n/', '.json5');
|
||||||
@@ -60,21 +56,9 @@ export function createTranslateLoader(transferState: TransferState) {
|
|||||||
AppModule
|
AppModule
|
||||||
],
|
],
|
||||||
providers: [
|
providers: [
|
||||||
// Initialize app config and extend environment
|
|
||||||
{
|
{
|
||||||
provide: APP_INITIALIZER,
|
provide: InitService,
|
||||||
useFactory: (
|
useClass: ServerInitService,
|
||||||
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: Angulartics2,
|
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