@astral/mobx-query 1.4.0 → 1.5.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.
@@ -1,56 +1,55 @@
1
+ import { type StatusStorage } from '../StatusStorage';
1
2
  /**
2
- * @description испольнитель запроса
3
+ * испольнитель запроса
3
4
  */
4
5
  type Executor<TResult> = () => Promise<TResult>;
5
6
  /**
6
- * @description вспомогательное хранилище данных, для композиции в Query сторах,
7
+ * вспомогательное хранилище данных, для композиции в Query сторах,
7
8
  * содержащее флаги загрузки и ошибки,
8
9
  * колбэки на успешный запрос и на ошибку,
9
10
  * данные последней ошибки,
10
11
  * а так же, управляющее синглтон промисом.
11
12
  */
12
13
  export declare class AuxiliaryQuery<TResult, TError = void> {
13
- /**
14
- * @description флаг обозначающий загрузку данных
15
- */
16
- isLoading: boolean;
17
- /**
18
- * @description флаг обозначающий, что последний запрос был зафейлен
19
- */
20
- isError: boolean;
21
- /**
22
- * @description данные о последней ошибке
23
- */
24
- error?: TError;
25
- /**
26
- * @description флаг, обозначающий успешность завершения последнего запроса
27
- */
28
- isSuccess: boolean;
14
+ private readonly statusStorage;
15
+ private readonly backgroundStatusStorage;
29
16
  /**
30
17
  * флаг, обозначающий простаивание, т.е. запроса еще не было
31
18
  */
32
19
  isIdle: boolean;
33
20
  /**
34
- * @description единый промис, для устранения гонки запросов
21
+ * единый промис, для устранения гонки запросов
22
+ */
23
+ private unifiedPromise?;
24
+ /**
25
+ * флаг, по которому реактивно определяется необходимость запуска инвалидации
35
26
  */
36
- unifiedPromise?: Promise<TResult>;
37
- constructor();
27
+ isInvalid: boolean;
28
+ constructor(statusStorage: StatusStorage<TError>, backgroundStatusStorage: StatusStorage<TError> | null);
38
29
  /**
39
- * @description метод ответственный за создание единого промиса,
30
+ * метод ответственный за создание единого промиса,
40
31
  * для устранения гонки запросов
41
32
  */
42
33
  getUnifiedPromise: (executor: Executor<TResult>) => Promise<TResult>;
34
+ private setSuccess;
35
+ private checkBackgroundAndSet;
43
36
  /**
44
- * @description обработчик успешного ответа
37
+ * обработчик успешного ответа
45
38
  */
46
39
  submitSuccess: () => void;
40
+ private setError;
47
41
  /**
48
- * @description обработчик ошибки
42
+ * обработчик ошибки
49
43
  */
50
- submitError: (e: TError) => void;
44
+ submitError: (error: TError) => void;
45
+ private setLoading;
51
46
  /**
52
- * @description метод, вызываемый в самом начале запроса, чтобы сбросить флаги в соответствующее значение
47
+ * метод, вызываемый в самом начале запроса, чтобы сбросить флаги в соответствующее значение
53
48
  */
54
49
  startLoading: () => void;
50
+ /**
51
+ * метод для инвалидации данных
52
+ */
53
+ invalidate: () => void;
55
54
  }
56
55
  export {};
@@ -1,35 +1,25 @@
1
- import { makeAutoObservable, runInAction } from 'mobx';
1
+ import { action, makeObservable, observable, runInAction } from 'mobx';
2
2
  /**
3
- * @description вспомогательное хранилище данных, для композиции в Query сторах,
3
+ * вспомогательное хранилище данных, для композиции в Query сторах,
4
4
  * содержащее флаги загрузки и ошибки,
5
5
  * колбэки на успешный запрос и на ошибку,
6
6
  * данные последней ошибки,
7
7
  * а так же, управляющее синглтон промисом.
8
8
  */
