Newer
Older
import { Resource, getUrl, hasLink } from '@ngxp/rest';
import { isEqual, isNull } from 'lodash-es';
import { Observable, combineLatest, filter, startWith, tap } from 'rxjs';
import { ResourceStateService } from '../ngrx/state.service';
import { isNotNull } from '../tech.util';
import { ServiceConfig } from './resource.model';
import { mapToFirst, mapToResource } from './resource.rxjs.operator';
import {
StateResource,
createEmptyStateResource,
isInvalidResourceCombination,
isLoadingRequired,
isStateResoureStable,
} from './resource.util';
export class ResourceLoader<B extends Resource, T extends Resource> {
configResource: B = null;
constructor(
private config: ServiceConfig<B>,
private resourceStateService: ResourceStateService<B, T>,
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
) {}
public get(): Observable<StateResource<T>> {
return combineLatest([
this.resourceStateService.selectResource(),
this.getConfigResource(),
]).pipe(
tap(([stateResource, configResource]) =>
this.handleResourceChanges(stateResource, configResource),
),
filter(
([stateResource, configResource]) =>
!isInvalidResourceCombination(stateResource, configResource),
),
mapToFirst<T, B>(),
startWith(createEmptyStateResource<T>(true)),
);
}
private getConfigResource(): Observable<B> {
return this.config.baseResource.pipe(filter(isStateResoureStable), mapToResource<B>());
}
handleResourceChanges(stateResource: StateResource<T>, configResource: B): void {
if (!isEqual(this.configResource, configResource)) {
this.handleConfigResourceChanges(stateResource, configResource);
} else if (this.shouldLoadResource(stateResource, configResource)) {
this.loadResource(configResource);
}
}
handleConfigResourceChanges(stateResource: StateResource<T>, configResource: B) {
this.configResource = configResource;
if (isStateResoureStable(stateResource)) {
this.updateStateResourceByConfigResource(stateResource, configResource);
}
}
updateStateResourceByConfigResource(stateResource: StateResource<T>, configResource: B): void {
if (this.shouldClearStateResource(stateResource, configResource)) {
this.resourceStateService.clearResource();
} else if (this.hasGetLink(configResource)) {
this.loadResource(configResource);
}
}
shouldClearStateResource(stateResource: StateResource<T>, configResource: B): boolean {
return (
(isNull(configResource) || this.hasNotGetLink(configResource)) &&
!this.isStateResourceEmpty(stateResource)
);
}
private hasNotGetLink(configResource: B) {
return !this.hasGetLink(configResource);
}
hasGetLink(configResource: B): boolean {
return isNotNull(configResource) && hasLink(configResource, this.config.getLinkRel);
}
private isStateResourceEmpty(stateResource: StateResource<T>): boolean {
return isEqual(stateResource, createEmptyStateResource());
}
shouldLoadResource(stateResource: StateResource<T>, configResource: B): boolean {
return (
isNotNull(configResource) &&
hasLink(configResource, this.config.getLinkRel) &&
isLoadingRequired(stateResource)
);
}
loadResource(configResource: B): void {
this.resourceStateService.loadResource(this.getGetUrl(configResource));
}
private getGetUrl(configResource: B): string {
return getUrl(configResource, this.config.getLinkRel);
}
}