diff --git a/src/app/core/bootstrap/providers/api-bootstrap.provider.ts b/src/app/core/bootstrap/providers/api-bootstrap.provider.ts new file mode 100644 index 0000000..eaddd0b --- /dev/null +++ b/src/app/core/bootstrap/providers/api-bootstrap.provider.ts @@ -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 { + return this.http.get(this.bootstrapUrl); + } +} diff --git a/src/app/core/bootstrap/providers/mock-bootstrap.provider.ts b/src/app/core/bootstrap/providers/mock-bootstrap.provider.ts new file mode 100644 index 0000000..9b9b325 --- /dev/null +++ b/src/app/core/bootstrap/providers/mock-bootstrap.provider.ts @@ -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 { + return this.http.get(this.bootstrapUrl); + } +} diff --git a/src/app/core/config/config-provider.interface.ts b/src/app/core/config/config-provider.interface.ts new file mode 100644 index 0000000..bc5a883 --- /dev/null +++ b/src/app/core/config/config-provider.interface.ts @@ -0,0 +1,6 @@ +import { Observable } from 'rxjs'; +import { BootstrapConfig } from '../../shared/models/config'; + +export interface ConfigProvider { + loadBootstrap(): Observable; +} diff --git a/src/app/core/config/config-provider.token.ts b/src/app/core/config/config-provider.token.ts new file mode 100644 index 0000000..12ec466 --- /dev/null +++ b/src/app/core/config/config-provider.token.ts @@ -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('CONFIG_PROVIDER', { + providedIn: 'root', + factory: () => inject(MockBootstrapProvider) +}); diff --git a/src/app/core/config/config.service.ts b/src/app/core/config/config.service.ts new file mode 100644 index 0000000..b722d39 --- /dev/null +++ b/src/app/core/config/config.service.ts @@ -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; + + loadBootstrap(forceRefresh: boolean = false): Observable { + 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; + } +}