@ethlete/query 5.15.1 → 5.16.0

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/.eslintrc.json +40 -0
  2. package/CHANGELOG.md +8 -0
  3. package/jest.config.ts +23 -0
  4. package/ng-package.json +8 -0
  5. package/package.json +6 -23
  6. package/project.json +37 -0
  7. package/{index.d.ts → src/index.ts} +2 -0
  8. package/src/lib/auth/auth-provider.types.ts +160 -0
  9. package/src/lib/auth/auth-provider.utils.ts +39 -0
  10. package/src/lib/auth/basic-auth-provider.ts +17 -0
  11. package/src/lib/auth/bearer-auth-provider.ts +243 -0
  12. package/src/lib/auth/custom-header-auth-provider.ts +13 -0
  13. package/{lib/class-validator/class-validator.types.d.ts → src/lib/class-validator/class-validator.types.ts} +4 -3
  14. package/src/lib/class-validator/class-validator.utils.ts +5 -0
  15. package/src/lib/devtools/components/query-devtools/query-devtools.component.html +402 -0
  16. package/src/lib/devtools/components/query-devtools/query-devtools.component.scss +360 -0
  17. package/src/lib/devtools/components/query-devtools/query-devtools.component.ts +427 -0
  18. package/src/lib/devtools/pipes/query-short-name.pipe.ts +24 -0
  19. package/src/lib/devtools/utils/query-client.utils.ts +25 -0
  20. package/src/lib/directives/infinity-query-trigger.directive.ts +58 -0
  21. package/src/lib/directives/infinity-query.directive.ts +208 -0
  22. package/src/lib/directives/query.directive.ts +201 -0
  23. package/src/lib/entity/entity-store.ts +180 -0
  24. package/src/lib/entity/entity.types.ts +34 -0
  25. package/src/lib/entity/entity.utils.ts +51 -0
  26. package/src/lib/gql/gql.ts +22 -0
  27. package/src/lib/infinite-query/infinity-query.ts +245 -0
  28. package/src/lib/infinite-query/infinity-query.types.ts +149 -0
  29. package/src/lib/infinite-query/infinity-query.utils.ts +14 -0
  30. package/src/lib/logger/logger.ts +30 -0
  31. package/src/lib/query/query.ts +631 -0
  32. package/src/lib/query/query.types.ts +532 -0
  33. package/src/lib/query/query.utils.spec.ts +92 -0
  34. package/src/lib/query/query.utils.ts +450 -0
  35. package/src/lib/query-client/query-client.spec.ts +77 -0
  36. package/src/lib/query-client/query-client.ts +195 -0
  37. package/src/lib/query-client/query-client.types.ts +101 -0
  38. package/src/lib/query-client/query-client.utils.spec.ts +61 -0
  39. package/src/lib/query-client/query-client.utils.ts +28 -0
  40. package/src/lib/query-creator/query-creator.ts +103 -0
  41. package/src/lib/query-creator/query-creator.types.ts +74 -0
  42. package/src/lib/query-form/query-form.ts +526 -0
  43. package/src/lib/query-form/query-form.types.ts +169 -0
  44. package/src/lib/query-form/query-form.utils.ts +116 -0
  45. package/src/lib/query-store/query-store.ts +192 -0
  46. package/src/lib/request/request.ts +253 -0
  47. package/src/lib/request/request.types.ts +164 -0
  48. package/src/lib/request/request.util.spec.ts +177 -0
  49. package/src/lib/request/request.util.ts +399 -0
  50. package/src/lib/stories/angular-example-page.mdx +85 -0
  51. package/src/lib/stories/authentication-page.mdx +35 -0
  52. package/src/lib/stories/changelog-page.mdx +9 -0
  53. package/src/lib/stories/client-page.mdx +100 -0
  54. package/src/lib/stories/queries-page.mdx +117 -0
  55. package/src/lib/symfony/symfony.types.ts +21 -0
  56. package/src/lib/symfony/symfony.utils.ts +43 -0
  57. package/src/lib/utils/data.utils.ts +280 -0
  58. package/src/lib/utils/deep-freeze.util.ts +21 -0
  59. package/{lib/utils/def.util.d.ts → src/lib/utils/def.util.ts} +1 -1
  60. package/src/test-setup.ts +1 -0
  61. package/tsconfig.json +29 -0
  62. package/tsconfig.lib.json +12 -0
  63. package/tsconfig.lib.prod.json +10 -0
  64. package/tsconfig.spec.json +11 -0
  65. package/esm2022/ethlete-query.mjs +0 -5
  66. package/esm2022/index.mjs +0 -20
  67. package/esm2022/lib/auth/auth-provider.types.mjs +0 -2
  68. package/esm2022/lib/auth/auth-provider.utils.mjs +0 -25
  69. package/esm2022/lib/auth/basic-auth-provider.mjs +0 -15
  70. package/esm2022/lib/auth/bearer-auth-provider.mjs +0 -168
  71. package/esm2022/lib/auth/custom-header-auth-provider.mjs +0 -12
  72. package/esm2022/lib/auth/index.mjs +0 -6
  73. package/esm2022/lib/class-validator/class-validator.types.mjs +0 -2
  74. package/esm2022/lib/class-validator/class-validator.utils.mjs +0 -4
  75. package/esm2022/lib/class-validator/index.mjs +0 -3
  76. package/esm2022/lib/devtools/components/query-devtools/index.mjs +0 -2
  77. package/esm2022/lib/devtools/components/query-devtools/query-devtools.component.mjs +0 -297
  78. package/esm2022/lib/devtools/pipes/index.mjs +0 -2
  79. package/esm2022/lib/devtools/pipes/query-short-name.pipe.mjs +0 -24
  80. package/esm2022/lib/devtools/utils/index.mjs +0 -2
  81. package/esm2022/lib/devtools/utils/query-client.utils.mjs +0 -13
  82. package/esm2022/lib/directives/index.mjs +0 -4
  83. package/esm2022/lib/directives/infinity-query-trigger.directive.mjs +0 -56
  84. package/esm2022/lib/directives/infinity-query.directive.mjs +0 -147
  85. package/esm2022/lib/directives/query.directive.mjs +0 -123
  86. package/esm2022/lib/entity/entity-store.mjs +0 -127
  87. package/esm2022/lib/entity/entity.types.mjs +0 -2
  88. package/esm2022/lib/entity/entity.utils.mjs +0 -29
  89. package/esm2022/lib/entity/index.mjs +0 -4
  90. package/esm2022/lib/gql/gql.mjs +0 -23
  91. package/esm2022/lib/gql/index.mjs +0 -2
  92. package/esm2022/lib/infinite-query/index.mjs +0 -4
  93. package/esm2022/lib/infinite-query/infinity-query.mjs +0 -171
  94. package/esm2022/lib/infinite-query/infinity-query.types.mjs +0 -2
  95. package/esm2022/lib/infinite-query/infinity-query.utils.mjs +0 -3
  96. package/esm2022/lib/logger/index.mjs +0 -2
  97. package/esm2022/lib/logger/logger.mjs +0 -16
  98. package/esm2022/lib/query/index.mjs +0 -4
  99. package/esm2022/lib/query/query.mjs +0 -428
  100. package/esm2022/lib/query/query.types.mjs +0 -2
  101. package/esm2022/lib/query/query.utils.mjs +0 -253
  102. package/esm2022/lib/query-client/index.mjs +0 -4
  103. package/esm2022/lib/query-client/query-client.mjs +0 -80
  104. package/esm2022/lib/query-client/query-client.types.mjs +0 -2
  105. package/esm2022/lib/query-client/query-client.utils.mjs +0 -20
  106. package/esm2022/lib/query-creator/index.mjs +0 -3
  107. package/esm2022/lib/query-creator/query-creator.mjs +0 -55
  108. package/esm2022/lib/query-creator/query-creator.types.mjs +0 -2
  109. package/esm2022/lib/query-form/index.mjs +0 -4
  110. package/esm2022/lib/query-form/query-form.mjs +0 -368
  111. package/esm2022/lib/query-form/query-form.types.mjs +0 -2
  112. package/esm2022/lib/query-form/query-form.utils.mjs +0 -97
  113. package/esm2022/lib/query-store/index.mjs +0 -2
  114. package/esm2022/lib/query-store/query-store.mjs +0 -144
  115. package/esm2022/lib/request/index.mjs +0 -4
  116. package/esm2022/lib/request/request.mjs +0 -196
  117. package/esm2022/lib/request/request.types.mjs +0 -2
  118. package/esm2022/lib/request/request.util.mjs +0 -252
  119. package/esm2022/lib/symfony/index.mjs +0 -3
  120. package/esm2022/lib/symfony/symfony.types.mjs +0 -2
  121. package/esm2022/lib/symfony/symfony.utils.mjs +0 -31
  122. package/esm2022/lib/utils/data.utils.mjs +0 -138
  123. package/esm2022/lib/utils/deep-freeze.util.mjs +0 -17
  124. package/esm2022/lib/utils/def.util.mjs +0 -8
  125. package/esm2022/lib/utils/index.mjs +0 -4
  126. package/fesm2022/ethlete-query.mjs +0 -3276
  127. package/fesm2022/ethlete-query.mjs.map +0 -1
  128. package/lib/auth/auth-provider.types.d.ts +0 -133
  129. package/lib/auth/auth-provider.utils.d.ts +0 -9
  130. package/lib/auth/basic-auth-provider.d.ts +0 -10
  131. package/lib/auth/bearer-auth-provider.d.ts +0 -23
  132. package/lib/auth/custom-header-auth-provider.d.ts +0 -9
  133. package/lib/class-validator/class-validator.utils.d.ts +0 -2
  134. package/lib/devtools/components/query-devtools/query-devtools.component.d.ts +0 -151
  135. package/lib/devtools/pipes/query-short-name.pipe.d.ts +0 -8
  136. package/lib/devtools/utils/query-client.utils.d.ts +0 -12
  137. package/lib/directives/infinity-query-trigger.directive.d.ts +0 -15
  138. package/lib/directives/infinity-query.directive.d.ts +0 -49
  139. package/lib/directives/query.directive.d.ts +0 -63
  140. package/lib/entity/entity-store.d.ts +0 -25
  141. package/lib/entity/entity.types.d.ts +0 -25
  142. package/lib/entity/entity.utils.d.ts +0 -12
  143. package/lib/gql/gql.d.ts +0 -6
  144. package/lib/infinite-query/infinity-query.d.ts +0 -29
  145. package/lib/infinite-query/infinity-query.types.d.ts +0 -104
  146. package/lib/infinite-query/infinity-query.utils.d.ts +0 -4
  147. package/lib/logger/logger.d.ts +0 -12
  148. package/lib/query/query.d.ts +0 -60
  149. package/lib/query/query.types.d.ts +0 -388
  150. package/lib/query/query.utils.d.ts +0 -91
  151. package/lib/query-client/query-client.d.ts +0 -29
  152. package/lib/query-client/query-client.types.d.ts +0 -82
  153. package/lib/query-client/query-client.utils.d.ts +0 -4
  154. package/lib/query-creator/query-creator.d.ts +0 -20
  155. package/lib/query-creator/query-creator.types.d.ts +0 -13
  156. package/lib/query-form/query-form.d.ts +0 -89
  157. package/lib/query-form/query-form.types.d.ts +0 -138
  158. package/lib/query-form/query-form.utils.d.ts +0 -13
  159. package/lib/query-store/query-store.d.ts +0 -31
  160. package/lib/request/request.d.ts +0 -3
  161. package/lib/request/request.types.d.ts +0 -126
  162. package/lib/request/request.util.d.ts +0 -92
  163. package/lib/symfony/symfony.types.d.ts +0 -19
  164. package/lib/symfony/symfony.utils.d.ts +0 -6
  165. package/lib/utils/data.utils.d.ts +0 -59
  166. package/lib/utils/deep-freeze.util.d.ts +0 -1
  167. /package/{lib/auth/index.d.ts → src/lib/auth/index.ts} +0 -0
  168. /package/{lib/class-validator/index.d.ts → src/lib/class-validator/index.ts} +0 -0
  169. /package/{lib/devtools/components/query-devtools/index.d.ts → src/lib/devtools/components/query-devtools/index.ts} +0 -0
  170. /package/{lib/devtools/pipes/index.d.ts → src/lib/devtools/pipes/index.ts} +0 -0
  171. /package/{lib/devtools/utils/index.d.ts → src/lib/devtools/utils/index.ts} +0 -0
  172. /package/{lib/directives/index.d.ts → src/lib/directives/index.ts} +0 -0
  173. /package/{lib/entity/index.d.ts → src/lib/entity/index.ts} +0 -0
  174. /package/{lib/gql/index.d.ts → src/lib/gql/index.ts} +0 -0
  175. /package/{lib/infinite-query/index.d.ts → src/lib/infinite-query/index.ts} +0 -0
  176. /package/{lib/logger/index.d.ts → src/lib/logger/index.ts} +0 -0
  177. /package/{lib/query/index.d.ts → src/lib/query/index.ts} +0 -0
  178. /package/{lib/query-client/index.d.ts → src/lib/query-client/index.ts} +0 -0
  179. /package/{lib/query-creator/index.d.ts → src/lib/query-creator/index.ts} +0 -0
  180. /package/{lib/query-form/index.d.ts → src/lib/query-form/index.ts} +0 -0
  181. /package/{lib/query-store/index.d.ts → src/lib/query-store/index.ts} +0 -0
  182. /package/{lib/request/index.d.ts → src/lib/request/index.ts} +0 -0
  183. /package/{lib/symfony/index.d.ts → src/lib/symfony/index.ts} +0 -0
  184. /package/{lib/utils/index.d.ts → src/lib/utils/index.ts} +0 -0
