phase-4: add provider-abstracted ConfigService with mock bootstrap loader
This commit is contained in:
16
src/app/core/bootstrap/providers/api-bootstrap.provider.ts
Normal file
16
src/app/core/bootstrap/providers/api-bootstrap.provider.ts
Normal file
@@ -0,0 +1,16 @@
|
||||
import { Injectable } from '@angular/core';
|
||||
import { HttpClient } from '@angular/common/http';
|
||||
import { Observable } from 'rxjs';
|
||||
import { BootstrapConfig } from '../../../shared/models/config';
|
||||
import { ConfigProvider } from '../../config/config-provider.interface';
|
||||
|
||||
@Injectable({ providedIn: 'root' })
|
||||
export class ApiBootstrapProvider implements ConfigProvider {
|
||||
private readonly bootstrapUrl = '/bootstrap';
|
||||
|
||||
constructor(private readonly http: HttpClient) {}
|
||||
|
||||
loadBootstrap(): Observable<BootstrapConfig> {
|
||||
return this.http.get<BootstrapConfig>(this.bootstrapUrl);
|
||||
}
|
||||
}
|
||||
16
src/app/core/bootstrap/providers/mock-bootstrap.provider.ts
Normal file
16
src/app/core/bootstrap/providers/mock-bootstrap.provider.ts
Normal file
@@ -0,0 +1,16 @@
|
||||
import { Injectable } from '@angular/core';
|
||||
import { HttpClient } from '@angular/common/http';
|
||||
import { Observable } from 'rxjs';
|
||||
import { BootstrapConfig } from '../../../shared/models/config';
|
||||
import { ConfigProvider } from '../../config/config-provider.interface';
|
||||
|
||||
@Injectable({ providedIn: 'root' })
|
||||
export class MockBootstrapProvider implements ConfigProvider {
|
||||
private readonly bootstrapUrl = '/assets/mock/bootstrap/bootstrap.json';
|
||||
|
||||
constructor(private readonly http: HttpClient) {}
|
||||
|
||||
loadBootstrap(): Observable<BootstrapConfig> {
|
||||
return this.http.get<BootstrapConfig>(this.bootstrapUrl);
|
||||
}
|
||||
}
|
||||
6
src/app/core/config/config-provider.interface.ts
Normal file
6
src/app/core/config/config-provider.interface.ts
Normal file
@@ -0,0 +1,6 @@
|
||||
import { Observable } from 'rxjs';
|
||||
import { BootstrapConfig } from '../../shared/models/config';
|
||||
|
||||
export interface ConfigProvider {
|
||||
loadBootstrap(): Observable<BootstrapConfig>;
|
||||
}
|
||||
8
src/app/core/config/config-provider.token.ts
Normal file
8
src/app/core/config/config-provider.token.ts
Normal file
@@ -0,0 +1,8 @@
|
||||
import { InjectionToken, inject } from '@angular/core';
|
||||
import { ConfigProvider } from './config-provider.interface';
|
||||
import { MockBootstrapProvider } from '../bootstrap/providers/mock-bootstrap.provider';
|
||||
|
||||
export const CONFIG_PROVIDER = new InjectionToken<ConfigProvider>('CONFIG_PROVIDER', {
|
||||
providedIn: 'root',
|
||||
factory: () => inject(MockBootstrapProvider)
|
||||
});
|
||||
35
src/app/core/config/config.service.ts
Normal file
35
src/app/core/config/config.service.ts
Normal file
@@ -0,0 +1,35 @@
|
||||
import { Injectable, inject } from '@angular/core';
|
||||
import { Observable, throwError } from 'rxjs';
|
||||
import { catchError, shareReplay, tap } from 'rxjs/operators';
|
||||
import { BootstrapConfig } from '../../shared/models/config';
|
||||
import { CONFIG_PROVIDER } from './config-provider.token';
|
||||
|
||||
@Injectable({ providedIn: 'root' })
|
||||
export class ConfigService {
|
||||
private readonly provider = inject(CONFIG_PROVIDER);
|
||||
|
||||
private bootstrapSnapshot: BootstrapConfig | null = null;
|
||||
private bootstrap$?: Observable<BootstrapConfig>;
|
||||
|
||||
loadBootstrap(forceRefresh: boolean = false): Observable<BootstrapConfig> {
|
||||
if (!this.bootstrap$ || forceRefresh) {
|
||||
this.bootstrap$ = this.provider.loadBootstrap().pipe(
|
||||
tap(config => {
|
||||
this.bootstrapSnapshot = config;
|
||||
}),
|
||||
shareReplay(1),
|
||||
catchError(error => {
|
||||
this.bootstrap$ = undefined;
|
||||
this.bootstrapSnapshot = null;
|
||||
return throwError(() => error);
|
||||
})
|
||||
);
|
||||
}
|
||||
|
||||
return this.bootstrap$;
|
||||
}
|
||||
|
||||
getBootstrapSnapshot(): BootstrapConfig | null {
|
||||
return this.bootstrapSnapshot;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user