@fozy-labs/rx-toolkit 0.4.18 → 0.5.0-rc.1

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.
Files changed (77) hide show
  1. package/README.md +20 -19
  2. package/dist/common/devtools/reduxDevtools.d.ts +17 -0
  3. package/dist/common/devtools/reduxDevtools.js +98 -17
  4. package/dist/common/devtools/types.d.ts +1 -0
  5. package/dist/common/options/DefaultOptions.d.ts +0 -2
  6. package/dist/common/options/DefaultOptions.js +0 -2
  7. package/dist/common/options/SharedOptions.d.ts +0 -2
  8. package/dist/common/options/SharedOptions.js +0 -1
  9. package/dist/query/api/resetAllQueriesCache.d.ts +1 -0
  10. package/dist/query/api/resetAllQueriesCache.js +4 -0
  11. package/dist/query/core/Opertation/Operation.js +10 -7
  12. package/dist/query/core/Opertation/OperationAgent.d.ts +0 -2
  13. package/dist/query/core/Opertation/OperationAgent.js +4 -21
  14. package/dist/query/core/QueriesCache.d.ts +1 -1
  15. package/dist/query/core/QueriesCache.js +2 -6
  16. package/dist/query/core/{CleanAllQueriesSignal.d.ts → ResetAllQueriesSignal.d.ts} +1 -1
  17. package/dist/query/core/ResetAllQueriesSignal.js +11 -0
  18. package/dist/query/core/Resource/Resource.js +7 -3
  19. package/dist/query/core/Resource/ResourceAgent.d.ts +2 -3
  20. package/dist/query/core/Resource/ResourceAgent.js +62 -29
  21. package/dist/query/index.d.ts +1 -1
  22. package/dist/query/index.js +1 -1
  23. package/dist/query/lib/IndirectMap.d.ts +1 -1
  24. package/dist/query/lib/IndirectMap.js +1 -1
  25. package/dist/query/lib/ReactiveCache.d.ts +1 -1
  26. package/dist/query/lib/ReactiveCache.js +2 -2
  27. package/dist/query/react/useOperationAgent.js +2 -5
  28. package/dist/query/react/useResourceAgent.js +1 -4
  29. package/dist/query/types/Operation.types.d.ts +1 -3
  30. package/dist/query/types/Resource.types.d.ts +1 -3
  31. package/dist/signals/base/Batcher.d.ts +1 -1
  32. package/dist/signals/base/Batcher.js +1 -1
  33. package/dist/signals/base/DependencyTracker.d.ts +18 -0
  34. package/dist/signals/base/DependencyTracker.js +13 -0
  35. package/dist/signals/base/Devtools.d.ts +1 -1
  36. package/dist/signals/base/Devtools.js +13 -1
  37. package/dist/signals/base/ReadonlySignal.d.ts +5 -7
  38. package/dist/signals/base/ReadonlySignal.js +20 -12
  39. package/dist/signals/base/index.d.ts +1 -2
  40. package/dist/signals/base/index.js +1 -2
  41. package/dist/signals/operators/index.d.ts +0 -2
  42. package/dist/signals/operators/index.js +0 -2
  43. package/dist/signals/operators/signalize.d.ts +2 -2
  44. package/dist/signals/operators/signalize.js +1 -1
  45. package/dist/signals/react/useSignal.d.ts +6 -2
  46. package/dist/signals/react/useSignal.js +2 -21
  47. package/dist/signals/signals/Computed.d.ts +13 -11
  48. package/dist/signals/signals/Computed.js +79 -26
  49. package/dist/signals/signals/Effect.d.ts +11 -7
  50. package/dist/signals/signals/Effect.js +60 -58
  51. package/dist/signals/signals/LocalSignal.d.ts +14 -7
  52. package/dist/signals/signals/LocalSignal.js +53 -36
  53. package/dist/signals/signals/Signal.d.ts +13 -37
  54. package/dist/signals/signals/Signal.js +44 -58
  55. package/dist/signals/types/index.d.ts +1 -0
  56. package/dist/signals/types/index.js +1 -0
  57. package/dist/signals/types/signals.types.d.ts +16 -0
  58. package/docs/CHANGELOG.md +32 -0
  59. package/docs/devtools/README.md +162 -29
  60. package/docs/migrations/0.5.0.md +73 -0
  61. package/docs/options/README.md +89 -0
  62. package/docs/query/README.md +425 -89
  63. package/docs/release/README.md +58 -6
  64. package/docs/signals/README.md +207 -34
  65. package/docs/usage/react/README.md +261 -49
  66. package/package.json +1 -1
  67. package/dist/query/api/cleanAllQueriesCache.d.ts +0 -1
  68. package/dist/query/api/cleanAllQueriesCache.js +0 -4
  69. package/dist/query/core/CleanAllQueriesSignal.js +0 -11
  70. package/dist/signals/base/Tracker.d.ts +0 -10
  71. package/dist/signals/base/Tracker.js +0 -7
  72. package/dist/signals/base/types.d.ts +0 -23
  73. package/dist/signals/operators/filterUpdates.d.ts +0 -5
  74. package/dist/signals/operators/filterUpdates.js +0 -18
  75. package/dist/signals/operators/mapSignals.d.ts +0 -3
  76. package/dist/signals/operators/mapSignals.js +0 -10
  77. /package/dist/signals/{base/types.js → types/signals.types.js} +0 -0
