From 40204328adefc6767170968bb992edcda9a0fe15 Mon Sep 17 00:00:00 2001 From: Giuseppe Digilio Date: Thu, 4 Apr 2024 18:21:38 +0200 Subject: [PATCH 1/7] [DURACOM-247] Resolve CodeQL alert --- src/app/core/lazy-service.ts | 24 ++++++++++++++---------- 1 file changed, 14 insertions(+), 10 deletions(-) diff --git a/src/app/core/lazy-service.ts b/src/app/core/lazy-service.ts index 701a1d7dacf..56882006a16 100644 --- a/src/app/core/lazy-service.ts +++ b/src/app/core/lazy-service.ts @@ -26,15 +26,19 @@ export function lazyService( injector: Injector, ): Observable { return defer(() => { - return loader() - .then((serviceOrDefault) => { - if ('default' in serviceOrDefault) { - return injector!.get(serviceOrDefault.default); - } - return injector!.get(serviceOrDefault); - }) - .catch((error) => { - throw error; - }); + if (typeof loader === 'function') { + return loader() + .then((serviceOrDefault) => { + if ('default' in serviceOrDefault) { + return injector!.get(serviceOrDefault.default); + } + return injector!.get(serviceOrDefault); + }) + .catch((error) => { + throw error; + }); + } else { + return null; + } }); } From d2ec558ac24332085d97a1a0ec1b962ac80354e5 Mon Sep 17 00:00:00 2001 From: Giuseppe Digilio Date: Fri, 5 Apr 2024 09:43:47 +0200 Subject: [PATCH 2/7] [DURACOM-247] Move check for initialized token to request effects --- src/app/core/data/request.effects.ts | 10 +++++++++- src/app/core/data/request.service.spec.ts | 8 -------- src/app/core/data/request.service.ts | 22 +++------------------- 3 files changed, 12 insertions(+), 28 deletions(-) diff --git a/src/app/core/data/request.effects.ts b/src/app/core/data/request.effects.ts index 6501f43133c..bc403bc2717 100644 --- a/src/app/core/data/request.effects.ts +++ b/src/app/core/data/request.effects.ts @@ -13,6 +13,7 @@ import { map, mergeMap, take, + withLatestFrom, } from 'rxjs/operators'; import { @@ -25,6 +26,7 @@ import { ParsedResponse } from '../cache/response.models'; import { DSpaceSerializer } from '../dspace-rest/dspace.serializer'; import { DspaceRestService } from '../dspace-rest/dspace-rest.service'; import { RawRestResponse } from '../dspace-rest/raw-rest-response.model'; +import { XSRFService } from '../xsrf/xsrf.service'; import { RequestActionTypes, RequestErrorAction, @@ -35,6 +37,7 @@ import { import { RequestService } from './request.service'; import { RequestEntry } from './request-entry.model'; import { RequestError } from './request-error.model'; +import { RestRequestMethod } from './rest-request-method'; import { RestRequestWithResponseParser } from './rest-request-with-response-parser.model'; @Injectable() @@ -48,7 +51,11 @@ export class RequestEffects { ); }), filter((entry: RequestEntry) => hasValue(entry)), - map((entry: RequestEntry) => entry.request), + withLatestFrom(this.xsrfService.tokenInitialized$), + // If it's a GET request, or we have an XSRF token, dispatch it immediately + // Otherwise wait for the XSRF token first + filter(([entry, tokenInitialized]: [RequestEntry, boolean]) => entry.request.method === RestRequestMethod.GET || tokenInitialized === true), + map(([entry, tokenInitialized]: [RequestEntry, boolean]) => entry.request), mergeMap((request: RestRequestWithResponseParser) => { let body = request.body; if (isNotEmpty(request.body) && !request.isMultipart) { @@ -89,6 +96,7 @@ export class RequestEffects { private restApi: DspaceRestService, private injector: Injector, protected requestService: RequestService, + protected xsrfService: XSRFService, ) { } } diff --git a/src/app/core/data/request.service.spec.ts b/src/app/core/data/request.service.spec.ts index e1949016790..d8fa04973e2 100644 --- a/src/app/core/data/request.service.spec.ts +++ b/src/app/core/data/request.service.spec.ts @@ -17,7 +17,6 @@ import { getTestScheduler, } from 'jasmine-marbles'; import { - BehaviorSubject, EMPTY, Observable, of as observableOf, @@ -34,7 +33,6 @@ import { ObjectCacheService } from '../cache/object-cache.service'; import { coreReducers } from '../core.reducers'; import { CoreState } from '../core-state.model'; import { UUIDService } from '../shared/uuid.service'; -import { XSRFService } from '../xsrf/xsrf.service'; import { RequestConfigureAction, RequestExecuteAction, @@ -62,7 +60,6 @@ describe('RequestService', () => { let uuidService: UUIDService; let store: Store; let mockStore: MockStore; - let xsrfService: XSRFService; const testUUID = '5f2a0d2a-effa-4d54-bd54-5663b960f9eb'; const testHref = 'https://rest.api/endpoint/selfLink'; @@ -108,16 +105,11 @@ describe('RequestService', () => { store = TestBed.inject(Store); mockStore = store as MockStore; mockStore.setState(initialState); - xsrfService = { - tokenInitialized$: new BehaviorSubject(false), - } as XSRFService; service = new RequestService( objectCache, uuidService, store, - xsrfService, - undefined, ); serviceAsAny = service as any; }); diff --git a/src/app/core/data/request.service.ts b/src/app/core/data/request.service.ts index 3e2bbfdc9f7..52ec9b56e27 100644 --- a/src/app/core/data/request.service.ts +++ b/src/app/core/data/request.service.ts @@ -34,16 +34,12 @@ import { ObjectCacheService } from '../cache/object-cache.service'; import { CommitSSBAction } from '../cache/server-sync-buffer.actions'; import { coreSelector } from '../core.selectors'; import { CoreState } from '../core-state.model'; -import { - IndexState, - MetaIndexState, -} from '../index/index.reducer'; +import { IndexState } from '../index/index.reducer'; import { getUrlWithoutEmbedParams, requestIndexSelector, } from '../index/index.selectors'; import { UUIDService } from '../shared/uuid.service'; -import { XSRFService } from '../xsrf/xsrf.service'; import { RequestConfigureAction, RequestExecuteAction, @@ -169,9 +165,7 @@ export class RequestService { constructor(private objectCache: ObjectCacheService, private uuidService: UUIDService, - private store: Store, - protected xsrfService: XSRFService, - private indexStore: Store) { + private store: Store) { } generateRequestId(): string { @@ -455,17 +449,7 @@ export class RequestService { private dispatchRequest(request: RestRequest) { asapScheduler.schedule(() => { this.store.dispatch(new RequestConfigureAction(request)); - // If it's a GET request, or we have an XSRF token, dispatch it immediately - if (request.method === RestRequestMethod.GET || this.xsrfService.tokenInitialized$.getValue() === true) { - this.store.dispatch(new RequestExecuteAction(request.uuid)); - } else { - // Otherwise wait for the XSRF token first - this.xsrfService.tokenInitialized$.pipe( - find((hasInitialized: boolean) => hasInitialized === true), - ).subscribe(() => { - this.store.dispatch(new RequestExecuteAction(request.uuid)); - }); - } + this.store.dispatch(new RequestExecuteAction(request.uuid)); }); } From aac61785d3a844f02c0af9627b327ddf2afcc63b Mon Sep 17 00:00:00 2001 From: Giuseppe Digilio Date: Fri, 5 Apr 2024 12:23:18 +0200 Subject: [PATCH 3/7] [DURACOM-247] Add condition to check function is not null --- src/app/core/lazy-service.ts | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/app/core/lazy-service.ts b/src/app/core/lazy-service.ts index 56882006a16..25f90f26b19 100644 --- a/src/app/core/lazy-service.ts +++ b/src/app/core/lazy-service.ts @@ -7,6 +7,8 @@ import { Observable, } from 'rxjs'; +import { isNotEmpty } from '../shared/empty.util'; + /** * Loads a service lazily. The service is loaded when the observable is subscribed to. * @@ -26,7 +28,7 @@ export function lazyService( injector: Injector, ): Observable { return defer(() => { - if (typeof loader === 'function') { + if (isNotEmpty(loader) && typeof loader === 'function') { return loader() .then((serviceOrDefault) => { if ('default' in serviceOrDefault) { From 2a3a13e2932a2ee824675d4c2beb7c0297b28f6a Mon Sep 17 00:00:00 2001 From: Giuseppe Digilio Date: Mon, 8 Apr 2024 19:21:20 +0200 Subject: [PATCH 4/7] [DURACOM-247] Refactored by providing the map of promises --- src/app/core/cache/builders/link.service.ts | 7 +++---- .../{lazy-service.ts => lazy-data-service.ts} | 15 ++++++++++----- .../dso-edit-metadata.component.ts | 7 +++---- .../eperson-group-list.component.ts | 7 +++---- .../resolvers/resource-policy-target.resolver.ts | 12 +++++++----- src/config/app-config.interface.ts | 2 +- 6 files changed, 27 insertions(+), 23 deletions(-) rename src/app/core/{lazy-service.ts => lazy-data-service.ts} (56%) diff --git a/src/app/core/cache/builders/link.service.ts b/src/app/core/cache/builders/link.service.ts index b1ced76bb8b..6265e89d532 100644 --- a/src/app/core/cache/builders/link.service.ts +++ b/src/app/core/cache/builders/link.service.ts @@ -1,7 +1,6 @@ import { Inject, Injectable, - InjectionToken, Injector, } from '@angular/core'; import { @@ -25,7 +24,7 @@ import { FollowLinkConfig } from '../../../shared/utils/follow-link-config.model import { HALDataService } from '../../data/base/hal-data-service.interface'; import { PaginatedList } from '../../data/paginated-list.model'; import { RemoteData } from '../../data/remote-data'; -import { lazyService } from '../../lazy-service'; +import { lazyDataService } from '../../lazy-data-service'; import { GenericConstructor } from '../../shared/generic-constructor'; import { HALResource } from '../../shared/hal-resource.model'; import { @@ -43,7 +42,7 @@ export class LinkService { constructor( protected injector: Injector, - @Inject(APP_DATA_SERVICES_MAP) private map: InjectionToken, + @Inject(APP_DATA_SERVICES_MAP) private map: LazyDataServicesMap, @Inject(LINK_DEFINITION_FACTORY) private getLinkDefinition: (source: GenericConstructor, linkName: keyof T['_links']) => LinkDefinition, @Inject(LINK_DEFINITION_MAP_FACTORY) private getLinkDefinitions: (source: GenericConstructor) => Map>, ) { @@ -73,7 +72,7 @@ export class LinkService { public resolveLinkWithoutAttaching(model, linkToFollow: FollowLinkConfig): Observable>> { const matchingLinkDef = this.getLinkDefinition(model.constructor, linkToFollow.name); if (hasValue(matchingLinkDef)) { - const lazyProvider$: Observable> = lazyService(this.map[matchingLinkDef.resourceType.value], this.injector); + const lazyProvider$: Observable> = lazyDataService(this.map, matchingLinkDef.resourceType.value, this.injector); return lazyProvider$.pipe( switchMap((provider: HALDataService) => { const link = model._links[matchingLinkDef.linkName]; diff --git a/src/app/core/lazy-service.ts b/src/app/core/lazy-data-service.ts similarity index 56% rename from src/app/core/lazy-service.ts rename to src/app/core/lazy-data-service.ts index 25f90f26b19..f2effd0b678 100644 --- a/src/app/core/lazy-service.ts +++ b/src/app/core/lazy-data-service.ts @@ -7,27 +7,32 @@ import { Observable, } from 'rxjs'; +import { LazyDataServicesMap } from '../../config/app-config.interface'; import { isNotEmpty } from '../shared/empty.util'; +import { HALDataService } from './data/base/hal-data-service.interface'; /** * Loads a service lazily. The service is loaded when the observable is subscribed to. * - * @param loader A function that returns a promise of the service to load. + * @param map 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$ = lazyService(() => import('./data-service').then((m) => m.MyService), this.injector); + * const dataService$ = lazyDataService({ 'data-service': () => import('./data-service').then((m) => m.MyService)}, 'data-service', this.injector); * or - * const dataService$ = lazyService(() => import('./data-service'), this.injector); + * const dataService$ = lazyDataService({'data-service': () => import('./data-service')}, 'data-service', this.injector); * ``` */ -export function lazyService( - loader: () => Promise> | Promise<{ default: Type }>, +export function lazyDataService( + map: LazyDataServicesMap, + key: string, injector: Injector, ): Observable { return defer(() => { + const loader: () => Promise> | { default: HALDataService }> = map[key]; if (isNotEmpty(loader) && typeof loader === 'function') { return loader() .then((serviceOrDefault) => { diff --git a/src/app/dso-shared/dso-edit-metadata/dso-edit-metadata.component.ts b/src/app/dso-shared/dso-edit-metadata/dso-edit-metadata.component.ts index 6365f1ea990..cded29230e2 100644 --- a/src/app/dso-shared/dso-edit-metadata/dso-edit-metadata.component.ts +++ b/src/app/dso-shared/dso-edit-metadata/dso-edit-metadata.component.ts @@ -7,7 +7,6 @@ import { ChangeDetectorRef, Component, Inject, - InjectionToken, Injector, Input, OnDestroy, @@ -42,7 +41,7 @@ import { import { ArrayMoveChangeAnalyzer } from '../../core/data/array-move-change-analyzer.service'; import { RemoteData } from '../../core/data/remote-data'; import { UpdateDataService } from '../../core/data/update-data.service'; -import { lazyService } from '../../core/lazy-service'; +import { lazyDataService } from '../../core/lazy-data-service'; import { DSpaceObject } from '../../core/shared/dspace-object.model'; import { getFirstCompletedRemoteData } from '../../core/shared/operators'; import { ResourceType } from '../../core/shared/resource-type'; @@ -152,7 +151,7 @@ export class DsoEditMetadataComponent implements OnInit, OnDestroy { protected parentInjector: Injector, protected arrayMoveChangeAnalyser: ArrayMoveChangeAnalyzer, protected cdr: ChangeDetectorRef, - @Inject(APP_DATA_SERVICES_MAP) private dataServiceMap: InjectionToken) { + @Inject(APP_DATA_SERVICES_MAP) private dataServiceMap: LazyDataServicesMap) { } /** @@ -186,7 +185,7 @@ export class DsoEditMetadataComponent implements OnInit, OnDestroy { */ retrieveDataService(): Observable> { if (hasNoValue(this.updateDataService)) { - const lazyProvider$: Observable> = lazyService(this.dataServiceMap[this.dsoType], this.parentInjector); + const lazyProvider$: Observable> = lazyDataService(this.dataServiceMap, this.dsoType, this.parentInjector); return lazyProvider$; } else { return EMPTY; diff --git a/src/app/shared/eperson-group-list/eperson-group-list.component.ts b/src/app/shared/eperson-group-list/eperson-group-list.component.ts index 0a33767e349..663418d20cd 100644 --- a/src/app/shared/eperson-group-list/eperson-group-list.component.ts +++ b/src/app/shared/eperson-group-list/eperson-group-list.component.ts @@ -7,7 +7,6 @@ import { Component, EventEmitter, Inject, - InjectionToken, Injector, Input, OnDestroy, @@ -35,7 +34,7 @@ import { EPersonDataService } from '../../core/eperson/eperson-data.service'; import { GroupDataService } from '../../core/eperson/group-data.service'; import { EPERSON } from '../../core/eperson/models/eperson.resource-type'; import { GROUP } from '../../core/eperson/models/group.resource-type'; -import { lazyService } from '../../core/lazy-service'; +import { lazyDataService } from '../../core/lazy-data-service'; import { PaginationService } from '../../core/pagination/pagination.service'; import { DSpaceObject } from '../../core/shared/dspace-object.model'; import { getFirstCompletedRemoteData } from '../../core/shared/operators'; @@ -133,7 +132,7 @@ export class EpersonGroupListComponent implements OnInit, OnDestroy { constructor(public dsoNameService: DSONameService, private parentInjector: Injector, private paginationService: PaginationService, - @Inject(APP_DATA_SERVICES_MAP) private dataServiceMap: InjectionToken) { + @Inject(APP_DATA_SERVICES_MAP) private dataServiceMap: LazyDataServicesMap) { } /** @@ -141,7 +140,7 @@ export class EpersonGroupListComponent implements OnInit, OnDestroy { */ ngOnInit(): void { const resourceType: ResourceType = (this.isListOfEPerson) ? EPERSON : GROUP; - const lazyProvider$: Observable = lazyService(this.dataServiceMap[resourceType.value], this.parentInjector); + const lazyProvider$: Observable = lazyDataService(this.dataServiceMap, resourceType.value, this.parentInjector); lazyProvider$.subscribe((dataService: EPersonDataService | GroupDataService) => { this.dataService = dataService; console.log(dataService); diff --git a/src/app/shared/resource-policies/resolvers/resource-policy-target.resolver.ts b/src/app/shared/resource-policies/resolvers/resource-policy-target.resolver.ts index 76748efad13..4a3712c7d17 100644 --- a/src/app/shared/resource-policies/resolvers/resource-policy-target.resolver.ts +++ b/src/app/shared/resource-policies/resolvers/resource-policy-target.resolver.ts @@ -1,6 +1,5 @@ import { inject, - InjectionToken, Injector, } from '@angular/core'; import { @@ -12,10 +11,13 @@ import { import { Observable } from 'rxjs'; import { switchMap } from 'rxjs/operators'; -import { LazyDataServicesMap } from '../../../../config/app-config.interface'; +import { + APP_DATA_SERVICES_MAP, + LazyDataServicesMap, +} from '../../../../config/app-config.interface'; import { IdentifiableDataService } from '../../../core/data/base/identifiable-data.service'; import { RemoteData } from '../../../core/data/remote-data'; -import { lazyService } from '../../../core/lazy-service'; +import { lazyDataService } from '../../../core/lazy-data-service'; import { DSpaceObject } from '../../../core/shared/dspace-object.model'; import { getFirstCompletedRemoteData } from '../../../core/shared/operators'; import { ResourceType } from '../../../core/shared/resource-type'; @@ -34,7 +36,7 @@ import { isEmpty } from '../../empty.util'; export const resourcePolicyTargetResolver: ResolveFn> = ( route: ActivatedRouteSnapshot, state: RouterStateSnapshot, - dataServiceMap: InjectionToken = inject(InjectionToken), + dataServiceMap: LazyDataServicesMap = inject(APP_DATA_SERVICES_MAP), parentInjector: Injector = inject(Injector), router: Router = inject(Router), ): Observable> => { @@ -46,7 +48,7 @@ export const resourcePolicyTargetResolver: ResolveFn> = } const resourceType: ResourceType = new ResourceType(targetType); - const lazyProvider$: Observable> = lazyService(dataServiceMap[resourceType.value], parentInjector); + const lazyProvider$: Observable> = lazyDataService(dataServiceMap, resourceType.value, parentInjector); return lazyProvider$.pipe( switchMap((dataService: IdentifiableDataService) => { diff --git a/src/config/app-config.interface.ts b/src/config/app-config.interface.ts index 2de471f20ea..540ebcbcb20 100644 --- a/src/config/app-config.interface.ts +++ b/src/config/app-config.interface.ts @@ -74,7 +74,7 @@ const APP_CONFIG = new InjectionToken('APP_CONFIG'); const APP_CONFIG_STATE = makeStateKey('APP_CONFIG_STATE'); export interface LazyDataServicesMap { - [type: string]: () => Promise>> + [type: string]: () => Promise> | { default: HALDataService }> } export const APP_DATA_SERVICES_MAP: InjectionToken = new InjectionToken('APP_DATA_SERVICES_MAP'); From 115445a6ab482d7aaf231140dae971552abc58c1 Mon Sep 17 00:00:00 2001 From: Giuseppe Digilio Date: Mon, 8 Apr 2024 22:25:01 +0200 Subject: [PATCH 5/7] [DURACOM-247] Move local variable within if statement --- src/app/core/lazy-data-service.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/app/core/lazy-data-service.ts b/src/app/core/lazy-data-service.ts index f2effd0b678..0c8e4cd08c9 100644 --- a/src/app/core/lazy-data-service.ts +++ b/src/app/core/lazy-data-service.ts @@ -32,8 +32,8 @@ export function lazyDataService( injector: Injector, ): Observable { return defer(() => { - const loader: () => Promise> | { default: HALDataService }> = map[key]; - if (isNotEmpty(loader) && typeof loader === 'function') { + if (isNotEmpty(map[key]) && typeof map[key] === 'function') { + const loader: () => Promise> | { default: HALDataService }> = map[key]; return loader() .then((serviceOrDefault) => { if ('default' in serviceOrDefault) { From 883ceeae270f9326ab7789ffae2892dda0c5f9f7 Mon Sep 17 00:00:00 2001 From: Giuseppe Digilio Date: Mon, 8 Apr 2024 23:04:47 +0200 Subject: [PATCH 6/7] [DURACOM-247] Refactored by using a map of promises --- .../core/cache/builders/link.service.spec.ts | 8 +-- src/app/core/data-services-map.ts | 72 ++++++++++++++++++- src/app/core/lazy-data-service.ts | 9 ++- .../dso-edit-metadata.component.spec.ts | 6 +- .../eperson-group-list.component.spec.ts | 13 ++-- src/config/app-config.interface.ts | 4 +- 6 files changed, 90 insertions(+), 22 deletions(-) diff --git a/src/app/core/cache/builders/link.service.spec.ts b/src/app/core/cache/builders/link.service.spec.ts index 96650f1a55e..4f7cd946e55 100644 --- a/src/app/core/cache/builders/link.service.spec.ts +++ b/src/app/core/cache/builders/link.service.spec.ts @@ -5,7 +5,7 @@ import { take, } from 'rxjs/operators'; -import { APP_DATA_SERVICES_MAP } from '../../../../config/app-config.interface'; +import { APP_DATA_SERVICES_MAP, LazyDataServicesMap } from '../../../../config/app-config.interface'; import { TestDataService } from '../../../shared/testing/test-data-service.mock'; import { followLink } from '../../../shared/utils/follow-link-config.model'; import { HALLink } from '../../shared/hal-link.model'; @@ -37,9 +37,9 @@ class TestModel implements HALResource { successor?: TestModel; } -const mockDataServiceMap: any = { - [TEST_MODEL.value]: () => import('../../../shared/testing/test-data-service.mock').then(m => m.TestDataService), -}; +const mockDataServiceMap: any = new Map([ + [TEST_MODEL.value, () => import('../../../shared/testing/test-data-service.mock').then(m => m.TestDataService)], +]); let testDataService: TestDataService; diff --git a/src/app/core/data-services-map.ts b/src/app/core/data-services-map.ts index 12fc91b6784..ad8686b6da9 100644 --- a/src/app/core/data-services-map.ts +++ b/src/app/core/data-services-map.ts @@ -69,7 +69,75 @@ import { CLAIMED_TASK } from './tasks/models/claimed-task-object.resource-type'; import { POOL_TASK } from './tasks/models/pool-task-object.resource-type'; import { WORKFLOW_ACTION } from './tasks/models/workflow-action-object.resource-type'; -export const LAZY_DATA_SERVICES: LazyDataServicesMap = { +export const LAZY_DATA_SERVICES: LazyDataServicesMap = new Map([ + [AUTHORIZATION.value, () => import('./data/feature-authorization/authorization-data.service').then(m => m.AuthorizationDataService)], + [BROWSE_DEFINITION.value, () => import('./browse/browse-definition-data.service').then(m => m.BrowseDefinitionDataService)], + [BULK_ACCESS_CONDITION_OPTIONS.value, () => import('./config/bulk-access-config-data.service').then(m => m.BulkAccessConfigDataService)], + [METADATA_SCHEMA.value, () => import('./data/metadata-schema-data.service').then(m => m.MetadataSchemaDataService)], + [SUBMISSION_UPLOADS_TYPE.value, () => import('./config/submission-uploads-config-data.service').then(m => m.SubmissionUploadsConfigDataService)], + [BITSTREAM.value, () => import('./data/bitstream-data.service').then(m => m.BitstreamDataService)], + [SUBMISSION_ACCESSES_TYPE.value, () => import('./config/submission-accesses-config-data.service').then(m => m.SubmissionAccessesConfigDataService)], + [SYSTEMWIDEALERT.value, () => import('./data/system-wide-alert-data.service').then(m => m.SystemWideAlertDataService)], + [USAGE_REPORT.value, () => import('./statistics/usage-report-data.service').then(m => m.UsageReportDataService)], + [ACCESS_STATUS.value, () => import('./data/access-status-data.service').then(m => m.AccessStatusDataService)], + [COLLECTION.value, () => import('./data/collection-data.service').then(m => m.CollectionDataService)], + [CLAIMED_TASK.value, () => import('./tasks/claimed-task-data.service').then(m => m.ClaimedTaskDataService)], + [VOCABULARY_ENTRY.value, () => import('./data/href-only-data.service').then(m => m.HrefOnlyDataService)], + [ITEM_TYPE.value, () => import('./data/href-only-data.service').then(m => m.HrefOnlyDataService)], + [LICENSE.value, () => import('./data/href-only-data.service').then(m => m.HrefOnlyDataService)], + [SUBSCRIPTION.value, () => import('../shared/subscriptions/subscriptions-data.service').then(m => m.SubscriptionsDataService)], + [COMMUNITY.value, () => import('./data/community-data.service').then(m => m.CommunityDataService)], + [VOCABULARY.value, () => import('./submission/vocabularies/vocabulary.data.service').then(m => m.VocabularyDataService)], + [BUNDLE.value, () => import('./data/bundle-data.service').then(m => m.BundleDataService)], + [CONFIG_PROPERTY.value, () => import('./data/configuration-data.service').then(m => m.ConfigurationDataService)], + [POOL_TASK.value, () => import('./tasks/pool-task-data.service').then(m => m.PoolTaskDataService)], + [CLAIMED_TASK.value, () => import('./tasks/claimed-task-data.service').then(m => m.ClaimedTaskDataService)], + [SUPERVISION_ORDER.value, () => import('./supervision-order/supervision-order-data.service').then(m => m.SupervisionOrderDataService)], + [WORKSPACEITEM.value, () => import('./submission/workspaceitem-data.service').then(m => m.WorkspaceitemDataService)], + [WORKFLOWITEM.value, () => import('./submission/workflowitem-data.service').then(m => m.WorkflowItemDataService)], + [VOCABULARY.value, () => import('./submission/vocabularies/vocabulary.data.service').then(m => m.VocabularyDataService)], + [VOCABULARY_ENTRY_DETAIL.value, () => import('./submission/vocabularies/vocabulary-entry-details.data.service').then(m => m.VocabularyEntryDetailsDataService)], + [SUBMISSION_CC_LICENSE_URL.value, () => import('./submission/submission-cc-license-url-data.service').then(m => m.SubmissionCcLicenseUrlDataService)], + [SUBMISSION_CC_LICENSE.value, () => import('./submission/submission-cc-license-data.service').then(m => m.SubmissionCcLicenseDataService)], + [USAGE_REPORT.value, () => import('./statistics/usage-report-data.service').then(m => m.UsageReportDataService)], + [RESOURCE_POLICY.value, () => import('./resource-policy/resource-policy-data.service').then(m => m.ResourcePolicyDataService)], + [RESEARCHER_PROFILE.value, () => import('./profile/researcher-profile-data.service').then(m => m.ResearcherProfileDataService)], + [ORCID_QUEUE.value, () => import('./orcid/orcid-queue-data.service').then(m => m.OrcidQueueDataService)], + [ORCID_HISTORY.value, () => import('./orcid/orcid-history-data.service').then(m => m.OrcidHistoryDataService)], + [FEEDBACK.value, () => import('./feedback/feedback-data.service').then(m => m.FeedbackDataService)], + [GROUP.value, () => import('./eperson/group-data.service').then(m => m.GroupDataService)], + [EPERSON.value, () => import('./eperson/eperson-data.service').then(m => m.EPersonDataService)], + [WORKFLOW_ACTION.value, () => import('./data/workflow-action-data.service').then(m => m.WorkflowActionDataService)], + [VERSION_HISTORY.value, () => import('./data/version-history-data.service').then(m => m.VersionHistoryDataService)], + [SITE.value, () => import('./data/site-data.service').then(m => m.SiteDataService)], + [ROOT.value, () => import('./data/root-data.service').then(m => m.RootDataService)], + [RELATIONSHIP_TYPE.value, () => import('./data/relationship-type-data.service').then(m => m.RelationshipTypeDataService)], + [RELATIONSHIP.value, () => import('./data/relationship-data.service').then(m => m.RelationshipDataService)], + [SCRIPT.value, () => import('./data/processes/script-data.service').then(m => m.ScriptDataService)], + [PROCESS.value, () => import('./data/processes/process-data.service').then(m => m.ProcessDataService)], + [METADATA_FIELD.value, () => import('./data/metadata-field-data.service').then(m => m.MetadataFieldDataService)], + [ITEM.value, () => import('./data/item-data.service').then(m => m.ItemDataService)], + [VERSION.value, () => import('./data/version-data.service').then(m => m.VersionDataService)], + [IDENTIFIERS.value, () => import('./data/identifier-data.service').then(m => m.IdentifierDataService)], + [FEATURE.value, () => import('./data/feature-authorization/authorization-data.service').then(m => m.AuthorizationDataService)], + [DSPACE_OBJECT.value, () => import('./data/dspace-object-data.service').then(m => m.DSpaceObjectDataService)], + [BITSTREAM_FORMAT.value, () => import('./data/bitstream-format-data.service').then(m => m.BitstreamFormatDataService)], + [SUBMISSION_COAR_NOTIFY_CONFIG.value, () => import('../submission/sections/section-coar-notify/coar-notify-config-data.service').then(m => m.CoarNotifyConfigDataService)], + [LDN_SERVICE_CONSTRAINT_FILTERS.value, () => import('../admin/admin-ldn-services/ldn-services-data/ldn-itemfilters-data.service').then(m => m.LdnItemfiltersService)], + [LDN_SERVICE.value, () => import('../admin/admin-ldn-services/ldn-services-data/ldn-services-data.service').then(m => m.LdnServicesService)], + [ADMIN_NOTIFY_MESSAGE.value, () => import('../admin/admin-notify-dashboard/services/admin-notify-messages.service').then(m => m.AdminNotifyMessagesService)], + [SUBMISSION_FORMS_TYPE.value, () => import('./config/submission-forms-config-data.service').then(m => m.SubmissionFormsConfigDataService)], + [NOTIFYREQUEST.value, () => import('./data/notify-services-status-data.service').then(m => m.NotifyRequestsStatusDataService)], + [QUALITY_ASSURANCE_EVENT_OBJECT.value, () => import('./notifications/qa/events/quality-assurance-event-data.service').then(m => m.QualityAssuranceEventDataService)], + [QUALITY_ASSURANCE_SOURCE_OBJECT.value, () => import('./notifications/qa/source/quality-assurance-source-data.service').then(m => m.QualityAssuranceSourceDataService)], + [QUALITY_ASSURANCE_TOPIC_OBJECT.value, () => import('./notifications/qa/topics/quality-assurance-topic-data.service').then(m => m.QualityAssuranceTopicDataService)], + [SUGGESTION.value, () => import('./notifications/suggestions-data.service').then(m => m.SuggestionsDataService)], + [SUGGESTION_SOURCE.value, () => import('./notifications/source/suggestion-source-data.service').then(m => m.SuggestionSourceDataService)], + [SUGGESTION_TARGET.value, () => import('./notifications/target/suggestion-target-data.service').then(m => m.SuggestionTargetDataService)], + [DUPLICATE.value, () => import('./submission/submission-duplicate-data.service').then(m => m.SubmissionDuplicateDataService)], + [CorrectionType.type.value, () => import('./submission/correctiontype-data.service').then(m => m.CorrectionTypeDataService)], +]); +/*export const LAZY_DATA_SERVICES: LazyDataServicesMap = { [AUTHORIZATION.value]: () => import('./data/feature-authorization/authorization-data.service').then(m => m.AuthorizationDataService), [BROWSE_DEFINITION.value]: () => import('./browse/browse-definition-data.service').then(m => m.BrowseDefinitionDataService), [BULK_ACCESS_CONDITION_OPTIONS.value]: () => import('./config/bulk-access-config-data.service').then(m => m.BulkAccessConfigDataService), @@ -136,6 +204,6 @@ export const LAZY_DATA_SERVICES: LazyDataServicesMap = { [SUGGESTION_TARGET.value]: () => import('./notifications/target/suggestion-target-data.service').then(m => m.SuggestionTargetDataService), [DUPLICATE.value]: () => import('./submission/submission-duplicate-data.service').then(m => m.SubmissionDuplicateDataService), [CorrectionType.type.value]: () => import('./submission/correctiontype-data.service').then(m => m.CorrectionTypeDataService), -}; +};*/ diff --git a/src/app/core/lazy-data-service.ts b/src/app/core/lazy-data-service.ts index 0c8e4cd08c9..1ad3dec384a 100644 --- a/src/app/core/lazy-data-service.ts +++ b/src/app/core/lazy-data-service.ts @@ -8,13 +8,12 @@ import { } from 'rxjs'; import { LazyDataServicesMap } from '../../config/app-config.interface'; -import { isNotEmpty } from '../shared/empty.util'; import { HALDataService } from './data/base/hal-data-service.interface'; /** * Loads a service lazily. The service is loaded when the observable is subscribed to. * - * @param map A map of promises returning the data services to load + * @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. @@ -27,13 +26,13 @@ import { HALDataService } from './data/base/hal-data-service.interface'; * ``` */ export function lazyDataService( - map: LazyDataServicesMap, + dataServicesMap: LazyDataServicesMap, key: string, injector: Injector, ): Observable { return defer(() => { - if (isNotEmpty(map[key]) && typeof map[key] === 'function') { - const loader: () => Promise> | { default: HALDataService }> = map[key]; + if (dataServicesMap.has(key) && typeof dataServicesMap.get(key) === 'function') { + const loader: () => Promise> | { default: HALDataService }> = dataServicesMap.get(key); return loader() .then((serviceOrDefault) => { if ('default' in serviceOrDefault) { diff --git a/src/app/dso-shared/dso-edit-metadata/dso-edit-metadata.component.spec.ts b/src/app/dso-shared/dso-edit-metadata/dso-edit-metadata.component.spec.ts index c3d82d07951..32822f18320 100644 --- a/src/app/dso-shared/dso-edit-metadata/dso-edit-metadata.component.spec.ts +++ b/src/app/dso-shared/dso-edit-metadata/dso-edit-metadata.component.spec.ts @@ -38,9 +38,9 @@ const REINSTATE_BTN = 'reinstate'; const SAVE_BTN = 'save'; const DISCARD_BTN = 'discard'; -const mockDataServiceMap: any = { - [ITEM.value]: () => import('../../shared/testing/test-data-service.mock').then(m => m.TestDataService), -}; +const mockDataServiceMap: any = new Map([ + [ITEM.value, () => import('../../shared/testing/test-data-service.mock').then(m => m.TestDataService)], +]); describe('DsoEditMetadataComponent', () => { let component: DsoEditMetadataComponent; diff --git a/src/app/shared/eperson-group-list/eperson-group-list.component.spec.ts b/src/app/shared/eperson-group-list/eperson-group-list.component.spec.ts index e09fa32526c..ca3837130d7 100644 --- a/src/app/shared/eperson-group-list/eperson-group-list.component.spec.ts +++ b/src/app/shared/eperson-group-list/eperson-group-list.component.spec.ts @@ -17,7 +17,10 @@ import { cold } from 'jasmine-marbles'; import uniqueId from 'lodash/uniqueId'; import { of as observableOf } from 'rxjs'; -import { APP_DATA_SERVICES_MAP } from '../../../config/app-config.interface'; +import { + APP_DATA_SERVICES_MAP, + LazyDataServicesMap, +} from '../../../config/app-config.interface'; import { DSONameService } from '../../core/breadcrumbs/dso-name.service'; import { buildPaginatedList } from '../../core/data/paginated-list.model'; import { RequestService } from '../../core/data/request.service'; @@ -41,10 +44,10 @@ import { SearchEvent } from './eperson-group-list-event-type'; import { EpersonSearchBoxComponent } from './eperson-search-box/eperson-search-box.component'; import { GroupSearchBoxComponent } from './group-search-box/group-search-box.component'; -const mockDataServiceMap: any = { - [EPERSON.value]: () => import('../../core/eperson/eperson-data.service').then(m => m.EPersonDataService), - [GROUP.value]: () => import('../../core/eperson/group-data.service').then(m => m.GroupDataService), -}; +const mockDataServiceMap: LazyDataServicesMap = new Map([ + [EPERSON.value, () => import('../../core/eperson/eperson-data.service').then(m => m.EPersonDataService)], + [GROUP.value, () => import('../../core/eperson/group-data.service').then(m => m.GroupDataService)], +]); describe('EpersonGroupListComponent test suite', () => { let comp: EpersonGroupListComponent; diff --git a/src/config/app-config.interface.ts b/src/config/app-config.interface.ts index 540ebcbcb20..9a4d56bee0f 100644 --- a/src/config/app-config.interface.ts +++ b/src/config/app-config.interface.ts @@ -73,9 +73,7 @@ const APP_CONFIG = new InjectionToken('APP_CONFIG'); const APP_CONFIG_STATE = makeStateKey('APP_CONFIG_STATE'); -export interface LazyDataServicesMap { - [type: string]: () => Promise> | { default: HALDataService }> -} +export type LazyDataServicesMap = Map Promise> | { default: HALDataService }>>; export const APP_DATA_SERVICES_MAP: InjectionToken = new InjectionToken('APP_DATA_SERVICES_MAP'); From b2f94b515a75f2df9c5720a1351bbad727545070 Mon Sep 17 00:00:00 2001 From: Giuseppe Digilio Date: Mon, 8 Apr 2024 23:08:04 +0200 Subject: [PATCH 7/7] [DURACOM-247] Fix lint --- .../core/cache/builders/link.service.spec.ts | 2 +- src/app/core/data-services-map.ts | 70 ------------------- 2 files changed, 1 insertion(+), 71 deletions(-) diff --git a/src/app/core/cache/builders/link.service.spec.ts b/src/app/core/cache/builders/link.service.spec.ts index 4f7cd946e55..d9878913888 100644 --- a/src/app/core/cache/builders/link.service.spec.ts +++ b/src/app/core/cache/builders/link.service.spec.ts @@ -5,7 +5,7 @@ import { take, } from 'rxjs/operators'; -import { APP_DATA_SERVICES_MAP, LazyDataServicesMap } from '../../../../config/app-config.interface'; +import { APP_DATA_SERVICES_MAP } from '../../../../config/app-config.interface'; import { TestDataService } from '../../../shared/testing/test-data-service.mock'; import { followLink } from '../../../shared/utils/follow-link-config.model'; import { HALLink } from '../../shared/hal-link.model'; diff --git a/src/app/core/data-services-map.ts b/src/app/core/data-services-map.ts index ad8686b6da9..8e76eef9258 100644 --- a/src/app/core/data-services-map.ts +++ b/src/app/core/data-services-map.ts @@ -137,73 +137,3 @@ export const LAZY_DATA_SERVICES: LazyDataServicesMap = new Map([ [DUPLICATE.value, () => import('./submission/submission-duplicate-data.service').then(m => m.SubmissionDuplicateDataService)], [CorrectionType.type.value, () => import('./submission/correctiontype-data.service').then(m => m.CorrectionTypeDataService)], ]); -/*export const LAZY_DATA_SERVICES: LazyDataServicesMap = { - [AUTHORIZATION.value]: () => import('./data/feature-authorization/authorization-data.service').then(m => m.AuthorizationDataService), - [BROWSE_DEFINITION.value]: () => import('./browse/browse-definition-data.service').then(m => m.BrowseDefinitionDataService), - [BULK_ACCESS_CONDITION_OPTIONS.value]: () => import('./config/bulk-access-config-data.service').then(m => m.BulkAccessConfigDataService), - [METADATA_SCHEMA.value]: () => import('./data/metadata-schema-data.service').then(m => m.MetadataSchemaDataService), - [SUBMISSION_UPLOADS_TYPE.value]: () => import('./config/submission-uploads-config-data.service').then(m => m.SubmissionUploadsConfigDataService), - [BITSTREAM.value]: () => import('./data/bitstream-data.service').then(m => m.BitstreamDataService), - [SUBMISSION_ACCESSES_TYPE.value]: () => import('./config/submission-accesses-config-data.service').then(m => m.SubmissionAccessesConfigDataService), - [SYSTEMWIDEALERT.value]: () => import('./data/system-wide-alert-data.service').then(m => m.SystemWideAlertDataService), - [USAGE_REPORT.value]: () => import('./statistics/usage-report-data.service').then(m => m.UsageReportDataService), - [ACCESS_STATUS.value]: () => import('./data/access-status-data.service').then(m => m.AccessStatusDataService), - [COLLECTION.value]: () => import('./data/collection-data.service').then(m => m.CollectionDataService), - [CLAIMED_TASK.value]: () => import('./tasks/claimed-task-data.service').then(m => m.ClaimedTaskDataService), - [VOCABULARY_ENTRY.value]: () => import('./data/href-only-data.service').then(m => m.HrefOnlyDataService), - [ITEM_TYPE.value]: () => import('./data/href-only-data.service').then(m => m.HrefOnlyDataService), - [LICENSE.value]: () => import('./data/href-only-data.service').then(m => m.HrefOnlyDataService), - [SUBSCRIPTION.value]: () => import('../shared/subscriptions/subscriptions-data.service').then(m => m.SubscriptionsDataService), - [COMMUNITY.value]: () => import('./data/community-data.service').then(m => m.CommunityDataService), - [VOCABULARY.value]: () => import('./submission/vocabularies/vocabulary.data.service').then(m => m.VocabularyDataService), - [BUNDLE.value]: () => import('./data/bundle-data.service').then(m => m.BundleDataService), - [CONFIG_PROPERTY.value]: () => import('./data/configuration-data.service').then(m => m.ConfigurationDataService), - [POOL_TASK.value]: () => import('./tasks/pool-task-data.service').then(m => m.PoolTaskDataService), - [CLAIMED_TASK.value]: () => import('./tasks/claimed-task-data.service').then(m => m.ClaimedTaskDataService), - [SUPERVISION_ORDER.value]: () => import('./supervision-order/supervision-order-data.service').then(m => m.SupervisionOrderDataService), - [WORKSPACEITEM.value]: () => import('./submission/workspaceitem-data.service').then(m => m.WorkspaceitemDataService), - [WORKFLOWITEM.value]: () => import('./submission/workflowitem-data.service').then(m => m.WorkflowItemDataService), - [VOCABULARY.value]: () => import('./submission/vocabularies/vocabulary.data.service').then(m => m.VocabularyDataService), - [VOCABULARY_ENTRY_DETAIL.value]: () => import('./submission/vocabularies/vocabulary-entry-details.data.service').then(m => m.VocabularyEntryDetailsDataService), - [SUBMISSION_CC_LICENSE_URL.value]: () => import('./submission/submission-cc-license-url-data.service').then(m => m.SubmissionCcLicenseUrlDataService), - [SUBMISSION_CC_LICENSE.value]: () => import('./submission/submission-cc-license-data.service').then(m => m.SubmissionCcLicenseDataService), - [USAGE_REPORT.value]: () => import('./statistics/usage-report-data.service').then(m => m.UsageReportDataService), - [RESOURCE_POLICY.value]: () => import('./resource-policy/resource-policy-data.service').then(m => m.ResourcePolicyDataService), - [RESEARCHER_PROFILE.value]: () => import('./profile/researcher-profile-data.service').then(m => m.ResearcherProfileDataService), - [ORCID_QUEUE.value]: () => import('./orcid/orcid-queue-data.service').then(m => m.OrcidQueueDataService), - [ORCID_HISTORY.value]: () => import('./orcid/orcid-history-data.service').then(m => m.OrcidHistoryDataService), - [FEEDBACK.value]: () => import('./feedback/feedback-data.service').then(m => m.FeedbackDataService), - [GROUP.value]: () => import('./eperson/group-data.service').then(m => m.GroupDataService), - [EPERSON.value]: () => import('./eperson/eperson-data.service').then(m => m.EPersonDataService), - [WORKFLOW_ACTION.value]: () => import('./data/workflow-action-data.service').then(m => m.WorkflowActionDataService), - [VERSION_HISTORY.value]: () => import('./data/version-history-data.service').then(m => m.VersionHistoryDataService), - [SITE.value]: () => import('./data/site-data.service').then(m => m.SiteDataService), - [ROOT.value]: () => import('./data/root-data.service').then(m => m.RootDataService), - [RELATIONSHIP_TYPE.value]: () => import('./data/relationship-type-data.service').then(m => m.RelationshipTypeDataService), - [RELATIONSHIP.value]: () => import('./data/relationship-data.service').then(m => m.RelationshipDataService), - [SCRIPT.value]: () => import('./data/processes/script-data.service').then(m => m.ScriptDataService), - [PROCESS.value]: () => import('./data/processes/process-data.service').then(m => m.ProcessDataService), - [METADATA_FIELD.value]: () => import('./data/metadata-field-data.service').then(m => m.MetadataFieldDataService), - [ITEM.value]: () => import('./data/item-data.service').then(m => m.ItemDataService), - [VERSION.value]: () => import('./data/version-data.service').then(m => m.VersionDataService), - [IDENTIFIERS.value]: () => import('./data/identifier-data.service').then(m => m.IdentifierDataService), - [FEATURE.value]: () => import('./data/feature-authorization/authorization-data.service').then(m => m.AuthorizationDataService), - [DSPACE_OBJECT.value]: () => import('./data/dspace-object-data.service').then(m => m.DSpaceObjectDataService), - [BITSTREAM_FORMAT.value]: () => import('./data/bitstream-format-data.service').then(m => m.BitstreamFormatDataService), - [SUBMISSION_COAR_NOTIFY_CONFIG.value]: () => import('../submission/sections/section-coar-notify/coar-notify-config-data.service').then(m => m.CoarNotifyConfigDataService), - [LDN_SERVICE_CONSTRAINT_FILTERS.value]: () => import('../admin/admin-ldn-services/ldn-services-data/ldn-itemfilters-data.service').then(m => m.LdnItemfiltersService), - [LDN_SERVICE.value]: () => import('../admin/admin-ldn-services/ldn-services-data/ldn-services-data.service').then(m => m.LdnServicesService), - [ADMIN_NOTIFY_MESSAGE.value]: () => import('../admin/admin-notify-dashboard/services/admin-notify-messages.service').then(m => m.AdminNotifyMessagesService), - [SUBMISSION_FORMS_TYPE.value]: () => import('./config/submission-forms-config-data.service').then(m => m.SubmissionFormsConfigDataService), - [NOTIFYREQUEST.value]: () => import('./data/notify-services-status-data.service').then(m => m.NotifyRequestsStatusDataService), - [QUALITY_ASSURANCE_EVENT_OBJECT.value]: () => import('./notifications/qa/events/quality-assurance-event-data.service').then(m => m.QualityAssuranceEventDataService), - [QUALITY_ASSURANCE_SOURCE_OBJECT.value]: () => import('./notifications/qa/source/quality-assurance-source-data.service').then(m => m.QualityAssuranceSourceDataService), - [QUALITY_ASSURANCE_TOPIC_OBJECT.value]: () => import('./notifications/qa/topics/quality-assurance-topic-data.service').then(m => m.QualityAssuranceTopicDataService), - [SUGGESTION.value]: () => import('./notifications/suggestions-data.service').then(m => m.SuggestionsDataService), - [SUGGESTION_SOURCE.value]: () => import('./notifications/source/suggestion-source-data.service').then(m => m.SuggestionSourceDataService), - [SUGGESTION_TARGET.value]: () => import('./notifications/target/suggestion-target-data.service').then(m => m.SuggestionTargetDataService), - [DUPLICATE.value]: () => import('./submission/submission-duplicate-data.service').then(m => m.SubmissionDuplicateDataService), - [CorrectionType.type.value]: () => import('./submission/correctiontype-data.service').then(m => m.CorrectionTypeDataService), -};*/ - -