@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.
@@ -1,17 +1,18 @@
1
- import { makeAutoObservable } from 'mobx';
1
+ import { action, makeObservable } from 'mobx';
2
2
  import { AuxiliaryQuery } from '../AuxiliaryQuery';
3
+ import { QueryContainer } from '../QueryContainer';
4
+ import { StatusStorage } from '../StatusStorage';
3
5
  /**
4
- * @description простой стор для запросов, которые не требуют кэширования,
6
+ * Простой квери для запросов, которые не требуют кэширования,
5
7
  * пример - POST запросы
6
8
  */
7
- export class Mutation {
9
+ export class Mutation extends QueryContainer {
8
10
  constructor(executor, { onError } = {}) {
11
+ const statusStorage = new StatusStorage();
12
+ super(statusStorage, null, new AuxiliaryQuery(statusStorage, null));
13
+ this.executor = executor;
9
14
  /**
10
- * @description инстанс вспомогательного стора
11
- */
12
- this.auxiliary = new AuxiliaryQuery();
13
- /**
14
- * @description синхронный метод получения/отправки данных
15
+ * Синхронный метод получения/отправки данных
15
16
  */
16
17
  this.sync = (options) => {
17
18
  const { onSuccess, onError, params } = options || {};
@@ -31,41 +32,13 @@ export class Mutation {
31
32
  });
32
33
  };
33
34
  /**
34
- * @description асинхронный метод получения/отправки данных,
35
+ * Асинхронный метод получения/отправки данных,
35
36
  * предполагается, что нужно будет самостоятельно обрабатывать ошибку
36
37
  */
37
38
  this.async = (params) => {
38
39
  return this.auxiliary.getUnifiedPromise(() => this.executor(params));
39
40
  };
40
- this.executor = executor;
41
41
  this.defaultOnError = onError;
42
- makeAutoObservable(this);
43
- }
44
- /**
45
- * @description флаг загрузки данных
46
- */
47
- get isLoading() {
48
- return this.auxiliary.isLoading;
49
- }
50
- /**
51
- * @description флаг обозначающий, что последний запрос был зафейлен
52
- */
53
- get isError() {
54
- return this.auxiliary.isError;
55
- }
56
- /**
57
- * @description данные о последней ошибке
58
- */
59
- get error() {
60
- return this.auxiliary.error;
61
- }
62
- /**
63
- * @description флаг обозначающий, что последний запрос был успешно завершен
64
- */
65
- get isSuccess() {
66
- return this.auxiliary.isSuccess;
67
- }
68
- get isIdle() {
69
- return this.auxiliary.isIdle;
42
+ makeObservable(this, { async: action, sync: action });
70
43
  }
71
44
  }
package/Query/Query.d.ts CHANGED
@@ -1,108 +1,103 @@
1
+ import { AuxiliaryQuery } from '../AuxiliaryQuery';
1
2
  import type { FetchPolicy, QueryBaseActions, Sync, SyncParams } from '../types';
2
3
  import type { DataStorage } from '../DataStorage';
4
+ import { QueryContainer } from '../QueryContainer';
5
+ import { type StatusStorage } from '../StatusStorage';
3
6
  /**
4
- * @description исполнитель запроса
7
+ * Исполнитель запроса
5
8
  */
6
9
  export type QueryExecutor<TResult> = () => Promise<TResult>;
