@fozy-labs/rx-toolkit 0.4.2 → 0.4.4
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 +4 -5
- package/dist/{devtools → common/devtools}/combineDevtools.d.ts +1 -1
- package/dist/{devtools → common/devtools}/index.d.ts +1 -0
- package/dist/{devtools → common/devtools}/index.js +1 -0
- package/dist/common/devtools/reduxDevtools.d.ts +16 -0
- package/dist/{devtools → common/devtools}/reduxDevtools.js +7 -4
- package/dist/{query/api → common/options}/DefaultOptions.d.ts +1 -1
- package/dist/{query/api → common/options}/DefaultOptions.js +1 -1
- package/dist/{query/core → common/options}/SharedOptions.d.ts +1 -1
- 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/common/utils/PromiseResolver.d.ts +7 -0
- package/dist/common/utils/PromiseResolver.js +14 -0
- package/dist/common/utils/index.d.ts +1 -0
- package/dist/common/utils/index.js +1 -0
- package/dist/index.d.ts +3 -2
- package/dist/index.js +3 -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 -18
- package/dist/query/core/Opertation/OperationAgent.d.ts +2 -2
- package/dist/query/core/Opertation/OperationAgent.js +1 -1
- package/dist/query/core/QueriesCache.d.ts +2 -1
- package/dist/query/core/QueriesCache.js +19 -16
- package/dist/query/core/Resource/Resource.d.ts +3 -9
- package/dist/query/core/Resource/Resource.js +79 -26
- package/dist/query/core/Resource/ResourceAgent.d.ts +2 -2
- package/dist/query/core/Resource/ResourceAgent.js +5 -4
- package/dist/query/core/Resource/ResourceRef.d.ts +1 -4
- package/dist/query/core/Resource/ResourceRef.js +10 -20
- package/dist/query/index.d.ts +0 -1
- package/dist/query/index.js +0 -1
- package/dist/query/lib/IndirectMap.js +1 -1
- package/dist/query/lib/ReactiveCache.d.ts +6 -22
- package/dist/query/lib/ReactiveCache.js +19 -39
- package/dist/query/react/useOperationAgent.d.ts +1 -2
- package/dist/query/react/useOperationAgent.js +2 -1
- package/dist/query/react/useResourceAgent.d.ts +3 -7
- package/dist/query/react/useResourceAgent.js +7 -3
- package/dist/query/react/useResourceRef.d.ts +1 -2
- package/dist/query/react/useResourceRef.js +1 -1
- package/dist/query/types/Operation.types.d.ts +1 -1
- package/dist/query/types/Resource.types.d.ts +29 -10
- package/dist/query/types/index.d.ts +3 -0
- package/dist/query/types/index.js +3 -0
- package/dist/signals/base/Computed.js +1 -2
- package/dist/signals/base/Effect.js +3 -2
- package/dist/signals/base/ReadonlySignal.d.ts +2 -3
- package/dist/signals/base/ReadonlySignal.js +2 -11
- package/dist/signals/base/Signal.d.ts +2 -2
- package/dist/signals/base/Signal.js +1 -1
- package/dist/signals/base/Tracker.d.ts +0 -4
- package/dist/signals/base/Tracker.js +0 -6
- package/dist/signals/base/types.d.ts +9 -0
- package/dist/signals/index.d.ts +1 -0
- package/dist/signals/index.js +1 -0
- 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/signals/README.md +1 -1
- package/package.json +1 -1
- package/dist/devtools/reduxDevtools.d.ts +0 -2
- package/dist/query/api/createSubResource.d.ts +0 -0
- package/dist/query/api/createSubResource.js +0 -1
- /package/dist/{devtools → common/devtools}/combineDevtools.js +0 -0
- /package/dist/{query/types/devtools.d.ts → common/devtools/types.d.ts} +0 -0
- /package/dist/{query/types/devtools.js → 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
|
@@ -29,22 +29,6 @@ export class ResourceRef {
|
|
|
29
29
|
unlockOne() {
|
|
30
30
|
this._cacheItem = this._resource.decrementLock(this._args, { cache: this._cacheItem });
|
|
31
31
|
}
|
|
32
|
-
update(updateFn) {
|
|
33
|
-
const cacheItem = this._cacheItem ?? this._resource.getQueryCache(this._args);
|
|
34
|
-
if (!cacheItem) {
|
|
35
|
-
console.warn('Trying to update non-existing cache item');
|
|
36
|
-
return {
|
|
37
|
-
rollback: () => { }
|
|
38
|
-
};
|
|
39
|
-
}
|
|
40
|
-
const value = cacheItem.value;
|
|
41
|
-
this._resource.updateData_legacy(this._args, updateFn, { cache: cacheItem });
|
|
42
|
-
return {
|
|
43
|
-
rollback: () => {
|
|
44
|
-
this._resource.updateData_legacy(this._args, () => value.data, { cache: cacheItem });
|
|
45
|
-
}
|
|
46
|
-
};
|
|
47
|
-
}
|
|
48
32
|
patch(patchFn) {
|
|
49
33
|
let isSkipped = true;
|
|
50
34
|
const reapplyFn = (data, savedData, transactions) => {
|
|
@@ -56,12 +40,14 @@ export class ResourceRef {
|
|
|
56
40
|
// Все pending - применяем и оставляем в очереди
|
|
57
41
|
// Все commited (которые после pending) - применяем, но оставляем в очереди
|
|
58
42
|
// Все aborted (которые после pending) - откатываем, но оставляем в очереди
|
|
43
|
+
// Если после aborted нет pending - пропускаем и убираем из очереди
|
|
59
44
|
// Те после применения всех транзакций, очередь должна начинаться с первой pending транзакции (если есть), включая все, что после неё.
|
|
60
45
|
let newSavedData = savedData ?? data;
|
|
61
46
|
let currentData = savedData ?? data;
|
|
62
47
|
const remainingTransactions = [];
|
|
63
48
|
let foundPending = false;
|
|
64
|
-
transactions.
|
|
49
|
+
const lastPendingIndex = transactions.findLastIndex(t => t.status === 'pending');
|
|
50
|
+
transactions.forEach((transaction, index) => {
|
|
65
51
|
if (transaction.status === 'pending') {
|
|
66
52
|
foundPending = true;
|
|
67
53
|
// Применяем pending транзакцию и оставляем в очереди
|
|
@@ -76,9 +62,13 @@ export class ResourceRef {
|
|
|
76
62
|
remainingTransactions.push(transaction);
|
|
77
63
|
}
|
|
78
64
|
else if (transaction.status === 'aborted') {
|
|
79
|
-
//
|
|
80
|
-
|
|
81
|
-
|
|
65
|
+
// Проверяем, есть ли pending после текущей aborted
|
|
66
|
+
const hasPendingAfter = index < lastPendingIndex;
|
|
67
|
+
if (hasPendingAfter) {
|
|
68
|
+
currentData = applyPatches(currentData, transaction.inversePatches);
|
|
69
|
+
remainingTransactions.push(transaction);
|
|
70
|
+
}
|
|
71
|
+
// Если pending нет - пропускаем и убираем из очереди
|
|
82
72
|
}
|
|
83
73
|
}
|
|
84
74
|
else {
|
package/dist/query/index.d.ts
CHANGED
package/dist/query/index.js
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { Observable, Subject } from "rxjs";
|
|
2
|
+
import { ReadableSignalLike } from "../../signals";
|
|
2
3
|
type Options<VALUE> = {
|
|
3
4
|
/**
|
|
4
5
|
* Начальное состояние кэша
|
|
@@ -6,9 +7,11 @@ type Options<VALUE> = {
|
|
|
6
7
|
initialState: VALUE;
|
|
7
8
|
/**
|
|
8
9
|
* Время жизни кэша в миллисекундах (пока нет подписок на кеш)
|
|
10
|
+
* Если указано `false`, кэш не будет очищаться автоматически.
|
|
11
|
+
* Если указано `0` или меньше, кэш будет очищаться сразу после отписки от него.
|
|
9
12
|
* @default 60_000 (1 минута)
|
|
10
13
|
*/
|
|
11
|
-
cacheLifeTime?: number;
|
|
14
|
+
cacheLifeTime?: number | false;
|
|
12
15
|
};
|
|
13
16
|
/**
|
|
14
17
|
* Класс `ReactiveCache` представляет собой реактивный кэш,
|
|
@@ -17,26 +20,15 @@ type Options<VALUE> = {
|
|
|
17
20
|
* @template VALUE Тип значения, хранимого в кэше.
|
|
18
21
|
*/
|
|
19
22
|
export declare class ReactiveCache<VALUE> {
|
|
20
|
-
/**
|
|
21
|
-
* Время жизни кэша в миллисекундах.
|
|
22
|
-
* Если значение больше 0, то кэш очищается через указанное время после отписки.
|
|
23
|
-
* @private
|
|
24
|
-
*/
|
|
25
|
-
private readonly _cacheLifeTime;
|
|
26
23
|
/**
|
|
27
24
|
* Внутренний `BehaviorSubject`, хранящий текущее состояние кэша.
|
|
28
25
|
* @private
|
|
29
26
|
*/
|
|
30
27
|
private _state$;
|
|
31
|
-
/**
|
|
32
|
-
* Текущее значение.
|
|
33
|
-
* @private
|
|
34
|
-
*/
|
|
35
|
-
private _value;
|
|
36
28
|
/**
|
|
37
29
|
* Реактивное значене (Observable)
|
|
38
30
|
*/
|
|
39
|
-
value$:
|
|
31
|
+
value$: ReadableSignalLike<VALUE>;
|
|
40
32
|
/**
|
|
41
33
|
* Значение без сайд-эффектов (для использования в DevTools)
|
|
42
34
|
*/
|
|
@@ -53,16 +45,8 @@ export declare class ReactiveCache<VALUE> {
|
|
|
53
45
|
* @param options.cacheLifeTime Время жизни кэша в миллисекундах (по умолчанию 60_000).
|
|
54
46
|
*/
|
|
55
47
|
constructor(options: Options<VALUE>);
|
|
56
|
-
|
|
57
|
-
* Возвращает текущее значение кэша.
|
|
58
|
-
* @returns {VALUE} Текущее значение кэша.
|
|
59
|
-
*/
|
|
48
|
+
private _getOnRefCountZero;
|
|
60
49
|
get value(): VALUE;
|
|
61
|
-
/**
|
|
62
|
-
* Возвращает текущее значение кэша.
|
|
63
|
-
* @returns {VALUE} Текущее значение кэша.
|
|
64
|
-
*/
|
|
65
|
-
peek(): VALUE;
|
|
66
50
|
/**
|
|
67
51
|
* Устанавливает новое значение в кэш и обновляет поток состояния.
|
|
68
52
|
*
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { finalize, ReplaySubject, share, Subject, takeUntil, timer } from "rxjs";
|
|
2
|
-
import {
|
|
1
|
+
import { BehaviorSubject, finalize, ReplaySubject, share, Subject, takeUntil, timer } from "rxjs";
|
|
2
|
+
import { signalize } from "../../signals";
|
|
3
3
|
/**
|
|
4
4
|
* Класс `ReactiveCache` представляет собой реактивный кэш,
|
|
5
5
|
* который позволяет управлять состоянием и временем жизни кэшированных данных.
|
|
@@ -7,22 +7,11 @@ import { Signal } from "../../signals";
|
|
|
7
7
|
* @template VALUE Тип значения, хранимого в кэше.
|
|
8
8
|
*/
|
|
9
9
|
export class ReactiveCache {
|
|
10
|
-
/**
|
|
11
|
-
* Время жизни кэша в миллисекундах.
|
|
12
|
-
* Если значение больше 0, то кэш очищается через указанное время после отписки.
|
|
13
|
-
* @private
|
|
14
|
-
*/
|
|
15
|
-
_cacheLifeTime;
|
|
16
10
|
/**
|
|
17
11
|
* Внутренний `BehaviorSubject`, хранящий текущее состояние кэша.
|
|
18
12
|
* @private
|
|
19
13
|
*/
|
|
20
14
|
_state$;
|
|
21
|
-
/**
|
|
22
|
-
* Текущее значение.
|
|
23
|
-
* @private
|
|
24
|
-
*/
|
|
25
|
-
_value;
|
|
26
15
|
/**
|
|
27
16
|
* Реактивное значене (Observable)
|
|
28
17
|
*/
|
|
@@ -43,46 +32,37 @@ export class ReactiveCache {
|
|
|
43
32
|
* @param options.cacheLifeTime Время жизни кэша в миллисекундах (по умолчанию 60_000).
|
|
44
33
|
*/
|
|
45
34
|
constructor(options) {
|
|
46
|
-
|
|
47
|
-
this._state$ = new
|
|
48
|
-
this._value = options.initialState;
|
|
35
|
+
const cacheLifeTime = options.cacheLifeTime ?? 60_000;
|
|
36
|
+
this._state$ = new BehaviorSubject(options.initialState);
|
|
49
37
|
this.spy$ = this._state$.pipe(takeUntil(this.onClean$));
|
|
50
|
-
this.value$ = this._state$.pipe(finalize(() => {
|
|
38
|
+
this.value$ = signalize(this._state$.pipe(finalize(() => {
|
|
51
39
|
this.complete();
|
|
52
40
|
}), share({
|
|
53
41
|
connector: () => new ReplaySubject(1),
|
|
54
|
-
|
|
55
|
-
* Если lifetime больше 0,
|
|
56
|
-
* то очистим кэш значения по истечении этого времени,
|
|
57
|
-
* иначе очищаем сразу после отписки.
|
|
58
|
-
*/
|
|
59
|
-
resetOnRefCountZero: this._cacheLifeTime > 0
|
|
60
|
-
? () => timer(this._cacheLifeTime)
|
|
61
|
-
: true,
|
|
42
|
+
resetOnRefCountZero: this._getOnRefCountZero(cacheLifeTime),
|
|
62
43
|
resetOnComplete: true,
|
|
63
|
-
}));
|
|
44
|
+
})));
|
|
45
|
+
}
|
|
46
|
+
_getOnRefCountZero(cacheLifeTime) {
|
|
47
|
+
if (cacheLifeTime === false) {
|
|
48
|
+
return false;
|
|
49
|
+
}
|
|
50
|
+
if (cacheLifeTime <= 0) {
|
|
51
|
+
return true;
|
|
52
|
+
}
|
|
53
|
+
return () => {
|
|
54
|
+
return timer(cacheLifeTime);
|
|
55
|
+
};
|
|
64
56
|
}
|
|
65
|
-
/**
|
|
66
|
-
* Возвращает текущее значение кэша.
|
|
67
|
-
* @returns {VALUE} Текущее значение кэша.
|
|
68
|
-
*/
|
|
69
57
|
get value() {
|
|
70
58
|
return this._state$.value;
|
|
71
59
|
}
|
|
72
|
-
/**
|
|
73
|
-
* Возвращает текущее значение кэша.
|
|
74
|
-
* @returns {VALUE} Текущее значение кэша.
|
|
75
|
-
*/
|
|
76
|
-
peek() {
|
|
77
|
-
return this._value;
|
|
78
|
-
}
|
|
79
60
|
/**
|
|
80
61
|
* Устанавливает новое значение в кэш и обновляет поток состояния.
|
|
81
62
|
*
|
|
82
63
|
* @param value Новое значение для кэша.
|
|
83
64
|
*/
|
|
84
65
|
next(value) {
|
|
85
|
-
this._value = value;
|
|
86
66
|
this._state$.next(value);
|
|
87
67
|
}
|
|
88
68
|
/**
|
|
@@ -90,7 +70,7 @@ export class ReactiveCache {
|
|
|
90
70
|
*/
|
|
91
71
|
complete() {
|
|
92
72
|
this._state$.complete();
|
|
93
|
-
this.onClean$.next(this.
|
|
73
|
+
this.onClean$.next(this._state$.value);
|
|
94
74
|
this.onClean$.complete();
|
|
95
75
|
}
|
|
96
76
|
}
|
|
@@ -1,5 +1,4 @@
|
|
|
1
|
-
import { OperationAgentInstanse, OperationDefinition, OperationQueryState } from "
|
|
2
|
-
import { Prettify } from "../types/shared.types";
|
|
1
|
+
import type { Prettify, OperationAgentInstanse, OperationDefinition, OperationQueryState } from "../../query/types";
|
|
3
2
|
type WithAgent<D extends OperationDefinition> = {
|
|
4
3
|
createAgent: () => OperationAgentInstanse<D>;
|
|
5
4
|
};
|
|
@@ -1,4 +1,5 @@
|
|
|
1
|
-
import { useConstant, useEventHandler
|
|
1
|
+
import { useConstant, useEventHandler } from "../../common/react";
|
|
2
|
+
import { useSignal } from "../../signals/react";
|
|
2
3
|
export function useOperationAgent(op) {
|
|
3
4
|
const agent = useConstant(() => op.createAgent());
|
|
4
5
|
const state = useSignal(agent.state$);
|
|
@@ -1,9 +1,5 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import {
|
|
3
|
-
import { SKIP } from "../SKIP_TOKEN";
|
|
4
|
-
type WithAgent<D extends ResourceDefinition> = {
|
|
5
|
-
createAgent: () => ResourceAgentInstance<D>;
|
|
6
|
-
};
|
|
1
|
+
import { Prettify, ResourceDefinition, ResourceInstance, ResourceQueryState } from "../../query/types";
|
|
2
|
+
import { SKIP } from "../../query/SKIP_TOKEN";
|
|
7
3
|
type Result<D extends ResourceDefinition> = Prettify<ResourceQueryState<D>>;
|
|
8
|
-
export declare function useResourceAgent<D extends ResourceDefinition>(res:
|
|
4
|
+
export declare function useResourceAgent<D extends ResourceDefinition>(res: ResourceInstance<D>, ...argss: D['Args'] extends void ? [] | [typeof SKIP] : [D['Args'] | typeof SKIP]): Result<D>;
|
|
9
5
|
export {};
|
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
import React from "react";
|
|
2
|
-
import { useConstant
|
|
3
|
-
import {
|
|
4
|
-
import {
|
|
2
|
+
import { useConstant } from "../../common/react";
|
|
3
|
+
import { useSignal } from "../../signals/react";
|
|
4
|
+
import { shallowEqual } from "../../query/lib/shallowEqual";
|
|
5
|
+
import { SKIP } from "../../query/SKIP_TOKEN";
|
|
5
6
|
export function useResourceAgent(res, ...argss) {
|
|
6
7
|
const args = (argss[0] === SKIP ? SKIP : argss[0]);
|
|
7
8
|
const agent = useConstant(() => {
|
|
@@ -21,5 +22,8 @@ export function useResourceAgent(res, ...argss) {
|
|
|
21
22
|
}
|
|
22
23
|
agent.initiate(args);
|
|
23
24
|
}, [args]);
|
|
25
|
+
React.useEffect(() => () => {
|
|
26
|
+
agent.complete();
|
|
27
|
+
}, []);
|
|
24
28
|
return useSignal(agent.state$);
|
|
25
29
|
}
|
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
import { SKIP } from "../../query/SKIP_TOKEN";
|
|
2
|
-
import { ResourceDefinition, ResourceInstance, ResourceRefInstanse } from "../../query/types
|
|
3
|
-
import { Prettify } from "../../query/types/shared.types";
|
|
2
|
+
import type { Prettify, ResourceDefinition, ResourceInstance, ResourceRefInstanse } from "../../query/types";
|
|
4
3
|
type Result<D extends ResourceDefinition> = Prettify<ResourceRefInstanse<D>> | null;
|
|
5
4
|
export declare function useResourceRef<D extends ResourceDefinition>(res: ResourceInstance<D>, ...argss: D['Args'] extends void ? [] | [typeof SKIP] : [D['Args'] | typeof SKIP]): Result<D>;
|
|
6
5
|
export {};
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { ReadableSignalLike } from "../../signals";
|
|
2
|
-
import { FallbackOnNever } from "
|
|
2
|
+
import { FallbackOnNever } from "./shared.types";
|
|
3
3
|
import { ResourceDefinition, ResourceInstance } from "./Resource.types";
|
|
4
4
|
/**
|
|
5
5
|
* Функция создания операции
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import { ReadableSignalLike } from "../../signals";
|
|
2
|
-
import { FallbackOnNever } from "../../query/types/shared.types";
|
|
3
1
|
import { Patch as ImmerPatch } from "immer";
|
|
2
|
+
import { ReadableSignalLike } from "../../signals";
|
|
3
|
+
import { FallbackOnNever } from "./shared.types";
|
|
4
4
|
/**
|
|
5
5
|
* Функция создания ресурса
|
|
6
6
|
*/
|
|
@@ -13,6 +13,31 @@ export type ResourceCreateOptions<D extends ResourceDefinition> = {
|
|
|
13
13
|
select?: (data: D["Result"]) => D["Selected"];
|
|
14
14
|
/** Функция запроса данных */
|
|
15
15
|
queryFn: (args: D["Args"], tools: ResourceQueryFnTools) => Promise<D["Result"]>;
|
|
16
|
+
/**
|
|
17
|
+
* Время жизни кеша в миллисекундах. По умолчанию 60_000 (1 минута).
|
|
18
|
+
* Если указано false - кеш не удаляется автоматически.
|
|
19
|
+
*/
|
|
20
|
+
cacheLifetime?: number | false;
|
|
21
|
+
onCacheEntryAdded?: (args: D["Args"], tools: CacheEntryAddedTools<D>) => void;
|
|
22
|
+
onQueryStarted?: (args: D["Args"], tools: QueryStartedTools<D>) => void;
|
|
23
|
+
};
|
|
24
|
+
export type CacheEntryAddedTools<D extends ResourceDefinition> = {
|
|
25
|
+
/** Функция для ожидания загрузки данных в кеш */
|
|
26
|
+
$cacheDataLoaded: Promise<void>;
|
|
27
|
+
/** Функция для ожидания удаления кеша */
|
|
28
|
+
$cacheEntryRemoved: Promise<void>;
|
|
29
|
+
};
|
|
30
|
+
export type QueryStartedTools<D extends ResourceDefinition> = {
|
|
31
|
+
/** Функция для уведомления об успешном завершении запроса */
|
|
32
|
+
$queryFulfilled: Promise<{
|
|
33
|
+
data: D["Result"];
|
|
34
|
+
error: undefined;
|
|
35
|
+
isError: false;
|
|
36
|
+
} | {
|
|
37
|
+
data: undefined;
|
|
38
|
+
error: unknown;
|
|
39
|
+
isError: true;
|
|
40
|
+
}>;
|
|
16
41
|
};
|
|
17
42
|
/**
|
|
18
43
|
* Определение типов ресурса
|
|
@@ -45,8 +70,8 @@ export type ResourceAgentInstance<D extends ResourceDefinition> = {
|
|
|
45
70
|
state$: ReadableSignalLike<ResourceQueryState<D>>;
|
|
46
71
|
/** Инициирует запрос с указанными аргументами */
|
|
47
72
|
initiate(args: D["Args"], force?: boolean): void;
|
|
48
|
-
/**
|
|
49
|
-
|
|
73
|
+
/** Завершает работу агента, позволяя освободить ресурсы */
|
|
74
|
+
complete(): void;
|
|
50
75
|
};
|
|
51
76
|
/**
|
|
52
77
|
* Состояние запроса ресурса
|
|
@@ -93,12 +118,6 @@ export type ResourceRefInstanse<D extends ResourceDefinition> = {
|
|
|
93
118
|
unlock: () => void;
|
|
94
119
|
};
|
|
95
120
|
unlockOne(): void;
|
|
96
|
-
/**
|
|
97
|
-
* @deprecated
|
|
98
|
-
*/
|
|
99
|
-
update(updateFn: (data: D['Data']) => D['Data']): {
|
|
100
|
-
rollback: () => void;
|
|
101
|
-
};
|
|
102
121
|
patch(patchFn: (data: D['Data']) => void): ResourceTransaction | null;
|
|
103
122
|
invalidate(): void;
|
|
104
123
|
create(data: D['Data']): void;
|
|
@@ -11,10 +11,10 @@ export class Effect {
|
|
|
11
11
|
* Выполняет функцию в tracked-контексте, подписываясь на Tracker.
|
|
12
12
|
*/
|
|
13
13
|
_runInTrackedContext(effectFn, isAsyncRun = false) {
|
|
14
|
-
|
|
14
|
+
let prevSubscriptions;
|
|
15
15
|
if (!isAsyncRun) {
|
|
16
16
|
this._rang = 0;
|
|
17
|
-
this._subscriptions
|
|
17
|
+
prevSubscriptions = this._subscriptions;
|
|
18
18
|
this._subscriptions = [];
|
|
19
19
|
}
|
|
20
20
|
let isTrackedContext = true;
|
|
@@ -43,6 +43,7 @@ export class Effect {
|
|
|
43
43
|
trackerSub.unsubscribe();
|
|
44
44
|
isTrackedContext = false;
|
|
45
45
|
scheduler = Batcher.scheduler(this._rang);
|
|
46
|
+
prevSubscriptions?.forEach((sub) => sub.unsubscribe());
|
|
46
47
|
}
|
|
47
48
|
unsubscribe() {
|
|
48
49
|
this.closed = true;
|
|
@@ -1,9 +1,8 @@
|
|
|
1
1
|
import { Observable, Subscriber, TeardownLogic } from "rxjs";
|
|
2
|
-
import { SyncObservable } from "./SyncObservable";
|
|
3
2
|
import type { ReadableSignalLike } from "./types";
|
|
3
|
+
import { SyncObservable } from "./SyncObservable";
|
|
4
4
|
export declare class ReadonlySignal<T> extends SyncObservable<T> implements ReadableSignalLike<T> {
|
|
5
|
-
|
|
6
|
-
private static _logIdIndex;
|
|
5
|
+
protected rang: number;
|
|
7
6
|
constructor(subscribe?: (this: Observable<T>, subscriber: Subscriber<T>) => TeardownLogic);
|
|
8
7
|
get value(): T;
|
|
9
8
|
peek(): T;
|
|
@@ -1,21 +1,12 @@
|
|
|
1
|
-
import { SharedOptions } from "../../query/core/SharedOptions";
|
|
2
1
|
import { SyncObservable } from "./SyncObservable";
|
|
3
2
|
import { Tracker } from "./Tracker";
|
|
4
3
|
export class ReadonlySignal extends SyncObservable {
|
|
5
|
-
|
|
6
|
-
static _logIdIndex = 0;
|
|
4
|
+
rang = 0;
|
|
7
5
|
constructor(subscribe) {
|
|
8
6
|
super(subscribe);
|
|
9
|
-
const stateDevtools = SharedOptions.DEVTOOLS?.state;
|
|
10
|
-
if (stateDevtools) {
|
|
11
|
-
const id = ReadonlySignal._logIdIndex++;
|
|
12
|
-
const key = `ReadonlySignal:i=${id}`;
|
|
13
|
-
const initialValue = this.peek();
|
|
14
|
-
this._devtools = stateDevtools(key, initialValue);
|
|
15
|
-
}
|
|
16
7
|
}
|
|
17
8
|
get value() {
|
|
18
|
-
Tracker.
|
|
9
|
+
Tracker.next(this.rang, this);
|
|
19
10
|
return super.value;
|
|
20
11
|
}
|
|
21
12
|
peek() {
|
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
import { BehaviorSubject, Observable } from "rxjs";
|
|
2
|
-
import {
|
|
2
|
+
import type { ReadableSignalLike, SignalLike, UnaryFunction } from "./types";
|
|
3
3
|
type SignalOptions = {
|
|
4
4
|
disableDevtools?: boolean;
|
|
5
5
|
devtoolsName?: string;
|
|
6
6
|
};
|
|
7
|
-
export declare class Signal<T> extends BehaviorSubject<T> implements
|
|
7
|
+
export declare class Signal<T> extends BehaviorSubject<T> implements SignalLike<T> {
|
|
8
8
|
private readonly _devtools;
|
|
9
9
|
protected _rang: number;
|
|
10
10
|
constructor(initialValue: T, options?: SignalOptions);
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { SharedOptions } from "../../query/core/SharedOptions";
|
|
2
1
|
import { BehaviorSubject } from "rxjs";
|
|
2
|
+
import { SharedOptions } from "../../common/options/SharedOptions";
|
|
3
3
|
import { Batcher } from "./Batcher";
|
|
4
4
|
import { Indexer } from "./Indexer";
|
|
5
5
|
import { Tracker } from "./Tracker";
|
|
@@ -4,10 +4,6 @@ type TrackedValue = {
|
|
|
4
4
|
obsv$: Observable<unknown>;
|
|
5
5
|
};
|
|
6
6
|
export declare const Tracker: {
|
|
7
|
-
/** @deprecated */
|
|
8
|
-
tracked_legacy$: Subject<Observable<unknown>>;
|
|
9
|
-
/** @deprecated */
|
|
10
|
-
next_legacy(value: Observable<unknown>): void;
|
|
11
7
|
tracked$: Subject<TrackedValue>;
|
|
12
8
|
next(rang: number, observable: Observable<unknown>): void;
|
|
13
9
|
};
|
|
@@ -1,11 +1,5 @@
|
|
|
1
1
|
import { Subject } from "rxjs";
|
|
2
2
|
export const Tracker = {
|
|
3
|
-
/** @deprecated */
|
|
4
|
-
tracked_legacy$: new Subject(),
|
|
5
|
-
/** @deprecated */
|
|
6
|
-
next_legacy(value) {
|
|
7
|
-
Tracker.tracked_legacy$.next(value);
|
|
8
|
-
},
|
|
9
3
|
tracked$: new Subject(),
|
|
10
4
|
next(rang, observable) {
|
|
11
5
|
Tracker.tracked$.next({ rang, obsv$: observable, });
|
|
@@ -7,6 +7,15 @@ 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
|
}
|
package/dist/signals/index.d.ts
CHANGED
package/dist/signals/index.js
CHANGED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from './useSignal';
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from './useSignal';
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import { ReadableSignalLike } from "
|
|
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);
|
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
|
|
package/package.json
CHANGED
|
File without changes
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
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
|