@@ -0,0 +1,245 @@
1
+ import { BehaviorSubject, Observable, combineLatest, map, of, shareReplay, switchMap, tap } from 'rxjs';
2
+ import { filterSuccess } from '../query';
3
+ import { AnyQueryCreator, ConstructQuery, QueryArgsOf, QueryDataOf } from '../query-creator';
4
+ import { InfinityQueryConfig, InfinityQueryParamLocation } from './infinity-query.types';
5
+
6
+ export class InfinityQuery<
7
+ QueryCreator extends AnyQueryCreator,
8
+ Query extends ConstructQuery<QueryCreator>,
9
+ Args extends QueryArgsOf<QueryCreator>,
10
+ QueryResponse extends QueryDataOf<QueryCreator>,
11
+ InfinityResponse extends unknown[],
12
+ > {
13
+ private readonly _queries$ = new BehaviorSubject<Query[]>([]);
14
+ private readonly _currentPage$ = new BehaviorSubject<number | null>(null);
15
+ private readonly _currentCalculatedPage$ = new BehaviorSubject<number | null>(null);
16
+ private readonly _totalPages$ = new BehaviorSubject<number | null>(null);
17
+ private readonly _itemsPerPage$ = new BehaviorSubject<number>(this._config.limitParam?.value ?? 10);
18
+
19
+ private readonly _data$ = this._queries$.pipe(
20
+ switchMap((queries) => {
21
+ if (!queries.length) {
22
+ return of([]);
23
+ }
24
+
25
+ return combineLatest(
26
+ queries.map((query) =>
27
+ query.state$.pipe(
28
+ filterSuccess(),
29
+ map((state) => ({ state, query })),
30
+ ),
31
+ ),
32
+ );
33
+ }),
34
+ tap((stateMaps) => {
35
+ const lastState = stateMaps[stateMaps.length - 1]?.state;
36
+ const lastQuery = stateMaps[stateMaps.length - 1]?.query;
37
+
38
+ if (!lastState || !lastQuery) {
39
+ return;
40
+ }
41
+
42
+ const totalPages =
43
+ this._config.response.totalPagesExtractor?.({
44
+ response: lastState.response as QueryResponse,
45
+ itemsPerPage: this.itemsPerPage,
46
+ args: lastQuery._arguments,
47
+ }) ??
48
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
49
+ (lastState.response as any)?.totalPages ??
50
+ null;
51
+
52
+ this._totalPages$.next(totalPages);
53
+ }),
54
+ map((stateMaps) => {
55
+ if (!stateMaps.length) {
56
+ return null;
57
+ }
58
+
59
+ const fullData = stateMaps.reduce(
60
+ (acc, stateMap) => {
61
+ const valExtractFn = this._config?.response?.valueExtractor;
62
+ let data = valExtractFn
63
+ ? valExtractFn?.(stateMap.state.response as QueryResponse)
64
+ : (stateMap.state.response as InfinityResponse);
65
+
66
+ if (this._config.response.reverse) {
67
+ data = [...data].reverse() as InfinityResponse;
68
+ }
69
+
70
+ if (this._config.response.appendItemsTo === 'start') {
71
+ acc.unshift(...data);
72
+ } else {
73
+ acc.push(...data);
74
+ }
75
+ return acc;
76
+ },
77
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
78
+ [] as any as InfinityResponse,
79
+ );
80
+
81
+ return fullData;
82
+ }),
83
+ shareReplay({ bufferSize: 1, refCount: true }),
84
+ );
85
+
86
+ private readonly _lastQuery$ = this._queries$.pipe(
87
+ map((queries) => queries[queries.length - 1] ?? null),
88
+ shareReplay({ bufferSize: 1, refCount: true }),
89
+ );
90
+
91
+ get currentPage$() {
92
+ return this._currentPage$.asObservable();
93
+ }
94
+
95
+ get currentPage() {
96
+ return this._currentPage$.getValue();
97
+ }
98
+
99
+ get currentCalculatedPage$() {
100
+ return this._currentCalculatedPage$.asObservable();
101
+ }
102
+
103
+ get currentCalculatedPage() {
104
+ return this._currentCalculatedPage$.getValue();
105
+ }
106
+
107
+ get totalPages$() {
108
+ return this._totalPages$.asObservable();
109
+ }
110
+
111
+ get totalPages() {
112
+ return this._totalPages$.getValue();
113
+ }
114
+
115
+ get itemsPerPage$() {
116
+ return this._itemsPerPage$.asObservable();
117
+ }
118
+
119
+ get itemsPerPage() {
120
+ return this._itemsPerPage$.getValue();
121
+ }
122
+
123
+ get data$() {
124
+ return this._data$;
125
+ }
126
+
127
+ get currentQuery$() {
128
+ return this._lastQuery$;
129
+ }
130
+
131
+ constructor(
132
+ private _config: InfinityQueryConfig<QueryCreator, Args, QueryResponse, InfinityResponse>,
133
+ private _destroy$: Observable<boolean>,
134
+ ) {}
135
+
136
+ nextPage() {
137
+ const newPage = (this._currentPage$.value ?? 0) + 1;
138
+ const calculatedPage =
139
+ this._config?.pageParam?.valueCalculator?.({
140
+ page: newPage,
141
+ totalPages: this.totalPages,
142
+ itemsPerPage: this.itemsPerPage,
143
+ }) ?? newPage;
144
+
145
+ if (this.totalPages !== null && newPage > this.totalPages) {
146
+ console.error(
147
+ 'Cannot load more pages, already at the end. Make sure to not render the infinity query trigger using *ngIf canLoadMore',
148
+ );
149
+ return;
150
+ }
151
+
152
+ const args = this._prepareArgs(this._config, calculatedPage);
153
+
154
+ const query = this._config.queryCreator.prepare(args).execute() as Query;
155
+
156
+ if (this._config.pollingInterval) {
157
+ query.poll({ interval: this._config.pollingInterval, takeUntil: this._destroy$ });
158
+ }
159
+
160
+ this._queries$.next([...this._queries$.value, query]);
161
+
162
+ this._currentPage$.next(newPage);
163
+ this._currentCalculatedPage$.next(calculatedPage);
164
+ }
165
+
166
+ reset(
167
+ newConfig?: Omit<
168
+ InfinityQueryConfig<QueryCreator, Args, QueryResponse, InfinityResponse>,
169
+ 'queryCreator' | 'response'
170
+ >,
171
+ ) {
172
+ this._config = { ...this._config, ...(newConfig ?? {}) };
173
+
174
+ this._currentPage$.next(null);
175
+ this._currentCalculatedPage$.next(null);
176
+ this._totalPages$.next(null);
177
+ this._itemsPerPage$.next(this._config.limitParam?.value ?? 10);
178
+ this._queries$.next([]);
179
+
180
+ this.nextPage();
181
+ }
182
+
183
+ private _prepareArgs(config: InfinityQueryConfig<QueryCreator, Args, QueryResponse, InfinityResponse>, page: number) {
184
+ const pageParamLocation = this._getPageParamLocation(config?.pageParam?.location);
185
+
186
+ const pageArgs = {
187
+ [pageParamLocation]: {
188
+ [config?.pageParam?.key ?? 'page']: page,
189
+ },
190
+ };
191
+
192
+ const limitParamLocation = this._getPageParamLocation(config?.limitParam?.location);
193
+
194
+ const limitArgs = {
195
+ [limitParamLocation]: {
196
+ [config?.limitParam?.key ?? 'limit']: config?.limitParam?.value ?? 10,
197
+ },
198
+ };
199
+
200
+ const defaultConfig = config?.defaultArgs ?? {};
201
+
202
+ const mergedArgs =
203
+ pageParamLocation === limitParamLocation
204
+ ? {
205
+ ...defaultConfig,
206
+ [pageParamLocation]: {
207
+ ...(config?.defaultArgs?.[pageParamLocation] ?? {}),
208
+ ...pageArgs[limitParamLocation],
209
+ ...limitArgs[limitParamLocation],
210
+ },
211
+ }
212
+ : {
213
+ ...defaultConfig,
214
+ [pageParamLocation]: {
215
+ ...(config?.defaultArgs?.[pageParamLocation] ?? {}),
216
+ ...pageArgs[pageParamLocation],
217
+ },
218
+ [limitParamLocation]: {
219
+ ...(config?.defaultArgs?.[limitParamLocation] ?? {}),
220
+ ...limitArgs[limitParamLocation],
221
+ },
222
+ };
223
+
224
+ return mergedArgs;
225
+ }
226
+
227
+ private _getPageParamLocation(location: InfinityQueryParamLocation | undefined) {
228
+ const loc = location ?? 'query';
229
+
230
+ switch (loc) {
231
+ case 'path':
232
+ return 'pathParams';
233
+ case 'query':
234
+ return 'queryParams';
235
+ case 'body':
236
+ return 'body';
237
+ case 'header':
238
+ return 'headers';
239
+ case 'variable':
240
+ return 'variables';
241
+ default:
242
+ throw new Error(`Invalid pageParamLocation: ${loc}`);
243
+ }
244
+ }
245
+ }
@@ -0,0 +1,149 @@
1
+ import { BaseArguments, WithHeaders } from '../query';
2
+ import { AnyQueryCreator, ConstructQuery, QueryArgsOf, QueryDataOf } from '../query-creator';
3
+ import { InfinityQuery } from './infinity-query';
4
+
5
+ export type InfinityQueryParamLocation = 'path' | 'query' | 'body' | 'header' | 'variable';
6
+
7
+ export type AppendItemsLocation = 'start' | 'end';
8
+
9
+ export interface PageParamCalculatorOptions {
10
+ page: number;
11
+ totalPages: number | null;
12
+ itemsPerPage: number;
13
+ }
14
+
15
+ export interface TotalPagesExtractorOptions<Arguments extends BaseArguments | undefined, QueryResponse> {
16
+ response: QueryResponse;
17
+ itemsPerPage: number;
18
+ args: Arguments;
19
+ }
20
+
21
+ export interface InfinityQueryConfig<
22
+ QueryCreator extends AnyQueryCreator,
23
+ Arguments extends BaseArguments | undefined,
24
+ QueryResponse,
25
+ InfinityResponse extends unknown[],
26
+ > {
27
+ /**
28
+ * The query creator to use for fetching pages.
29
+ */
30
+ queryCreator: QueryCreator;
31
+
32
+ /**
33
+ * The interval in milliseconds to poll on. If not provided, polling will be disabled.
34
+ * @default undefined
35
+ */
36
+ pollingInterval?: number;
37
+
38
+ /**
39
+ * The args that will be merged with the page arg.
40
+ */
41
+ defaultArgs?: Arguments & WithHeaders;
42
+
43
+ pageParam?: {
44
+ /**
45
+ * The location where the page param is in request.
46
+ *
47
+ * @default "query"
48
+ */
49
+ location?: InfinityQueryParamLocation;
50
+
51
+ /**
52
+ * Used as page param name.
53
+ *
54
+ * @default "page"
55
+ */
56
+ key?: string;
57
+
58
+ /**
59
+ * A function that calculates the page value for the next request.
60
+ * E.g. if the pagination is done with a `skip` param, the `pageParamName` should be `skip` and this function should return the correct value.
61
+ */
62
+ valueCalculator?: (data: PageParamCalculatorOptions) => number;
63
+ };
64
+
65
+ limitParam?: {
66
+ /**
67
+ * The location where the limit param is in request.
68
+ *
69
+ * @default "query"
70
+ */
71
+ location?: InfinityQueryParamLocation;
72
+
73
+ /**
74
+ * Used as limit param name.
75
+ *
76
+ * @default "limit"
77
+ */
78
+ key?: string;
79
+
80
+ /**
81
+ * The value of the limit param.
82
+ *
83
+ * @default 10
84
+ */
85
+ value?: number;
86
+ };
87
+
88
+ response: {
89
+ /**
90
+ * Determines if the response should get reversed before appending to the data array.
91
+ *
92
+ * @default false
93
+ */
94
+ reverse?: boolean;
95
+
96
+ /**
97
+ * Determines where to put the new items in the data array.
98
+ *
99
+ * @default "end"
100
+ */
101
+ appendItemsTo?: AppendItemsLocation;
102
+
103
+ /**
104
+ * The type of the array that will be created by the infinite query.
105
+ */
106
+ arrayType: InfinityResponse;
107
+
108
+ /**
109
+ * A function that returns the data array from the response.
110
+ * This function should return the type provided in `responseArrayType`.
111
+ */
112
+ valueExtractor?: (response: QueryResponse) => InfinityResponse;
113
+
114
+ /**
115
+ * The property in the response that contains the total page count.
116
+ *
117
+ * @default "totalPages"
118
+ */
119
+ totalPagesExtractor?: (
120
+ data: TotalPagesExtractorOptions<QueryArgsOf<QueryCreator> & WithHeaders, QueryResponse>,
121
+ ) => number;
122
+ };
123
+ }
124
+
125
+ type OmitUndefined<T> = T extends undefined ? never : T;
126
+
127
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
128
+ export type AnyInfinityQueryConfig = InfinityQueryConfig<any, any, any, any>;
129
+
130
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
131
+ export type AnyInfinityQuery = InfinityQuery<any, any, any, any, any>;
132
+
133
+ export type InfinityQueryConfigType<
134
+ QueryCreator extends AnyQueryCreator,
135
+ InfinityResponse extends unknown[],
136
+ > = InfinityQueryConfig<
137
+ QueryCreator,
138
+ OmitUndefined<QueryArgsOf<QueryCreator>>,
139
+ QueryDataOf<QueryCreator>,
140
+ InfinityResponse
141
+ >;
142
+
143
+ export type InfinityQueryOf<Cfg extends AnyInfinityQueryConfig | null> = InfinityQuery<
144
+ NonNullable<Cfg>['queryCreator'],
145
+ ConstructQuery<NonNullable<Cfg>['queryCreator']>,
146
+ QueryArgsOf<NonNullable<Cfg>['queryCreator']>,
147
+ QueryDataOf<NonNullable<Cfg>['queryCreator']>,
148
+ NonNullable<Cfg>['response']['arrayType']
149
+ >;
@@ -0,0 +1,14 @@
1
+ import { AnyQueryCreator, QueryArgsOf, QueryDataOf } from '../query-creator';
2
+ import { InfinityQueryConfig, PageParamCalculatorOptions } from './infinity-query.types';
3
+
4
+ export const createInfinityQueryConfig = <
5
+ QueryCreator extends AnyQueryCreator,
6
+ Args extends QueryArgsOf<QueryCreator>,
7
+ QueryResponse extends QueryDataOf<QueryCreator>,
8
+ InfinityResponse extends unknown[],
9
+ >(
10
+ config: InfinityQueryConfig<QueryCreator, Args, QueryResponse, InfinityResponse>,
11
+ ) => config;
12
+
13
+ export const skipPaginationPageParamCalculator = ({ page, itemsPerPage }: PageParamCalculatorOptions) =>
14
+ itemsPerPage * (page - 1);
@@ -0,0 +1,30 @@
1
+ export const buildErrorMessage = (code: string, message: string) => `[@ethlete\\query:${code}] ${message}`;
2
+
3
+ export class QueryError extends Error {
4
+ data?: unknown;
5
+
6
+ constructor(code: string, message: string, data?: unknown) {
7
+ super(buildErrorMessage(code, message));
8
+ this.name = 'QueryError';
9
+ this.data = data;
10
+ }
11
+ }
12
+
13
+ export const invalidBaseRouteError = (data: unknown) =>
14
+ new QueryError('001', 'The baseRoute must not end with a slash', data);
15
+
16
+ export const invalidRouteError = (data: unknown) => new QueryError('002', 'The route must start with a slash', data);
17
+
18
+ export const pathParamsMissingInRouteFunctionError = (data: unknown) =>
19
+ new QueryError('003', 'The route is a function but pathParams are missing', data);
20
+
21
+ export const queryStateAlreadyHasKeyError = (data: unknown) =>
22
+ new QueryError('004', 'The query state already contains the provided key', data);
23
+
24
+ export const queryStateDoesNotContainKeyError = (data: unknown) =>
25
+ new QueryError('005', 'The query state does not contain the provided key', data);
26
+
27
+ export const queryStateCannotTransformError = (data: unknown) =>
28
+ new QueryError('006', 'The query state cannot be transformed because it is not loading', data);
29
+
30
+ export const invalidBodyError = (data: unknown) => new QueryError('007', 'The body is not valid or upsupported', data);