@fozy-labs/rx-toolkit 0.4.1 → 0.4.3
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/README.md +44 -39
- package/dist/common/devtools/combineDevtools.d.ts +2 -0
- package/dist/common/devtools/combineDevtools.js +10 -0
- package/dist/common/devtools/index.d.ts +3 -0
- package/dist/common/devtools/index.js +3 -0
- package/dist/common/devtools/reduxDevtools.d.ts +2 -0
- package/dist/common/devtools/reduxDevtools.js +24 -0
- package/dist/common/devtools/types.d.ts +6 -0
- package/dist/{query/api → common/options}/DefaultOptions.d.ts +2 -2
- package/dist/{query/api → common/options}/DefaultOptions.js +1 -1
- package/dist/common/options/SharedOptions.d.ts +5 -0
- package/dist/common/options/index.d.ts +1 -0
- package/dist/common/options/index.js +1 -0
- package/dist/{react-hooks → common/react}/index.d.ts +2 -3
- package/dist/{react-hooks → common/react}/index.js +2 -3
- package/dist/{react-hooks → common/react}/useObservable.js +2 -2
- package/dist/{react-hooks → common/react}/useSyncObservable.js +2 -1
- package/dist/index.d.ts +4 -2
- package/dist/index.js +4 -2
- package/dist/query/api/createOperation.d.ts +1 -5
- package/dist/query/api/createOperation.js +0 -4
- package/dist/query/api/createResource.d.ts +1 -1
- package/dist/query/core/Opertation/Operation.d.ts +2 -3
- package/dist/query/core/Opertation/Operation.js +6 -5
- package/dist/query/core/Opertation/OperationAgent.d.ts +3 -3
- package/dist/query/core/Opertation/OperationAgent.js +3 -3
- package/dist/query/core/QueriesCache.js +12 -6
- package/dist/query/core/Resource/Resource.d.ts +15 -3
- package/dist/query/core/Resource/Resource.js +36 -4
- package/dist/query/core/Resource/ResourceAgent.d.ts +2 -2
- package/dist/query/core/Resource/ResourceAgent.js +3 -3
- package/dist/query/core/Resource/ResourceRef.d.ts +2 -1
- package/dist/query/core/Resource/ResourceRef.js +96 -2
- package/dist/query/index.d.ts +1 -2
- package/dist/query/index.js +1 -2
- package/dist/query/lib/IndirectMap.js +1 -1
- package/dist/query/lib/ReactiveCache.js +2 -2
- package/dist/query/react/useOperationAgent.d.ts +1 -2
- package/dist/query/react/useOperationAgent.js +2 -1
- package/dist/query/react/useResourceAgent.d.ts +2 -3
- package/dist/query/react/useResourceAgent.js +4 -3
- package/dist/query/react/useResourceRef.d.ts +5 -0
- package/dist/query/react/useResourceRef.js +8 -0
- package/dist/query/types/Operation.types.d.ts +44 -3
- package/dist/query/types/Resource.types.d.ts +17 -2
- package/dist/query/types/index.d.ts +3 -0
- package/dist/query/types/index.js +3 -0
- package/dist/signals/base/Batcher.d.ts +6 -0
- package/dist/signals/base/Batcher.js +55 -0
- package/dist/{signal → signals}/base/Computed.d.ts +5 -2
- package/dist/{signal → signals}/base/Computed.js +7 -3
- package/dist/{signal → signals}/base/Effect.d.ts +3 -3
- package/dist/signals/base/Effect.js +51 -0
- package/dist/signals/base/Indexer.d.ts +4 -0
- package/dist/signals/base/Indexer.js +6 -0
- package/dist/{signal → signals}/base/ReadonlySignal.d.ts +4 -1
- package/dist/signals/base/ReadonlySignal.js +46 -0
- package/dist/{signal → signals}/base/Signal.d.ts +14 -3
- package/dist/{signal → signals}/base/Signal.js +23 -3
- package/dist/signals/base/Tracker.d.ts +10 -0
- package/dist/signals/base/Tracker.js +7 -0
- package/dist/{signal → signals}/base/types.d.ts +9 -1
- package/dist/signals/base/types.js +1 -0
- package/dist/{signal → signals}/extends/LocalSignal.d.ts +1 -1
- package/dist/{signal → signals}/extends/LocalSignal.js +3 -3
- package/dist/{signal → signals}/index.d.ts +1 -0
- package/dist/{signal → signals}/index.js +1 -0
- package/dist/{signal → signals}/operators/filterUpdates.js +1 -1
- package/dist/signals/operators/index.d.ts +3 -0
- package/dist/signals/operators/index.js +3 -0
- package/dist/{signal → signals}/operators/mapSignals.js +1 -1
- package/dist/{signal → signals}/operators/signalize.d.ts +1 -1
- package/dist/{signal → signals}/operators/signalize.js +1 -1
- package/dist/signals/react/index.d.ts +1 -0
- package/dist/signals/react/index.js +1 -0
- package/dist/{react-hooks → signals/react}/useSignal.d.ts +1 -1
- package/dist/{react-hooks → signals/react}/useSignal.js +1 -1
- package/docs/devtools/README.md +95 -0
- package/docs/query/README.md +25 -14
- package/docs/signals/README.md +11 -8
- package/package.json +13 -8
- package/dist/query/api/createDevtools.d.ts +0 -1
- package/dist/query/api/createDevtools.js +0 -6
- package/dist/query/api/createSubResource.d.ts +0 -0
- package/dist/query/api/createSubResource.js +0 -1
- package/dist/query/core/SharedOptions.d.ts +0 -5
- package/dist/signal/base/Batcher.d.ts +0 -7
- package/dist/signal/base/Batcher.js +0 -21
- package/dist/signal/base/Effect.js +0 -69
- package/dist/signal/base/ReadonlySignal.js +0 -20
- package/dist/signal/base/Tracker.d.ts +0 -5
- package/dist/signal/base/Tracker.js +0 -7
- package/dist/signal/operators/batch.d.ts +0 -2
- package/dist/signal/operators/batch.js +0 -27
- package/dist/signal/operators/index.d.ts +0 -4
- package/dist/signal/operators/index.js +0 -4
- /package/dist/{signal/base → common/devtools}/types.js +0 -0
- /package/dist/{query/core → common/options}/SharedOptions.js +0 -0
- /package/dist/{react-hooks → common/react}/useConstant.d.ts +0 -0
- /package/dist/{react-hooks → common/react}/useConstant.js +0 -0
- /package/dist/{react-hooks → common/react}/useEventHandler.d.ts +0 -0
- /package/dist/{react-hooks → common/react}/useEventHandler.js +0 -0
- /package/dist/{react-hooks → common/react}/useObservable.d.ts +0 -0
- /package/dist/{react-hooks → common/react}/useSyncObservable.d.ts +0 -0
- /package/dist/{signal → signals}/base/SyncObservable.d.ts +0 -0
- /package/dist/{signal → signals}/base/SyncObservable.js +0 -0
- /package/dist/{signal → signals}/base/index.d.ts +0 -0
- /package/dist/{signal → signals}/base/index.js +0 -0
- /package/dist/{signal → signals}/extends/index.d.ts +0 -0
- /package/dist/{signal → signals}/extends/index.js +0 -0
- /package/dist/{signal → signals}/operators/filterUpdates.d.ts +0 -0
- /package/dist/{signal → signals}/operators/mapSignals.d.ts +0 -0
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import { type Observable, Subject } from "rxjs";
|
|
2
|
+
type TrackedValue = {
|
|
3
|
+
rang: number;
|
|
4
|
+
obsv$: Observable<unknown>;
|
|
5
|
+
};
|
|
6
|
+
export declare const Tracker: {
|
|
7
|
+
tracked$: Subject<TrackedValue>;
|
|
8
|
+
next(rang: number, observable: Observable<unknown>): void;
|
|
9
|
+
};
|
|
10
|
+
export {};
|
|
@@ -7,9 +7,17 @@ export interface ReadableSignalLike<T = unknown> extends Observable<T> {
|
|
|
7
7
|
*/
|
|
8
8
|
get(): T;
|
|
9
9
|
}
|
|
10
|
+
export interface SignalLike<T = unknown> extends ReadableSignalLike<T> {
|
|
11
|
+
set value(value: T);
|
|
12
|
+
next(value: T): void;
|
|
13
|
+
asReadonly(): ReadableSignalLike<T>;
|
|
14
|
+
/**
|
|
15
|
+
* @deprecated use `value` instead.
|
|
16
|
+
*/
|
|
17
|
+
set(value: T): void;
|
|
18
|
+
}
|
|
10
19
|
export interface UnaryFunction<T, R> {
|
|
11
20
|
(source: T): R;
|
|
12
21
|
}
|
|
13
22
|
export type SignalOperatorFn<T, R> = UnaryFunction<ReadableSignalLike<T>, ReadableSignalLike<R>>;
|
|
14
23
|
export type MonoTypeSignalOperatorFn<T> = SignalOperatorFn<T, T>;
|
|
15
|
-
export type ObservableToSignalFn<T> = UnaryFunction<Observable<T>, ReadableSignalLike<T>>;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import { signalize } from "../../signal/operators";
|
|
2
1
|
import { z } from "zod/v4";
|
|
3
|
-
import { Computed } from "
|
|
2
|
+
import { Computed } from "../base";
|
|
3
|
+
import { signalize } from "../operators";
|
|
4
4
|
const NullOrString = z.string().nullable();
|
|
5
5
|
const NONE = Symbol('NONE');
|
|
6
6
|
export class LocalSignal extends Computed {
|
|
@@ -56,7 +56,7 @@ export class LocalSignal extends Computed {
|
|
|
56
56
|
return checkEffect(value) ? value : defaultValue;
|
|
57
57
|
}
|
|
58
58
|
return value;
|
|
59
|
-
});
|
|
59
|
+
}, { devtoolsName: 'LocalSignal' });
|
|
60
60
|
this._options = _options;
|
|
61
61
|
}
|
|
62
62
|
_onChange(value) {
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { createOperatorSubscriber } from "rxjs/internal/operators/OperatorSubscriber";
|
|
2
|
-
import { ReadonlySignal } from "
|
|
2
|
+
import { ReadonlySignal } from "../base";
|
|
3
3
|
export function filterUpdates(predicate, thisArg) {
|
|
4
4
|
return (source) => new ReadonlySignal((destination) => {
|
|
5
5
|
let index = 0;
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { createOperatorSubscriber } from "rxjs/internal/operators/OperatorSubscriber";
|
|
2
|
-
import { ReadonlySignal } from "
|
|
2
|
+
import { ReadonlySignal } from "../base";
|
|
3
3
|
export function mapSignals(project, thisArg) {
|
|
4
4
|
return (source) => new ReadonlySignal((destination) => {
|
|
5
5
|
let index = 0;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from './useSignal';
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from './useSignal';
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import
|
|
1
|
+
import { ReadableSignalLike } from "../../signals";
|
|
2
2
|
export declare function useSignal<T>(signal$: ReadableSignalLike<T>): T;
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import React from "react";
|
|
2
|
-
import { useEventHandler } from "
|
|
2
|
+
import { useEventHandler } from "../../common/react";
|
|
3
3
|
export function useSignal(signal$) {
|
|
4
4
|
const subscribe = React.useCallback((update) => {
|
|
5
5
|
const subscription = signal$.subscribe(update);
|
|
@@ -0,0 +1,95 @@
|
|
|
1
|
+
# Devtools
|
|
2
|
+
|
|
3
|
+
RxToolkit предоставляет интеграцию с популярными инструментами разработчика для отладки реактивных приложений в реальном времени. Вы можете отслеживать изменения сигналов, выполнение операций и состояние ресурсов, анализировать граф зависимостей и исследовать поведение реактивной системы.
|
|
4
|
+
|
|
5
|
+
**Отслеживает изменения состояния:**
|
|
6
|
+
- Сигналов (Signal/Computed)
|
|
7
|
+
- Ресурсов и операций (Resource/Operation)
|
|
8
|
+
|
|
9
|
+
## Redux DevTools
|
|
10
|
+
|
|
11
|
+
Популярное браузерное расширение для отладки состояния приложений. **RxToolkit включает встроенный адаптер `reduxDevtools()`**.
|
|
12
|
+
|
|
13
|
+
**Установка:**
|
|
14
|
+
1. Установите [расширение](https://github.com/reduxjs/redux-devtools) для браузера
|
|
15
|
+
2. Подключите в коде:
|
|
16
|
+
|
|
17
|
+
```typescript
|
|
18
|
+
import { DefaultOptions, reduxDevtools } from '@fozy-labs/rx-toolkit';
|
|
19
|
+
|
|
20
|
+
DefaultOptions.update({
|
|
21
|
+
DEVTOOLS: reduxDevtools()
|
|
22
|
+
});
|
|
23
|
+
```
|
|
24
|
+
|
|
25
|
+
## @reatom/devtools
|
|
26
|
+
|
|
27
|
+
Npm пакет, содержащий отладчик, работающий прямо в браузере.
|
|
28
|
+
Совместим по API с `rx-toolkit`.
|
|
29
|
+
После подключения в углу страницы появляется кнопка,
|
|
30
|
+
которая открывает панель инструментов.
|
|
31
|
+
|
|
32
|
+
**Установка:**
|
|
33
|
+
```bash
|
|
34
|
+
npm install @reatom/devtools
|
|
35
|
+
```
|
|
36
|
+
|
|
37
|
+
**Подключение:**
|
|
38
|
+
```typescript
|
|
39
|
+
import { DefaultOptions } from '@fozy-labs/rx-toolkit';
|
|
40
|
+
import { createDevtools } from '@reatom/devtools';
|
|
41
|
+
|
|
42
|
+
DefaultOptions.update({
|
|
43
|
+
DEVTOOLS: createDevtools({
|
|
44
|
+
initVisibility: true
|
|
45
|
+
})
|
|
46
|
+
});
|
|
47
|
+
```
|
|
48
|
+
|
|
49
|
+
**Может пригодиться:**
|
|
50
|
+
- Если в вашей среде не удобно или проблематично установить браузерное расширение.
|
|
51
|
+
- Если вы уже работали с Reatom.
|
|
52
|
+
|
|
53
|
+
## Практики
|
|
54
|
+
|
|
55
|
+
### Development-режим
|
|
56
|
+
|
|
57
|
+
Подключайте devtools только в разработке:
|
|
58
|
+
|
|
59
|
+
```typescript
|
|
60
|
+
// Node.js/Webpack
|
|
61
|
+
if (process.env.NODE_ENV !== 'production') {
|
|
62
|
+
DefaultOptions.update({ DEVTOOLS: reduxDevtools() });
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
// Vite
|
|
66
|
+
if (import.meta.env.DEV) {
|
|
67
|
+
DefaultOptions.update({ DEVTOOLS: reduxDevtools() });
|
|
68
|
+
}
|
|
69
|
+
```
|
|
70
|
+
|
|
71
|
+
### SSR-совместимость
|
|
72
|
+
|
|
73
|
+
Защитите от выполнения на сервере:
|
|
74
|
+
|
|
75
|
+
```typescript
|
|
76
|
+
if (typeof window !== 'undefined' && process.env.NODE_ENV !== 'production') {
|
|
77
|
+
DefaultOptions.update({ DEVTOOLS: reduxDevtools() });
|
|
78
|
+
}
|
|
79
|
+
```
|
|
80
|
+
|
|
81
|
+
### Несколько инструментов
|
|
82
|
+
|
|
83
|
+
Можно комбинировать несколько devtools:
|
|
84
|
+
|
|
85
|
+
```typescript
|
|
86
|
+
import { combineDevtools, reduxDevtools } from '@fozy-labs/rx-toolkit';
|
|
87
|
+
import { createDevtools } from '@reatom/devtools';
|
|
88
|
+
|
|
89
|
+
DefaultOptions.update({
|
|
90
|
+
DEVTOOLS: combineDevtools(
|
|
91
|
+
reduxDevtools({ name: 'MyApp' }),
|
|
92
|
+
createDevtools({ initVisibility: true })
|
|
93
|
+
)
|
|
94
|
+
});
|
|
95
|
+
```
|
package/docs/query/README.md
CHANGED
|
@@ -28,6 +28,7 @@ Operations представляют одноразовые операции ил
|
|
|
28
28
|
Agents представляют собой интеллектуальные обертки над ресурсами (или операциями),
|
|
29
29
|
которые обеспечивают более удобную работу с состояниями запросов для потребителей.
|
|
30
30
|
|
|
31
|
+
|
|
31
32
|
#### Основная проблема, которую решают агенты
|
|
32
33
|
|
|
33
34
|
Кэш ресурсов (или операций) содержит "сырые" состояния отдельных запросов, но потребителям нужна более высокоуровневая логика.
|
|
@@ -36,6 +37,15 @@ Agents представляют собой интеллектуальные об
|
|
|
36
37
|
- При смене аргументов запроса нужно показывать данные предыдущего запроса, пока загружается новый
|
|
37
38
|
- Состояние загрузки должно отражать контекст использования, а не просто состояние кэша
|
|
38
39
|
|
|
40
|
+
|
|
41
|
+
### ResourceRef (Ссылка на ресурс)
|
|
42
|
+
Ref - это абстракция, для взаимодействия с ресурсом.
|
|
43
|
+
|
|
44
|
+
**Особенности:**
|
|
45
|
+
- Операции использует ref под капотом, чтобы управлять связанным ресурсом.
|
|
46
|
+
- Ref могут ссылаться на отсутствующий ресурс.
|
|
47
|
+
|
|
48
|
+
|
|
39
49
|
## API
|
|
40
50
|
|
|
41
51
|
### createResource
|
|
@@ -98,6 +108,7 @@ const updateUser = createOperation<
|
|
|
98
108
|
|
|
99
109
|
## Свойства Link
|
|
100
110
|
```typescript
|
|
111
|
+
|
|
101
112
|
/**
|
|
102
113
|
* Настройки связи операции с ресурсом
|
|
103
114
|
*/
|
|
@@ -107,30 +118,30 @@ export type LinkOptions<D extends OperationDefinition, RD extends ResourceDefini
|
|
|
107
118
|
* @required
|
|
108
119
|
*/
|
|
109
120
|
resource: ResourceInstance<RD>;
|
|
110
|
-
|
|
121
|
+
|
|
111
122
|
/**
|
|
112
|
-
* Функция для получения аргументов ресурса из аргументов
|
|
123
|
+
* Функция для получения аргументов ресурса из аргументов операции.
|
|
113
124
|
* Используется для определения какой именно элемент в кэше ресурса нужно обновить
|
|
114
125
|
* @required
|
|
115
126
|
*/
|
|
116
127
|
forwardArgs: (args: D["Args"]) => RD["Args"];
|
|
117
|
-
|
|
128
|
+
|
|
118
129
|
/**
|
|
119
|
-
* Флаг для инвалидации (очистки) кэша ресурса после выполнения
|
|
130
|
+
* Флаг для инвалидации (очистки) кэша ресурса после выполнения операции.
|
|
120
131
|
* При true - кэш будет очищен и ресурс будет перезагружен при следующем обращении
|
|
121
132
|
* @optional @default false
|
|
122
133
|
*/
|
|
123
134
|
invalidate?: boolean;
|
|
124
|
-
|
|
135
|
+
|
|
125
136
|
/**
|
|
126
|
-
* Флаг для блокировки ресурса во время выполнения
|
|
137
|
+
* Флаг для блокировки ресурса во время выполнения операции.
|
|
127
138
|
* При true - ресурс будет заблокирован и не сможет выполнять новые запросы
|
|
128
139
|
* @optional @default false
|
|
129
140
|
*/
|
|
130
141
|
lock?: boolean;
|
|
131
|
-
|
|
142
|
+
|
|
132
143
|
/**
|
|
133
|
-
* Функция для обновления кэша ресурса после успешного выполнения
|
|
144
|
+
* Функция для обновления кэша ресурса после успешного выполнения операции.
|
|
134
145
|
* Получает draft объект для мутации, аргументы операции и результат операции
|
|
135
146
|
* @optional
|
|
136
147
|
*/
|
|
@@ -141,10 +152,10 @@ export type LinkOptions<D extends OperationDefinition, RD extends ResourceDefini
|
|
|
141
152
|
args: D["Args"];
|
|
142
153
|
/** Результат выполнения операции */
|
|
143
154
|
data: D["Data"];
|
|
144
|
-
}) => void | RD["Data"]
|
|
145
|
-
|
|
155
|
+
}) => void | RD["Data"];
|
|
156
|
+
|
|
146
157
|
/**
|
|
147
|
-
* Функция для оптимистичного обновления кэша ресурса ДО выполнения
|
|
158
|
+
* Функция для оптимистичного обновления кэша ресурса ДО выполнения операции.
|
|
148
159
|
* Позволяет обновить UI немедленно, до получения ответа от сервера
|
|
149
160
|
* @optional
|
|
150
161
|
*/
|
|
@@ -153,10 +164,10 @@ export type LinkOptions<D extends OperationDefinition, RD extends ResourceDefini
|
|
|
153
164
|
draft: RD["Data"];
|
|
154
165
|
/** Аргументы, с которыми была вызвана операция */
|
|
155
166
|
args: D["Args"];
|
|
156
|
-
}) => void | RD["Data"]
|
|
157
|
-
|
|
167
|
+
}) => void | RD["Data"];
|
|
168
|
+
|
|
158
169
|
/**
|
|
159
|
-
* Функция для создания нового элемента в кэше
|
|
170
|
+
* Функция для создания нового элемента в кэше ресурса.
|
|
160
171
|
* Используется когда операция создает новую сущность, которую нужно добавить в кэш
|
|
161
172
|
* @optional
|
|
162
173
|
*/
|
package/docs/signals/README.md
CHANGED
|
@@ -17,7 +17,7 @@ const age = new Signal(25);
|
|
|
17
17
|
// Подписка на изменения
|
|
18
18
|
const subscription = name.subscribe(newName => {
|
|
19
19
|
console.log(`Name changed to: ${newName}`);
|
|
20
|
-
});
|
|
20
|
+
}); // Выведет: "Name changed to: John" при инициализации
|
|
21
21
|
|
|
22
22
|
name.value = 'Jane'; // Выведет: "Name changed to: Jane"
|
|
23
23
|
|
|
@@ -67,10 +67,18 @@ sub.unsubscribe();
|
|
|
67
67
|
// TODO убрать zod из core, добавить возможность передавать "driver".
|
|
68
68
|
|
|
69
69
|
```typescript
|
|
70
|
+
import { z } from 'zod/v4';
|
|
70
71
|
import { LocalSignal } from '@fozy-labs/rx-toolkit';
|
|
71
72
|
|
|
73
|
+
enum FILTER {
|
|
74
|
+
ALL = 'all',
|
|
75
|
+
CHANNELS = 'channels',
|
|
76
|
+
CHATS = 'chats',
|
|
77
|
+
MEETINGS = 'meetings',
|
|
78
|
+
}
|
|
79
|
+
|
|
72
80
|
const selectedFilter$ = new LocalSignal({
|
|
73
|
-
key: '
|
|
81
|
+
key: 'memberships-list-selected-filter',
|
|
74
82
|
defaultValue: FILTER.ALL,
|
|
75
83
|
zodSchema: z.enum(FILTER),
|
|
76
84
|
});
|
|
@@ -78,10 +86,6 @@ const selectedFilter$ = new LocalSignal({
|
|
|
78
86
|
|
|
79
87
|
## Operators (Операторы)
|
|
80
88
|
|
|
81
|
-
### batched
|
|
82
|
-
Группирует несколько обновлений в одну транзакцию для оптимизации производительности.
|
|
83
|
-
// TODO: проверить, тк не используется в fozy, добавить пример использования
|
|
84
|
-
|
|
85
89
|
### mapSignals
|
|
86
90
|
// TODO: добавить описание
|
|
87
91
|
|
|
@@ -91,9 +95,8 @@ const selectedFilter$ = new LocalSignal({
|
|
|
91
95
|
Преобразует Observable в Signal.
|
|
92
96
|
|
|
93
97
|
```typescript
|
|
94
|
-
import { signalize } from '@fozy-labs/rx-toolkit';
|
|
95
98
|
import { interval } from 'rxjs';
|
|
96
|
-
import { Effect } from
|
|
99
|
+
import { signalize, Effect } from '@fozy-labs/rx-toolkit';
|
|
97
100
|
|
|
98
101
|
// Создаем Observable, который эмитит значение каждую секунду
|
|
99
102
|
const timer$ = interval(1000).pipe(
|
package/package.json
CHANGED
|
@@ -1,22 +1,19 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@fozy-labs/rx-toolkit",
|
|
3
|
-
"version": "0.4.
|
|
3
|
+
"version": "0.4.3",
|
|
4
4
|
"main": "./dist/index.js",
|
|
5
5
|
"types": "./dist/index.d.ts",
|
|
6
6
|
"type": "module",
|
|
7
7
|
"scripts": {
|
|
8
8
|
"build": "rimraf ./dist && tsc && tsc-alias",
|
|
9
|
-
"build:watch": "
|
|
9
|
+
"build:watch": "npm run build && (concurrently \"tsc -w\" \"tsc-alias -w\")",
|
|
10
10
|
"ts-check": "tsc --noEmit"
|
|
11
11
|
},
|
|
12
|
-
"dependencies": {
|
|
13
|
-
"@reatom/devtools": "0.13.1"
|
|
14
|
-
},
|
|
15
12
|
"devDependencies": {
|
|
13
|
+
"concurrently": "9.2.0",
|
|
16
14
|
"rimraf": "6.0.1",
|
|
17
15
|
"tsc-alias": "^1.8.16",
|
|
18
16
|
"tsconfig-paths": "4.2.0",
|
|
19
|
-
"concurrently": "9.2.0",
|
|
20
17
|
"typescript": "5.9.2",
|
|
21
18
|
"zod": "4.1.11"
|
|
22
19
|
},
|
|
@@ -29,7 +26,12 @@
|
|
|
29
26
|
"author": "Vladimir Panev <vova6255@gmail.com>",
|
|
30
27
|
"homepage": "https://github.com/fozy-labs/rx-toolkit",
|
|
31
28
|
"license": "MIT",
|
|
32
|
-
"keywords": [
|
|
29
|
+
"keywords": [
|
|
30
|
+
"react",
|
|
31
|
+
"rxjs",
|
|
32
|
+
"toolkit",
|
|
33
|
+
"state-management"
|
|
34
|
+
],
|
|
33
35
|
"repository": {
|
|
34
36
|
"type": "git",
|
|
35
37
|
"url": "git+https://github.com/fozy-labs/rx-toolkit.git"
|
|
@@ -53,5 +55,8 @@
|
|
|
53
55
|
"publishConfig": {
|
|
54
56
|
"access": "public"
|
|
55
57
|
},
|
|
56
|
-
"preferGlobal": false
|
|
58
|
+
"preferGlobal": false,
|
|
59
|
+
"dependencies": {
|
|
60
|
+
"immer": "^10.1.3"
|
|
61
|
+
}
|
|
57
62
|
}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
export declare function createDevtools(): import("@reatom/devtools").Devtools;
|
|
File without changes
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
@@ -1,21 +0,0 @@
|
|
|
1
|
-
import { BehaviorSubject } from "rxjs";
|
|
2
|
-
export const Batcher = {
|
|
3
|
-
isLocked$: new BehaviorSubject(false),
|
|
4
|
-
lock() {
|
|
5
|
-
if (this.isLocked$.value)
|
|
6
|
-
return;
|
|
7
|
-
this.isLocked$.next(true);
|
|
8
|
-
},
|
|
9
|
-
unlock() {
|
|
10
|
-
if (!this.isLocked$.value)
|
|
11
|
-
return;
|
|
12
|
-
this.isLocked$.next(false);
|
|
13
|
-
},
|
|
14
|
-
batch(fn) {
|
|
15
|
-
if (this.isLocked$.value)
|
|
16
|
-
return fn();
|
|
17
|
-
this.lock();
|
|
18
|
-
fn();
|
|
19
|
-
this.unlock();
|
|
20
|
-
},
|
|
21
|
-
};
|
|
@@ -1,69 +0,0 @@
|
|
|
1
|
-
import { Batcher } from "../../signal/base/Batcher";
|
|
2
|
-
import { Tracker } from "./Tracker";
|
|
3
|
-
export class Effect {
|
|
4
|
-
_doLog;
|
|
5
|
-
closed = false;
|
|
6
|
-
_subscriptions = [];
|
|
7
|
-
constructor(effectFn, _doLog = false) {
|
|
8
|
-
this._doLog = _doLog;
|
|
9
|
-
if (this._doLog)
|
|
10
|
-
console.log("Run EffectFn. Reason: init");
|
|
11
|
-
this._runInTrackedContext(effectFn, false);
|
|
12
|
-
}
|
|
13
|
-
/**
|
|
14
|
-
* Выполняет функцию в tracked-контексте, подписываясь на Tracker.
|
|
15
|
-
*/
|
|
16
|
-
_runInTrackedContext(effectFn, doUnsubscribe = true) {
|
|
17
|
-
// Отписываемся от предыдущих подписок
|
|
18
|
-
if (doUnsubscribe) {
|
|
19
|
-
this._subscriptions.forEach((sub) => sub.unsubscribe());
|
|
20
|
-
this._subscriptions = [];
|
|
21
|
-
}
|
|
22
|
-
let isTrackedContext = true;
|
|
23
|
-
let isWaitingBatching = false;
|
|
24
|
-
// Подписываемся на Tracker. Во время выполнения подпишемся на все tracked наблюдатели.
|
|
25
|
-
const trackerSub = Tracker.tracked$.subscribe((tracked$) => {
|
|
26
|
-
if (!isTrackedContext)
|
|
27
|
-
return;
|
|
28
|
-
this._subscriptions.push(tracked$.subscribe(() => {
|
|
29
|
-
if (isTrackedContext) {
|
|
30
|
-
return;
|
|
31
|
-
}
|
|
32
|
-
if (isWaitingBatching) {
|
|
33
|
-
if (this._doLog)
|
|
34
|
-
console.log("Effect: still waiting for batching to finish", { tracked$ });
|
|
35
|
-
return;
|
|
36
|
-
}
|
|
37
|
-
if (Batcher.isLocked$.value) {
|
|
38
|
-
// console.log("Effect: waiting for batching to finish");
|
|
39
|
-
isWaitingBatching = true;
|
|
40
|
-
const sub = Batcher.isLocked$
|
|
41
|
-
.subscribe((isLocked) => {
|
|
42
|
-
if (isLocked)
|
|
43
|
-
return;
|
|
44
|
-
sub.unsubscribe();
|
|
45
|
-
isWaitingBatching = false;
|
|
46
|
-
if (this._doLog)
|
|
47
|
-
console.log("Run EffectFn. Reason: tracked observable change after batching", { tracked$ });
|
|
48
|
-
this._runInTrackedContext(effectFn);
|
|
49
|
-
});
|
|
50
|
-
return;
|
|
51
|
-
}
|
|
52
|
-
if (this._doLog)
|
|
53
|
-
console.log("Run EffectFn. Reason: tracked observable change", { tracked$ });
|
|
54
|
-
this._runInTrackedContext(effectFn);
|
|
55
|
-
}));
|
|
56
|
-
});
|
|
57
|
-
effectFn((fn) => {
|
|
58
|
-
if (this._doLog)
|
|
59
|
-
console.log("Run EffectFn. Reason: manual trigger sub context");
|
|
60
|
-
this._runInTrackedContext(fn, false);
|
|
61
|
-
});
|
|
62
|
-
trackerSub.unsubscribe();
|
|
63
|
-
isTrackedContext = false;
|
|
64
|
-
}
|
|
65
|
-
unsubscribe() {
|
|
66
|
-
this.closed = true;
|
|
67
|
-
this._subscriptions.forEach((sub) => sub.unsubscribe());
|
|
68
|
-
}
|
|
69
|
-
}
|
|
@@ -1,20 +0,0 @@
|
|
|
1
|
-
import { SyncObservable } from "./SyncObservable";
|
|
2
|
-
import { Tracker } from "./Tracker";
|
|
3
|
-
export class ReadonlySignal extends SyncObservable {
|
|
4
|
-
constructor(subscribe) {
|
|
5
|
-
super(subscribe);
|
|
6
|
-
}
|
|
7
|
-
get value() {
|
|
8
|
-
Tracker.next(this);
|
|
9
|
-
return super.value;
|
|
10
|
-
}
|
|
11
|
-
peek() {
|
|
12
|
-
return super.value;
|
|
13
|
-
}
|
|
14
|
-
/**
|
|
15
|
-
* @deprecated
|
|
16
|
-
*/
|
|
17
|
-
get() {
|
|
18
|
-
return this.value;
|
|
19
|
-
}
|
|
20
|
-
}
|
|
@@ -1,27 +0,0 @@
|
|
|
1
|
-
import { createOperatorSubscriber } from "rxjs/internal/operators/OperatorSubscriber";
|
|
2
|
-
import { ReadonlySignal, Batcher } from "../base";
|
|
3
|
-
export function batched() {
|
|
4
|
-
return (source) => {
|
|
5
|
-
let lockSubscription = null;
|
|
6
|
-
let lastResult = undefined;
|
|
7
|
-
return new ReadonlySignal((destination) => source.subscribe(createOperatorSubscriber(destination, (value) => {
|
|
8
|
-
if (lockSubscription) {
|
|
9
|
-
lastResult = value;
|
|
10
|
-
return;
|
|
11
|
-
}
|
|
12
|
-
if (Batcher.isLocked$.value) {
|
|
13
|
-
lastResult = value;
|
|
14
|
-
lockSubscription = Batcher.isLocked$.subscribe((isLocked) => {
|
|
15
|
-
if (!isLocked) {
|
|
16
|
-
lockSubscription.unsubscribe();
|
|
17
|
-
lockSubscription = null;
|
|
18
|
-
destination.next(lastResult);
|
|
19
|
-
lastResult = undefined;
|
|
20
|
-
}
|
|
21
|
-
});
|
|
22
|
-
return;
|
|
23
|
-
}
|
|
24
|
-
destination.next(value);
|
|
25
|
-
})));
|
|
26
|
-
};
|
|
27
|
-
}
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|