@ethlete/query 5.16.0 → 5.16.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (184) hide show
  1. package/CHANGELOG.md +12 -0
  2. package/esm2022/ethlete-query.mjs +5 -0
  3. package/esm2022/index.mjs +20 -0
  4. package/esm2022/lib/auth/auth-provider.types.mjs +2 -0
  5. package/esm2022/lib/auth/auth-provider.utils.mjs +25 -0
  6. package/esm2022/lib/auth/basic-auth-provider.mjs +15 -0
  7. package/esm2022/lib/auth/bearer-auth-provider.mjs +168 -0
  8. package/esm2022/lib/auth/custom-header-auth-provider.mjs +12 -0
  9. package/esm2022/lib/auth/index.mjs +6 -0
  10. package/esm2022/lib/class-validator/class-validator.types.mjs +2 -0
  11. package/esm2022/lib/class-validator/class-validator.utils.mjs +4 -0
  12. package/esm2022/lib/class-validator/index.mjs +3 -0
  13. package/esm2022/lib/devtools/components/query-devtools/index.mjs +2 -0
  14. package/esm2022/lib/devtools/components/query-devtools/query-devtools.component.mjs +297 -0
  15. package/esm2022/lib/devtools/pipes/index.mjs +2 -0
  16. package/esm2022/lib/devtools/pipes/query-short-name.pipe.mjs +24 -0
  17. package/esm2022/lib/devtools/utils/index.mjs +2 -0
  18. package/esm2022/lib/devtools/utils/query-client.utils.mjs +13 -0
  19. package/esm2022/lib/directives/index.mjs +4 -0
  20. package/esm2022/lib/directives/infinity-query-trigger.directive.mjs +56 -0
  21. package/esm2022/lib/directives/infinity-query.directive.mjs +147 -0
  22. package/esm2022/lib/directives/query.directive.mjs +123 -0
  23. package/esm2022/lib/entity/entity-store.mjs +127 -0
  24. package/esm2022/lib/entity/entity.types.mjs +2 -0
  25. package/esm2022/lib/entity/entity.utils.mjs +29 -0
  26. package/esm2022/lib/entity/index.mjs +4 -0
  27. package/esm2022/lib/gql/gql.mjs +23 -0
  28. package/esm2022/lib/gql/index.mjs +2 -0
  29. package/esm2022/lib/infinite-query/index.mjs +4 -0
  30. package/esm2022/lib/infinite-query/infinity-query.mjs +171 -0
  31. package/esm2022/lib/infinite-query/infinity-query.types.mjs +2 -0
  32. package/esm2022/lib/infinite-query/infinity-query.utils.mjs +3 -0
  33. package/esm2022/lib/logger/index.mjs +2 -0
  34. package/esm2022/lib/logger/logger.mjs +16 -0
  35. package/esm2022/lib/query/index.mjs +4 -0
  36. package/esm2022/lib/query/query.mjs +430 -0
  37. package/esm2022/lib/query/query.types.mjs +2 -0
  38. package/esm2022/lib/query/query.utils.mjs +253 -0
  39. package/esm2022/lib/query-client/index.mjs +4 -0
  40. package/esm2022/lib/query-client/query-client.mjs +80 -0
  41. package/esm2022/lib/query-client/query-client.types.mjs +2 -0
  42. package/esm2022/lib/query-client/query-client.utils.mjs +20 -0
  43. package/esm2022/lib/query-creator/index.mjs +3 -0
  44. package/esm2022/lib/query-creator/query-creator.mjs +55 -0
  45. package/esm2022/lib/query-creator/query-creator.types.mjs +2 -0
  46. package/esm2022/lib/query-form/index.mjs +4 -0
  47. package/esm2022/lib/query-form/query-form.mjs +379 -0
  48. package/esm2022/lib/query-form/query-form.types.mjs +2 -0
  49. package/esm2022/lib/query-form/query-form.utils.mjs +97 -0
  50. package/esm2022/lib/query-store/index.mjs +2 -0
  51. package/esm2022/lib/query-store/query-store.mjs +144 -0
  52. package/esm2022/lib/request/index.mjs +4 -0
  53. package/esm2022/lib/request/request.mjs +196 -0
  54. package/esm2022/lib/request/request.types.mjs +2 -0
  55. package/esm2022/lib/request/request.util.mjs +252 -0
  56. package/esm2022/lib/symfony/index.mjs +3 -0
  57. package/esm2022/lib/symfony/symfony.types.mjs +2 -0
  58. package/esm2022/lib/symfony/symfony.utils.mjs +31 -0
  59. package/esm2022/lib/utils/data.utils.mjs +138 -0
  60. package/esm2022/lib/utils/deep-freeze.util.mjs +17 -0
  61. package/esm2022/lib/utils/def.util.mjs +8 -0
  62. package/esm2022/lib/utils/index.mjs +4 -0
  63. package/fesm2022/ethlete-query.mjs +3289 -0
  64. package/fesm2022/ethlete-query.mjs.map +1 -0
  65. package/{src/index.ts → index.d.ts} +0 -2
  66. package/lib/auth/auth-provider.types.d.ts +133 -0
  67. package/lib/auth/auth-provider.utils.d.ts +9 -0
  68. package/lib/auth/basic-auth-provider.d.ts +10 -0
  69. package/lib/auth/bearer-auth-provider.d.ts +23 -0
  70. package/lib/auth/custom-header-auth-provider.d.ts +9 -0
  71. package/{src/lib/class-validator/class-validator.types.ts → lib/class-validator/class-validator.types.d.ts} +3 -4
  72. package/lib/class-validator/class-validator.utils.d.ts +2 -0
  73. package/lib/devtools/components/query-devtools/query-devtools.component.d.ts +151 -0
  74. package/lib/devtools/pipes/query-short-name.pipe.d.ts +8 -0
  75. package/lib/devtools/utils/query-client.utils.d.ts +12 -0
  76. package/lib/directives/infinity-query-trigger.directive.d.ts +15 -0
  77. package/lib/directives/infinity-query.directive.d.ts +49 -0
  78. package/lib/directives/query.directive.d.ts +63 -0
  79. package/lib/entity/entity-store.d.ts +25 -0
  80. package/lib/entity/entity.types.d.ts +25 -0
  81. package/lib/entity/entity.utils.d.ts +12 -0
  82. package/lib/gql/gql.d.ts +6 -0
  83. package/lib/infinite-query/infinity-query.d.ts +29 -0
  84. package/lib/infinite-query/infinity-query.types.d.ts +104 -0
  85. package/lib/infinite-query/infinity-query.utils.d.ts +4 -0
  86. package/lib/logger/logger.d.ts +12 -0
  87. package/lib/query/query.d.ts +60 -0
  88. package/lib/query/query.types.d.ts +388 -0
  89. package/lib/query/query.utils.d.ts +82 -0
  90. package/lib/query-client/query-client.d.ts +29 -0
  91. package/lib/query-client/query-client.types.d.ts +82 -0
  92. package/lib/query-client/query-client.utils.d.ts +4 -0
  93. package/lib/query-creator/query-creator.d.ts +20 -0
  94. package/lib/query-creator/query-creator.types.d.ts +13 -0
  95. package/lib/query-form/query-form.d.ts +91 -0
  96. package/lib/query-form/query-form.types.d.ts +145 -0
  97. package/lib/query-form/query-form.utils.d.ts +13 -0
  98. package/lib/query-store/query-store.d.ts +31 -0
  99. package/lib/request/request.d.ts +3 -0
  100. package/lib/request/request.types.d.ts +126 -0
  101. package/lib/request/request.util.d.ts +92 -0
  102. package/lib/symfony/symfony.types.d.ts +19 -0
  103. package/lib/symfony/symfony.utils.d.ts +6 -0
  104. package/lib/utils/data.utils.d.ts +59 -0
  105. package/lib/utils/deep-freeze.util.d.ts +1 -0
  106. package/{src/lib/utils/def.util.ts → lib/utils/def.util.d.ts} +1 -1
  107. package/package.json +23 -6
  108. package/.eslintrc.json +0 -40
  109. package/jest.config.ts +0 -23
  110. package/ng-package.json +0 -8
  111. package/project.json +0 -37
  112. package/src/lib/auth/auth-provider.types.ts +0 -160
  113. package/src/lib/auth/auth-provider.utils.ts +0 -39
  114. package/src/lib/auth/basic-auth-provider.ts +0 -17
  115. package/src/lib/auth/bearer-auth-provider.ts +0 -243
  116. package/src/lib/auth/custom-header-auth-provider.ts +0 -13
  117. package/src/lib/class-validator/class-validator.utils.ts +0 -5
  118. package/src/lib/devtools/components/query-devtools/query-devtools.component.html +0 -402
  119. package/src/lib/devtools/components/query-devtools/query-devtools.component.scss +0 -360
  120. package/src/lib/devtools/components/query-devtools/query-devtools.component.ts +0 -427
  121. package/src/lib/devtools/pipes/query-short-name.pipe.ts +0 -24
  122. package/src/lib/devtools/utils/query-client.utils.ts +0 -25
  123. package/src/lib/directives/infinity-query-trigger.directive.ts +0 -58
  124. package/src/lib/directives/infinity-query.directive.ts +0 -208
  125. package/src/lib/directives/query.directive.ts +0 -201
  126. package/src/lib/entity/entity-store.ts +0 -180
  127. package/src/lib/entity/entity.types.ts +0 -34
  128. package/src/lib/entity/entity.utils.ts +0 -51
  129. package/src/lib/gql/gql.ts +0 -22
  130. package/src/lib/infinite-query/infinity-query.ts +0 -245
  131. package/src/lib/infinite-query/infinity-query.types.ts +0 -149
  132. package/src/lib/infinite-query/infinity-query.utils.ts +0 -14
  133. package/src/lib/logger/logger.ts +0 -30
  134. package/src/lib/query/query.ts +0 -631
  135. package/src/lib/query/query.types.ts +0 -532
  136. package/src/lib/query/query.utils.spec.ts +0 -92
  137. package/src/lib/query/query.utils.ts +0 -450
  138. package/src/lib/query-client/query-client.spec.ts +0 -77
  139. package/src/lib/query-client/query-client.ts +0 -195
  140. package/src/lib/query-client/query-client.types.ts +0 -101
  141. package/src/lib/query-client/query-client.utils.spec.ts +0 -61
  142. package/src/lib/query-client/query-client.utils.ts +0 -28
  143. package/src/lib/query-creator/query-creator.ts +0 -103
  144. package/src/lib/query-creator/query-creator.types.ts +0 -74
  145. package/src/lib/query-form/query-form.ts +0 -526
  146. package/src/lib/query-form/query-form.types.ts +0 -169
  147. package/src/lib/query-form/query-form.utils.ts +0 -116
  148. package/src/lib/query-store/query-store.ts +0 -192
  149. package/src/lib/request/request.ts +0 -253
  150. package/src/lib/request/request.types.ts +0 -164
  151. package/src/lib/request/request.util.spec.ts +0 -177
  152. package/src/lib/request/request.util.ts +0 -399
  153. package/src/lib/stories/angular-example-page.mdx +0 -85
  154. package/src/lib/stories/authentication-page.mdx +0 -35
  155. package/src/lib/stories/changelog-page.mdx +0 -9
  156. package/src/lib/stories/client-page.mdx +0 -100
  157. package/src/lib/stories/queries-page.mdx +0 -117
  158. package/src/lib/symfony/symfony.types.ts +0 -21
  159. package/src/lib/symfony/symfony.utils.ts +0 -43
  160. package/src/lib/utils/data.utils.ts +0 -280
  161. package/src/lib/utils/deep-freeze.util.ts +0 -21
  162. package/src/test-setup.ts +0 -1
  163. package/tsconfig.json +0 -29
  164. package/tsconfig.lib.json +0 -12
  165. package/tsconfig.lib.prod.json +0 -10
  166. package/tsconfig.spec.json +0 -11
  167. /package/{src/lib/auth/index.ts → lib/auth/index.d.ts} +0 -0
  168. /package/{src/lib/class-validator/index.ts → lib/class-validator/index.d.ts} +0 -0
  169. /package/{src/lib/devtools/components/query-devtools/index.ts → lib/devtools/components/query-devtools/index.d.ts} +0 -0
  170. /package/{src/lib/devtools/pipes/index.ts → lib/devtools/pipes/index.d.ts} +0 -0
  171. /package/{src/lib/devtools/utils/index.ts → lib/devtools/utils/index.d.ts} +0 -0
  172. /package/{src/lib/directives/index.ts → lib/directives/index.d.ts} +0 -0
  173. /package/{src/lib/entity/index.ts → lib/entity/index.d.ts} +0 -0
  174. /package/{src/lib/gql/index.ts → lib/gql/index.d.ts} +0 -0
  175. /package/{src/lib/infinite-query/index.ts → lib/infinite-query/index.d.ts} +0 -0
  176. /package/{src/lib/logger/index.ts → lib/logger/index.d.ts} +0 -0
  177. /package/{src/lib/query/index.ts → lib/query/index.d.ts} +0 -0
  178. /package/{src/lib/query-client/index.ts → lib/query-client/index.d.ts} +0 -0
  179. /package/{src/lib/query-creator/index.ts → lib/query-creator/index.d.ts} +0 -0
  180. /package/{src/lib/query-form/index.ts → lib/query-form/index.d.ts} +0 -0
  181. /package/{src/lib/query-store/index.ts → lib/query-store/index.d.ts} +0 -0
  182. /package/{src/lib/request/index.ts → lib/request/index.d.ts} +0 -0
  183. /package/{src/lib/symfony/index.ts → lib/symfony/index.d.ts} +0 -0
  184. /package/{src/lib/utils/index.ts → lib/utils/index.d.ts} +0 -0