7
- export type QueryParams<TResult, TError> = {
10
+ export type QueryParams<TResult, TError, TIsBackground extends boolean = false> = {
8
11
  /**
9
- * @description обработчик ошибки, вызываемый по умолчанию
12
+ * Обработчик ошибки, вызываемый по умолчанию
10
13
  */
11
14
  onError?: SyncParams<TResult, TError>['onError'];
12
15
  /**
13
- * @description флаг, отвечающий за автоматический запрос данных при обращении к полю data
16
+ * Флаг, отвечающий за автоматический запрос данных при обращении к полю data
14
17
  */
15
18
  enabledAutoFetch?: boolean;
19
+ /**
20
+ * Политика получения данных.
21
+ * @enum cache-first - данные сначала берутся из кеша, если их нет, тогда идет обращение к сети, ответ записывается в кэш
22
+ * @enum network-only - данные всегда берутся из сети, при этом ответ записывается в кэш
23
+ */
16
24
  fetchPolicy?: FetchPolicy;
17
25
  /**
18
- * @description инстанс хранилища данных
26
+ * Инстанс хранилища данных
19
27
  */
20
28
  dataStorage: DataStorage<TResult>;
21
- };
22
- /**
23
- * @description стор для работы с запросами,
24
- * которые должны быть закешированы,
25
- * но им не требуется усложнение в виде работы с фильтрами и инфинити запросами
26
- */
27
- export declare class Query<TResult, TError = void> implements QueryBaseActions<TResult, TError, undefined> {
28
29
  /**
29
- * @description инстанс вспомогательного стора
30
+ * Инстанс хранилища основных статусов
30
31
  */
31
- private auxiliary;
32
+ statusStorage: StatusStorage<TError>;
32
33
  /**
33
- * @description флаг, по которому реактивно определяется необходимость запуска инвалидации
34
+ * Инстанс хранилища фоновых статусов
34
35
  */
35
- private isInvalid;
36
+ backgroundStatusStorage?: TIsBackground extends true ? StatusStorage<TError> : null | undefined;
36
37
  /**
37
- * @description хранилище данных, для обеспечения возможности синхронизации данных между разными инстансами
38
+ * Колбэк, вызываемый при успешном завершении запроса, подразумевается использование, для подтверждения валидности данных, чтобы квери не был удален из памяти
38
39
  */
39
- private storage;
40
+ submitValidity?: () => void;
41
+ };
42
+ /**
43
+ * Стор для работы с запросами,
44
+ * которые должны быть закешированы,
45
+ * но им не требуется усложнение в виде работы с фильтрами и инфинити запросами
46
+ */
47
+ export declare class Query<TResult, TError = void, TIsBackground extends boolean = false> extends QueryContainer<TError, AuxiliaryQuery<TResult, TError>, TIsBackground> implements QueryBaseActions<TResult, TError, undefined> {
48
+ private readonly executor;
40
49
  /**
41
- * @description исполнитель запроса, ожидается,
42
- * что будет использоваться что-то из слоя sources
50
+ * Хранилище данных, для обеспечения возможности синхронизации данных между разными инстансами
43
51
  */
44
- private executor;
52
+ private storage;
45
53
  /**
46
- * @description обработчик ошибки, вызываемый по умолчанию
54
+ * Обработчик ошибки, вызываемый по умолчанию
47
55
  */
48
56
  private defaultOnError?;
49
57
  /**
50
- * @description флаг, отвечающий за автоматический запрос данных при обращении к полю data
58
+ * Флаг, отвечающий за автоматический запрос данных при обращении к полю data
51
59
  */
52
60
  private enabledAutoFetch?;
53
61
  /**
54
- * @description стандартное поведение политики кеширования
62
+ * Стандартное поведение политики кеширования
55
63
  */
56
64
  private readonly defaultFetchPolicy?;
57
- constructor(executor: QueryExecutor<TResult>, { onError, enabledAutoFetch, fetchPolicy, dataStorage, }: QueryParams<TResult, TError>);
65
+ /**
66
+ * Колбэк, вызываемый при успешном завершении запроса, подразумевается использование, для подтверждения валидности данных, чтобы квери не был удален из памяти
67
+ */
68
+ private readonly submitValidity?;
69
+ constructor(executor: QueryExecutor<TResult>, { onError, enabledAutoFetch, fetchPolicy, dataStorage, statusStorage, backgroundStatusStorage, submitValidity, }: QueryParams<TResult, TError, TIsBackground>);
58
70
  private get isNetworkOnly();
59
71
  /**
60
- * @description метод для инвалидации данных
72
+ * Метод для инвалидации данных
61
73
  */
62
74
  invalidate: () => void;
63
75
  /**
64
- * @description синхронный метод получения данных
76
+ * Синхронный метод получения данных
65
77
  */
66
78
  sync: Sync<TResult, TError, undefined>;
67
79
  /**
68
- * @description обработчик успешного ответа
80
+ * Обработчик успешного ответа
69
81
  */
70
82
  private submitSuccess;
71
83
  /**
72
- * @description форс метод для установки данных
84
+ * Форс метод для установки данных
73
85
  */
74
86
  forceUpdate: (data: TResult) => void;
75
87
  /**
76
- * @description метод для переиспользования синхронной логики запроса
88
+ * Метод для переиспользования синхронной логики запроса
77
89
  */
78
- private proceedSync;
90
+ protected proceedSync: Sync<TResult, TError>;
79
91
  /**
80
- * @description асинхронный метод получения данных,
92
+ * Асинхронный метод получения данных,
81
93
  * предполагается, что нужно будет самостоятельно обрабатывать ошибку
82
94
  */
83
95
  async: () => Promise<TResult>;
84
96
  /**
85
- * @description содержит реактивные данные
97
+ * Содержит реактивные данные
86
98
  * благодаря mobx, при изменении isInvalid, свойство будет вычисляться заново,
87
99
  * следовательно, стриггерится условие невалидности,
88
100
  * и начнется запрос, в результате которого, данные обновятся
89
101
  */
90
102
  get data(): TResult | undefined;
91
- /**
92
- * @description флаг загрузки данных
93
- */
94
- get isLoading(): boolean;
95
- /**
96
- * @description флаг обозначающий, что последний запрос был зафейлен
97
- */
98
- get isError(): boolean;
99
- /**
100
- * @description данные о последней ошибке
101
- */
102
- get error(): TError | undefined;
103
- /**
104
- * @description флаг обозначающий, что последний запрос был успешно завершен
105
- */
106
- get isSuccess(): boolean;
107
- get isIdle(): boolean;
108
103
  }
package/Query/Query.js CHANGED
@@ -1,52 +1,48 @@
1
- import { makeAutoObservable, when } from 'mobx';
1
+ import { action, computed, makeObservable, when } from 'mobx';
2
2
  import { AuxiliaryQuery } from '../AuxiliaryQuery';
3
+ import { QueryContainer } from '../QueryContainer';
3
4
  /**
4
- * @description стор для работы с запросами,
5
+ * Стор для работы с запросами,
5
6
  * которые должны быть закешированы,
6
7
  * но им не требуется усложнение в виде работы с фильтрами и инфинити запросами
7
8
  */
8
- export class Query {
9
- constructor(executor, { onError, enabledAutoFetch, fetchPolicy, dataStorage, }) {
10
- /**
11
- * @description инстанс вспомогательного стора
12
- */
13
- this.auxiliary = new AuxiliaryQuery();
14
- /**
15
- * @description флаг, по которому реактивно определяется необходимость запуска инвалидации
16
- */
17
- this.isInvalid = false;
9
+ export class Query extends QueryContainer {
10
+ constructor(executor, { onError, enabledAutoFetch, fetchPolicy, dataStorage, statusStorage, backgroundStatusStorage = null, submitValidity, }) {
11
+ super(statusStorage, backgroundStatusStorage, new AuxiliaryQuery(statusStorage, backgroundStatusStorage));
12
+ this.executor = executor;
18
13
  /**
19
- * @description метод для инвалидации данных
14
+ * Метод для инвалидации данных
20
15
  */
21
16
  this.invalidate = () => {
22
- this.isInvalid = true;
17
+ this.auxiliary.invalidate();
23
18
  };
24
19
  /**
25
- * @description синхронный метод получения данных
20
+ * Синхронный метод получения данных
26
21
  */
27
22
  this.sync = (params) => {
28
23
  const isInstanceAllow = !(this.isLoading || this.isSuccess);
29
- if (this.isNetworkOnly || this.isInvalid || isInstanceAllow) {
24
+ if (this.isNetworkOnly || this.auxiliary.isInvalid || isInstanceAllow) {
30
25
  this.proceedSync(params);
31
26
  }
32
27
  };
33
28
  /**
34
- * @description обработчик успешного ответа
29
+ * Обработчик успешного ответа
35
30
  */
36
31
  this.submitSuccess = (resData) => {
32
+ var _a;
37
33
  this.storage.setData(resData);
38
- this.isInvalid = false;
34
+ (_a = this.submitValidity) === null || _a === void 0 ? void 0 : _a.call(this);
39
35
  return resData;
40
36
  };
41
37
  /**
42
- * @description форс метод для установки данных
38
+ * Форс метод для установки данных
43
39
  */
44
40
  this.forceUpdate = (data) => {
45
41
  this.auxiliary.submitSuccess();
46
42
  this.submitSuccess(data);
47
43
  };
48
44
  /**
49
- * @description метод для переиспользования синхронной логики запроса
45
+ * Метод для переиспользования синхронной логики запроса
50
46
  */
51
47
  this.proceedSync = (options) => {
52
48
  const { onSuccess, onError } = options || {};
@@ -67,29 +63,35 @@ export class Query {
67
63
  });
68
64
  };
69
65
  /**
70
- * @description асинхронный метод получения данных,
66
+ * Асинхронный метод получения данных,
71
67
  * предполагается, что нужно будет самостоятельно обрабатывать ошибку
72
68
  */
73
69
  this.async = () => {
74
- if (!this.isNetworkOnly && this.isSuccess && !this.isInvalid) {
70
+ if (!this.isNetworkOnly && this.isSuccess && !this.auxiliary.isInvalid) {
75
71
  return Promise.resolve(this.storage.data);
76
72
  }
77
73
  return this.auxiliary
78
74
  .getUnifiedPromise(this.executor)
79
75
  .then(this.submitSuccess);
80
76
  };
81
- this.executor = executor;
82
77
  this.defaultOnError = onError;
83
78
  this.enabledAutoFetch = enabledAutoFetch;
84
79
  this.defaultFetchPolicy = fetchPolicy;
85
80
  this.storage = dataStorage;
86
- makeAutoObservable(this);
81
+ this.submitValidity = submitValidity;
82
+ makeObservable(this, {
83
+ async: action,
84
+ sync: action,
85
+ forceUpdate: action,
86
+ data: computed,
87
+ submitSuccess: action,
88
+ });
87
89
  }
88
90
  get isNetworkOnly() {
89
91
  return this.defaultFetchPolicy === 'network-only';
90
92
  }
91
93
  /**
92
- * @description содержит реактивные данные
94
+ * Содержит реактивные данные
93
95
  * благодаря mobx, при изменении isInvalid, свойство будет вычисляться заново,
94
96
  * следовательно, стриггерится условие невалидности,
95
97
  * и начнется запрос, в результате которого, данные обновятся
@@ -99,7 +101,7 @@ export class Query {
99
101
  !this.isSuccess &&
100
102
  !this.isLoading &&
101
103
  !this.isError;
102
- if (this.isInvalid || shouldSync) {
104
+ if (this.auxiliary.isInvalid || shouldSync) {
103
105
  // т.к. при вызове апдейта, изменяются флаги, на которые подписан data,
104
106
  // нужно вызывать этот экшн асинхронно
105
107
  when(() => true, this.proceedSync);
@@ -107,31 +109,4 @@ export class Query {
107
109
  // возвращаем имеющиеся данные
108
110
  return this.storage.data;
109
111
  }
110
- /**
111
- * @description флаг загрузки данных
112
- */
113
- get isLoading() {
114
- return this.auxiliary.isLoading;
115
- }
116
- /**
117
- * @description флаг обозначающий, что последний запрос был зафейлен
118
- */
119
- get isError() {
120
- return this.auxiliary.isError;
121
- }
122
- /**
123
- * @description данные о последней ошибке
124
- */
125
- get error() {
126
- return this.auxiliary.error;
127
- }
128
- /**
129
- * @description флаг обозначающий, что последний запрос был успешно завершен
130
- */
131
- get isSuccess() {
132
- return this.auxiliary.isSuccess;
133
- }
134
- get isIdle() {
135
- return this.auxiliary.isIdle;
136
- }
137
112
  }
@@ -0,0 +1,61 @@
1
+ import { type StatusStorage } from '../StatusStorage';
2
+ export type QueryContainerAuxiliary = {
3
+ isIdle: boolean;
4
+ };
5
+ type Statuses<TError> = StatusStorage<TError>;
6
+ /**
7
+ * Контейнер для бойлерплейт части,
8
+ * позволяет не повторять в каждом наследуемом классе использование стандартных статусов
9
+ */
10
+ export declare abstract class QueryContainer<TError, TAuxiliary extends QueryContainerAuxiliary, TIsBackground extends boolean> implements Statuses<TError> {
11
+ private readonly statusStorage;
12
+ private readonly backgroundStatusStorage;
13
+ protected readonly auxiliary: TAuxiliary;
14
+ protected constructor(statusStorage: StatusStorage<TError>, backgroundStatusStorage: StatusStorage<TError> | null, auxiliary: TAuxiliary);
15
+ /**
16
+ * Флаг загрузки данных
17
+ */
18
+ get isLoading(): boolean;
19
+ /**
20
+ * Флаг обозначающий, что последний запрос был зафейлен
21
+ */
22
+ get isError(): boolean;
23
+ /**
24
+ * Данные о последней ошибке
25
+ */
26
+ get error(): TError | undefined;
27
+ /**
28
+ * Флаг обозначающий, что последний запрос был успешно завершен
29
+ */
30
+ get isSuccess(): boolean;
31
+ /**
32
+ * Флаг, обозначающий простаивание, т.е. запроса еще не было
33
+ */
34
+ get isIdle(): boolean;
35
+ /**
36
+ * Статусы, изменяющиеся после первого успешного запроса в режиме isBackground: true
37
+ * @example
38
+ * const query = mobxQuery.createQuery(
39
+ * ['some cache key'],
40
+ * () => Promise.resolve('foo'),
41
+ * { isBackground: true }
42
+ * );
43
+ *
44
+ * await query.async();
45
+ * console.log(query.isLoading); // переключался в true на момент запроса
46
+ * console.log(query.isSuccess); // true
47
+ *
48
+ * query.invalidate();
49
+ * await query.async();
50
+ * console.log(query.isLoading); // не изменялся
51
+ * console.log(query.isSuccess); // остался неизменным - true
52
+ *
53
+ * console.log(query.background.isLoading); // переключался в true на момент обновления
54
+ * console.log(query.background.isSuccess); // true
55
+ *
56
+ * @exception isBackground:false (а так же по умолчанию) background не доступен, и равен null
57
+ * @exception Mutation не доступен в мутации и равен null
58
+ */
59
+ get background(): TIsBackground extends true ? Statuses<TError> : null;
60
+ }
61
+ export {};
@@ -0,0 +1,79 @@
1
+ import { computed, makeObservable } from 'mobx';
2
+ /**
3
+ * Контейнер для бойлерплейт части,
4
+ * позволяет не повторять в каждом наследуемом классе использование стандартных статусов
5
+ */
6
+ export class QueryContainer {
7
+ constructor(statusStorage, backgroundStatusStorage, auxiliary) {
8
+ this.statusStorage = statusStorage;
9
+ this.backgroundStatusStorage = backgroundStatusStorage;
10
+ this.auxiliary = auxiliary;
11
+ makeObservable(this, {
12
+ error: computed,
13
+ isError: computed,
14
+ isIdle: computed,
15
+ isLoading: computed,
16
+ isSuccess: computed,
17
+ });
18
+ }
19
+ /**
20
+ * Флаг загрузки данных
21
+ */
22
+ get isLoading() {
23
+ return this.statusStorage.isLoading;
24
+ }
25
+ /**
26
+ * Флаг обозначающий, что последний запрос был зафейлен
27
+ */
28
+ get isError() {
29
+ return this.statusStorage.isError;
30
+ }
31
+ /**
32
+ * Данные о последней ошибке
33
+ */
34
+ get error() {
35
+ return this.statusStorage.error;
36
+ }
37
+ /**
38
+ * Флаг обозначающий, что последний запрос был успешно завершен
39
+ */
40
+ get isSuccess() {
41
+ return this.statusStorage.isSuccess;
42
+ }
43
+ /**
44
+ * Флаг, обозначающий простаивание, т.е. запроса еще не было
45
+ */
46
+ get isIdle() {
47
+ return this.auxiliary.isIdle;
48
+ }
49
+ /**
50
+ * Статусы, изменяющиеся после первого успешного запроса в режиме isBackground: true
51
+ * @example
52
+ * const query = mobxQuery.createQuery(
53
+ * ['some cache key'],
54
+ * () => Promise.resolve('foo'),
55
+ * { isBackground: true }
56
+ * );
57
+ *
58
+ * await query.async();
59
+ * console.log(query.isLoading); // переключался в true на момент запроса
60
+ * console.log(query.isSuccess); // true
61
+ *
62
+ * query.invalidate();
63
+ * await query.async();
64
+ * console.log(query.isLoading); // не изменялся
65
+ * console.log(query.isSuccess); // остался неизменным - true
66
+ *
67
+ * console.log(query.background.isLoading); // переключался в true на момент обновления
68
+ * console.log(query.background.isSuccess); // true
69
+ *
70
+ * @exception isBackground:false (а так же по умолчанию) background не доступен, и равен null
71
+ * @exception Mutation не доступен в мутации и равен null
72
+ */
73
+ get background() {
74
+ if (!this.backgroundStatusStorage) {
75
+ return null;
76
+ }
77
+ return this.backgroundStatusStorage;
78
+ }
79
+ }
@@ -0,0 +1 @@
1
+ export * from './QueryContainer';
@@ -0,0 +1 @@
1
+ export * from './QueryContainer';
package/README.md CHANGED
@@ -342,6 +342,31 @@ console.log(query.isError); // 'true'
342
342
  console.log(query.error); // 'foo'
343
343
  ```
344
344
 
345
+ ## Режим фонового обновления
346
+ `Query` и `InfiniteQuery` имеют режим фонового обновления. Предполагается, что будет хорошо подходить для обновления данных через websocket.
347
+
348
+ В этом режиме, основные статусные флаги `isSuccess`, `isLoading`, `isError`, `error` будут изменяться до первого успешного запроса. Последующие запросы уже будут изменять статусные флаги под полем `background`
349
+
350
+ ```ts
351
+ const query = mobxQuery.createQuery(
352
+ ['some cache key'],
353
+ () => Promise.resolve('foo'),
354
+ { isBackground: true }
355
+ );
356
+
357
+ await query.async();
358
+ console.log(query.isLoading); // переключался в true на момент запроса
359
+ console.log(query.isSuccess); // true
360
+
361
+ query.invalidate();
362
+ await query.async();
363
+ console.log(query.isLoading); // не изменялся
364
+ console.log(query.isSuccess); // остался неизменным - true
365
+
366
+ console.log(query.background.isLoading); // переключался в true на момент обновления
367
+ console.log(query.background.isSuccess); // true
368
+ ```
369
+
345
370
  # Тестирование
346
371
 
347
372
  ## Тестирование при включенном ```enabledAutoFetch```
@@ -0,0 +1,24 @@
1
+ import { StorageFactory } from '../StorageFactory';
2
+ export declare class StatusStorage<TError> {
3
+ constructor();
4
+ /**
5
+ * Флаг обозначающий загрузку данных
6
+ */
7
+ isLoading: boolean;
8
+ /**
9
+ * Флаг обозначающий, что последний запрос был зафейлен
10
+ */
11
+ isError: boolean;
12
+ /**
13
+ * Данные о последней ошибке
14
+ */
15
+ error?: TError;
16
+ /**
17
+ * Флаг, обозначающий успешность завершения последнего запроса
18
+ */
19
+ isSuccess: boolean;
20
+ }
21
+ export declare class StatusStorageFactory extends StorageFactory<StatusStorage<void>> {
22
+ constructor();
23
+ getStorage: <TError>(keyHash: string) => StatusStorage<TError>;
24
+ }
@@ -0,0 +1,36 @@
1
+ import { makeObservable, observable } from 'mobx';
2
+ import { StorageFactory } from '../StorageFactory';
3
+ export class StatusStorage {
4
+ constructor() {
5
+ /**
6
+ * Флаг обозначающий загрузку данных
7
+ */
8
+ this.isLoading = false;
9
+ /**
10
+ * Флаг обозначающий, что последний запрос был зафейлен
11
+ */
12
+ this.isError = false;
13
+ /**
14
+ * Данные о последней ошибке
15
+ */
16
+ this.error = undefined;
17
+ /**
18
+ * Флаг, обозначающий успешность завершения последнего запроса
19
+ */
20
+ this.isSuccess = false;
21
+ makeObservable(this, {
22
+ error: observable,
23
+ isError: observable,
24
+ isLoading: observable,
25
+ isSuccess: observable,
26
+ });
27
+ }
28
+ }
29
+ export class StatusStorageFactory extends StorageFactory {
30
+ constructor() {
31
+ super(() => new StatusStorage());
32
+ this.getStorage = (keyHash) => {
33
+ return this.getInternalStorage(keyHash);
34
+ };
35
+ }
36
+ }
@@ -0,0 +1 @@
1
+ export * from './StatusStorage';
@@ -0,0 +1 @@
1
+ export * from './StatusStorage';
@@ -0,0 +1,9 @@
1
+ export declare abstract class StorageFactory<TStorage extends {}> {
2
+ private readonly createStorage;
3
+ private readonly adaptableMap;
4
+ protected constructor(createStorage: () => TStorage);
5
+ /**
6
+ * Фабричный метод получения/создания инстанса хранилища по ключу
7
+ */
8
+ getInternalStorage: (keyHash: string) => TStorage;
9
+ }
@@ -0,0 +1,19 @@
1
+ import { AdaptableMap } from '../AdaptableMap';
2
+ export class StorageFactory {
3
+ constructor(createStorage) {
4
+ this.createStorage = createStorage;
5
+ this.adaptableMap = new AdaptableMap();
6
+ /**
7
+ * Фабричный метод получения/создания инстанса хранилища по ключу
8
+ */
9
+ this.getInternalStorage = (keyHash) => {
10
+ const storage = this.adaptableMap.get(keyHash);
11
+ if (!storage) {
12
+ const createdStorage = this.createStorage();
13
+ this.adaptableMap.set(keyHash, createdStorage);
14
+ return createdStorage;
15
+ }
16
+ return storage;
17
+ };
18
+ }
19
+ }
@@ -0,0 +1 @@
1
+ export * from './StorageFactory';
@@ -0,0 +1 @@
1
+ export * from './StorageFactory';