@astral/mobx-query 1.13.2 → 1.15.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.
@@ -11,6 +11,7 @@ export type InfiniteParams = {
11
11
  export type InfiniteDataStorage<TResult> = DataStorage<{
12
12
  data: TResult[];
13
13
  offset: number;
14
+ isEndReached: boolean;
14
15
  }>;
15
16
  /**
16
17
  * Исполнитель запроса, ожидается,
@@ -68,10 +69,6 @@ export declare class InfiniteQuery<TResult, TError = void, TIsBackground extends
68
69
  * Хранилище данных, для обеспечения возможности синхронизации данных между разными инстансами
69
70
  */
70
71
  private storage;
71
- /**
72
- * Флаг того, что мы достигли предела запрашиваемых элементов
73
- */
74
- isEndReached: boolean;
75
72
  /**
76
73
  * Обработчик ошибки, вызываемый по умолчанию
77
74
  */
@@ -98,6 +95,11 @@ export declare class InfiniteQuery<TResult, TError = void, TIsBackground extends
98
95
  * Обработчик успешного запроса, проверяет что мы достигли предела
99
96
  */
100
97
  private submitSuccess;
98
+ /**
99
+ * Флаг того, что мы достигли предела запрашиваемых элементов
100
+ */
101
+ get isEndReached(): boolean;
102
+ private calcIsEndReachedByResult;
101
103
  /**
102
104
  * Форс метод для установки данных
103
105
  */
@@ -1,4 +1,4 @@
1
- import { action, computed, makeObservable, observable, when } from 'mobx';
1
+ import { action, computed, makeObservable, when } from 'mobx';
2
2
  import { AuxiliaryQuery } from '../AuxiliaryQuery';
3
3
  import { QueryContainer } from '../QueryContainer';
4
4
  export const DEFAULT_INFINITE_ITEMS_COUNT = 30;
@@ -10,26 +10,19 @@ export class InfiniteQuery extends QueryContainer {
10
10
  constructor(executor, { incrementCount = DEFAULT_INFINITE_ITEMS_COUNT, onError, enabledAutoFetch, fetchPolicy, dataStorage, statusStorage, backgroundStatusStorage = null, submitValidity, }) {
11
11
  super(statusStorage, backgroundStatusStorage, new AuxiliaryQuery(statusStorage, backgroundStatusStorage));
12
12
  this.executor = executor;
13
- /**
14
- * Флаг того, что мы достигли предела запрашиваемых элементов
15
- */
16
- this.isEndReached = false;
17
13
  /**
18
14
  * Обработчик успешного запроса, проверяет что мы достигли предела
19
15
  */
20
- this.submitSuccess = (result, onSuccess, isIncrement) => {
16
+ this.submitSuccess = (result, isEndReached) => {
21
17
  var _a;
22
- onSuccess === null || onSuccess === void 0 ? void 0 : onSuccess(result);
23
- if (isIncrement && this.storage.hasData) {
24
- this.storage.setData((current) => ({
25
- offset: current === null || current === void 0 ? void 0 : current.offset,
26
- data: [...current === null || current === void 0 ? void 0 : current.data, ...result],
27
- }));
28
- }
29
- else {
30
- this.storage.setData({ offset: 0, data: result });
31
- (_a = this.submitValidity) === null || _a === void 0 ? void 0 : _a.call(this);
32
- }
18
+ this.storage.setData((current) => ({
19
+ offset: current === null || current === void 0 ? void 0 : current.offset,
20
+ data: result,
21
+ isEndReached,
22
+ }));
23
+ (_a = this.submitValidity) === null || _a === void 0 ? void 0 : _a.call(this);
24
+ };
25
+ this.calcIsEndReachedByResult = (result) => {
33
26
  // убеждаемся что результат запроса действительно массив,
34
27
  // и если количество элементов в ответе меньше,
35
28
  // чем запрашивалось, значит у бэка их больше нет,
@@ -37,9 +30,9 @@ export class InfiniteQuery extends QueryContainer {
37
30
  // когда последняя отданная страница содержит ровно то количество,
38
31
  // сколько может содержать страница, а следующая уже просто пустая.
39
32
  if (Array.isArray(result) && result.length < this.incrementCount) {
40
- // включаем флаг достижения предела
41
- this.isEndReached = true;
33
+ return true;
42
34
  }
35
+ return false;
43
36
  };
44
37
  /**
45
38
  * Форс метод для установки данных
@@ -48,10 +41,10 @@ export class InfiniteQuery extends QueryContainer {
48
41
  var _a;
49
42
  this.auxiliary.submitSuccess();
50
43
  if (typeof param === 'function') {
51
- this.submitSuccess(param((_a = this.storage.data) === null || _a === void 0 ? void 0 : _a.data));
44
+ this.submitSuccess(param((_a = this.storage.data) === null || _a === void 0 ? void 0 : _a.data), this.isEndReached);
52
45
  }
53
46
  else {
54
- this.submitSuccess(param);
47
+ this.submitSuccess(param, this.isEndReached);
55
48
  }
56
49
  };
57
50
  /**
@@ -72,12 +65,14 @@ export class InfiniteQuery extends QueryContainer {
72
65
  return ({
73
66
  offset: ((_a = current === null || current === void 0 ? void 0 : current.offset) !== null && _a !== void 0 ? _a : 0) + this.incrementCount,
74
67
  data: current === null || current === void 0 ? void 0 : current.data,
68
+ isEndReached: Boolean(current === null || current === void 0 ? void 0 : current.isEndReached),
75
69
  });
76
70
  });
77
71
  // запускаем запрос с последними параметрами, и флагом необходимости инкремента
78
72
  this.auxiliary
79
73
  .getUnifiedPromise(this.infiniteExecutor, (resData) => {
80
- this.submitSuccess(resData, undefined, true);
74
+ var _a;
75
+ this.submitSuccess([...(_a = this.storage.data) === null || _a === void 0 ? void 0 : _a.data, ...resData], this.calcIsEndReachedByResult(resData));
81
76
  })
82
77
  .catch((e) => { var _a; return (_a = this.defaultOnError) === null || _a === void 0 ? void 0 : _a.call(this, e); });
83
78
  }
@@ -100,11 +95,15 @@ export class InfiniteQuery extends QueryContainer {
100
95
  * Метод для переиспользования синхронной логики запроса
101
96
  */
102
97
  this.proceedSync = ({ onSuccess, onError, } = {}) => {
103
- this.storage.setData((current) => ({ offset: 0, data: current === null || current === void 0 ? void 0 : current.data }));
104
- this.isEndReached = false;
98
+ this.storage.setData((current) => ({
99
+ offset: 0,
100
+ data: current === null || current === void 0 ? void 0 : current.data,
101
+ isEndReached: false,
102
+ }));
105
103
  this.auxiliary
106
104
  .getUnifiedPromise(this.infiniteExecutor, (resData) => {
107
- this.submitSuccess(resData, onSuccess);
105
+ onSuccess === null || onSuccess === void 0 ? void 0 : onSuccess(resData);
106
+ this.submitSuccess(resData, this.calcIsEndReachedByResult(resData));
108
107
  })
109
108
  .catch((e) => {
110
109
  var _a;
@@ -130,9 +129,12 @@ export class InfiniteQuery extends QueryContainer {
130
129
  if (!this.isNetworkOnly && this.isSuccess && !this.auxiliary.isInvalid) {
131
130
  return Promise.resolve((_a = this.storage.data) === null || _a === void 0 ? void 0 : _a.data);
132
131
  }
133
- this.storage.setData((current) => ({ offset: 0, data: current === null || current === void 0 ? void 0 : current.data }));
134
- this.isEndReached = false;
135
- return this.auxiliary.getUnifiedPromise(this.infiniteExecutor, this.submitSuccess);
132
+ this.storage.setData((current) => ({
133
+ offset: 0,
134
+ data: current === null || current === void 0 ? void 0 : current.data,
135
+ isEndReached: false,
136
+ }));
137
+ return this.auxiliary.getUnifiedPromise(this.infiniteExecutor, (data) => this.submitSuccess(data, this.calcIsEndReachedByResult(data)));
136
138
  };
137
139
  this.storage = dataStorage;
138
140
  this.incrementCount = incrementCount;
@@ -148,7 +150,7 @@ export class InfiniteQuery extends QueryContainer {
148
150
  sync: action,
149
151
  fetchMore: action,
150
152
  submitSuccess: action,
151
- isEndReached: observable,
153
+ isEndReached: computed,
152
154
  });
153
155
  }
154
156
  get isNetworkOnly() {
@@ -161,6 +163,13 @@ export class InfiniteQuery extends QueryContainer {
161
163
  var _a, _b;
162
164
  return (_b = (_a = this.storage.data) === null || _a === void 0 ? void 0 : _a.offset) !== null && _b !== void 0 ? _b : 0;
163
165
  }
166
+ /**
167
+ * Флаг того, что мы достигли предела запрашиваемых элементов
168
+ */
169
+ get isEndReached() {
170
+ var _a;
171
+ return Boolean((_a = this.storage.data) === null || _a === void 0 ? void 0 : _a.isEndReached);
172
+ }
164
173
  /**
165
174
  * Метод для обогащения параметров текущими значениями для инфинити
166
175
  */
@@ -8,6 +8,13 @@ import type { CacheKey, FetchPolicy } from '../types';
8
8
  * будет вызван, если при вызове sync не был передан отдельный onError параметр
9
9
  */
10
10
  type OnError<TError = unknown> = (error: TError) => void;
11
+ type WithSynchronization = {
12
+ /**
13
+ * Флаг, отвечающий за синхронизацию данных между инстансами одной и той же квери в разных вкладках браузера
14
+ * @default либо значение переданное при создании MobxQuery, либо false
15
+ */
16
+ enabledSynchronization?: boolean;
17
+ };
11
18
  type MobxQueryParams = {
12
19
  /**
13
20
  * Политика получения данных по умолчанию.
@@ -24,6 +31,11 @@ type MobxQueryParams = {
24
31
  * @default false
25
32
  */
26
33
  enabledAutoFetch?: boolean;
34
+ /**
35
+ * Флаг, отвечающий за синхронизацию данных между инстансами одной и той же квери в разных вкладках браузера
36
+ * @default false
37
+ */
38
+ enabledSynchronization?: boolean;
27
39
  };
28
40
  export type CreateQueryParams<TResult, TError, TIsBackground extends boolean> = Omit<QueryParams<TResult, TError, TIsBackground>, 'dataStorage' | 'statusStorage' | 'backgroundStatusStorage' | 'submitValidity'> & {
29
41
  /**
@@ -31,14 +43,14 @@ export type CreateQueryParams<TResult, TError, TIsBackground extends boolean> =
31
43
  * @default false
32
44
  */
33
45
  isBackground?: TIsBackground;
34
- };
46
+ } & WithSynchronization;
35
47
  export type CreateInfiniteQueryParams<TResult, TError, TIsBackground extends boolean> = Omit<InfiniteQueryParams<TResult, TError, TIsBackground>, 'dataStorage' | 'statusStorage' | 'backgroundStatusStorage' | 'submitValidity'> & {
36
48
  /**
37
49
  * Режим фонового обновления
38
50
  * @default false
39
51
  */
40
52
  isBackground?: TIsBackground;
41
- };
53
+ } & WithSynchronization;
42
54
  export type CreateMutationParams<TResult, TError> = MutationParams<TResult, TError>;
43
55
  /**
44
56
  * Внутриний тип кешируемого стора
@@ -83,8 +95,13 @@ export declare class MobxQuery<TDefaultError = void> {
83
95
  * @default false
84
96
  */
85
97
  private readonly defaultEnabledAutoFetch;
98
+ private readonly defauleEnabledSynchronization;
99
+ private readonly synchronizationService;
86
100
  private serialize;
87
- constructor({ onError, fetchPolicy, enabledAutoFetch, }?: MobxQueryParams);
101
+ constructor({ onError, fetchPolicy, enabledAutoFetch, enabledSynchronization, }?: MobxQueryParams, _BroadcastChannel?: {
102
+ new (name: string): BroadcastChannel;
103
+ prototype: BroadcastChannel;
104
+ });
88
105
  /**
89
106
  * Проверяет пересечение ключей в зависимости от стратегии
90
107
  * @param invalidatedKeys - Ключи для инвалидации
@@ -5,11 +5,12 @@ import { Mutation, } from '../Mutation';
5
5
  import { Query } from '../Query';
6
6
  import { InfiniteQuerySet, MutationSet, QuerySet, } from '../Sets';
7
7
  import { StatusStorageFactory } from '../StatusStorage';
8
+ import { SynchronizationService } from '../SynchronizationService';
8
9
  /**
9
10
  * Сервис, позволяющий кэшировать данные.
10
11
  */
11
12
  export class MobxQuery {
12
- constructor({ onError, fetchPolicy = 'cache-first', enabledAutoFetch = false, } = {}) {
13
+ constructor({ onError, fetchPolicy = 'cache-first', enabledAutoFetch = false, enabledSynchronization = false, } = {}, _BroadcastChannel = globalThis.BroadcastChannel) {
13
14
  /**
14
15
  * Объект соответствия хешей ключей и их значений
15
16
  */
@@ -77,10 +78,19 @@ export class MobxQuery {
77
78
  */
78
79
  this.getExistsQueries = (keys, strategy = 'partial-match') => this.getExistsKeyHashes(keys, strategy).map(({ keyHash }) => this.queriesMap.get(keyHash));
79
80
  // Метод для подтверждения того, что квери успешно получил валидные данные
80
- this.submitValidity = (keyHash) => {
81
+ this.submitValidity = (keys, isNetworkOnly, enabledSynchronization) => {
82
+ if (enabledSynchronization) {
83
+ this.synchronizationService.emit(keys);
84
+ }
85
+ // 'network-only' квери не будут конвертироваться,
86
+ // следовательно, они всегда будут храниться как "слабые",
87
+ // что позволит сборщику мусора удалять их из памяти при отсутствии ссылок
88
+ if (isNetworkOnly) {
89
+ return;
90
+ }
81
91
  // конвертируем квери в сильный,
82
92
  // чтобы сборщик мусора не удалил наш кеш преждевременно
83
- this.queriesMap.convertToStrong(keyHash);
93
+ this.queriesMap.convertToStrong(keys.queryKeyHash);
84
94
  };
85
95
  /**
86
96
  * Метод инвалидации всех query
@@ -112,13 +122,10 @@ export class MobxQuery {
112
122
  dataStorage: this.queryDataStorageFactory.getStorage(keys.dataKeyHash),
113
123
  statusStorage: this.statusStorageFactory.getStorage(keys.statusKeyHash),
114
124
  backgroundStatusStorage: this.getBackgroundStatusStorage(keys.backgroundStatusKeyHash, Boolean(createParams === null || createParams === void 0 ? void 0 : createParams.isBackground)),
115
- submitValidity:
116
- // 'network-only' квери не будут подтверждать свою валидность,
117
- // следовательно, они всегда будут храниться как "слабые",
118
- // что позволит сборщику мусора удалять их из памяти при отсутствии ссылок
119
- fetchPolicy !== 'network-only'
120
- ? () => this.submitValidity(keys.queryKeyHash)
121
- : undefined,
125
+ submitValidity: () => {
126
+ var _a;
127
+ return this.submitValidity(keys, fetchPolicy !== 'network-only', (_a = createParams === null || createParams === void 0 ? void 0 : createParams.enabledSynchronization) !== null && _a !== void 0 ? _a : this.defauleEnabledSynchronization);
128
+ },
122
129
  });
123
130
  this.queriesMap.set(keys.queryKeyHash, query);
124
131
  this.keys.set(keys.queryKeyHash, keys.queryKey);
@@ -220,5 +227,7 @@ export class MobxQuery {
220
227
  this.defaultErrorHandler = onError;
221
228
  this.defaultFetchPolicy = fetchPolicy;
222
229
  this.defaultEnabledAutoFetch = enabledAutoFetch;
230
+ this.defauleEnabledSynchronization = enabledSynchronization;
231
+ this.synchronizationService = new SynchronizationService(this.statusStorageFactory, this.queryDataStorageFactory, _BroadcastChannel);
223
232
  }
224
233
  }
@@ -1,8 +1,7 @@
1
- import { type StatusStorage } from '../StatusStorage';
1
+ import { type Statuses } from '../StatusStorage';
2
2
  export type QueryContainerAuxiliary = {
3
3
  isIdle: boolean;
4
4
  };
5
- type Statuses<TError> = StatusStorage<TError>;
6
5
  /**
7
6
  * Контейнер для бойлерплейт части,
8
7
  * позволяет не повторять в каждом наследуемом классе использование стандартных статусов
@@ -11,7 +10,7 @@ export declare abstract class QueryContainer<TError, TAuxiliary extends QueryCon
11
10
  private readonly statusStorage;
12
11
  private readonly backgroundStatusStorage;
13
12
  protected readonly auxiliary: TAuxiliary;
14
- protected constructor(statusStorage: StatusStorage<TError>, backgroundStatusStorage: StatusStorage<TError> | null, auxiliary: TAuxiliary);
13
+ protected constructor(statusStorage: Statuses<TError>, backgroundStatusStorage: Statuses<TError> | null, auxiliary: TAuxiliary);
15
14
  /**
16
15
  * Флаг загрузки данных
17
16
  */
@@ -32,6 +31,13 @@ export declare abstract class QueryContainer<TError, TAuxiliary extends QueryCon
32
31
  * Флаг, обозначающий простаивание, т.е. запроса еще не было
33
32
  */
34
33
  get isIdle(): boolean;
34
+ get status(): {
35
+ isLoading: boolean;
36
+ isError: boolean;
37
+ error: TError | undefined;
38
+ isSuccess: boolean;
39
+ isIdle: boolean;
40
+ };
35
41
  /**
36
42
  * Статусы, изменяющиеся после первого успешного запроса в режиме isBackground: true
37
43
  * @example
@@ -58,4 +64,3 @@ export declare abstract class QueryContainer<TError, TAuxiliary extends QueryCon
58
64
  */
59
65
  get background(): TIsBackground extends true ? Statuses<TError> : null;
60
66
  }
61
- export {};
@@ -46,6 +46,15 @@ export class QueryContainer {
46
46
  get isIdle() {
47
47
  return this.auxiliary.isIdle;
48
48
  }
49
+ get status() {
50
+ return {
51
+ isLoading: this.isLoading,
52
+ isError: this.isError,
53
+ error: this.error,
54
+ isSuccess: this.isSuccess,
55
+ isIdle: this.isIdle,
56
+ };
57
+ }
49
58
  /**
50
59
  * Статусы, изменяющиеся после первого успешного запроса в режиме isBackground: true
51
60
  * @example
package/README.md CHANGED
@@ -137,6 +137,10 @@ class DocStore {
137
137
  public get isLoading() {
138
138
  return this.docQuery.isLoading;
139
139
  }
140
+
141
+ public get status() {
142
+ return this.docQuery.status;
143
+ }
140
144
  }
141
145
  ```
142
146
 
@@ -662,6 +666,25 @@ console.log(queryA.data); // ['дополнительный элемент']
662
666
  console.log(queryB.data); // ['дополнительный элемент']
663
667
  ```
664
668
 
669
+ ## Синхронизация данных между вкладками
670
+
671
+ Для синхронизации данных между вкладками необходимо воспользоваться флагом `enabledSynchronization` при создании MobxQuery.
672
+ Тогда все query с совпадающими ключами на разных вкладках будут одновременно изменять свои данные
673
+
674
+ ```ts
675
+ new MobxQuery({
676
+ enabledSynchronization: true,
677
+ });
678
+ ```
679
+
680
+ Для точечного управления синхронизацией, можно передавать флаг `enabledSynchronization` при создании query
681
+
682
+ ```ts
683
+ docsFetcher.queries.document.createWithConfig({
684
+ enabledSynchronization: true,
685
+ })
686
+ ```
687
+
665
688
  ## Тестирование Fetcher на сонове QuerySet и InfiniteQuerySet.
666
689
 
667
690
  Для мокинга QuerySet и InfiniteQuerySet необходимо использовать mock следующего вида:
@@ -824,12 +847,20 @@ export type Query<TResult = unknown, TError = unknown, TIsBackground = boolean>
824
847
  /**
825
848
  * Текущая ошибка
826
849
  */
827
- error: TError | null;
850
+ error: TError | undefined;
828
851
 
829
852
  /**
830
853
  * Флаг, обозначающий простаивание, т.е. запроса еще не было
831
854
  */
832
855
  isIdle: boolean;
856
+
857
+ status: {
858
+ isLoading: boolean;
859
+ isSuccess: boolean;
860
+ isError: boolean;
861
+ error: TError | undefined;
862
+ isIdle: boolean;
863
+ }
833
864
 
834
865
  /**
835
866
  * Синхронизирует данные с сервером
@@ -1,5 +1,11 @@
1
1
  import { StorageFactory } from '../StorageFactory';
2
- export declare class StatusStorage<TError> {
2
+ export type Statuses<TError> = {
3
+ isLoading: boolean;
4
+ isError: boolean;
5
+ error?: TError;
6
+ isSuccess: boolean;
7
+ };
8
+ export declare class StatusStorage<TError> implements Statuses<TError> {
3
9
  constructor();
4
10
  /**
5
11
  * Флаг обозначающий загрузку данных
@@ -17,8 +23,10 @@ export declare class StatusStorage<TError> {
17
23
  * Флаг, обозначающий успешность завершения последнего запроса
18
24
  */
19
25
  isSuccess: boolean;
26
+ setStatues: (data: Statuses<TError>) => void;
27
+ get statuses(): Statuses<TError>;
20
28
  }
21
- export declare class StatusStorageFactory extends StorageFactory<StatusStorage<void>> {
29
+ export declare class StatusStorageFactory extends StorageFactory<StatusStorage<any>> {
22
30
  constructor();
23
31
  getStorage: <TError>(keyHash: string) => StatusStorage<TError>;
24
32
  }
@@ -1,4 +1,4 @@
1
- import { makeObservable, observable } from 'mobx';
1
+ import { makeAutoObservable } from 'mobx';
2
2
  import { StorageFactory } from '../StorageFactory';
3
3
  export class StatusStorage {
4
4
  constructor() {
@@ -18,14 +18,24 @@ export class StatusStorage {
18
18
  * Флаг, обозначающий успешность завершения последнего запроса
19
19
  */
20
20
  this.isSuccess = false;
21
- makeObservable(this, {
22
- error: observable,
23
- isError: observable,
24
- isLoading: observable,
25
- isSuccess: observable,
26
- });
21
+ this.setStatues = (data) => {
22
+ this.isLoading = data.isLoading;
23
+ this.isError = data.isError;
24
+ this.error = data.error;
25
+ this.isSuccess = data.isSuccess;
26
+ };
27
+ makeAutoObservable(this);
28
+ }
29
+ get statuses() {
30
+ return {
31
+ isLoading: this.isLoading,
32
+ isError: this.isError,
33
+ error: this.error,
34
+ isSuccess: this.isSuccess,
35
+ };
27
36
  }
28
37
  }
38
+ // biome-ignore lint/suspicious/noExplicitAny: any нужен для вывода типов
29
39
  export class StatusStorageFactory extends StorageFactory {
30
40
  constructor() {
31
41
  super(() => new StatusStorage());
@@ -0,0 +1,16 @@
1
+ import { type DataStorageFactory } from '../DataStorage';
2
+ import { type StatusStorageFactory } from '../StatusStorage';
3
+ export declare class SynchronizationService {
4
+ private readonly _statusStorageFactory;
5
+ private readonly _dataStorageFactory;
6
+ private readonly broadcastChannel?;
7
+ constructor(_statusStorageFactory: StatusStorageFactory, _dataStorageFactory: DataStorageFactory, _BroadcastChannel?: {
8
+ new (name: string): BroadcastChannel;
9
+ prototype: BroadcastChannel;
10
+ });
11
+ private init;
12
+ emit: (keys: {
13
+ dataKeyHash: string;
14
+ statusKeyHash: string;
15
+ }) => void;
16
+ }
@@ -0,0 +1,29 @@
1
+ export class SynchronizationService {
2
+ constructor(_statusStorageFactory, _dataStorageFactory, _BroadcastChannel = globalThis.BroadcastChannel) {
3
+ this._statusStorageFactory = _statusStorageFactory;
4
+ this._dataStorageFactory = _dataStorageFactory;
5
+ this.init = () => {
6
+ var _a;
7
+ (_a = this.broadcastChannel) === null || _a === void 0 ? void 0 : _a.addEventListener('message', (event) => {
8
+ var _a, _b;
9
+ (_a = this._dataStorageFactory
10
+ .getStorage(event.data.dataKeyHash)) === null || _a === void 0 ? void 0 : _a.setData(event.data.data);
11
+ (_b = this._statusStorageFactory
12
+ .getStorage(event.data.statusKeyHash)) === null || _b === void 0 ? void 0 : _b.setStatues(event.data.statuses);
13
+ });
14
+ };
15
+ this.emit = (keys) => {
16
+ var _a, _b, _c;
17
+ (_a = this.broadcastChannel) === null || _a === void 0 ? void 0 : _a.postMessage({
18
+ dataKeyHash: keys.dataKeyHash,
19
+ statusKeyHash: keys.statusKeyHash,
20
+ data: (_b = this._dataStorageFactory.getStorage(keys.dataKeyHash)) === null || _b === void 0 ? void 0 : _b.data,
21
+ statuses: (_c = this._statusStorageFactory.getStorage(keys.statusKeyHash)) === null || _c === void 0 ? void 0 : _c.statuses,
22
+ });
23
+ };
24
+ if (_BroadcastChannel) {
25
+ this.broadcastChannel = new _BroadcastChannel('@astral/mobx-query');
26
+ }
27
+ this.init();
28
+ }
29
+ }
@@ -0,0 +1 @@
1
+ export * from './SynchronizationService';
@@ -0,0 +1 @@
1
+ export * from './SynchronizationService';
@@ -11,6 +11,7 @@ export type InfiniteParams = {
11
11
  export type InfiniteDataStorage<TResult> = DataStorage<{
12
12
  data: TResult[];
13
13
  offset: number;
14
+ isEndReached: boolean;
14
15
  }>;
15
16
  /**
16
17
  * Исполнитель запроса, ожидается,
@@ -68,10 +69,6 @@ export declare class InfiniteQuery<TResult, TError = void, TIsBackground extends
68
69
  * Хранилище данных, для обеспечения возможности синхронизации данных между разными инстансами
69
70
  */
70
71
  private storage;
71
- /**
72
- * Флаг того, что мы достигли предела запрашиваемых элементов
73
- */
74
- isEndReached: boolean;
75
72
  /**
76
73
  * Обработчик ошибки, вызываемый по умолчанию
77
74
  */
@@ -98,6 +95,11 @@ export declare class InfiniteQuery<TResult, TError = void, TIsBackground extends
98
95
  * Обработчик успешного запроса, проверяет что мы достигли предела
99
96
  */
100
97
  private submitSuccess;
98
+ /**
99
+ * Флаг того, что мы достигли предела запрашиваемых элементов
100
+ */
101
+ get isEndReached(): boolean;
102
+ private calcIsEndReachedByResult;
101
103
  /**
102
104
  * Форс метод для установки данных
103
105
  */
@@ -13,26 +13,19 @@ class InfiniteQuery extends QueryContainer_1.QueryContainer {
13
13
  constructor(executor, { incrementCount = exports.DEFAULT_INFINITE_ITEMS_COUNT, onError, enabledAutoFetch, fetchPolicy, dataStorage, statusStorage, backgroundStatusStorage = null, submitValidity, }) {
14
14
  super(statusStorage, backgroundStatusStorage, new AuxiliaryQuery_1.AuxiliaryQuery(statusStorage, backgroundStatusStorage));
15
15
  this.executor = executor;
16
- /**
17
- * Флаг того, что мы достигли предела запрашиваемых элементов
18
- */
19
- this.isEndReached = false;
20
16
  /**
21
17
  * Обработчик успешного запроса, проверяет что мы достигли предела
22
18
  */
23
- this.submitSuccess = (result, onSuccess, isIncrement) => {
19
+ this.submitSuccess = (result, isEndReached) => {
24
20
  var _a;
25
- onSuccess === null || onSuccess === void 0 ? void 0 : onSuccess(result);
26
- if (isIncrement && this.storage.hasData) {
27
- this.storage.setData((current) => ({
28
- offset: current === null || current === void 0 ? void 0 : current.offset,
29
- data: [...current === null || current === void 0 ? void 0 : current.data, ...result],
30
- }));
31
- }
32
- else {
33
- this.storage.setData({ offset: 0, data: result });
34
- (_a = this.submitValidity) === null || _a === void 0 ? void 0 : _a.call(this);
35
- }
21
+ this.storage.setData((current) => ({
22
+ offset: current === null || current === void 0 ? void 0 : current.offset,
23
+ data: result,
24
+ isEndReached,
25
+ }));
26
+ (_a = this.submitValidity) === null || _a === void 0 ? void 0 : _a.call(this);
27
+ };
28
+ this.calcIsEndReachedByResult = (result) => {
36
29
  // убеждаемся что результат запроса действительно массив,
37
30
  // и если количество элементов в ответе меньше,
38
31
  // чем запрашивалось, значит у бэка их больше нет,
@@ -40,9 +33,9 @@ class InfiniteQuery extends QueryContainer_1.QueryContainer {
40
33
  // когда последняя отданная страница содержит ровно то количество,
41
34
  // сколько может содержать страница, а следующая уже просто пустая.
42
35
  if (Array.isArray(result) && result.length < this.incrementCount) {
43
- // включаем флаг достижения предела
44
- this.isEndReached = true;
36
+ return true;
45
37
  }
38
+ return false;
46
39
  };
47
40
  /**
48
41
  * Форс метод для установки данных
@@ -51,10 +44,10 @@ class InfiniteQuery extends QueryContainer_1.QueryContainer {
51
44
  var _a;
52
45
  this.auxiliary.submitSuccess();
53
46
  if (typeof param === 'function') {
54
- this.submitSuccess(param((_a = this.storage.data) === null || _a === void 0 ? void 0 : _a.data));
47
+ this.submitSuccess(param((_a = this.storage.data) === null || _a === void 0 ? void 0 : _a.data), this.isEndReached);
55
48
  }
56
49
  else {
57
- this.submitSuccess(param);
50
+ this.submitSuccess(param, this.isEndReached);
58
51
  }
59
52
  };
60
53
  /**
@@ -75,12 +68,14 @@ class InfiniteQuery extends QueryContainer_1.QueryContainer {
75
68
  return ({
76
69
  offset: ((_a = current === null || current === void 0 ? void 0 : current.offset) !== null && _a !== void 0 ? _a : 0) + this.incrementCount,
77
70
  data: current === null || current === void 0 ? void 0 : current.data,
71
+ isEndReached: Boolean(current === null || current === void 0 ? void 0 : current.isEndReached),
78
72
  });
79
73
  });
80
74
  // запускаем запрос с последними параметрами, и флагом необходимости инкремента
81
75
  this.auxiliary
82
76
  .getUnifiedPromise(this.infiniteExecutor, (resData) => {
83
- this.submitSuccess(resData, undefined, true);
77
+ var _a;
78
+ this.submitSuccess([...(_a = this.storage.data) === null || _a === void 0 ? void 0 : _a.data, ...resData], this.calcIsEndReachedByResult(resData));
84
79
  })
85
80
  .catch((e) => { var _a; return (_a = this.defaultOnError) === null || _a === void 0 ? void 0 : _a.call(this, e); });
86
81
  }
@@ -103,11 +98,15 @@ class InfiniteQuery extends QueryContainer_1.QueryContainer {
103
98
  * Метод для переиспользования синхронной логики запроса
104
99
  */
105
100
  this.proceedSync = ({ onSuccess, onError, } = {}) => {
106
- this.storage.setData((current) => ({ offset: 0, data: current === null || current === void 0 ? void 0 : current.data }));
107
- this.isEndReached = false;
101
+ this.storage.setData((current) => ({
102
+ offset: 0,
103
+ data: current === null || current === void 0 ? void 0 : current.data,
104
+ isEndReached: false,
105
+ }));
108
106
  this.auxiliary
109
107
  .getUnifiedPromise(this.infiniteExecutor, (resData) => {
110
- this.submitSuccess(resData, onSuccess);
108
+ onSuccess === null || onSuccess === void 0 ? void 0 : onSuccess(resData);
109
+ this.submitSuccess(resData, this.calcIsEndReachedByResult(resData));
111
110
  })
112
111
  .catch((e) => {
113
112
  var _a;
@@ -133,9 +132,12 @@ class InfiniteQuery extends QueryContainer_1.QueryContainer {
133
132
  if (!this.isNetworkOnly && this.isSuccess && !this.auxiliary.isInvalid) {
134
133
  return Promise.resolve((_a = this.storage.data) === null || _a === void 0 ? void 0 : _a.data);
135
134
  }
136
- this.storage.setData((current) => ({ offset: 0, data: current === null || current === void 0 ? void 0 : current.data }));
137
- this.isEndReached = false;
138
- return this.auxiliary.getUnifiedPromise(this.infiniteExecutor, this.submitSuccess);
135
+ this.storage.setData((current) => ({
136
+ offset: 0,
137
+ data: current === null || current === void 0 ? void 0 : current.data,
138
+ isEndReached: false,
139
+ }));
140
+ return this.auxiliary.getUnifiedPromise(this.infiniteExecutor, (data) => this.submitSuccess(data, this.calcIsEndReachedByResult(data)));
139
141
  };
140
142
  this.storage = dataStorage;
141
143
  this.incrementCount = incrementCount;
@@ -151,7 +153,7 @@ class InfiniteQuery extends QueryContainer_1.QueryContainer {
151
153
  sync: mobx_1.action,
152
154
  fetchMore: mobx_1.action,
153
155
  submitSuccess: mobx_1.action,
154
- isEndReached: mobx_1.observable,
156
+ isEndReached: mobx_1.computed,
155
157
  });
156
158
  }
157
159
  get isNetworkOnly() {
@@ -164,6 +166,13 @@ class InfiniteQuery extends QueryContainer_1.QueryContainer {
164
166
  var _a, _b;
165
167
  return (_b = (_a = this.storage.data) === null || _a === void 0 ? void 0 : _a.offset) !== null && _b !== void 0 ? _b : 0;
166
168
  }
169
+ /**
170
+ * Флаг того, что мы достигли предела запрашиваемых элементов
171
+ */
172
+ get isEndReached() {
173
+ var _a;
174
+ return Boolean((_a = this.storage.data) === null || _a === void 0 ? void 0 : _a.isEndReached);
175
+ }
167
176
  /**
168
177
  * Метод для обогащения параметров текущими значениями для инфинити
169
178
  */
@@ -8,6 +8,13 @@ import type { CacheKey, FetchPolicy } from '../types';
8
8
  * будет вызван, если при вызове sync не был передан отдельный onError параметр
9
9
  */
10
10
  type OnError<TError = unknown> = (error: TError) => void;
11
+ type WithSynchronization = {
12
+ /**
13
+ * Флаг, отвечающий за синхронизацию данных между инстансами одной и той же квери в разных вкладках браузера
14
+ * @default либо значение переданное при создании MobxQuery, либо false
15
+ */
16
+ enabledSynchronization?: boolean;
17
+ };
11
18
  type MobxQueryParams = {
12
19
  /**
13
20
  * Политика получения данных по умолчанию.
@@ -24,6 +31,11 @@ type MobxQueryParams = {
24
31
  * @default false
25
32
  */
26
33
  enabledAutoFetch?: boolean;
34
+ /**
35
+ * Флаг, отвечающий за синхронизацию данных между инстансами одной и той же квери в разных вкладках браузера
36
+ * @default false
37
+ */
38
+ enabledSynchronization?: boolean;
27
39
  };
28
40
  export type CreateQueryParams<TResult, TError, TIsBackground extends boolean> = Omit<QueryParams<TResult, TError, TIsBackground>, 'dataStorage' | 'statusStorage' | 'backgroundStatusStorage' | 'submitValidity'> & {
29
41
  /**
@@ -31,14 +43,14 @@ export type CreateQueryParams<TResult, TError, TIsBackground extends boolean> =
31
43
  * @default false
32
44
  */
33
45
  isBackground?: TIsBackground;
34
- };
46
+ } & WithSynchronization;
35
47
  export type CreateInfiniteQueryParams<TResult, TError, TIsBackground extends boolean> = Omit<InfiniteQueryParams<TResult, TError, TIsBackground>, 'dataStorage' | 'statusStorage' | 'backgroundStatusStorage' | 'submitValidity'> & {
36
48
  /**
37
49
  * Режим фонового обновления
38
50
  * @default false
39
51
  */
40
52
  isBackground?: TIsBackground;
41
- };
53
+ } & WithSynchronization;
42
54
  export type CreateMutationParams<TResult, TError> = MutationParams<TResult, TError>;
43
55
  /**
44
56
  * Внутриний тип кешируемого стора
@@ -83,8 +95,13 @@ export declare class MobxQuery<TDefaultError = void> {
83
95
  * @default false
84
96
  */
85
97
  private readonly defaultEnabledAutoFetch;
98
+ private readonly defauleEnabledSynchronization;
99
+ private readonly synchronizationService;
86
100
  private serialize;
87
- constructor({ onError, fetchPolicy, enabledAutoFetch, }?: MobxQueryParams);
101
+ constructor({ onError, fetchPolicy, enabledAutoFetch, enabledSynchronization, }?: MobxQueryParams, _BroadcastChannel?: {
102
+ new (name: string): BroadcastChannel;
103
+ prototype: BroadcastChannel;
104
+ });
88
105
  /**
89
106
  * Проверяет пересечение ключей в зависимости от стратегии
90
107
  * @param invalidatedKeys - Ключи для инвалидации
@@ -8,11 +8,12 @@ const Mutation_1 = require("../Mutation");
8
8
  const Query_1 = require("../Query");
9
9
  const Sets_1 = require("../Sets");
10
10
  const StatusStorage_1 = require("../StatusStorage");
11
+ const SynchronizationService_1 = require("../SynchronizationService");
11
12
  /**
12
13
  * Сервис, позволяющий кэшировать данные.
13
14
  */
14
15
  class MobxQuery {
15
- constructor({ onError, fetchPolicy = 'cache-first', enabledAutoFetch = false, } = {}) {
16
+ constructor({ onError, fetchPolicy = 'cache-first', enabledAutoFetch = false, enabledSynchronization = false, } = {}, _BroadcastChannel = globalThis.BroadcastChannel) {
16
17
  /**
17
18
  * Объект соответствия хешей ключей и их значений
18
19
  */
@@ -80,10 +81,19 @@ class MobxQuery {
80
81
  */
81
82
  this.getExistsQueries = (keys, strategy = 'partial-match') => this.getExistsKeyHashes(keys, strategy).map(({ keyHash }) => this.queriesMap.get(keyHash));
82
83
  // Метод для подтверждения того, что квери успешно получил валидные данные
83
- this.submitValidity = (keyHash) => {
84
+ this.submitValidity = (keys, isNetworkOnly, enabledSynchronization) => {
85
+ if (enabledSynchronization) {
86
+ this.synchronizationService.emit(keys);
87
+ }
88
+ // 'network-only' квери не будут конвертироваться,
89
+ // следовательно, они всегда будут храниться как "слабые",
90
+ // что позволит сборщику мусора удалять их из памяти при отсутствии ссылок
91
+ if (isNetworkOnly) {
92
+ return;
93
+ }
84
94
  // конвертируем квери в сильный,
85
95
  // чтобы сборщик мусора не удалил наш кеш преждевременно
86
- this.queriesMap.convertToStrong(keyHash);
96
+ this.queriesMap.convertToStrong(keys.queryKeyHash);
87
97
  };
88
98
  /**
89
99
  * Метод инвалидации всех query
@@ -115,13 +125,10 @@ class MobxQuery {
115
125
  dataStorage: this.queryDataStorageFactory.getStorage(keys.dataKeyHash),
116
126
  statusStorage: this.statusStorageFactory.getStorage(keys.statusKeyHash),
117
127
  backgroundStatusStorage: this.getBackgroundStatusStorage(keys.backgroundStatusKeyHash, Boolean(createParams === null || createParams === void 0 ? void 0 : createParams.isBackground)),
118
- submitValidity:
119
- // 'network-only' квери не будут подтверждать свою валидность,
120
- // следовательно, они всегда будут храниться как "слабые",
121
- // что позволит сборщику мусора удалять их из памяти при отсутствии ссылок
122
- fetchPolicy !== 'network-only'
123
- ? () => this.submitValidity(keys.queryKeyHash)
124
- : undefined,
128
+ submitValidity: () => {
129
+ var _a;
130
+ return this.submitValidity(keys, fetchPolicy !== 'network-only', (_a = createParams === null || createParams === void 0 ? void 0 : createParams.enabledSynchronization) !== null && _a !== void 0 ? _a : this.defauleEnabledSynchronization);
131
+ },
125
132
  });
126
133
  this.queriesMap.set(keys.queryKeyHash, query);
127
134
  this.keys.set(keys.queryKeyHash, keys.queryKey);
@@ -223,6 +230,8 @@ class MobxQuery {
223
230
  this.defaultErrorHandler = onError;
224
231
  this.defaultFetchPolicy = fetchPolicy;
225
232
  this.defaultEnabledAutoFetch = enabledAutoFetch;
233
+ this.defauleEnabledSynchronization = enabledSynchronization;
234
+ this.synchronizationService = new SynchronizationService_1.SynchronizationService(this.statusStorageFactory, this.queryDataStorageFactory, _BroadcastChannel);
226
235
  }
227
236
  }
228
237
  exports.MobxQuery = MobxQuery;
@@ -1,8 +1,7 @@
1
- import { type StatusStorage } from '../StatusStorage';
1
+ import { type Statuses } from '../StatusStorage';
2
2
  export type QueryContainerAuxiliary = {
3
3
  isIdle: boolean;
4
4
  };
5
- type Statuses<TError> = StatusStorage<TError>;
6
5
  /**
7
6
  * Контейнер для бойлерплейт части,
8
7
  * позволяет не повторять в каждом наследуемом классе использование стандартных статусов
@@ -11,7 +10,7 @@ export declare abstract class QueryContainer<TError, TAuxiliary extends QueryCon
11
10
  private readonly statusStorage;
12
11
  private readonly backgroundStatusStorage;
13
12
  protected readonly auxiliary: TAuxiliary;
14
- protected constructor(statusStorage: StatusStorage<TError>, backgroundStatusStorage: StatusStorage<TError> | null, auxiliary: TAuxiliary);
13
+ protected constructor(statusStorage: Statuses<TError>, backgroundStatusStorage: Statuses<TError> | null, auxiliary: TAuxiliary);
15
14
  /**
16
15
  * Флаг загрузки данных
17
16
  */
@@ -32,6 +31,13 @@ export declare abstract class QueryContainer<TError, TAuxiliary extends QueryCon
32
31
  * Флаг, обозначающий простаивание, т.е. запроса еще не было
33
32
  */
34
33
  get isIdle(): boolean;
34
+ get status(): {
35
+ isLoading: boolean;
36
+ isError: boolean;
37
+ error: TError | undefined;
38
+ isSuccess: boolean;
39
+ isIdle: boolean;
40
+ };
35
41
  /**
36
42
  * Статусы, изменяющиеся после первого успешного запроса в режиме isBackground: true
37
43
  * @example
@@ -58,4 +64,3 @@ export declare abstract class QueryContainer<TError, TAuxiliary extends QueryCon
58
64
  */
59
65
  get background(): TIsBackground extends true ? Statuses<TError> : null;
60
66
  }
61
- export {};
@@ -49,6 +49,15 @@ class QueryContainer {
49
49
  get isIdle() {
50
50
  return this.auxiliary.isIdle;
51
51
  }
52
+ get status() {
53
+ return {
54
+ isLoading: this.isLoading,
55
+ isError: this.isError,
56
+ error: this.error,
57
+ isSuccess: this.isSuccess,
58
+ isIdle: this.isIdle,
59
+ };
60
+ }
52
61
  /**
53
62
  * Статусы, изменяющиеся после первого успешного запроса в режиме isBackground: true
54
63
  * @example
@@ -1,5 +1,11 @@
1
1
  import { StorageFactory } from '../StorageFactory';
2
- export declare class StatusStorage<TError> {
2
+ export type Statuses<TError> = {
3
+ isLoading: boolean;
4
+ isError: boolean;
5
+ error?: TError;
6
+ isSuccess: boolean;
7
+ };
8
+ export declare class StatusStorage<TError> implements Statuses<TError> {
3
9
  constructor();
4
10
  /**
5
11
  * Флаг обозначающий загрузку данных
@@ -17,8 +23,10 @@ export declare class StatusStorage<TError> {
17
23
  * Флаг, обозначающий успешность завершения последнего запроса
18
24
  */
19
25
  isSuccess: boolean;
26
+ setStatues: (data: Statuses<TError>) => void;
27
+ get statuses(): Statuses<TError>;
20
28
  }
21
- export declare class StatusStorageFactory extends StorageFactory<StatusStorage<void>> {
29
+ export declare class StatusStorageFactory extends StorageFactory<StatusStorage<any>> {
22
30
  constructor();
23
31
  getStorage: <TError>(keyHash: string) => StatusStorage<TError>;
24
32
  }
@@ -21,15 +21,25 @@ class StatusStorage {
21
21
  * Флаг, обозначающий успешность завершения последнего запроса
22
22
  */
23
23
  this.isSuccess = false;
24
- (0, mobx_1.makeObservable)(this, {
25
- error: mobx_1.observable,
26
- isError: mobx_1.observable,
27
- isLoading: mobx_1.observable,
28
- isSuccess: mobx_1.observable,
29
- });
24
+ this.setStatues = (data) => {
25
+ this.isLoading = data.isLoading;
26
+ this.isError = data.isError;
27
+ this.error = data.error;
28
+ this.isSuccess = data.isSuccess;
29
+ };
30
+ (0, mobx_1.makeAutoObservable)(this);
31
+ }
32
+ get statuses() {
33
+ return {
34
+ isLoading: this.isLoading,
35
+ isError: this.isError,
36
+ error: this.error,
37
+ isSuccess: this.isSuccess,
38
+ };
30
39
  }
31
40
  }
32
41
  exports.StatusStorage = StatusStorage;
42
+ // biome-ignore lint/suspicious/noExplicitAny: any нужен для вывода типов
33
43
  class StatusStorageFactory extends StorageFactory_1.StorageFactory {
34
44
  constructor() {
35
45
  super(() => new StatusStorage());
@@ -0,0 +1,16 @@
1
+ import { type DataStorageFactory } from '../DataStorage';
2
+ import { type StatusStorageFactory } from '../StatusStorage';
3
+ export declare class SynchronizationService {
4
+ private readonly _statusStorageFactory;
5
+ private readonly _dataStorageFactory;
6
+ private readonly broadcastChannel?;
7
+ constructor(_statusStorageFactory: StatusStorageFactory, _dataStorageFactory: DataStorageFactory, _BroadcastChannel?: {
8
+ new (name: string): BroadcastChannel;
9
+ prototype: BroadcastChannel;
10
+ });
11
+ private init;
12
+ emit: (keys: {
13
+ dataKeyHash: string;
14
+ statusKeyHash: string;
15
+ }) => void;
16
+ }
@@ -0,0 +1,33 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.SynchronizationService = void 0;
4
+ class SynchronizationService {
5
+ constructor(_statusStorageFactory, _dataStorageFactory, _BroadcastChannel = globalThis.BroadcastChannel) {
6
+ this._statusStorageFactory = _statusStorageFactory;
7
+ this._dataStorageFactory = _dataStorageFactory;
8
+ this.init = () => {
9
+ var _a;
10
+ (_a = this.broadcastChannel) === null || _a === void 0 ? void 0 : _a.addEventListener('message', (event) => {
11
+ var _a, _b;
12
+ (_a = this._dataStorageFactory
13
+ .getStorage(event.data.dataKeyHash)) === null || _a === void 0 ? void 0 : _a.setData(event.data.data);
14
+ (_b = this._statusStorageFactory
15
+ .getStorage(event.data.statusKeyHash)) === null || _b === void 0 ? void 0 : _b.setStatues(event.data.statuses);
16
+ });
17
+ };
18
+ this.emit = (keys) => {
19
+ var _a, _b, _c;
20
+ (_a = this.broadcastChannel) === null || _a === void 0 ? void 0 : _a.postMessage({
21
+ dataKeyHash: keys.dataKeyHash,
22
+ statusKeyHash: keys.statusKeyHash,
23
+ data: (_b = this._dataStorageFactory.getStorage(keys.dataKeyHash)) === null || _b === void 0 ? void 0 : _b.data,
24
+ statuses: (_c = this._statusStorageFactory.getStorage(keys.statusKeyHash)) === null || _c === void 0 ? void 0 : _c.statuses,
25
+ });
26
+ };
27
+ if (_BroadcastChannel) {
28
+ this.broadcastChannel = new _BroadcastChannel('@astral/mobx-query');
29
+ }
30
+ this.init();
31
+ }
32
+ }
33
+ exports.SynchronizationService = SynchronizationService;
@@ -0,0 +1 @@
1
+ export * from './SynchronizationService';
@@ -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("./SynchronizationService"), exports);
package/package.json CHANGED
@@ -7,7 +7,7 @@
7
7
  "mobx": "^6.9.0",
8
8
  "utility-types": "3.11.0"
9
9
  },
10
- "version": "1.13.2",
10
+ "version": "1.15.0",
11
11
  "author": "Astral.Soft",
12
12
  "license": "MIT",
13
13
  "repository": {