@astral/mobx-query 1.4.0 → 1.6.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.
- package/AdaptableMap/AdaptableMap.d.ts +29 -0
- package/AdaptableMap/AdaptableMap.js +77 -0
- package/AdaptableMap/index.d.ts +1 -0
- package/AdaptableMap/index.js +1 -0
- package/AuxiliaryQuery/AuxiliaryQuery.d.ts +25 -26
- package/AuxiliaryQuery/AuxiliaryQuery.js +59 -34
- package/DataStorage/DataStorage.d.ts +11 -14
- package/DataStorage/DataStorage.js +12 -18
- package/InfiniteQuery/InfiniteQuery.d.ts +50 -55
- package/InfiniteQuery/InfiniteQuery.js +34 -57
- package/MobxQuery/MobxQuery.d.ts +48 -22
- package/MobxQuery/MobxQuery.js +88 -51
- package/Mutation/Mutation.d.ts +11 -34
- package/Mutation/Mutation.js +11 -38
- package/Query/Query.d.ts +45 -50
- package/Query/Query.js +28 -53
- package/QueryContainer/QueryContainer.d.ts +61 -0
- package/QueryContainer/QueryContainer.js +79 -0
- package/QueryContainer/index.d.ts +1 -0
- package/QueryContainer/index.js +1 -0
- package/README.md +25 -0
- package/StatusStorage/StatusStorage.d.ts +24 -0
- package/StatusStorage/StatusStorage.js +36 -0
- package/StatusStorage/index.d.ts +1 -0
- package/StatusStorage/index.js +1 -0
- package/StorageFactory/StorageFactory.d.ts +9 -0
- package/StorageFactory/StorageFactory.js +19 -0
- package/StorageFactory/index.d.ts +1 -0
- package/StorageFactory/index.js +1 -0
- package/package.json +1 -1
- package/types.d.ts +12 -12
|
@@ -1,40 +1,36 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { action, computed, makeObservable, when } from 'mobx';
|
|
2
2
|
import { AuxiliaryQuery } from '../AuxiliaryQuery';
|
|
3
|
+
import { QueryContainer } from '../QueryContainer';
|
|
3
4
|
export const DEFAULT_INFINITE_ITEMS_COUNT = 30;
|
|
4
5
|
/**
|
|
5
|
-
*
|
|
6
|
+
* Квери для работы с инфинити запросами,
|
|
6
7
|
* которые должны быть закешированы,
|
|
7
8
|
*/
|
|
8
|
-
export class InfiniteQuery {
|
|
9
|
-
constructor(executor, { incrementCount = DEFAULT_INFINITE_ITEMS_COUNT, onError, enabledAutoFetch, fetchPolicy, dataStorage, }) {
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
*/
|
|
13
|
-
this.auxiliary = new AuxiliaryQuery();
|
|
9
|
+
export class InfiniteQuery extends QueryContainer {
|
|
10
|
+
constructor(executor, { incrementCount = DEFAULT_INFINITE_ITEMS_COUNT, onError, enabledAutoFetch, fetchPolicy, dataStorage, statusStorage, backgroundStatusStorage = null, submitValidity, }) {
|
|
11
|
+
super(statusStorage, backgroundStatusStorage, new AuxiliaryQuery(statusStorage, backgroundStatusStorage));
|
|
12
|
+
this.executor = executor;
|
|
14
13
|
/**
|
|
15
|
-
*
|
|
14
|
+
* Счетчик отступа для инфинити запроса
|
|
16
15
|
*/
|
|
17
16
|
this.offset = 0;
|
|
18
17
|
/**
|
|
19
|
-
*
|
|
18
|
+
* Флаг того, что мы достигли предела запрашиваемых элементов
|
|
20
19
|
*/
|
|
21
20
|
this.isEndReached = false;
|
|
22
21
|
/**
|
|
23
|
-
*
|
|
24
|
-
*/
|
|
25
|
-
this.isInvalid = false;
|
|
26
|
-
/**
|
|
27
|
-
* @description обработчик успешного запроса, проверяет что мы достигли предела
|
|
22
|
+
* Обработчик успешного запроса, проверяет что мы достигли предела
|
|
28
23
|
*/
|
|
29
24
|
this.submitSuccess = (result, onSuccess, isIncrement) => {
|
|
25
|
+
var _a;
|
|
30
26
|
onSuccess === null || onSuccess === void 0 ? void 0 : onSuccess(result);
|
|
31
27
|
if (isIncrement && this.storage.hasData) {
|
|
32
28
|
this.storage.setData([...this.storage.data, ...result]);
|
|
33
29
|
}
|
|
34
30
|
else {
|
|
35
31
|
this.storage.setData(result);
|
|
32
|
+
(_a = this.submitValidity) === null || _a === void 0 ? void 0 : _a.call(this);
|
|
36
33
|
}
|
|
37
|
-
this.isInvalid = false;
|
|
38
34
|
// убеждаемся что результат запроса действительно массив,
|
|
39
35
|
// и если количество элементов в ответе меньше,
|
|
40
36
|
// чем запрашивалось, значит у бэка их больше нет,
|
|
@@ -47,7 +43,7 @@ export class InfiniteQuery {
|
|
|
47
43
|
}
|
|
48
44
|
};
|
|
49
45
|
/**
|
|
50
|
-
*
|
|
46
|
+
* Форс метод для установки данных
|
|
51
47
|
*/
|
|
52
48
|
this.forceUpdate = (data) => {
|
|
53
49
|
this.offset = 0;
|
|
@@ -56,13 +52,13 @@ export class InfiniteQuery {
|
|
|
56
52
|
this.submitSuccess(data);
|
|
57
53
|
};
|
|
58
54
|
/**
|
|
59
|
-
*
|
|
55
|
+
* Метод для инвалидации данных
|
|
60
56
|
*/
|
|
61
57
|
this.invalidate = () => {
|
|
62
|
-
this.
|
|
58
|
+
this.auxiliary.invalidate();
|
|
63
59
|
};
|
|
64
60
|
/**
|
|
65
|
-
*
|
|
61
|
+
* Метод для запроса следующего набора данных
|
|
66
62
|
*/
|
|
67
63
|
this.fetchMore = () => {
|
|
68
64
|
// если мы еще не достигли предела
|
|
@@ -78,16 +74,16 @@ export class InfiniteQuery {
|
|
|
78
74
|
}
|
|
79
75
|
};
|
|
80
76
|
/**
|
|
81
|
-
*
|
|
77
|
+
* Синхронный метод получения данных
|
|
82
78
|
*/
|
|
83
79
|
this.sync = (params) => {
|
|
84
80
|
const isInstanceAllow = !(this.isLoading || this.isSuccess);
|
|
85
|
-
if (this.isNetworkOnly || this.isInvalid || isInstanceAllow) {
|
|
81
|
+
if (this.isNetworkOnly || this.auxiliary.isInvalid || isInstanceAllow) {
|
|
86
82
|
this.proceedSync(params);
|
|
87
83
|
}
|
|
88
84
|
};
|
|
89
85
|
/**
|
|
90
|
-
*
|
|
86
|
+
* Метод для переиспользования синхронной логики запроса
|
|
91
87
|
*/
|
|
92
88
|
this.proceedSync = ({ onSuccess, onError, } = {}) => {
|
|
93
89
|
this.offset = 0;
|
|
@@ -108,13 +104,13 @@ export class InfiniteQuery {
|
|
|
108
104
|
});
|
|
109
105
|
};
|
|
110
106
|
/**
|
|
111
|
-
*
|
|
107
|
+
* Асинхронный метод получения данных,
|
|
112
108
|
* подходит для изменения параметров запроса(фильтров),
|
|
113
109
|
* при котором будет сброшен offset,
|
|
114
110
|
* предполагается, что нужно будет самостоятельно обрабатывать ошибку
|
|
115
111
|
*/
|
|
116
112
|
this.async = () => {
|
|
117
|
-
if (!this.isNetworkOnly && this.isSuccess && !this.isInvalid) {
|
|
113
|
+
if (!this.isNetworkOnly && this.isSuccess && !this.auxiliary.isInvalid) {
|
|
118
114
|
return Promise.resolve(this.storage.data);
|
|
119
115
|
}
|
|
120
116
|
this.offset = 0;
|
|
@@ -132,17 +128,25 @@ export class InfiniteQuery {
|
|
|
132
128
|
};
|
|
133
129
|
this.storage = dataStorage;
|
|
134
130
|
this.incrementCount = incrementCount;
|
|
135
|
-
this.executor = executor;
|
|
136
131
|
this.defaultOnError = onError;
|
|
137
132
|
this.enabledAutoFetch = enabledAutoFetch;
|
|
138
133
|
this.defaultFetchPolicy = fetchPolicy;
|
|
139
|
-
|
|
134
|
+
this.submitValidity = submitValidity;
|
|
135
|
+
makeObservable(this, {
|
|
136
|
+
data: computed,
|
|
137
|
+
infiniteExecutor: computed,
|
|
138
|
+
forceUpdate: action,
|
|
139
|
+
async: action,
|
|
140
|
+
sync: action,
|
|
141
|
+
fetchMore: action,
|
|
142
|
+
submitSuccess: action,
|
|
143
|
+
});
|
|
140
144
|
}
|
|
141
145
|
get isNetworkOnly() {
|
|
142
146
|
return this.defaultFetchPolicy === 'network-only';
|
|
143
147
|
}
|
|
144
148
|
/**
|
|
145
|
-
*
|
|
149
|
+
* Метод для обогащения параметров текущими значениями для инфинити
|
|
146
150
|
*/
|
|
147
151
|
get infiniteExecutor() {
|
|
148
152
|
return () => this.executor({
|
|
@@ -151,7 +155,7 @@ export class InfiniteQuery {
|
|
|
151
155
|
});
|
|
152
156
|
}
|
|
153
157
|
/**
|
|
154
|
-
*
|
|
158
|
+
* Вычисляемое свойство, содержащее реактивные данные,
|
|
155
159
|
* благодаря mobx, при изменении isInvalid, свойство будет вычисляться заново,
|
|
156
160
|
* следовательно, стриггерится условие невалидности,
|
|
157
161
|
* и начнется запрос, в результате которого, данные обновятся
|
|
@@ -161,7 +165,7 @@ export class InfiniteQuery {
|
|
|
161
165
|
!this.isSuccess &&
|
|
162
166
|
!this.isLoading &&
|
|
163
167
|
!this.isError;
|
|
164
|
-
if (this.isInvalid || shouldSync) {
|
|
168
|
+
if (this.auxiliary.isInvalid || shouldSync) {
|
|
165
169
|
// т.к. при вызове апдейта, изменяются флаги, на которые подписан data,
|
|
166
170
|
// нужно вызывать этот экшн асинхронно
|
|
167
171
|
when(() => true, this.proceedSync);
|
|
@@ -169,31 +173,4 @@ export class InfiniteQuery {
|
|
|
169
173
|
// возвращаем имеющиеся данные
|
|
170
174
|
return this.storage.data;
|
|
171
175
|
}
|
|
172
|
-
/**
|
|
173
|
-
* @description флаг загрузки данных
|
|
174
|
-
*/
|
|
175
|
-
get isLoading() {
|
|
176
|
-
return this.auxiliary.isLoading;
|
|
177
|
-
}
|
|
178
|
-
/**
|
|
179
|
-
* @description флаг обозначающий, что последний запрос был зафейлен
|
|
180
|
-
*/
|
|
181
|
-
get isError() {
|
|
182
|
-
return this.auxiliary.isError;
|
|
183
|
-
}
|
|
184
|
-
/**
|
|
185
|
-
* @description данные о последней ошибке
|
|
186
|
-
*/
|
|
187
|
-
get error() {
|
|
188
|
-
return this.auxiliary.error;
|
|
189
|
-
}
|
|
190
|
-
/**
|
|
191
|
-
* @description флаг обозначающий, что последний запрос был успешно завершен
|
|
192
|
-
*/
|
|
193
|
-
get isSuccess() {
|
|
194
|
-
return this.auxiliary.isSuccess;
|
|
195
|
-
}
|
|
196
|
-
get isIdle() {
|
|
197
|
-
return this.auxiliary.isIdle;
|
|
198
|
-
}
|
|
199
176
|
}
|
package/MobxQuery/MobxQuery.d.ts
CHANGED
|
@@ -3,80 +3,106 @@ import { type InfiniteExecutor, InfiniteQuery, type InfiniteQueryParams } from '
|
|
|
3
3
|
import { Mutation, type MutationExecutor, type MutationParams } from '../Mutation';
|
|
4
4
|
import type { CacheKey, FetchPolicy } from '../types';
|
|
5
5
|
/**
|
|
6
|
-
*
|
|
6
|
+
* Стандартный обработчик ошибки запроса,
|
|
7
7
|
* будет вызван, если при вызове sync не был передан отдельный onError параметр
|
|
8
8
|
*/
|
|
9
9
|
type OnError<TError = unknown> = (error: TError) => void;
|
|
10
10
|
type MobxQueryParams = {
|
|
11
|
+
/**
|
|
12
|
+
* Политика получения данных по умолчанию.
|
|
13
|
+
* @enum cache-first - данные сначала берутся из кеша, если их нет, тогда идет обращение к сети, ответ записывается в кэш
|
|
14
|
+
* @enum network-only - данные всегда берутся из сети, при этом ответ записывается в кэш
|
|
15
|
+
*/
|
|
11
16
|
fetchPolicy?: FetchPolicy;
|
|
17
|
+
/**
|
|
18
|
+
* обработчик ошибок по умолчанию
|
|
19
|
+
*/
|
|
12
20
|
onError?: OnError;
|
|
13
21
|
/**
|
|
14
|
-
*
|
|
22
|
+
* Флаг, отвечающий за автоматический запрос данных при обращении к полю data по умолчанию.
|
|
15
23
|
* @default false
|
|
16
24
|
*/
|
|
17
25
|
enabledAutoFetch?: boolean;
|
|
18
26
|
};
|
|
19
|
-
type CreateQueryParams<TResult, TError> = Omit<QueryParams<TResult, TError>, 'dataStorage'
|
|
20
|
-
|
|
27
|
+
type CreateQueryParams<TResult, TError, TIsBackground extends boolean> = Omit<QueryParams<TResult, TError, TIsBackground>, 'dataStorage' | 'statusStorage' | 'backgroundStatusStorage' | 'submitValidity'> & {
|
|
28
|
+
/**
|
|
29
|
+
* Режим фонового обновления
|
|
30
|
+
* @default false
|
|
31
|
+
*/
|
|
32
|
+
isBackground?: TIsBackground;
|
|
33
|
+
};
|
|
34
|
+
type CreateInfiniteQueryParams<TResult, TError, TIsBackground extends boolean> = Omit<InfiniteQueryParams<TResult, TError, TIsBackground>, 'dataStorage' | 'statusStorage' | 'backgroundStatusStorage' | 'submitValidity'> & {
|
|
35
|
+
/**
|
|
36
|
+
* Режим фонового обновления
|
|
37
|
+
* @default false
|
|
38
|
+
*/
|
|
39
|
+
isBackground?: TIsBackground;
|
|
40
|
+
};
|
|
21
41
|
/**
|
|
22
|
-
*
|
|
42
|
+
* Сервис, позволяющий кэшировать данные.
|
|
23
43
|
*/
|
|
24
44
|
export declare class MobxQuery<TDefaultError = void> {
|
|
25
45
|
/**
|
|
26
|
-
*
|
|
46
|
+
* Объект соответствия хешей ключей и их значений
|
|
27
47
|
*/
|
|
28
48
|
private keys;
|
|
29
49
|
/**
|
|
30
|
-
*
|
|
50
|
+
* Map соответствия хешей ключей к запомненным сторам
|
|
31
51
|
*/
|
|
32
|
-
private
|
|
52
|
+
private queriesMap;
|
|
33
53
|
/**
|
|
34
|
-
*
|
|
54
|
+
* Фабрика создания хранилищ данных для обычного Query
|
|
35
55
|
*/
|
|
36
56
|
private queryDataStorageFactory;
|
|
37
57
|
/**
|
|
38
|
-
*
|
|
58
|
+
* Фабрика создания хранилищ статусов между экземплярами Query и экземллярами Infinite Query.
|
|
39
59
|
*/
|
|
40
|
-
private
|
|
60
|
+
private statusStorageFactory;
|
|
41
61
|
/**
|
|
42
|
-
*
|
|
62
|
+
* Стандартный обработчик ошибок, будет использован, если не передан другой
|
|
43
63
|
*/
|
|
44
64
|
private readonly defaultErrorHandler?;
|
|
45
65
|
/**
|
|
46
|
-
*
|
|
66
|
+
* Стандартное поведение политики кеширования
|
|
47
67
|
*/
|
|
48
68
|
private readonly defaultFetchPolicy;
|
|
49
69
|
/**
|
|
50
|
-
*
|
|
70
|
+
* Флаг, отвечающий за автоматический запрос данных при обращении к полю data
|
|
51
71
|
* @default false
|
|
52
72
|
*/
|
|
53
73
|
private readonly defaultEnabledAutoFetch;
|
|
54
74
|
private serialize;
|
|
55
75
|
constructor({ onError, fetchPolicy, enabledAutoFetch, }?: MobxQueryParams);
|
|
56
76
|
/**
|
|
57
|
-
*
|
|
77
|
+
* Метод для инвалидации по списку ключей,
|
|
58
78
|
* предполагается использование из домена
|
|
59
79
|
*/
|
|
60
80
|
invalidate: (keysParts: CacheKey[]) => void;
|
|
81
|
+
private submitValidity;
|
|
61
82
|
/**
|
|
62
|
-
*
|
|
83
|
+
* Метод инвалидации всех query
|
|
63
84
|
*/
|
|
64
85
|
invalidateQueries: () => void;
|
|
65
86
|
/**
|
|
66
|
-
*
|
|
87
|
+
* Метод, который занимается проверкой наличия квери по ключу,
|
|
67
88
|
* и если нет, создает новый, добавляет его к себе в память, и возвращает его пользователю
|
|
68
89
|
*/
|
|
69
90
|
private getCachedQuery;
|
|
70
91
|
/**
|
|
71
|
-
*
|
|
92
|
+
* Метод для создания ключей к внутренним хранилищам
|
|
93
|
+
*/
|
|
94
|
+
private makeKeys;
|
|
95
|
+
private getBackgroundStatusStorage;
|
|
96
|
+
/**
|
|
97
|
+
* Метод создания стора, кешируется
|
|
72
98
|
*/
|
|
73
|
-
createQuery: <TResult, TError = TDefaultError>(key: CacheKey[], executor: QueryExecutor<TResult>, params?: CreateQueryParams<TResult, TError> | undefined) => Query<TResult, TError>;
|
|
99
|
+
createQuery: <TResult, TError = TDefaultError, TIsBackground extends boolean = false>(key: CacheKey[], executor: QueryExecutor<TResult>, params?: CreateQueryParams<TResult, TError, TIsBackground> | undefined) => Query<TResult, TError, TIsBackground>;
|
|
74
100
|
/**
|
|
75
|
-
*
|
|
101
|
+
* Метод создания инфинит стора, кешируется
|
|
76
102
|
*/
|
|
77
|
-
createInfiniteQuery: <TResult, TError = TDefaultError>(key: CacheKey[], executor: InfiniteExecutor<TResult>, params?: CreateInfiniteQueryParams<TResult, TError> | undefined) => InfiniteQuery<TResult, TError>;
|
|
103
|
+
createInfiniteQuery: <TResult, TError = TDefaultError, TIsBackground extends boolean = false>(key: CacheKey[], executor: InfiniteExecutor<TResult>, params?: CreateInfiniteQueryParams<TResult, TError, TIsBackground> | undefined) => InfiniteQuery<TResult, TError, TIsBackground>;
|
|
78
104
|
/**
|
|
79
|
-
*
|
|
105
|
+
* Метод создания мутации, не кешируется
|
|
80
106
|
*/
|
|
81
107
|
createMutation: <TResult, TError = TDefaultError, TExecutorParams = void>(executor: MutationExecutor<TResult, TExecutorParams>, params?: MutationParams<TResult, TError> | undefined) => Mutation<TResult, TError, TExecutorParams>;
|
|
82
108
|
}
|
package/MobxQuery/MobxQuery.js
CHANGED
|
@@ -2,71 +2,99 @@ import { Query } from '../Query';
|
|
|
2
2
|
import { InfiniteQuery, } from '../InfiniteQuery';
|
|
3
3
|
import { Mutation, } from '../Mutation';
|
|
4
4
|
import { DataStorageFactory } from '../DataStorage';
|
|
5
|
+
import { StatusStorageFactory } from '../StatusStorage';
|
|
6
|
+
import { AdaptableMap } from '../AdaptableMap';
|
|
5
7
|
/**
|
|
6
|
-
*
|
|
8
|
+
* Время, спустя которое, запись о query c network-only будет удалена
|
|
7
9
|
*/
|
|
8
10
|
const DEFAULT_TIME_TO_CLEAN = 100;
|
|
9
11
|
/**
|
|
10
|
-
*
|
|
12
|
+
* Сервис, позволяющий кэшировать данные.
|
|
11
13
|
*/
|
|
12
14
|
export class MobxQuery {
|
|
13
15
|
constructor({ onError, fetchPolicy = 'cache-first', enabledAutoFetch = false, } = {}) {
|
|
14
16
|
/**
|
|
15
|
-
*
|
|
17
|
+
* Объект соответствия хешей ключей и их значений
|
|
16
18
|
*/
|
|
17
|
-
this.keys =
|
|
19
|
+
this.keys = new Map();
|
|
18
20
|
/**
|
|
19
|
-
*
|
|
21
|
+
* Map соответствия хешей ключей к запомненным сторам
|
|
20
22
|
*/
|
|
21
|
-
this.
|
|
23
|
+
this.queriesMap = new AdaptableMap();
|
|
22
24
|
/**
|
|
23
|
-
*
|
|
25
|
+
* Фабрика создания хранилищ данных для обычного Query
|
|
24
26
|
*/
|
|
25
27
|
this.queryDataStorageFactory = new DataStorageFactory();
|
|
26
28
|
/**
|
|
27
|
-
*
|
|
29
|
+
* Фабрика создания хранилищ статусов между экземплярами Query и экземллярами Infinite Query.
|
|
28
30
|
*/
|
|
29
|
-
this.
|
|
31
|
+
this.statusStorageFactory = new StatusStorageFactory();
|
|
30
32
|
this.serialize = (data) => JSON.stringify(data);
|
|
31
33
|
/**
|
|
32
|
-
*
|
|
34
|
+
* Метод для инвалидации по списку ключей,
|
|
33
35
|
* предполагается использование из домена
|
|
34
36
|
*/
|
|
35
37
|
this.invalidate = (keysParts) => {
|
|
36
|
-
//
|
|
38
|
+
// Сет сериализовонных ключей
|
|
37
39
|
const keysSet = new Set(keysParts.map(this.serialize));
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
40
|
+
[...this.keys.keys()].forEach((keyHash) => {
|
|
41
|
+
const key = this.keys.get(keyHash);
|
|
42
|
+
if (!key) {
|
|
43
|
+
return;
|
|
44
|
+
}
|
|
45
|
+
// Проверяем, есть ли пересечение между закешированными ключами и набором ключей для инвалидации
|
|
46
|
+
const hasTouchedElement = key.some((valuePart) => keysSet.has(this.serialize(valuePart)));
|
|
43
47
|
if (hasTouchedElement) {
|
|
44
|
-
|
|
48
|
+
const query = this.queriesMap.get(keyHash);
|
|
49
|
+
if (query) {
|
|
50
|
+
query.invalidate();
|
|
51
|
+
// Конвертируем инвалидированный квери в слабый,
|
|
52
|
+
// чтобы сборщик мусора мог удалить неиспользуемые квери
|
|
53
|
+
this.queriesMap.convertToWeak(keyHash);
|
|
54
|
+
}
|
|
45
55
|
}
|
|
46
56
|
});
|
|
47
57
|
};
|
|
58
|
+
// Метод для подтверждения того, что квери успешно получил валидные данные
|
|
59
|
+
this.submitValidity = (keyHash) => {
|
|
60
|
+
// конвертируем квери в сильный,
|
|
61
|
+
// чтобы сборщик мусора не удалил наш кеш преждевременно
|
|
62
|
+
this.queriesMap.convertToStrong(keyHash);
|
|
63
|
+
};
|
|
48
64
|
/**
|
|
49
|
-
*
|
|
65
|
+
* Метод инвалидации всех query
|
|
50
66
|
*/
|
|
51
67
|
this.invalidateQueries = () => {
|
|
52
|
-
[...this.
|
|
53
|
-
|
|
68
|
+
[...this.keys.keys()].forEach((keyHash) => {
|
|
69
|
+
var _a;
|
|
70
|
+
(_a = this.queriesMap.get(keyHash)) === null || _a === void 0 ? void 0 : _a.invalidate();
|
|
71
|
+
this.queriesMap.convertToWeak(keyHash);
|
|
54
72
|
});
|
|
55
73
|
};
|
|
56
74
|
/**
|
|
57
|
-
*
|
|
75
|
+
* Метод, который занимается проверкой наличия квери по ключу,
|
|
58
76
|
* и если нет, создает новый, добавляет его к себе в память, и возвращает его пользователю
|
|
59
77
|
*/
|
|
60
|
-
this.getCachedQuery = (key,
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
const
|
|
64
|
-
|
|
65
|
-
|
|
78
|
+
this.getCachedQuery = (key, createInstance, type, createParams) => {
|
|
79
|
+
var _a, _b;
|
|
80
|
+
const fetchPolicy = (createParams === null || createParams === void 0 ? void 0 : createParams.fetchPolicy) || this.defaultFetchPolicy;
|
|
81
|
+
const keys = this.makeKeys(key, fetchPolicy, (_a = createParams === null || createParams === void 0 ? void 0 : createParams.isBackground) !== null && _a !== void 0 ? _a : false, type);
|
|
82
|
+
const cachedQuery = this.queriesMap.get(keys.queryKeyHash);
|
|
83
|
+
if (cachedQuery) {
|
|
84
|
+
return cachedQuery;
|
|
66
85
|
}
|
|
67
|
-
const
|
|
68
|
-
|
|
69
|
-
|
|
86
|
+
const query = createInstance({
|
|
87
|
+
onError: ((createParams === null || createParams === void 0 ? void 0 : createParams.onError) ||
|
|
88
|
+
this.defaultErrorHandler),
|
|
89
|
+
enabledAutoFetch: (_b = createParams === null || createParams === void 0 ? void 0 : createParams.enabledAutoFetch) !== null && _b !== void 0 ? _b : this.defaultEnabledAutoFetch,
|
|
90
|
+
fetchPolicy: fetchPolicy,
|
|
91
|
+
dataStorage: this.queryDataStorageFactory.getStorage(keys.dataKeyHash),
|
|
92
|
+
statusStorage: this.statusStorageFactory.getStorage(keys.statusKeyHash),
|
|
93
|
+
backgroundStatusStorage: this.getBackgroundStatusStorage(keys.backgroundStatusKeyHash, Boolean(createParams === null || createParams === void 0 ? void 0 : createParams.isBackground)),
|
|
94
|
+
submitValidity: () => this.submitValidity(keys.queryKeyHash),
|
|
95
|
+
});
|
|
96
|
+
this.queriesMap.set(keys.queryKeyHash, query);
|
|
97
|
+
this.keys.set(keys.queryKeyHash, keys.queryKey);
|
|
70
98
|
// Ожидается, что network-only квери не должны кешироваться,
|
|
71
99
|
// но, с введением StrictMode в реакт 18, проявилась проблема,
|
|
72
100
|
// что network-only квери, созданные в одном реакт компоненте,
|
|
@@ -76,36 +104,45 @@ export class MobxQuery {
|
|
|
76
104
|
// делают по отдельному запросу к данным единомоментно,
|
|
77
105
|
if (fetchPolicy === 'network-only') {
|
|
78
106
|
setTimeout(() => {
|
|
79
|
-
this.
|
|
80
|
-
|
|
107
|
+
this.queriesMap.delete(keys.queryKeyHash);
|
|
108
|
+
this.keys.delete(keys.queryKeyHash);
|
|
81
109
|
}, DEFAULT_TIME_TO_CLEAN);
|
|
82
110
|
}
|
|
83
|
-
return
|
|
111
|
+
return query;
|
|
84
112
|
};
|
|
85
113
|
/**
|
|
86
|
-
*
|
|
114
|
+
* Метод для создания ключей к внутренним хранилищам
|
|
87
115
|
*/
|
|
88
|
-
this.
|
|
89
|
-
const
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
116
|
+
this.makeKeys = (rootKey, fetchPolicy, isBackground, type) => {
|
|
117
|
+
const queryKey = [...rootKey, { fetchPolicy, isBackground, type }];
|
|
118
|
+
const queryKeyHash = this.serialize(queryKey);
|
|
119
|
+
const dataKeyHash = this.serialize([...rootKey, { type }]);
|
|
120
|
+
const statusKeyHash = this.serialize([...rootKey, { type }]);
|
|
121
|
+
const backgroundStatusKeyHash = this.serialize([
|
|
122
|
+
...rootKey,
|
|
123
|
+
{ type, isBackground },
|
|
124
|
+
]);
|
|
125
|
+
return {
|
|
126
|
+
queryKey,
|
|
127
|
+
queryKeyHash,
|
|
128
|
+
statusKeyHash,
|
|
129
|
+
backgroundStatusKeyHash,
|
|
130
|
+
dataKeyHash,
|
|
131
|
+
};
|
|
95
132
|
};
|
|
133
|
+
this.getBackgroundStatusStorage = (keyHash, hasBackground) => (hasBackground
|
|
134
|
+
? this.statusStorageFactory.getStorage(keyHash)
|
|
135
|
+
: null);
|
|
96
136
|
/**
|
|
97
|
-
*
|
|
137
|
+
* Метод создания стора, кешируется
|
|
98
138
|
*/
|
|
99
|
-
this.
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
this.defaultErrorHandler), enabledAutoFetch: (_a = params === null || params === void 0 ? void 0 : params.enabledAutoFetch) !== null && _a !== void 0 ? _a : this.defaultEnabledAutoFetch, dataStorage: this.infiniteQueryDataStorageFactory.getStorage(key), fetchPolicy: fetchPolicy }));
|
|
105
|
-
}, fetchPolicy);
|
|
106
|
-
};
|
|
139
|
+
this.createQuery = (key, executor, params) => this.getCachedQuery(key, (internalParams) => new Query(executor, Object.assign(Object.assign(Object.assign({}, params), internalParams), { dataStorage: internalParams.dataStorage })), Query.name, params);
|
|
140
|
+
/**
|
|
141
|
+
* Метод создания инфинит стора, кешируется
|
|
142
|
+
*/
|
|
143
|
+
this.createInfiniteQuery = (key, executor, params) => this.getCachedQuery(key, (internalParams) => new InfiniteQuery(executor, Object.assign(Object.assign(Object.assign({}, params), internalParams), { dataStorage: internalParams.dataStorage })), InfiniteQuery.name, params);
|
|
107
144
|
/**
|
|
108
|
-
*
|
|
145
|
+
* Метод создания мутации, не кешируется
|
|
109
146
|
*/
|
|
110
147
|
this.createMutation = (executor, params) => new Mutation(executor, Object.assign(Object.assign({}, params), { onError: (params === null || params === void 0 ? void 0 : params.onError) || this.defaultErrorHandler }));
|
|
111
148
|
this.defaultErrorHandler = onError;
|
package/Mutation/Mutation.d.ts
CHANGED
|
@@ -1,57 +1,34 @@
|
|
|
1
|
+
import { AuxiliaryQuery } from '../AuxiliaryQuery';
|
|
1
2
|
import type { QueryBaseActions, Sync, SyncParams } from '../types';
|
|
3
|
+
import { QueryContainer } from '../QueryContainer';
|
|
2
4
|
/**
|
|
3
|
-
*
|
|
5
|
+
* Исполнитель запроса
|
|
4
6
|
*/
|
|
5
7
|
export type MutationExecutor<TResult, TParams> = (params: TParams) => Promise<TResult>;
|
|
6
8
|
export type MutationParams<TResult, TError> = {
|
|
7
9
|
/**
|
|
8
|
-
*
|
|
10
|
+
* Обработчик ошибки, вызываемый по умолчанию
|
|
9
11
|
*/
|
|
10
12
|
onError?: SyncParams<TResult, TError>['onError'];
|
|
11
13
|
};
|
|
12
14
|
/**
|
|
13
|
-
*
|
|
15
|
+
* Простой квери для запросов, которые не требуют кэширования,
|
|
14
16
|
* пример - POST запросы
|
|
15
17
|
*/
|
|
16
|
-
export declare class Mutation<TResult, TError = void, TExecutorParams = void> implements QueryBaseActions<TResult, TError, TExecutorParams> {
|
|
18
|
+
export declare class Mutation<TResult, TError = void, TExecutorParams = void> extends QueryContainer<TError, AuxiliaryQuery<TResult, TError>, false> implements QueryBaseActions<TResult, TError, TExecutorParams> {
|
|
19
|
+
private readonly executor;
|
|
17
20
|
/**
|
|
18
|
-
*
|
|
21
|
+
* Обработчик ошибки, вызываемый по умолчанию
|
|
19
22
|
*/
|
|
20
|
-
private
|
|
21
|
-
/**
|
|
22
|
-
* @description исполнитель запроса, ожидается,
|
|
23
|
-
* что будет использоваться что-то из слоя sources
|
|
24
|
-
*/
|
|
25
|
-
private executor;
|
|
26
|
-
/**
|
|
27
|
-
* @description обработчик ошибки, вызываемый по умолчанию
|
|
28
|
-
*/
|
|
29
|
-
private defaultOnError?;
|
|
23
|
+
private readonly defaultOnError?;
|
|
30
24
|
constructor(executor: MutationExecutor<TResult, TExecutorParams>, { onError }?: MutationParams<TResult, TError>);
|
|
31
25
|
/**
|
|
32
|
-
*
|
|
26
|
+
* Синхронный метод получения/отправки данных
|
|
33
27
|
*/
|
|
34
28
|
sync: Sync<TResult, TError, TExecutorParams>;
|
|
35
29
|
/**
|
|
36
|
-
*
|
|
30
|
+
* Асинхронный метод получения/отправки данных,
|
|
37
31
|
* предполагается, что нужно будет самостоятельно обрабатывать ошибку
|
|
38
32
|
*/
|
|
39
33
|
async: (params: TExecutorParams) => Promise<TResult>;
|
|
40
|
-
/**
|
|
41
|
-
* @description флаг загрузки данных
|
|
42
|
-
*/
|
|
43
|
-
get isLoading(): boolean;
|
|
44
|
-
/**
|
|
45
|
-
* @description флаг обозначающий, что последний запрос был зафейлен
|
|
46
|
-
*/
|
|
47
|
-
get isError(): boolean;
|
|
48
|
-
/**
|
|
49
|
-
* @description данные о последней ошибке
|
|
50
|
-
*/
|
|
51
|
-
get error(): TError | undefined;
|
|
52
|
-
/**
|
|
53
|
-
* @description флаг обозначающий, что последний запрос был успешно завершен
|
|
54
|
-
*/
|
|
55
|
-
get isSuccess(): boolean;
|
|
56
|
-
get isIdle(): boolean;
|
|
57
34
|
}
|