@@ -1,208 +0,0 @@
1
- /* eslint-disable @typescript-eslint/no-explicit-any */
2
- import {
3
- ChangeDetectorRef,
4
- Directive,
5
- ErrorHandler,
6
- inject,
7
- InjectionToken,
8
- Input,
9
- TemplateRef,
10
- ViewContainerRef,
11
- } from '@angular/core';
12
- import { toSignal } from '@angular/core/rxjs-interop';
13
- import { createDestroy, DelayableDirective } from '@ethlete/core';
14
- import { BehaviorSubject, combineLatest, Subject, takeUntil, tap, withLatestFrom } from 'rxjs';
15
- import { InfinityQuery, InfinityQueryConfig, InfinityQueryOf } from '../infinite-query';
16
- import {
17
- BaseArguments,
18
- isQueryStateFailure,
19
- isQueryStateLoading,
20
- isQueryStateSuccess,
21
- switchQueryState,
22
- } from '../query';
23
- import { AnyQueryCreator, ConstructQuery } from '../query-creator';
24
- import { RequestError } from '../request';
25
-
26
- interface InfinityQueryContext<
27
- Q extends InfinityQueryConfig<AnyQueryCreator, BaseArguments | undefined, any, unknown[]>,
28
- > {
29
- $implicit: Q['response']['arrayType'] | null;
30
- etInfinityQuery: Q['response']['arrayType'] | null;
31
- loading: boolean;
32
- error: RequestError<unknown> | null;
33
-
34
- isFirstLoad: boolean;
35
- canLoadMore: boolean;
36
- currentPage: number | null;
37
- currentCalculatedPage: number | null;
38
- totalPages: number | null;
39
- itemsPerPage: number | null;
40
-
41
- currentQuery: ConstructQuery<Q['queryCreator']> | null;
42
- }
43
-
44
- export const INFINITY_QUERY_TOKEN = new InjectionToken<InfinityQueryDirective<any>>('INFINITY_QUERY_TOKEN');
45
-
46
- @Directive({
47
- // eslint-disable-next-line @angular-eslint/directive-selector
48
- selector: '[etInfinityQuery]',
49
- exportAs: 'etInfinityQuery',
50
- standalone: true,
51
- providers: [{ provide: INFINITY_QUERY_TOKEN, useExisting: InfinityQueryDirective }],
52
- hostDirectives: [DelayableDirective],
53
- })
54
- export class InfinityQueryDirective<
55
- Q extends InfinityQueryConfig<AnyQueryCreator, BaseArguments | undefined, any, unknown[]>,
56
- > {
57
- private readonly _queryConfigChanged$ = new Subject<boolean>();
58
- private readonly _viewContext: InfinityQueryContext<Q> = {
59
- $implicit: null,
60
- etInfinityQuery: null,
61
- loading: false,
62
- error: null,
63
-
64
- isFirstLoad: false,
65
- canLoadMore: false,
66
- currentPage: null,
67
- currentCalculatedPage: null,
68
- totalPages: null,
69
- itemsPerPage: null,
70
-
71
- currentQuery: null,
72
- };
73
- private _infinityQueryInstance: InfinityQueryOf<Q> | null = null;
74
-
75
- private readonly _destroy$ = createDestroy();
76
- private readonly _cdr = inject(ChangeDetectorRef);
77
- private readonly _viewContainerRef = inject(ViewContainerRef);
78
- private readonly _mainTemplateRef = inject(TemplateRef<InfinityQueryContext<Q>>);
79
- private readonly _errorHandler = inject(ErrorHandler);
80
- private readonly _delayable = inject(DelayableDirective, { host: true });
81
-
82
- private readonly _data$ = new BehaviorSubject<Q['response']['arrayType']>([]);
83
-
84
- @Input('etInfinityQuery')
85
- get infinityQuery(): Q {
86
- return this._infinityQuery;
87
- }
88
- set infinityQuery(v: Q) {
89
- this._cleanup();
90
-
91
- this._infinityQuery = v;
92
- this._infinityQueryInstance = this._setupInfinityQuery(v);
93
- this._infinityQueryInstance.nextPage();
94
- }
95
- private _infinityQuery!: Q;
96
-
97
- get context() {
98
- return this._viewContext;
99
- }
100
-
101
- get instance() {
102
- return this._infinityQueryInstance;
103
- }
104
-
105
- get data$() {
106
- return this._data$.asObservable();
107
- }
108
-
109
- data = toSignal(this._data$, { requireSync: true });
110
-
111
- static ngTemplateContextGuard<
112
- Q extends InfinityQueryConfig<AnyQueryCreator, BaseArguments | undefined, any, unknown[]>,
113
- >(dir: InfinityQueryDirective<Q>, ctx: unknown): ctx is InfinityQueryContext<Q> {
114
- return true;
115
- }
116
-
117
- constructor() {
118
- this._viewContainerRef.createEmbeddedView(this._mainTemplateRef, this._viewContext);
119
- }
120
-
121
- private _setupInfinityQuery(config: Q) {
122
- const instance = new InfinityQuery(config, this._destroy$) as InfinityQueryOf<Q>;
123
-
124
- combineLatest([
125
- instance.currentQuery$.pipe(switchQueryState(), withLatestFrom(instance.currentQuery$)),
126
- this._delayable.isDelayed$,
127
- instance.data$,
128
- ])
129
- .pipe(
130
- tap(([[state, currentQuery], isDelayed, infinityArray]) => {
131
- this._viewContext.currentPage = instance.currentPage;
132
- this._viewContext.totalPages = instance.totalPages;
133
- this._viewContext.itemsPerPage = instance.itemsPerPage;
134
- this._viewContext.canLoadMore =
135
- (instance.totalPages !== null &&
136
- instance.currentPage !== null &&
137
- instance.totalPages > instance.currentPage) ||
138
- false;
139
- this._viewContext.currentCalculatedPage = instance.currentCalculatedPage;
140
- this._viewContext.currentQuery = currentQuery;
141
-
142
- if (isQueryStateLoading(state) || isDelayed || !infinityArray) {
143
- this._viewContext.loading = state ? state.meta.triggeredVia !== 'poll' : true;
144
- this._viewContext.error = null;
145
- this._viewContext.isFirstLoad = this.context.etInfinityQuery === null;
146
- } else if (isQueryStateFailure(state)) {
147
- this._viewContext.loading = false;
148
- this._viewContext.error = state.error;
149
- this._viewContext.isFirstLoad = false;
150
- this._errorHandler.handleError(state.error);
151
- } else if (isQueryStateSuccess(state)) {
152
- this._viewContext.loading = false;
153
- this._viewContext.error = null;
154
- this._viewContext.isFirstLoad = false;
155
- this._viewContext.etInfinityQuery = this._viewContext.$implicit =
156
- infinityArray as Q['response']['arrayType'];
157
- this._data$.next(infinityArray);
158
- }
159
-
160
- this._cdr.markForCheck();
161
- }),
162
- takeUntil(this._destroy$),
163
- takeUntil(this._queryConfigChanged$),
164
- )
165
- .subscribe();
166
-
167
- return instance;
168
- }
169
-
170
- loadNextPage() {
171
- if (!this._infinityQueryInstance) {
172
- return;
173
- }
174
-
175
- if (this._viewContext.loading) {
176
- return;
177
- }
178
-
179
- this._infinityQueryInstance.nextPage();
180
- }
181
-
182
- reset(newConfig?: Omit<Q, 'queryCreator' | 'response'>) {
183
- if (!this._infinityQueryInstance) {
184
- return;
185
- }
186
-
187
- this._infinityQueryInstance.reset(newConfig as any);
188
- }
189
-
190
- private _cleanup() {
191
- this._queryConfigChanged$.next(true);
192
-
193
- this._viewContext.loading = false;
194
- this._viewContext.error = null;
195
- this._viewContext.etInfinityQuery = null;
196
- this._viewContext.$implicit = null;
197
-
198
- this._viewContext.isFirstLoad = false;
199
- this._viewContext.canLoadMore = false;
200
- this._viewContext.currentPage = null;
201
- this._viewContext.itemsPerPage = null;
202
- this._viewContext.totalPages = null;
203
-
204
- this._viewContext.currentQuery = null;
205
-
206
- this._data$.next([]);
207
- }
208
- }
@@ -1,201 +0,0 @@
1
- import {
2
- ChangeDetectorRef,
3
- Directive,
4
- ErrorHandler,
5
- Input,
6
- OnDestroy,
7
- OnInit,
8
- TemplateRef,
9
- ViewContainerRef,
10
- inject,
11
- } from '@angular/core';
12
- import { Subscription, tap } from 'rxjs';
13
- import {
14
- AnyQuery,
15
- AnyQueryCollection,
16
- QueryCollectionKeysOf,
17
- QueryOf,
18
- QueryState,
19
- extractQuery,
20
- isQueryCollection,
21
- isQueryStateCancelled,
22
- isQueryStateFailure,
23
- isQueryStateLoading,
24
- isQueryStatePrepared,
25
- isQueryStateSuccess,
26
- } from '../query';
27
- import { QueryDataOf } from '../query-creator';
28
- import { RequestError, RequestProgress } from '../request';
29
-
30
- interface QueryContext<Q extends AnyQuery | AnyQueryCollection | null> {
31
- /**
32
- * The queries's response data.
33
- */
34
- $implicit: QueryDataOf<QueryOf<Q>> | null;
35
-
36
- /**
37
- * The queries's response data.
38
- */
39
- etQuery: QueryDataOf<QueryOf<Q>> | null;
40
-
41
- /**
42
- * The query used inside this directive. Useful if for instance the query gets unwrapped via async pipe inside the directive.
43
- */
44
- query: QueryOf<Q> | null;
45
-
46
- /**
47
- * Is true when the query is triggered by user interaction.
48
- */
49
- loading: boolean;
50
-
51
- /**
52
- * Is true when the query is triggered by either polling or auto refresh event.
53
- */
54
- refreshing: boolean;
55
-
56
- /**
57
- * The query's progress state.
58
- */
59
- progress: RequestProgress | null;
60
-
61
- /**
62
- * The query's error state.
63
- */
64
- error: RequestError<unknown> | null;
65
-
66
- /**
67
- * The query's scope (only available when the query is a collection)
68
- */
69
- scope: QueryCollectionKeysOf<Q> | null;
70
- }
71
-
72
- @Directive({
73
- // eslint-disable-next-line @angular-eslint/directive-selector
74
- selector: '[etQuery]',
75
- standalone: true,
76
- })
77
- export class QueryDirective<Q extends AnyQuery | AnyQueryCollection | null> implements OnInit, OnDestroy {
78
- private _mainTemplateRef = inject<TemplateRef<QueryContext<Q>>>(TemplateRef);
79
- private _viewContainerRef = inject(ViewContainerRef);
80
- private _errorHandler = inject(ErrorHandler);
81
- private _cdr = inject(ChangeDetectorRef);
82
-
83
- private _isMainViewCreated = false;
84
- private _subscription: Subscription | null = null;
85
-
86
- private readonly _viewContext: QueryContext<Q> = {
87
- $implicit: null,
88
- etQuery: null,
89
- loading: false,
90
- refreshing: false,
91
- error: null,
92
- progress: null,
93
- scope: null,
94
- query: null,
95
- };
96
-
97
- @Input('etQuery')
98
- get query(): Q {
99
- return this._query;
100
- }
101
- set query(v: Q) {
102
- this._query = v;
103
-
104
- this._subscribeToQuery();
105
- }
106
- private _query!: Q;
107
-
108
- @Input('etQueryCache')
109
- get cache(): boolean {
110
- return this._cache;
111
- }
112
- set cache(v: boolean) {
113
- this._cache = v;
114
- }
115
- private _cache = false;
116
-
117
- static ngTemplateContextGuard<Q extends AnyQuery | AnyQueryCollection | null>(
118
- dir: QueryDirective<Q>,
119
- ctx: unknown,
120
- ): ctx is QueryContext<Q> {
121
- return true;
122
- }
123
-
124
- ngOnInit(): void {
125
- this._renderMainView();
126
- }
127
-
128
- ngOnDestroy(): void {
129
- this._subscription?.unsubscribe();
130
- }
131
-
132
- private _subscribeToQuery(): void {
133
- this._subscription?.unsubscribe();
134
- this._subscription = null;
135
-
136
- const query = extractQuery(this.query);
137
-
138
- if (!query) {
139
- this._viewContext.$implicit = null;
140
- this._viewContext.etQuery = null;
141
- this._viewContext.loading = false;
142
- this._viewContext.refreshing = false;
143
- this._viewContext.error = null;
144
- this._viewContext.progress = null;
145
- this._viewContext.scope = null;
146
- this._viewContext.query = null;
147
- return;
148
- }
149
-
150
- if (isQueryStatePrepared(query.rawState) || isQueryStateCancelled(query.rawState)) {
151
- query.execute();
152
- }
153
-
154
- const sub = query.state$.pipe(tap((state) => this._updateView(state))).subscribe();
155
-
156
- this._viewContext.scope = isQueryCollection(query) ? (query.type as QueryCollectionKeysOf<Q>) : null;
157
- this._viewContext.query = query as QueryOf<Q>;
158
-
159
- this._subscription = sub;
160
- }
161
-
162
- private _updateView(state: QueryState) {
163
- if (isQueryStateLoading(state)) {
164
- this._viewContext.progress = state.progress ?? null;
165
- this._viewContext.refreshing = state.meta.triggeredVia === 'auto' || state.meta.triggeredVia === 'poll';
166
-
167
- if (!this._viewContext.refreshing) {
168
- this._viewContext.loading = true;
169
- }
170
- } else {
171
- this._viewContext.loading = false;
172
- this._viewContext.refreshing = false;
173
- this._viewContext.progress = null;
174
- }
175
-
176
- if (isQueryStateSuccess(state)) {
177
- this._viewContext.etQuery = state.response as QueryDataOf<QueryOf<Q>>;
178
- this._viewContext.$implicit = state.response as QueryDataOf<QueryOf<Q>>;
179
- } else if (!this.cache) {
180
- this._viewContext.etQuery = null;
181
- this._viewContext.$implicit = null;
182
- }
183
-
184
- if (isQueryStateFailure(state)) {
185
- this._viewContext.error = state.error;
186
-
187
- this._errorHandler.handleError(state.error);
188
- } else {
189
- this._viewContext.error = null;
190
- }
191
-
192
- this._cdr.markForCheck();
193
- }
194
-
195
- private _renderMainView(): void {
196
- if (!this._isMainViewCreated) {
197
- this._isMainViewCreated = true;
198
- this._viewContainerRef.createEmbeddedView(this._mainTemplateRef, this._viewContext);
199
- }
200
- }
201
- }
@@ -1,180 +0,0 @@
1
- import { Observable, Subject, debounceTime, filter, map, shareReplay, startWith } from 'rxjs';
2
- import { EntityKey, EntityStoreConfig } from './entity.types';
3
-
4
- class EntityStoreError extends Error {
5
- constructor(
6
- message: string,
7
- public detail?: unknown,
8
- ) {
9
- super(message);
10
- this.name = 'EntityStoreError';
11
- }
12
- }
13
-
14
- function flatten<T>(arr: T[][]): T[] {
15
- return arr.reduce((acc, val) => acc.concat(val), []);
16
- }
17
-
18
- export class EntityStore<T> {
19
- /**
20
- * @internal
21
- */
22
- readonly _dictionary = new Map<EntityKey, T>();
23
-
24
- /**
25
- * @internal
26
- */
27
- readonly _change$ = new Subject<EntityKey | EntityKey[]>();
28
-
29
- constructor(private readonly _config: EntityStoreConfig) {}
30
-
31
- select(key: EntityKey): Observable<T | null>;
32
- select(keys: EntityKey[]): Observable<T[]>;
33
- select(keys: EntityKey[][]): Observable<T[]>;
34
- select(keyOrKeys: EntityKey | EntityKey[] | EntityKey[][]): Observable<T | null> | Observable<T[]> {
35
- if (Array.isArray(keyOrKeys)) {
36
- const _keys = this._normalizeKeys(keyOrKeys);
37
- return this._selectMany(_keys as EntityKey[]);
38
- }
39
-
40
- return this._select(keyOrKeys);
41
- }
42
-
43
- /**
44
- * **Note:** Prefer `select` over `selectWhere` when possible.
45
- */
46
- selectWhere(predicate: (value: T) => boolean): Observable<T[]> {
47
- return this._change$.pipe(
48
- startWith(null),
49
- debounceTime(0),
50
- map(() => Array.from(this._dictionary.values()).filter(predicate)),
51
- shareReplay({ bufferSize: 1, refCount: true }),
52
- );
53
- }
54
-
55
- set(key: EntityKey, value: T): void;
56
- set(keys: EntityKey[], values: T[]): void;
57
- set(keys: EntityKey[][], values: T[][]): void;
58
- set(keyOrKeys: EntityKey | EntityKey[] | EntityKey[][], valueOrValues: T | T[] | T[][]) {
59
- const _keys = this._normalizeKeys(keyOrKeys);
60
-
61
- if (Array.isArray(_keys)) {
62
- if (!Array.isArray(valueOrValues)) {
63
- throw new EntityStoreError('When setting multiple keys, values must be an array', {
64
- keyOrValues: _keys,
65
- valueOrValues,
66
- });
67
- }
68
-
69
- const _values = (Array.isArray(valueOrValues[0]) ? flatten(valueOrValues as T[][]) : valueOrValues) as T[];
70
-
71
- for (let i = 0; i < _keys.length; i++) {
72
- const k = _keys[i];
73
- const v = _values[i];
74
-
75
- if (k === undefined || v === undefined) continue;
76
-
77
- this._set(k, v);
78
- }
79
- } else {
80
- this._set(_keys, valueOrValues as T);
81
- }
82
-
83
- this._change$.next(_keys);
84
- }
85
-
86
- remove(key: EntityKey): void;
87
- remove(keys: EntityKey[]): void;
88
- remove(keys: EntityKey[][]): void;
89
- remove(keyOrKeys: EntityKey | EntityKey[] | EntityKey[][]) {
90
- const _keys = this._normalizeKeys(keyOrKeys);
91
-
92
- if (Array.isArray(_keys)) {
93
- for (const key of _keys) {
94
- this._remove(key);
95
- }
96
- } else {
97
- this._remove(_keys);
98
- }
99
-
100
- this._change$.next(_keys);
101
- }
102
-
103
- logState() {
104
- console.log('EntityStore:', this._config.name, {
105
- dictionary: this._dictionary,
106
- });
107
- }
108
-
109
- private _select(key: EntityKey): Observable<T | null> {
110
- if (this._config.logActions) {
111
- console.log('EntityStore: select', this._config.name, key);
112
- }
113
-
114
- return this._change$.pipe(
115
- startWith(null),
116
- filter((v) => {
117
- if (v === null) {
118
- return true;
119
- }
120
-
121
- if (Array.isArray(v)) {
122
- return v.includes(key);
123
- }
124
-
125
- return v === key;
126
- }),
127
- map(() => this._dictionary.get(key) ?? null),
128
- );
129
- }
130
-
131
- private _selectMany(keys: EntityKey[]): Observable<T[]> {
132
- if (this._config.logActions) {
133
- console.log('EntityStore: selectMany', this._config.name, keys);
134
- }
135
-
136
- return this._change$.pipe(
137
- startWith(null),
138
- filter((v) => {
139
- if (v === null) {
140
- return true;
141
- }
142
-
143
- if (Array.isArray(v)) {
144
- return keys.some((key) => v.includes(key));
145
- }
146
-
147
- return keys.includes(v);
148
- }),
149
- map(() => keys.map((key) => this._dictionary.get(key)).filter((value): value is T => value !== undefined)),
150
- );
151
- }
152
-
153
- private _set(key: EntityKey, value: T) {
154
- if (this._config.logActions) {
155
- console.log('EntityStore: set', this._config.name, key, value);
156
- }
157
-
158
- this._dictionary.set(key, value);
159
- }
160
-
161
- private _remove(key: EntityKey) {
162
- if (this._config.logActions) {
163
- console.log('EntityStore: remove', this._config.name, key);
164
- }
165
-
166
- this._dictionary.delete(key);
167
- }
168
-
169
- private _normalizeKeys(keys: EntityKey | EntityKey[] | EntityKey[][]): EntityKey | EntityKey[] {
170
- if (Array.isArray(keys)) {
171
- if (Array.isArray(keys[0])) {
172
- return flatten(keys as EntityKey[][]);
173
- }
174
-
175
- return keys as EntityKey[];
176
- }
177
-
178
- return keys;
179
- }
180
- }
@@ -1,34 +0,0 @@
1
- export type EntityKey = string | number;
2
-
3
- export interface EntityStoreConfig {
4
- name: string;
5
- logActions?: boolean;
6
- }
7
-
8
- export interface InsertFromConfig<
9
- OriginStoreType,
10
- OriginKeys extends keyof NonNullable<OriginStoreType>,
11
- IdFn extends (value: NonNullable<OriginStoreType>) => EntityKey | EntityKey[],
12
- > {
13
- /**
14
- * The property key of which the value should be replaced.
15
- */
16
- for: OriginKeys;
17
-
18
- /**
19
- * A function that returns the id of the entity. Can also return an array of ids.
20
- */
21
- id: IdFn;
22
- }
23
-
24
- export interface RemoveFromConfig<T> {
25
- /**
26
- * The where function to select the entities to remove.
27
- */
28
- where: (entity: T) => boolean;
29
-
30
- /**
31
- * A function that returns the id of the entity.
32
- */
33
- id: (entity: T) => EntityKey;
34
- }
@@ -1,51 +0,0 @@
1
- import { Paginated } from '@ethlete/types';
2
- import { map, of, switchMap, take, tap } from 'rxjs';
3
- import { EntityStore } from './entity-store';
4
- import { EntityKey, InsertFromConfig, RemoveFromConfig } from './entity.types';
5
-
6
- export function mapToPaginated<T>(response: Paginated<T>) {
7
- return map((items) => ({ ...response, items }) as Paginated<T>);
8
- }
9
-
10
- // FIXME: This breaks if SubStoreType is an array
11
- /**
12
- * Use an other store to represent a property of the current entity.
13
- */
14
- export const insertFrom = <
15
- OriginStoreType,
16
- OriginKeys extends keyof NonNullable<OriginStoreType>,
17
- SubStoreType extends NonNullable<OriginStoreType>[OriginKeys] extends Array<infer U>
18
- ? U
19
- : NonNullable<OriginStoreType>[OriginKeys],
20
- IdFn extends (value: NonNullable<OriginStoreType>) => EntityKey | EntityKey[],
21
- ComputedEntityType extends ReturnType<IdFn> extends Array<unknown>
22
- ? OriginStoreType
23
- : Omit<OriginStoreType, OriginKeys> & { [K in OriginKeys]: SubStoreType | null },
24
- >(
25
- store: EntityStore<SubStoreType>,
26
- { for: key, id }: InsertFromConfig<OriginStoreType, OriginKeys, IdFn>,
27
- ) =>
28
- switchMap((value: OriginStoreType) => {
29
- if (!value) return of(null);
30
-
31
- const ids = id(value);
32
-
33
- if (Array.isArray(ids)) {
34
- return store.select(ids).pipe(map((data) => ({ ...value, [key]: data }) as ComputedEntityType));
35
- } else {
36
- return store.select(ids).pipe(map((data) => ({ ...value, [key]: data }) as ComputedEntityType));
37
- }
38
- });
39
-
40
- /**
41
- * Remove entities from a store based on a where function.
42
- */
43
- export const removeFrom = <T>(store: EntityStore<T>, { where, id }: RemoveFromConfig<T>) => {
44
- store
45
- .selectWhere(where)
46
- .pipe(
47
- tap((entities) => store.remove(entities.map(id))),
48
- take(1),
49
- )
50
- .subscribe();
51
- };
@@ -1,22 +0,0 @@
1
- const getOpName = /(query|mutation) ?([\w\d-_]+)? ?\(.*?\)? \{/;
2
-
3
- export const transformGql = (str: string) => {
4
- str = Array.isArray(str) ? str.join('') : str;
5
- const name = getOpName.exec(str);
6
- return function (variables: Record<string, unknown> | null | undefined) {
7
- const data: Record<string, unknown> = { query: str };
8
- if (variables) data['variables'] = JSON.stringify(variables);
9
- if (name && name.length) {
10
- const operationName = name[2];
11
- if (operationName) data['operationName'] = name[2];
12
- }
13
- return data as { query: string; variables?: string; operationName?: string };
14
- };
15
- };
16
-
17
- export const gql = (strings: TemplateStringsArray, ...values: string[]) => {
18
- const str = strings.reduce((acc, cur, i) => {
19
- return acc + cur + (values[i] || '');
20
- }, '');
21
- return str;
22
- };