@fozy-labs/rx-toolkit 0.4.1 → 0.4.2
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 +41 -35
- package/dist/devtools/combineDevtools.d.ts +2 -0
- package/dist/devtools/combineDevtools.js +10 -0
- package/dist/devtools/index.d.ts +2 -0
- package/dist/devtools/index.js +2 -0
- package/dist/devtools/reduxDevtools.d.ts +2 -0
- package/dist/devtools/reduxDevtools.js +24 -0
- package/dist/index.d.ts +2 -1
- package/dist/index.js +2 -1
- package/dist/query/api/DefaultOptions.d.ts +2 -2
- package/dist/query/core/Opertation/Operation.js +5 -4
- package/dist/query/core/Opertation/OperationAgent.d.ts +1 -1
- package/dist/query/core/Opertation/OperationAgent.js +3 -3
- package/dist/query/core/QueriesCache.js +11 -5
- package/dist/query/core/Resource/Resource.d.ts +14 -2
- package/dist/query/core/Resource/Resource.js +34 -2
- package/dist/query/core/Resource/ResourceAgent.d.ts +1 -1
- 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/core/SharedOptions.d.ts +2 -2
- package/dist/query/index.d.ts +1 -1
- package/dist/query/index.js +1 -1
- package/dist/query/lib/ReactiveCache.js +2 -2
- package/dist/query/react/useResourceRef.d.ts +6 -0
- package/dist/query/react/useResourceRef.js +8 -0
- package/dist/query/types/Operation.types.d.ts +43 -2
- package/dist/query/types/Resource.types.d.ts +16 -1
- package/dist/query/types/devtools.d.ts +6 -0
- package/dist/react-hooks/useSignal.d.ts +1 -1
- 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 +2 -0
- package/dist/signals/base/ReadonlySignal.js +30 -0
- package/dist/{signal → signals}/base/Signal.d.ts +12 -1
- package/dist/{signal → signals}/base/Signal.js +23 -3
- package/dist/signals/base/Tracker.d.ts +14 -0
- package/dist/signals/base/Tracker.js +13 -0
- package/dist/{signal → signals}/base/types.d.ts +0 -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}/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/docs/devtools/README.md +95 -0
- package/docs/query/README.md +25 -14
- package/docs/signals/README.md +10 -7
- package/package.json +13 -8
- package/dist/query/api/createDevtools.d.ts +0 -1
- package/dist/query/api/createDevtools.js +0 -6
- 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/types.js → query/types/devtools.js} +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}/index.d.ts +0 -0
- /package/dist/{signal → signals}/index.js +0 -0
- /package/dist/{signal → signals}/operators/filterUpdates.d.ts +0 -0
- /package/dist/{signal → signals}/operators/mapSignals.d.ts +0 -0
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
|
@@ -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.2",
|
|
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;
|
|
@@ -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
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|