9
9
  export class AuxiliaryQuery {
10
- constructor() {
11
- /**
12
- * @description флаг обозначающий загрузку данных
13
- */
14
- this.isLoading = false;
15
- /**
16
- * @description флаг обозначающий, что последний запрос был зафейлен
17
- */
18
- this.isError = false;
19
- /**
20
- * @description данные о последней ошибке
21
- */
22
- this.error = undefined;
23
- /**
24
- * @description флаг, обозначающий успешность завершения последнего запроса
25
- */
26
- this.isSuccess = false;
10
+ constructor(statusStorage, backgroundStatusStorage) {
11
+ this.statusStorage = statusStorage;
12
+ this.backgroundStatusStorage = backgroundStatusStorage;
27
13
  /**
28
14
  * флаг, обозначающий простаивание, т.е. запроса еще не было
29
15
  */
30
16
  this.isIdle = true;
31
17
  /**
32
- * @description метод ответственный за создание единого промиса,
18
+ * флаг, по которому реактивно определяется необходимость запуска инвалидации
19
+ */
20
+ this.isInvalid = false;
21
+ /**
22
+ * метод ответственный за создание единого промиса,
33
23
  * для устранения гонки запросов
34
24
  */
35
25
  this.getUnifiedPromise = (executor) => {
@@ -50,36 +40,71 @@ export class AuxiliaryQuery {
50
40
  .finally(() => {
51
41
  this.unifiedPromise = undefined;
52
42
  runInAction(() => {
53
- this.isLoading = false;
43
+ this.statusStorage.isLoading = false;
54
44
  });
55
45
  });
56
46
  }
57
47
  return this.unifiedPromise;
58
48
  };
49
+ this.setSuccess = (storage) => {
50
+ storage.isError = false;
51
+ storage.isSuccess = true;
52
+ };
53
+ this.checkBackgroundAndSet = (setStorage) => {
54
+ if (this.backgroundStatusStorage && this.statusStorage.isSuccess) {
55
+ setStorage(this.backgroundStatusStorage);
56
+ }
57
+ else {
58
+ setStorage(this.statusStorage);
59
+ }
60
+ };
59
61
  /**
60
- * @description обработчик успешного ответа
62
+ * обработчик успешного ответа
61
63
  */
62
64
  this.submitSuccess = () => {
63
- this.isError = false;
64
- this.isSuccess = true;
65
+ this.checkBackgroundAndSet(this.setSuccess);
66
+ this.isInvalid = false;
67
+ };
68
+ this.setError = (storage, error) => {
69
+ storage.isSuccess = false;
70
+ storage.isError = true;
71
+ storage.error = error;
65
72
  };
66
73
  /**
67
- * @description обработчик ошибки
74
+ * обработчик ошибки
68
75
  */
69
- this.submitError = (e) => {
70
- this.isSuccess = false;
71
- this.isError = true;
72
- this.error = e;
76
+ this.submitError = (error) => {
77
+ this.checkBackgroundAndSet((storage) => this.setError(storage, error));
78
+ };
79
+ this.setLoading = (storage) => {
80
+ storage.isLoading = true;
81
+ storage.isError = false;
82
+ storage.isSuccess = false;
73
83
  };
74
84
  /**
75
- * @description метод, вызываемый в самом начале запроса, чтобы сбросить флаги в соответствующее значение
85
+ * метод, вызываемый в самом начале запроса, чтобы сбросить флаги в соответствующее значение
76
86
  */
77
87
  this.startLoading = () => {
78
88
  this.isIdle = false;
79
- this.isLoading = true;
80
- this.isError = false;
81
- this.isSuccess = false;
89
+ this.checkBackgroundAndSet(this.setLoading);
90
+ };
91
+ /**
92
+ * метод для инвалидации данных
93
+ */
94
+ this.invalidate = () => {
95
+ this.isInvalid = true;
82
96
  };
83
- makeAutoObservable(this, { unifiedPromise: false });
97
+ makeObservable(this, {
98
+ getUnifiedPromise: action,
99
+ isIdle: observable,
100
+ isInvalid: observable,
101
+ submitSuccess: action,
102
+ setSuccess: action,
103
+ setError: action,
104
+ setLoading: action,
105
+ submitError: action,
106
+ startLoading: action,
107
+ invalidate: action,
108
+ });
84
109
  }
85
110
  }
@@ -1,36 +1,34 @@
1
1
  import type { CacheKey } from '../types';
2
+ import { StorageFactory } from '../StorageFactory';
2
3
  /**
3
- * @description хранилище данных, предназначено для обеспечения единого интерфейса при работе с данными
4
+ * хранилище данных, предназначено для обеспечения единого интерфейса при работе с данными
4
5
  */
5
6
  export declare class DataStorage<TData> {
6
7
  /**
7
- * @description поле, отвечающее за непосредственное хранение данных
8
+ * поле, отвечающее за непосредственное хранение данных
8
9
  */
9
10
  private internalData?;
10
11
  constructor();
11
12
  /**
12
- * @description флаг, отображающий наличие данных
13
+ * флаг, отображающий наличие данных
13
14
  */
14
15
  get hasData(): boolean;
15
16
  /**
16
- * @description метод для установки данных
17
+ * метод для установки данных
17
18
  */
18
19
  setData: (value: TData) => void;
19
20
  /**
20
- * @description геттер данных
21
+ * геттер данных
21
22
  */
22
23
  get data(): TData | undefined;
23
24
  }
24
25
  /**
25
- * @description фабрика ответственная за создание и хранение экземляров хранилищ
26
+ * фабрика ответственная за создание и хранение экземляров хранилищ
26
27
  */
27
- export declare class DataStorageFactory {
28
- /**
29
- * @description Map хранящий инстансы хранилищ по хэшу ключа
30
- */
31
- private storageMap;
28
+ export declare class DataStorageFactory extends StorageFactory<DataStorage<unknown>> {
29
+ constructor();
32
30
  /**
33
- * @description фабричный метод получения/создания инстанса хранилища по ключу
31
+ * фабричный метод получения/создания инстанса хранилища по ключу
34
32
  */
35
33
  getStorage: <TData>(key: CacheKey[]) => DataStorage<TData>;
36
34
  }
@@ -1,15 +1,16 @@
1
1
  import { makeAutoObservable } from 'mobx';
2
+ import { StorageFactory } from '../StorageFactory';
2
3
  /**
3
- * @description хранилище данных, предназначено для обеспечения единого интерфейса при работе с данными
4
+ * хранилище данных, предназначено для обеспечения единого интерфейса при работе с данными
4
5
  */
5
6
  export class DataStorage {
6
7
  constructor() {
7
8
  /**
8
- * @description поле, отвечающее за непосредственное хранение данных
9
+ * поле, отвечающее за непосредственное хранение данных
9
10
  */
10
11
  this.internalData = undefined;
11
12
  /**
12
- * @description метод для установки данных
13
+ * метод для установки данных
13
14
  */
14
15
  this.setData = (value) => {
15
16
  this.internalData = value;
@@ -17,36 +18,29 @@ export class DataStorage {
17
18
  makeAutoObservable(this);
18
19
  }
19
20
  /**
20
- * @description флаг, отображающий наличие данных
21
+ * флаг, отображающий наличие данных
21
22
  */
22
23
  get hasData() {
23
24
  return Boolean(this.internalData);
24
25
  }
25
26
  /**
26
- * @description геттер данных
27
+ * геттер данных
27
28
  */
28
29
  get data() {
29
30
  return this.internalData;
30
31
  }
31
32
  }
32
33
  /**
33
- * @description фабрика ответственная за создание и хранение экземляров хранилищ
34
+ * фабрика ответственная за создание и хранение экземляров хранилищ
34
35
  */
35
- export class DataStorageFactory {
36
+ export class DataStorageFactory extends StorageFactory {
36
37
  constructor() {
38
+ super(() => new DataStorage());
37
39
  /**
38
- * @description Map хранящий инстансы хранилищ по хэшу ключа
39
- */
40
- this.storageMap = new Map();
41
- /**
42
- * @description фабричный метод получения/создания инстанса хранилища по ключу
40
+ * фабричный метод получения/создания инстанса хранилища по ключу
43
41
  */
44
42
  this.getStorage = (key) => {
45
- const keyHash = JSON.stringify(key);
46
- if (!this.storageMap.has(keyHash)) {
47
- this.storageMap.set(keyHash, new DataStorage());
48
- }
49
- return this.storageMap.get(keyHash);
43
+ return this.getInternalStorage(key);
50
44
  };
51
45
  }
52
46
  }
@@ -1,140 +1,122 @@
1
1
  import type { FetchPolicy, QueryBaseActions, Sync, SyncParams } from '../types';
2
+ import { AuxiliaryQuery } from '../AuxiliaryQuery';
2
3
  import type { DataStorage } from '../DataStorage';
4
+ import { QueryContainer } from '../QueryContainer';
5
+ import { type StatusStorage } from '../StatusStorage';
3
6
  export declare const DEFAULT_INFINITE_ITEMS_COUNT = 30;
4
7
  export type InfiniteParams = {
5
8
  offset: number;
6
9
  count: number;
7
10
  };
8
11
  /**
9
- * @description исполнитель запроса, ожидается,
12
+ * исполнитель запроса, ожидается,
10
13
  * что будет использоваться что-то возвращающее массив данных
11
14
  */
12
15
  export type InfiniteExecutor<TResult> = (params: InfiniteParams) => Promise<Array<TResult>>;
13
- export type InfiniteQueryParams<TResult, TError> = {
16
+ export type InfiniteQueryParams<TResult, TError, TIsBackground extends boolean = false> = {
14
17
  /**
15
- * @description количество запрашиваемых элементов
18
+ * количество запрашиваемых элементов
16
19
  * @default 30
17
20
  */
18
21
  incrementCount?: number;
19
22
  /**
20
- * @description обработчик ошибки, вызываемый по умолчанию
23
+ * обработчик ошибки, вызываемый по умолчанию
21
24
  */
22
25
  onError?: SyncParams<TResult, TError>['onError'];
23
26
  /**
24
- * @description флаг, отвечающий за автоматический запрос данных при обращении к полю data
27
+ * флаг, отвечающий за автоматический запрос данных при обращении к полю data
25
28
  */
26
29
  enabledAutoFetch?: boolean;
30
+ /**
31
+ * инстанс хранилища основных статусов
32
+ */
33
+ statusStorage: StatusStorage<TError>;
27
34
  fetchPolicy?: FetchPolicy;
28
35
  /**
29
- * @description инстанс хранилища данных
36
+ * инстанс хранилища данных
30
37
  */
31
38
  dataStorage: DataStorage<TResult[]>;
39
+ /**
40
+ * инстанс хранилища фоновых статусов
41
+ */
42
+ backgroundStatusStorage?: TIsBackground extends true ? StatusStorage<TError> : null | undefined;
32
43
  };
33
44
  /**
34
- * @description стор для работы с инфинити запросами,
45
+ * стор для работы с инфинити запросами,
35
46
  * которые должны быть закешированы,
36
47
  */
37
- export declare class InfiniteQuery<TResult, TError = void> implements QueryBaseActions<Array<TResult>, TError> {
48
+ export declare class InfiniteQuery<TResult, TError = void, TIsBackground extends boolean = false> extends QueryContainer<TError, AuxiliaryQuery<Array<TResult>, TError>, TIsBackground> implements QueryBaseActions<Array<TResult>, TError> {
49
+ private readonly executor;
38
50
  /**
39
- * @description инстанс вспомогательного стора
40
- */
41
- private auxiliary;
42
- /**
43
- * @description счетчик отступа для инфинити запроса
51
+ * счетчик отступа для инфинити запроса
44
52
  */
45
53
  private offset;
46
54
  /**
47
- * @description количество запрашиваемых элементов
55
+ * количество запрашиваемых элементов
48
56
  */
49
57
  private readonly incrementCount;
50
58
  /**
51
- * @description исполнитель запроса, ожидается,
52
- * что будет использоваться что-то из слоя sources, возвращающее массив данных
53
- */
54
- private executor;
55
- /**
56
- * @description хранилище данных, для обеспечения возможности синхронизации данных между разными инстансами
59
+ * хранилище данных, для обеспечения возможности синхронизации данных между разными инстансами
57
60
  */
58
61
  private storage;
59
62
  /**
60
- * @description флаг того, что мы достигли предела запрашиваемых элементов
63
+ * флаг того, что мы достигли предела запрашиваемых элементов
61
64
  */
62
65
  isEndReached: boolean;
63
66
  /**
64
- * @description флаг необходимости выполнить обновления данных
65
- */
66
- private isInvalid;
67
- /**
68
- * @description обработчик ошибки, вызываемый по умолчанию
67
+ * обработчик ошибки, вызываемый по умолчанию
69
68
  */
70
69
  private defaultOnError?;
71
70
  /**
72
- * @description флаг, отвечающий за автоматический запрос данных при обращении к полю data
71
+ * флаг, отвечающий за автоматический запрос данных при обращении к полю data
73
72
  */
74
73
  private enabledAutoFetch?;
75
74
  /**
76
- * @description стандартное поведение политики кеширования
75
+ * стандартное поведение политики кеширования
77
76
  */
78
77
  private readonly defaultFetchPolicy?;
79
- constructor(executor: InfiniteExecutor<TResult>, { incrementCount, onError, enabledAutoFetch, fetchPolicy, dataStorage, }: InfiniteQueryParams<TResult, TError>);
78
+ constructor(executor: InfiniteExecutor<TResult>, { incrementCount, onError, enabledAutoFetch, fetchPolicy, dataStorage, statusStorage, backgroundStatusStorage, }: InfiniteQueryParams<TResult, TError, TIsBackground>);
80
79
  private get isNetworkOnly();
81
80
  /**
82
- * @description обработчик успешного запроса, проверяет что мы достигли предела
81
+ * обработчик успешного запроса, проверяет что мы достигли предела
83
82
  */
84
83
  private submitSuccess;
85
84
  /**
86
- * @description форс метод для установки данных
85
+ * форс метод для установки данных
87
86
  */
88
87
  forceUpdate: (data: TResult[]) => void;
89
88
  /**
90
- * @description метод для обогащения параметров текущими значениями для инфинити
89
+ * метод для обогащения параметров текущими значениями для инфинити
91
90
  */
92
91
  private get infiniteExecutor();
93
92
  /**
94
- * @description метод для инвалидации данных
93
+ * метод для инвалидации данных
95
94
  */
96
95
  invalidate: () => void;
97
96
  /**
98
- * @description метод для запроса следующего набора данных
97
+ * метод для запроса следующего набора данных
99
98
  */
100
99
  fetchMore: () => void;
101
100
  /**
102
- * @description синхронный метод получения данных
101
+ * синхронный метод получения данных
103
102
  */
104
103
  sync: Sync<Array<TResult>, TError>;
105
104
  /**
106
- * @description метод для переиспользования синхронной логики запроса
105
+ * метод для переиспользования синхронной логики запроса
107
106
  */
108
107
  private proceedSync;
109
108
  /**
110
- * @description aсинхронный метод получения данных,
109
+ * aсинхронный метод получения данных,
111
110
  * подходит для изменения параметров запроса(фильтров),
112
111
  * при котором будет сброшен offset,
113
112
  * предполагается, что нужно будет самостоятельно обрабатывать ошибку
114
113
  */
115
114
  async: () => Promise<TResult[]>;
116
115
  /**
117
- * @description вычисляемое свойство, содержащее реактивные данные,
116
+ * вычисляемое свойство, содержащее реактивные данные,
118
117
  * благодаря mobx, при изменении isInvalid, свойство будет вычисляться заново,
119
118
  * следовательно, стриггерится условие невалидности,
120
119
  * и начнется запрос, в результате которого, данные обновятся
121
120
  */
122
121
  get data(): TResult[] | undefined;
123
- /**
124
- * @description флаг загрузки данных
125
- */
126
- get isLoading(): boolean;
127
- /**
128
- * @description флаг обозначающий, что последний запрос был зафейлен
129
- */
130
- get isError(): boolean;
131
- /**
132
- * @description данные о последней ошибке
133
- */
134
- get error(): TError | undefined;
135
- /**
136
- * @description флаг обозначающий, что последний запрос был успешно завершен
137
- */
138
- get isSuccess(): boolean;
139
- get isIdle(): boolean;
140
122
  }