import { Injector, Type, } from '@angular/core'; import { defer, Observable, } from 'rxjs'; import { LazyDataServicesMap } from '../../config/app-config.interface'; import { HALDataService } from './data/base/hal-data-service.interface'; /** * Loads a service lazily. The service is loaded when the observable is subscribed to. * * @param dataServicesMap A map of promises returning the data services to load * @param key The key of the service * @param injector The injector to use to load the service. If not provided, the current injector is used. * @returns An observable of the service. * * @example * ```ts * const dataService$ = lazyDataService({ 'data-service': () => import('./data-service').then((m) => m.MyService)}, 'data-service', this.injector); * or * const dataService$ = lazyDataService({'data-service': () => import('./data-service')}, 'data-service', this.injector); * ``` */ export function lazyDataService<T>( dataServicesMap: LazyDataServicesMap, key: string, injector: Injector, ): Observable<T> { return defer(() => { if (dataServicesMap.has(key) && typeof dataServicesMap.get(key) === 'function') { const loader: () => Promise<Type<HALDataService<any>> | { default: HALDataService<any> }> = dataServicesMap.get(key); return loader() .then((serviceOrDefault) => { if ('default' in serviceOrDefault) { return injector!.get(serviceOrDefault.default); } return injector!.get(serviceOrDefault); }) .catch((error) => { throw error; }); } else { return null; } }); }