@@ -1,7 +1,59 @@
1
- ```shell
2
- npm run ts-check
3
- npm run build
4
- npm version patch
5
- npm publish
6
- git push origin develop --tag
1
+ # Релиз
2
+
3
+ Процесс выпуска новой версии RxToolkit.
4
+
5
+ ## Подготовка
6
+
7
+ 1. Убедитесь, что все изменения закоммичены
8
+ 2. Обновите CHANGELOG (если есть)
9
+ 3. Проверьте документацию
10
+
11
+ ## Команды релиза
12
+
13
+ ```bash
14
+ # 1. Проверка типов
15
+ npm run ts-check
16
+
17
+ # 2. Сборка проекта
18
+ npm run build
19
+
20
+ # 3. Обновление версии
21
+ npm version patch # для патч-версии (0.4.18 -> 0.4.19)
22
+ npm version minor # для минорной версии (0.4.18 -> 0.5.0)
23
+ npm version major # для мажорной версии (0.4.18 -> 1.0.0)
24
+
25
+ # 4. Публикация в npm
26
+ npm publish
27
+
28
+ # 5. Пуш тегов в репозиторий
29
+ git push origin develop --tags
30
+ ```
31
+
32
+ ## rc
33
+
34
+ ### Выпуск релиза-кандидата (RC)
35
+
36
+ ```bash
37
+ # 1. Проверка типов
38
+ npm run ts-check
39
+
40
+ # 2. Сборка проекта
41
+ npm run build
42
+
43
+ # 3. Обновление версии до RC
44
+ npm version prerelease --preid=rc
45
+ # пример: 1.2.0 → 1.2.0-rc.0
46
+
47
+ # 4. Публикация RC (НЕ latest!)
48
+ npm publish --tag rc
49
+
50
+ # 5. Пуш тегов
51
+ git push origin develop --tags
52
+ ```
53
+
54
+ ### Переход с RC на stable
55
+ ```bash
56
+ npm version <latest_version>
57
+ npm publish
58
+ git push origin develop --tags
7
59
  ```
@@ -6,65 +6,160 @@ RxSignals — это реактивная система управления с
6
6
 
7
7
  ### Signal
8
8
 
9
- Базовый класс для создания реактивных сигналов.
9
+ Базовый класс для создания реактивных сигналов с изменяемым состоянием.
10
10
 
11
11
  **Пример использования:**
12
12
 
13
13
  ```typescript
14
+ import { Signal } from '@fozy-labs/rx-toolkit';
15
+
14
16
  const name = new Signal('John');
15
17
  const age = new Signal(25);
16
18
 
