@astral/mobx-query 1.8.0 → 1.9.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/MobxQuery/MobxQuery.d.ts +44 -0
- package/MobxQuery/MobxQuery.js +48 -0
- package/README.md +1048 -287
- package/Sets/InfiniteQuerySet/InfiniteQuerySet.d.ts +60 -0
- package/Sets/InfiniteQuerySet/InfiniteQuerySet.js +71 -0
- package/Sets/InfiniteQuerySet/index.d.ts +1 -0
- package/Sets/InfiniteQuerySet/index.js +1 -0
- package/Sets/MutationSet/MutationSet.d.ts +32 -0
- package/Sets/MutationSet/MutationSet.js +31 -0
- package/Sets/MutationSet/index.d.ts +1 -0
- package/Sets/MutationSet/index.js +1 -0
- package/Sets/QuerySet/QuerySet.d.ts +64 -0
- package/Sets/QuerySet/QuerySet.js +72 -0
- package/Sets/QuerySet/index.d.ts +1 -0
- package/Sets/QuerySet/index.js +1 -0
- package/Sets/index.d.ts +3 -0
- package/Sets/index.js +3 -0
- package/Sets/utils/generateQuerySetBaseKey/generateQuerySetBaseKey.d.ts +4 -0
- package/Sets/utils/generateQuerySetBaseKey/generateQuerySetBaseKey.js +5 -0
- package/Sets/utils/generateQuerySetBaseKey/index.d.ts +1 -0
- package/Sets/utils/generateQuerySetBaseKey/index.js +1 -0
- package/Sets/utils/generateQuerySetKeys/generateQuerySetKeys.d.ts +9 -0
- package/Sets/utils/generateQuerySetKeys/generateQuerySetKeys.js +20 -0
- package/Sets/utils/generateQuerySetKeys/index.d.ts +1 -0
- package/Sets/utils/generateQuerySetKeys/index.js +1 -0
- package/Sets/utils/index.d.ts +2 -0
- package/Sets/utils/index.js +2 -0
- package/index.d.ts +2 -1
- package/index.js +1 -0
- package/node/AdaptableMap/AdaptableMap.d.ts +29 -0
- package/node/AdaptableMap/AdaptableMap.js +81 -0
- package/node/AdaptableMap/index.d.ts +1 -0
- package/node/AdaptableMap/index.js +17 -0
- package/node/AuxiliaryQuery/AuxiliaryQuery.d.ts +55 -0
- package/node/AuxiliaryQuery/AuxiliaryQuery.js +115 -0
- package/node/AuxiliaryQuery/index.d.ts +1 -0
- package/node/AuxiliaryQuery/index.js +17 -0
- package/node/DataStorage/DataStorage.d.ts +33 -0
- package/node/DataStorage/DataStorage.js +51 -0
- package/node/DataStorage/index.d.ts +1 -0
- package/node/DataStorage/index.js +17 -0
- package/node/InfiniteQuery/InfiniteQuery.d.ts +135 -0
- package/node/InfiniteQuery/InfiniteQuery.js +169 -0
- package/node/InfiniteQuery/index.d.ts +1 -0
- package/node/InfiniteQuery/index.js +17 -0
- package/node/MobxQuery/MobxQuery.d.ts +176 -0
- package/node/MobxQuery/MobxQuery.js +225 -0
- package/node/MobxQuery/index.d.ts +1 -0
- package/node/MobxQuery/index.js +17 -0
- package/node/Mutation/Mutation.d.ts +34 -0
- package/node/Mutation/Mutation.js +47 -0
- package/node/Mutation/index.d.ts +1 -0
- package/node/Mutation/index.js +17 -0
- package/node/Query/Query.d.ts +103 -0
- package/node/Query/Query.js +113 -0
- package/node/Query/index.d.ts +1 -0
- package/node/Query/index.js +17 -0
- package/node/QueryContainer/QueryContainer.d.ts +61 -0
- package/node/QueryContainer/QueryContainer.js +83 -0
- package/node/QueryContainer/index.d.ts +1 -0
- package/node/QueryContainer/index.js +17 -0
- package/node/Sets/InfiniteQuerySet/InfiniteQuerySet.d.ts +60 -0
- package/node/Sets/InfiniteQuerySet/InfiniteQuerySet.js +75 -0
- package/node/Sets/InfiniteQuerySet/index.d.ts +1 -0
- package/node/Sets/InfiniteQuerySet/index.js +17 -0
- package/node/Sets/MutationSet/MutationSet.d.ts +32 -0
- package/node/Sets/MutationSet/MutationSet.js +35 -0
- package/node/Sets/MutationSet/index.d.ts +1 -0
- package/node/Sets/MutationSet/index.js +17 -0
- package/node/Sets/QuerySet/QuerySet.d.ts +64 -0
- package/node/Sets/QuerySet/QuerySet.js +76 -0
- package/node/Sets/QuerySet/index.d.ts +1 -0
- package/node/Sets/QuerySet/index.js +17 -0
- package/node/Sets/index.d.ts +3 -0
- package/node/Sets/index.js +19 -0
- package/node/Sets/utils/generateQuerySetBaseKey/generateQuerySetBaseKey.d.ts +4 -0
- package/node/Sets/utils/generateQuerySetBaseKey/generateQuerySetBaseKey.js +12 -0
- package/node/Sets/utils/generateQuerySetBaseKey/index.d.ts +1 -0
- package/node/Sets/utils/generateQuerySetBaseKey/index.js +17 -0
- package/node/Sets/utils/generateQuerySetKeys/generateQuerySetKeys.d.ts +9 -0
- package/node/Sets/utils/generateQuerySetKeys/generateQuerySetKeys.js +27 -0
- package/node/Sets/utils/generateQuerySetKeys/index.d.ts +1 -0
- package/node/Sets/utils/generateQuerySetKeys/index.js +17 -0
- package/node/Sets/utils/index.d.ts +2 -0
- package/node/Sets/utils/index.js +18 -0
- package/node/StatusStorage/StatusStorage.d.ts +24 -0
- package/node/StatusStorage/StatusStorage.js +41 -0
- package/node/StatusStorage/index.d.ts +1 -0
- package/node/StatusStorage/index.js +17 -0
- package/node/StorageFactory/StorageFactory.d.ts +9 -0
- package/node/StorageFactory/StorageFactory.js +23 -0
- package/node/StorageFactory/index.d.ts +1 -0
- package/node/StorageFactory/index.js +17 -0
- package/node/index.d.ts +6 -0
- package/node/index.js +11 -0
- package/node/types.d.ts +55 -0
- package/node/types.js +2 -0
- package/package.json +11 -4
|
@@ -0,0 +1,115 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.AuxiliaryQuery = void 0;
|
|
4
|
+
const mobx_1 = require("mobx");
|
|
5
|
+
/**
|
|
6
|
+
* Вспомогательное хранилище данных, для композиции в Query сторах,
|
|
7
|
+
* содержащее флаги загрузки и ошибки,
|
|
8
|
+
* колбэки на успешный запрос и на ошибку,
|
|
9
|
+
* данные последней ошибки,
|
|
10
|
+
* а так же, управляющее синглтон промисом.
|
|
11
|
+
*/
|
|
12
|
+
class AuxiliaryQuery {
|
|
13
|
+
constructor(statusStorage, backgroundStatusStorage) {
|
|
14
|
+
this.statusStorage = statusStorage;
|
|
15
|
+
this.backgroundStatusStorage = backgroundStatusStorage;
|
|
16
|
+
/**
|
|
17
|
+
* Флаг, обозначающий простаивание, т.е. запроса еще не было
|
|
18
|
+
*/
|
|
19
|
+
this.isIdle = true;
|
|
20
|
+
/**
|
|
21
|
+
* Флаг, по которому реактивно определяется необходимость запуска инвалидации
|
|
22
|
+
*/
|
|
23
|
+
this.isInvalid = false;
|
|
24
|
+
/**
|
|
25
|
+
* Метод ответственный за создание единого промиса,
|
|
26
|
+
* для устранения гонки запросов
|
|
27
|
+
*/
|
|
28
|
+
this.getUnifiedPromise = (executor, onSuccess) => {
|
|
29
|
+
// проверяем, если синглтона нет, то надо создать
|
|
30
|
+
if (!Boolean(this.unifiedPromise)) {
|
|
31
|
+
this.startLoading();
|
|
32
|
+
this.unifiedPromise = executor()
|
|
33
|
+
.then((resData) => {
|
|
34
|
+
(0, mobx_1.runInAction)(this.submitSuccess);
|
|
35
|
+
onSuccess === null || onSuccess === void 0 ? void 0 : onSuccess(resData);
|
|
36
|
+
return resData;
|
|
37
|
+
})
|
|
38
|
+
.catch((e) => {
|
|
39
|
+
(0, mobx_1.runInAction)(() => {
|
|
40
|
+
this.submitError(e);
|
|
41
|
+
});
|
|
42
|
+
throw e;
|
|
43
|
+
})
|
|
44
|
+
.finally(() => {
|
|
45
|
+
this.unifiedPromise = undefined;
|
|
46
|
+
(0, mobx_1.runInAction)(() => {
|
|
47
|
+
this.statusStorage.isLoading = false;
|
|
48
|
+
});
|
|
49
|
+
});
|
|
50
|
+
}
|
|
51
|
+
return this.unifiedPromise;
|
|
52
|
+
};
|
|
53
|
+
this.setSuccess = (storage) => {
|
|
54
|
+
storage.isError = false;
|
|
55
|
+
storage.isSuccess = true;
|
|
56
|
+
};
|
|
57
|
+
this.checkBackgroundAndSet = (setStorage) => {
|
|
58
|
+
if (this.backgroundStatusStorage && this.statusStorage.isSuccess) {
|
|
59
|
+
setStorage(this.backgroundStatusStorage);
|
|
60
|
+
}
|
|
61
|
+
else {
|
|
62
|
+
setStorage(this.statusStorage);
|
|
63
|
+
}
|
|
64
|
+
};
|
|
65
|
+
/**
|
|
66
|
+
* Обработчик успешного ответа
|
|
67
|
+
*/
|
|
68
|
+
this.submitSuccess = () => {
|
|
69
|
+
this.checkBackgroundAndSet(this.setSuccess);
|
|
70
|
+
this.isInvalid = false;
|
|
71
|
+
};
|
|
72
|
+
this.setError = (storage, error) => {
|
|
73
|
+
storage.isSuccess = false;
|
|
74
|
+
storage.isError = true;
|
|
75
|
+
storage.error = error;
|
|
76
|
+
};
|
|
77
|
+
/**
|
|
78
|
+
* Обработчик ошибки
|
|
79
|
+
*/
|
|
80
|
+
this.submitError = (error) => {
|
|
81
|
+
this.checkBackgroundAndSet((storage) => this.setError(storage, error));
|
|
82
|
+
};
|
|
83
|
+
this.setLoading = (storage) => {
|
|
84
|
+
storage.isLoading = true;
|
|
85
|
+
storage.isError = false;
|
|
86
|
+
storage.isSuccess = false;
|
|
87
|
+
};
|
|
88
|
+
/**
|
|
89
|
+
* Метод, вызываемый в самом начале запроса, чтобы сбросить флаги в соответствующее значение
|
|
90
|
+
*/
|
|
91
|
+
this.startLoading = () => {
|
|
92
|
+
this.isIdle = false;
|
|
93
|
+
this.checkBackgroundAndSet(this.setLoading);
|
|
94
|
+
};
|
|
95
|
+
/**
|
|
96
|
+
* Метод для инвалидации данных
|
|
97
|
+
*/
|
|
98
|
+
this.invalidate = () => {
|
|
99
|
+
this.isInvalid = true;
|
|
100
|
+
};
|
|
101
|
+
(0, mobx_1.makeObservable)(this, {
|
|
102
|
+
getUnifiedPromise: mobx_1.action,
|
|
103
|
+
isIdle: mobx_1.observable,
|
|
104
|
+
isInvalid: mobx_1.observable,
|
|
105
|
+
submitSuccess: mobx_1.action,
|
|
106
|
+
setSuccess: mobx_1.action,
|
|
107
|
+
setError: mobx_1.action,
|
|
108
|
+
setLoading: mobx_1.action,
|
|
109
|
+
submitError: mobx_1.action,
|
|
110
|
+
startLoading: mobx_1.action,
|
|
111
|
+
invalidate: mobx_1.action,
|
|
112
|
+
});
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
exports.AuxiliaryQuery = AuxiliaryQuery;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from './AuxiliaryQuery';
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __exportStar = (this && this.__exportStar) || function(m, exports) {
|
|
14
|
+
for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
|
|
15
|
+
};
|
|
16
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
17
|
+
__exportStar(require("./AuxiliaryQuery"), exports);
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
import { StorageFactory } from '../StorageFactory';
|
|
2
|
+
/**
|
|
3
|
+
* Хранилище данных, предназначено для обеспечения единого интерфейса при работе с данными
|
|
4
|
+
*/
|
|
5
|
+
export declare class DataStorage<TData> {
|
|
6
|
+
/**
|
|
7
|
+
* Поле, отвечающее за непосредственное хранение данных
|
|
8
|
+
*/
|
|
9
|
+
private internalData?;
|
|
10
|
+
constructor();
|
|
11
|
+
/**
|
|
12
|
+
* Флаг, отображающий наличие данных
|
|
13
|
+
*/
|
|
14
|
+
get hasData(): boolean;
|
|
15
|
+
/**
|
|
16
|
+
* Метод для установки данных
|
|
17
|
+
*/
|
|
18
|
+
setData: (value: TData) => void;
|
|
19
|
+
/**
|
|
20
|
+
* Геттер данных
|
|
21
|
+
*/
|
|
22
|
+
get data(): TData | undefined;
|
|
23
|
+
}
|
|
24
|
+
/**
|
|
25
|
+
* Фабрика ответственная за создание и хранение экземляров хранилищ
|
|
26
|
+
*/
|
|
27
|
+
export declare class DataStorageFactory extends StorageFactory<DataStorage<unknown>> {
|
|
28
|
+
constructor();
|
|
29
|
+
/**
|
|
30
|
+
* Фабричный метод получения/создания инстанса хранилища по ключу
|
|
31
|
+
*/
|
|
32
|
+
getStorage: <TData>(keyHash: string) => DataStorage<TData>;
|
|
33
|
+
}
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.DataStorageFactory = exports.DataStorage = void 0;
|
|
4
|
+
const mobx_1 = require("mobx");
|
|
5
|
+
const StorageFactory_1 = require("../StorageFactory");
|
|
6
|
+
/**
|
|
7
|
+
* Хранилище данных, предназначено для обеспечения единого интерфейса при работе с данными
|
|
8
|
+
*/
|
|
9
|
+
class DataStorage {
|
|
10
|
+
constructor() {
|
|
11
|
+
/**
|
|
12
|
+
* Поле, отвечающее за непосредственное хранение данных
|
|
13
|
+
*/
|
|
14
|
+
this.internalData = undefined;
|
|
15
|
+
/**
|
|
16
|
+
* Метод для установки данных
|
|
17
|
+
*/
|
|
18
|
+
this.setData = (value) => {
|
|
19
|
+
this.internalData = value;
|
|
20
|
+
};
|
|
21
|
+
(0, mobx_1.makeAutoObservable)(this);
|
|
22
|
+
}
|
|
23
|
+
/**
|
|
24
|
+
* Флаг, отображающий наличие данных
|
|
25
|
+
*/
|
|
26
|
+
get hasData() {
|
|
27
|
+
return Boolean(this.internalData);
|
|
28
|
+
}
|
|
29
|
+
/**
|
|
30
|
+
* Геттер данных
|
|
31
|
+
*/
|
|
32
|
+
get data() {
|
|
33
|
+
return this.internalData;
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
exports.DataStorage = DataStorage;
|
|
37
|
+
/**
|
|
38
|
+
* Фабрика ответственная за создание и хранение экземляров хранилищ
|
|
39
|
+
*/
|
|
40
|
+
class DataStorageFactory extends StorageFactory_1.StorageFactory {
|
|
41
|
+
constructor() {
|
|
42
|
+
super(() => new DataStorage());
|
|
43
|
+
/**
|
|
44
|
+
* Фабричный метод получения/создания инстанса хранилища по ключу
|
|
45
|
+
*/
|
|
46
|
+
this.getStorage = (keyHash) => {
|
|
47
|
+
return this.getInternalStorage(keyHash);
|
|
48
|
+
};
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
exports.DataStorageFactory = DataStorageFactory;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from './DataStorage';
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __exportStar = (this && this.__exportStar) || function(m, exports) {
|
|
14
|
+
for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
|
|
15
|
+
};
|
|
16
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
17
|
+
__exportStar(require("./DataStorage"), exports);
|
|
@@ -0,0 +1,135 @@
|
|
|
1
|
+
import type { FetchPolicy, QueryBaseActions, Sync, SyncParams } from '../types';
|
|
2
|
+
import { AuxiliaryQuery } from '../AuxiliaryQuery';
|
|
3
|
+
import type { DataStorage } from '../DataStorage';
|
|
4
|
+
import { QueryContainer } from '../QueryContainer';
|
|
5
|
+
import { type StatusStorage } from '../StatusStorage';
|
|
6
|
+
export declare const DEFAULT_INFINITE_ITEMS_COUNT = 30;
|
|
7
|
+
export type InfiniteParams = {
|
|
8
|
+
offset: number;
|
|
9
|
+
count: number;
|
|
10
|
+
};
|
|
11
|
+
/**
|
|
12
|
+
* Исполнитель запроса, ожидается,
|
|
13
|
+
* что будет использоваться что-то возвращающее массив данных
|
|
14
|
+
*/
|
|
15
|
+
export type InfiniteExecutor<TResult> = (params: InfiniteParams) => Promise<Array<TResult>>;
|
|
16
|
+
export type InfiniteQueryParams<TResult, TError, TIsBackground extends boolean = false> = {
|
|
17
|
+
/**
|
|
18
|
+
* Количество запрашиваемых элементов
|
|
19
|
+
* @default 30
|
|
20
|
+
*/
|
|
21
|
+
incrementCount?: number;
|
|
22
|
+
/**
|
|
23
|
+
* Обработчик ошибки, вызываемый по умолчанию
|
|
24
|
+
*/
|
|
25
|
+
onError?: SyncParams<TResult, TError>['onError'];
|
|
26
|
+
/**
|
|
27
|
+
* Флаг, отвечающий за автоматический запрос данных при обращении к полю data
|
|
28
|
+
*/
|
|
29
|
+
enabledAutoFetch?: boolean;
|
|
30
|
+
/**
|
|
31
|
+
* Инстанс хранилища основных статусов
|
|
32
|
+
*/
|
|
33
|
+
statusStorage: StatusStorage<TError>;
|
|
34
|
+
/**
|
|
35
|
+
* Политика получения данных.
|
|
36
|
+
* @enum cache-first - данные сначала берутся из кеша, если их нет, тогда идет обращение к сети, ответ записывается в кэш
|
|
37
|
+
* @enum network-only - данные всегда берутся из сети, при этом ответ записывается в кэш
|
|
38
|
+
*/
|
|
39
|
+
fetchPolicy?: FetchPolicy;
|
|
40
|
+
/**
|
|
41
|
+
* Инстанс хранилища данных
|
|
42
|
+
*/
|
|
43
|
+
dataStorage: DataStorage<TResult[]>;
|
|
44
|
+
/**
|
|
45
|
+
* Инстанс хранилища фоновых статусов
|
|
46
|
+
*/
|
|
47
|
+
backgroundStatusStorage?: TIsBackground extends true ? StatusStorage<TError> : null | undefined;
|
|
48
|
+
/**
|
|
49
|
+
* Колбэк, вызываемый при успешном завершении запроса, подразумевается использование, для подтверждения валидности данных, чтобы квери не был удален из памяти
|
|
50
|
+
*/
|
|
51
|
+
submitValidity?: () => void;
|
|
52
|
+
};
|
|
53
|
+
/**
|
|
54
|
+
* Квери для работы с инфинити запросами,
|
|
55
|
+
* которые должны быть закешированы,
|
|
56
|
+
*/
|
|
57
|
+
export declare class InfiniteQuery<TResult, TError = void, TIsBackground extends boolean = false> extends QueryContainer<TError, AuxiliaryQuery<Array<TResult>, TError>, TIsBackground> implements QueryBaseActions<Array<TResult>, TError> {
|
|
58
|
+
private readonly executor;
|
|
59
|
+
/**
|
|
60
|
+
* Счетчик отступа для инфинити запроса
|
|
61
|
+
*/
|
|
62
|
+
private offset;
|
|
63
|
+
/**
|
|
64
|
+
* Количество запрашиваемых элементов
|
|
65
|
+
*/
|
|
66
|
+
private readonly incrementCount;
|
|
67
|
+
/**
|
|
68
|
+
* Хранилище данных, для обеспечения возможности синхронизации данных между разными инстансами
|
|
69
|
+
*/
|
|
70
|
+
private storage;
|
|
71
|
+
/**
|
|
72
|
+
* Флаг того, что мы достигли предела запрашиваемых элементов
|
|
73
|
+
*/
|
|
74
|
+
isEndReached: boolean;
|
|
75
|
+
/**
|
|
76
|
+
* Обработчик ошибки, вызываемый по умолчанию
|
|
77
|
+
*/
|
|
78
|
+
private defaultOnError?;
|
|
79
|
+
/**
|
|
80
|
+
* Флаг, отвечающий за автоматический запрос данных при обращении к полю data
|
|
81
|
+
*/
|
|
82
|
+
private enabledAutoFetch?;
|
|
83
|
+
/**
|
|
84
|
+
* Стандартное поведение политики кеширования
|
|
85
|
+
*/
|
|
86
|
+
private readonly defaultFetchPolicy?;
|
|
87
|
+
/**
|
|
88
|
+
* Колбэк, вызываемый при успешном завершении запроса, подразумевается использование, для подтверждения валидности данных, чтобы квери не был удален из памяти
|
|
89
|
+
*/
|
|
90
|
+
private readonly submitValidity?;
|
|
91
|
+
constructor(executor: InfiniteExecutor<TResult>, { incrementCount, onError, enabledAutoFetch, fetchPolicy, dataStorage, statusStorage, backgroundStatusStorage, submitValidity, }: InfiniteQueryParams<TResult, TError, TIsBackground>);
|
|
92
|
+
private get isNetworkOnly();
|
|
93
|
+
/**
|
|
94
|
+
* Обработчик успешного запроса, проверяет что мы достигли предела
|
|
95
|
+
*/
|
|
96
|
+
private submitSuccess;
|
|
97
|
+
/**
|
|
98
|
+
* Форс метод для установки данных
|
|
99
|
+
*/
|
|
100
|
+
forceUpdate: (data: TResult[]) => void;
|
|
101
|
+
/**
|
|
102
|
+
* Метод для обогащения параметров текущими значениями для инфинити
|
|
103
|
+
*/
|
|
104
|
+
private get infiniteExecutor();
|
|
105
|
+
/**
|
|
106
|
+
* Метод для инвалидации данных
|
|
107
|
+
*/
|
|
108
|
+
invalidate: () => void;
|
|
109
|
+
/**
|
|
110
|
+
* Метод для запроса следующего набора данных
|
|
111
|
+
*/
|
|
112
|
+
fetchMore: () => void;
|
|
113
|
+
/**
|
|
114
|
+
* Синхронный метод получения данных
|
|
115
|
+
*/
|
|
116
|
+
sync: Sync<Array<TResult>, TError>;
|
|
117
|
+
/**
|
|
118
|
+
* Метод для переиспользования синхронной логики запроса
|
|
119
|
+
*/
|
|
120
|
+
private proceedSync;
|
|
121
|
+
/**
|
|
122
|
+
* Асинхронный метод получения данных,
|
|
123
|
+
* подходит для изменения параметров запроса(фильтров),
|
|
124
|
+
* при котором будет сброшен offset,
|
|
125
|
+
* предполагается, что нужно будет самостоятельно обрабатывать ошибку
|
|
126
|
+
*/
|
|
127
|
+
async: () => Promise<TResult[]>;
|
|
128
|
+
/**
|
|
129
|
+
* Вычисляемое свойство, содержащее реактивные данные,
|
|
130
|
+
* благодаря mobx, при изменении isInvalid, свойство будет вычисляться заново,
|
|
131
|
+
* следовательно, стриггерится условие невалидности,
|
|
132
|
+
* и начнется запрос, в результате которого, данные обновятся
|
|
133
|
+
*/
|
|
134
|
+
get data(): TResult[] | undefined;
|
|
135
|
+
}
|
|
@@ -0,0 +1,169 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.InfiniteQuery = exports.DEFAULT_INFINITE_ITEMS_COUNT = void 0;
|
|
4
|
+
const mobx_1 = require("mobx");
|
|
5
|
+
const AuxiliaryQuery_1 = require("../AuxiliaryQuery");
|
|
6
|
+
const QueryContainer_1 = require("../QueryContainer");
|
|
7
|
+
exports.DEFAULT_INFINITE_ITEMS_COUNT = 30;
|
|
8
|
+
/**
|
|
9
|
+
* Квери для работы с инфинити запросами,
|
|
10
|
+
* которые должны быть закешированы,
|
|
11
|
+
*/
|
|
12
|
+
class InfiniteQuery extends QueryContainer_1.QueryContainer {
|
|
13
|
+
constructor(executor, { incrementCount = exports.DEFAULT_INFINITE_ITEMS_COUNT, onError, enabledAutoFetch, fetchPolicy, dataStorage, statusStorage, backgroundStatusStorage = null, submitValidity, }) {
|
|
14
|
+
super(statusStorage, backgroundStatusStorage, new AuxiliaryQuery_1.AuxiliaryQuery(statusStorage, backgroundStatusStorage));
|
|
15
|
+
this.executor = executor;
|
|
16
|
+
/**
|
|
17
|
+
* Счетчик отступа для инфинити запроса
|
|
18
|
+
*/
|
|
19
|
+
this.offset = 0;
|
|
20
|
+
/**
|
|
21
|
+
* Флаг того, что мы достигли предела запрашиваемых элементов
|
|
22
|
+
*/
|
|
23
|
+
this.isEndReached = false;
|
|
24
|
+
/**
|
|
25
|
+
* Обработчик успешного запроса, проверяет что мы достигли предела
|
|
26
|
+
*/
|
|
27
|
+
this.submitSuccess = (result, onSuccess, isIncrement) => {
|
|
28
|
+
var _a;
|
|
29
|
+
onSuccess === null || onSuccess === void 0 ? void 0 : onSuccess(result);
|
|
30
|
+
if (isIncrement && this.storage.hasData) {
|
|
31
|
+
this.storage.setData([...this.storage.data, ...result]);
|
|
32
|
+
}
|
|
33
|
+
else {
|
|
34
|
+
this.storage.setData(result);
|
|
35
|
+
(_a = this.submitValidity) === null || _a === void 0 ? void 0 : _a.call(this);
|
|
36
|
+
}
|
|
37
|
+
// убеждаемся что результат запроса действительно массив,
|
|
38
|
+
// и если количество элементов в ответе меньше,
|
|
39
|
+
// чем запрашивалось, значит у бэка их больше нет,
|
|
40
|
+
// другими словами мы допускаем что, может произойти лишний запрос,
|
|
41
|
+
// когда последняя отданная страница содержит ровно то количество,
|
|
42
|
+
// сколько может содержать страница, а следующая уже просто пустая.
|
|
43
|
+
if (Array.isArray(result) && result.length < this.incrementCount) {
|
|
44
|
+
// включаем флаг достижения предела
|
|
45
|
+
this.isEndReached = true;
|
|
46
|
+
}
|
|
47
|
+
};
|
|
48
|
+
/**
|
|
49
|
+
* Форс метод для установки данных
|
|
50
|
+
*/
|
|
51
|
+
this.forceUpdate = (data) => {
|
|
52
|
+
this.auxiliary.submitSuccess();
|
|
53
|
+
this.submitSuccess(data);
|
|
54
|
+
};
|
|
55
|
+
/**
|
|
56
|
+
* Метод для инвалидации данных
|
|
57
|
+
*/
|
|
58
|
+
this.invalidate = () => {
|
|
59
|
+
this.auxiliary.invalidate();
|
|
60
|
+
};
|
|
61
|
+
/**
|
|
62
|
+
* Метод для запроса следующего набора данных
|
|
63
|
+
*/
|
|
64
|
+
this.fetchMore = () => {
|
|
65
|
+
// если мы еще не достигли предела
|
|
66
|
+
if (!this.isEndReached && this.storage.data) {
|
|
67
|
+
// прибавляем к офсету число запрашиваемых элементов
|
|
68
|
+
this.offset += this.incrementCount;
|
|
69
|
+
// запускаем запрос с последними параметрами, и флагом необходимости инкремента
|
|
70
|
+
this.auxiliary
|
|
71
|
+
.getUnifiedPromise(this.infiniteExecutor, (resData) => {
|
|
72
|
+
this.submitSuccess(resData, undefined, true);
|
|
73
|
+
})
|
|
74
|
+
.catch((e) => { var _a; return (_a = this.defaultOnError) === null || _a === void 0 ? void 0 : _a.call(this, e); });
|
|
75
|
+
}
|
|
76
|
+
};
|
|
77
|
+
/**
|
|
78
|
+
* Синхронный метод получения данных
|
|
79
|
+
*/
|
|
80
|
+
this.sync = (params) => {
|
|
81
|
+
const isInstanceAllow = !(this.isLoading || this.isSuccess);
|
|
82
|
+
if (this.isNetworkOnly || this.auxiliary.isInvalid || isInstanceAllow) {
|
|
83
|
+
this.proceedSync(params);
|
|
84
|
+
}
|
|
85
|
+
};
|
|
86
|
+
/**
|
|
87
|
+
* Метод для переиспользования синхронной логики запроса
|
|
88
|
+
*/
|
|
89
|
+
this.proceedSync = ({ onSuccess, onError, } = {}) => {
|
|
90
|
+
this.offset = 0;
|
|
91
|
+
this.isEndReached = false;
|
|
92
|
+
this.auxiliary
|
|
93
|
+
.getUnifiedPromise(this.infiniteExecutor, (resData) => {
|
|
94
|
+
this.submitSuccess(resData, onSuccess);
|
|
95
|
+
})
|
|
96
|
+
.catch((e) => {
|
|
97
|
+
var _a;
|
|
98
|
+
if (onError) {
|
|
99
|
+
onError(e);
|
|
100
|
+
}
|
|
101
|
+
else {
|
|
102
|
+
(_a = this.defaultOnError) === null || _a === void 0 ? void 0 : _a.call(this, e);
|
|
103
|
+
}
|
|
104
|
+
});
|
|
105
|
+
};
|
|
106
|
+
/**
|
|
107
|
+
* Асинхронный метод получения данных,
|
|
108
|
+
* подходит для изменения параметров запроса(фильтров),
|
|
109
|
+
* при котором будет сброшен offset,
|
|
110
|
+
* предполагается, что нужно будет самостоятельно обрабатывать ошибку
|
|
111
|
+
*/
|
|
112
|
+
this.async = () => {
|
|
113
|
+
if (!this.isNetworkOnly && this.isSuccess && !this.auxiliary.isInvalid) {
|
|
114
|
+
return Promise.resolve(this.storage.data);
|
|
115
|
+
}
|
|
116
|
+
this.offset = 0;
|
|
117
|
+
this.isEndReached = false;
|
|
118
|
+
return this.auxiliary.getUnifiedPromise(this.infiniteExecutor, this.submitSuccess);
|
|
119
|
+
};
|
|
120
|
+
this.storage = dataStorage;
|
|
121
|
+
this.incrementCount = incrementCount;
|
|
122
|
+
this.defaultOnError = onError;
|
|
123
|
+
this.enabledAutoFetch = enabledAutoFetch;
|
|
124
|
+
this.defaultFetchPolicy = fetchPolicy;
|
|
125
|
+
this.submitValidity = submitValidity;
|
|
126
|
+
(0, mobx_1.makeObservable)(this, {
|
|
127
|
+
data: mobx_1.computed,
|
|
128
|
+
infiniteExecutor: mobx_1.computed,
|
|
129
|
+
forceUpdate: mobx_1.action,
|
|
130
|
+
async: mobx_1.action,
|
|
131
|
+
sync: mobx_1.action,
|
|
132
|
+
fetchMore: mobx_1.action,
|
|
133
|
+
submitSuccess: mobx_1.action,
|
|
134
|
+
isEndReached: mobx_1.observable,
|
|
135
|
+
});
|
|
136
|
+
}
|
|
137
|
+
get isNetworkOnly() {
|
|
138
|
+
return this.defaultFetchPolicy === 'network-only';
|
|
139
|
+
}
|
|
140
|
+
/**
|
|
141
|
+
* Метод для обогащения параметров текущими значениями для инфинити
|
|
142
|
+
*/
|
|
143
|
+
get infiniteExecutor() {
|
|
144
|
+
return () => this.executor({
|
|
145
|
+
offset: this.offset,
|
|
146
|
+
count: this.incrementCount,
|
|
147
|
+
});
|
|
148
|
+
}
|
|
149
|
+
/**
|
|
150
|
+
* Вычисляемое свойство, содержащее реактивные данные,
|
|
151
|
+
* благодаря mobx, при изменении isInvalid, свойство будет вычисляться заново,
|
|
152
|
+
* следовательно, стриггерится условие невалидности,
|
|
153
|
+
* и начнется запрос, в результате которого, данные обновятся
|
|
154
|
+
*/
|
|
155
|
+
get data() {
|
|
156
|
+
const shouldSync = this.enabledAutoFetch &&
|
|
157
|
+
!this.isSuccess &&
|
|
158
|
+
!this.isLoading &&
|
|
159
|
+
!this.isError;
|
|
160
|
+
if (this.auxiliary.isInvalid || shouldSync) {
|
|
161
|
+
// т.к. при вызове апдейта, изменяются флаги, на которые подписан data,
|
|
162
|
+
// нужно вызывать этот экшн асинхронно
|
|
163
|
+
(0, mobx_1.when)(() => true, this.proceedSync);
|
|
164
|
+
}
|
|
165
|
+
// возвращаем имеющиеся данные
|
|
166
|
+
return this.storage.data;
|
|
167
|
+
}
|
|
168
|
+
}
|
|
169
|
+
exports.InfiniteQuery = InfiniteQuery;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from './InfiniteQuery';
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __exportStar = (this && this.__exportStar) || function(m, exports) {
|
|
14
|
+
for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
|
|
15
|
+
};
|
|
16
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
17
|
+
__exportStar(require("./InfiniteQuery"), exports);
|