17
- // Подписка на изменения
18
- const subscription = name.subscribe(newName => {
19
- console.log(`Name changed to: ${newName}`);
20
- }); // Выведет: "Name changed to: John" при инициализации
19
+ // Чтение значения (с отслеживанием зависимостей)
20
+ console.log(name.get()); // "John"
21
21
 
22
- name.value = 'Jane'; // Выведет: "Name changed to: Jane"
22
+ // Чтение значения без отслеживания
23
+ console.log(name.peek()); // "John"
24
+
25
+ // Запись нового значения
26
+ name.set('Jane');
27
+
28
+ // Подписка на изменения через RxJS Observable
29
+ const subscription = name.obs.subscribe(newName => {
30
+ console.log(`Name changed to: ${newName}`);
31
+ });
23
32
 
24
33
  // Отписка
25
34
  subscription.unsubscribe();
26
35
  ```
27
36
 
37
+ **API Signal:**
38
+ - `get()` — получить значение и зарегистрировать зависимость (для использования внутри Computed/Effect)
39
+ - `peek()` — получить значение без регистрации зависимости
40
+ - `set(value)` — установить новое значение
41
+ - `obs` — RxJS Observable для подписки на изменения
42
+
28
43
  ### Computed
29
44
 
30
45
  Создает вычисляемое значение, которое автоматически обновляется при изменении зависимостей.
31
46
 
32
47
  ```typescript
48
+ import { Signal, Computed } from '@fozy-labs/rx-toolkit';
49
+
33
50
  const firstName = new Signal('John');
34
51
  const lastName = new Signal('Doe');
35
52
 
36
- const fullName = new Computed(() => `${firstName.value} ${lastName.value}`);
53
+ const fullName = new Computed(() => `${firstName.get()} ${lastName.get()}`);
37
54
 
38
- console.log(fullName.value); // "John Doe"
55
+ console.log(fullName.get()); // "John Doe"
39
56
 
40
- firstName.value = 'Jane';
41
- console.log(fullName.value); // "Jane Doe"
57
+ firstName.set('Jane');
58
+ console.log(fullName.get()); // "Jane Doe"
59
+
60
+ // Подписка на изменения
61
+ fullName.obs.subscribe(name => console.log(name));
42
62
  ```
43
63
 
64
+ **API Computed:**
65
+ - `get()` — получить вычисленное значение с регистрацией зависимости
66
+ - `peek()` — получить значение без регистрации зависимости
67
+ - `obs` — RxJS Observable для подписки на изменения
68
+
44
69
  ### Effect
45
70
 
46
- Создает эффект, который выполняется при изменении используемых сигналов.
71
+ Создает побочный эффект, который автоматически выполняется при изменении используемых сигналов.
47
72
 
48
73
  ```typescript
74
+ import { Signal, Effect } from '@fozy-labs/rx-toolkit';
75
+
49
76
  const count = new Signal(0);
50
77
  const message = new Signal('Hello');
51
78
 
52
- const sub = new Effect(() => {
53
- // Выведет: "Hello: 0" при инициализации
54
- console.log(`${message.value}: ${count.value}`);
79
+ const effect = new Effect(() => {
80
+ // Выведет: "Hello: 0" при инициализации
81
+ console.log(`${message.get()}: ${count.get()}`);
55
82
  });
56
83
 
57
- count.value = 1; // Выведет: "Hello: 1"
58
- message.value = 'Hi'; // Выведет: "Hi: 1"
84
+ count.set(1); // Выведет: "Hello: 1"
85
+ message.set('Hi'); // Выведет: "Hi: 1"
59
86
 
60
87
  // Остановка эффекта
61
- sub.unsubscribe();
88
+ effect.unsubscribe();
89
+ ```
90
+
91
+ **Cleanup функция (teardown):**
92
+
93
+ Effect поддерживает возврат функции очистки, которая вызывается перед следующим выполнением или при отписке:
94
+
95
+ ```typescript
96
+ const effect = new Effect(() => {
97
+ const timer = setInterval(() => console.log(count.get()), 1000);
98
+
99
+ // Cleanup - вызывается перед повторным выполнением эффекта
100
+ return () => {
101
+ clearInterval(timer);
102
+ };
103
+ });
104
+ ```
105
+
106
+ ## Функциональный стиль API
107
+
108
+ Для более компактного синтаксиса доступны статические методы `Signal.create()`, `Signal.compute()` и `Signal.effect()`:
109
+
110
+ ```typescript
111
+ import { Signal } from '@fozy-labs/rx-toolkit';
112
+
113
+ class CounterStore {
114
+ // Создание сигнала в функциональном стиле (вызывается как функция)
115
+ count$ = Signal.create(0);
116
+
117
+ // Computed в функциональном стиле
118
+ doubled$ = Signal.compute(() => this.count$() * 2);
119
+ squared$ = Signal.compute(() => (this.doubled$() / 2) ** 2);
120
+
121
+ increment = () => this.count$.set(this.count$.peek() + 1);
122
+ decrement = () => this.count$.set(this.count$.peek() - 1);
123
+ reset = () => this.count$.set(0);
124
+ }
125
+
126
+ const store = new CounterStore();
127
+
128
+ // Чтение значения - вызов как функции
129
+ console.log(store.count$()); // 0
130
+ console.log(store.doubled$()); // 0
131
+
132
+ store.increment();
133
+ console.log(store.count$()); // 1
134
+ console.log(store.doubled$()); // 2
135
+ console.log(store.squared$()); // 1
136
+ ```
137
+
138
+ **API функциональных сигналов:**
139
+ - `signal$()` — вызов как функции возвращает значение (аналог `get()`)
140
+ - `signal$.peek()` — получить значение без отслеживания
141
+ - `signal$.set(value)` — установить значение
142
+ - `signal$.obs` — RxJS Observable
143
+
144
+ ### ReadonlySignal
145
+
146
+ Базовый класс для сигналов только для чтения. Используется внутри `signalize` и для создания кастомных сигналов.
147
+
148
+ ```typescript
149
+ import { ReadonlySignal } from '@fozy-labs/rx-toolkit';
150
+
151
+ const customSignal = new ReadonlySignal((subscriber) => {
152
+ // Логика подписки
153
+ subscriber.next(initialValue);
154
+ return () => {
155
+ // Cleanup
156
+ };
157
+ });
62
158
  ```
63
159
 
64
160
  ### LocalSignal
65
161
 
66
- Сигнал, который синхронизируется с локальным хранилищем (localStorage).
67
- // TODO убрать zod из core, добавить возможность передавать "driver".
162
+ Сигнал, который автоматически синхронизируется с `localStorage`.
68
163
 
69
164
  ```typescript
70
165
  import { z } from 'zod/v4';
@@ -77,25 +172,33 @@ enum FILTER {
77
172
  MEETINGS = 'meetings',
78
173
  }
79
174
 
80
- const selectedFilter$ = new LocalSignal({
175
+ const selectedFilter$ = LocalSignal.create({
81
176
  key: 'memberships-list-selected-filter',
82
177
  defaultValue: FILTER.ALL,
83
- zodSchema: z.enum(FILTER),
178
+ zodSchema: z.nativeEnum(FILTER), // Опционально: валидация через Zod
84
179
  });
85
- ```
86
180
 
87
- ## Operators (Операторы)
181
+ // Использование
182
+ console.log(selectedFilter$.peek()); // Значение из localStorage или FILTER.ALL
183
+ selectedFilter$.set(FILTER.CHANNELS); // Сохраняется в localStorage
184
+ ```
88
185
 
89
- ### mapSignals
90
- // TODO: добавить описание
186
+ **Опции LocalSignal:**
187
+ - `key` ключ для localStorage
188
+ - `defaultValue` — значение по умолчанию
189
+ - `zodSchema` — опциональная Zod-схема для валидации
190
+ - `userId` — опциональный идентификатор пользователя для изоляции данных
191
+ - `checkEffect` — функция валидации значения
192
+ - `devtoolsOptions` — настройки для devtools
91
193
 
194
+ ## Операторы
92
195
 
93
196
  ### signalize
94
197
 
95
- Преобразует Observable в Signal.
198
+ Преобразует RxJS Observable в Signal. Позволяет использовать любой Observable как реактивный сигнал.
96
199
 
97
200
  ```typescript
98
- import { interval } from 'rxjs';
201
+ import { interval, startWith } from 'rxjs';
99
202
  import { signalize, Effect } from '@fozy-labs/rx-toolkit';
100
203
 
101
204
  // Создаем Observable, который эмитит значение каждую секунду
@@ -106,17 +209,87 @@ const timer$ = interval(1000).pipe(
106
209
  // Преобразуем Observable в Signal
107
210
  const tick$ = signalize(timer$);
108
211
 
109
- // Теперь можно использовать timerSignal как обычный Signal
212
+ // Теперь можно использовать tick$ как обычный Signal
110
213
  new Effect(() => {
111
- console.log(`Timer: ${tick$.value}`);
112
- })
214
+ console.log(`Timer: ${tick$.get()}`);
215
+ });
216
+
217
+ // Доступ к значению без подписки
218
+ console.log(tick$.peek());
219
+ ```
220
+
221
+ ## Батчинг обновлений (Batcher)
222
+
223
+ RxSignals автоматически группирует множественные обновления сигналов в один цикл обновления. Это обеспечивает:
224
+ - Консистентность состояния
225
+ - Оптимальную производительность
226
+ - Предсказуемый порядок выполнения эффектов
227
+
228
+ ```typescript
229
+ const a = Signal.create(1);
230
+ const b = Signal.create((2);
231
+ const sum = Signal.compute(() => a() + b());
232
+
233
+ new Effect(() => {
234
+ console.log(`Sum: ${sum()}`);
235
+ });
236
+
237
+ // Оба изменения обрабатываются в одном батче
238
+ Batcher.run(() => {
239
+ a.set(10);
240
+ b.set(20);
241
+ });
242
+ // Effect выведет: "Sum: 30" (один раз, а не два)
243
+ ```
244
+
245
+ ## Интеграция с RxJS
246
+
247
+ Сигналы полностью совместимы с RxJS. Каждый сигнал предоставляет `obs` — стандартный RxJS Observable:
248
+
249
+ ```typescript
250
+ import { filter, take, debounceTime } from 'rxjs';
251
+ import { Signal, Computed, signalize } from '@fozy-labs/rx-toolkit';
252
+
253
+ const clicks = Signal.create(0);
254
+
255
+ // Используем RxJS операторы
256
+ const tenClicks$ = clicks.obs.pipe(
257
+ filter(value => value === 10),
258
+ take(1)
259
+ );
260
+
261
+ tenClicks$.subscribe(() => {
262
+ console.log('Reached 10 clicks!');
263
+ });
264
+
265
+ // Или наоборот - превращаем Observable в Signal
266
+ const debouncedClicks$ = signalize(
267
+ clicks.obs.pipe(
268
+ debounceTime(300)
269
+ )
270
+ );
271
+
272
+ // Теперь debouncedClicks$ можно использовать в Computed/Effect
273
+ const doubled = Signal.compute(() => debouncedClicks$() * 2);
113
274
  ```
114
275
 
115
- ### filterUpdates
276
+ ## Devtools
277
+
278
+ Сигналы поддерживают интеграцию с Redux DevTools для отладки:
279
+
280
+ ```typescript
281
+ import { Signal } from '@fozy-labs/rx-toolkit';
282
+
283
+ // С именем для devtools
284
+ const count$ = Signal.create(0, 'counter');
116
285
 
117
- Фильтрует обновления сигнала.
118
- // TODO: добавить пример использования, подумать над целесообразностью
286
+ // Или с расширенными опциями
287
+ const user$ = Signal.create(null, {
288
+ isDisabled: false, // Отключить отслеживание в devtools
289
+ });
290
+ ```
119
291
 
120
- ## React Integration
292
+ ## React интеграция
121
293
 
122
294
  См. [React интеграция](../usage/react/README.md) для подробной информации о том, как использовать RxSignals в React приложениях.
295
+