@fozy-labs/rx-toolkit 0.5.3-rc.2 → 0.5.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/LICENSE +21 -21
- package/README.md +143 -137
- package/dist/common/devtools/combineDevtools.js +3 -3
- package/dist/common/devtools/index.d.ts +3 -3
- package/dist/common/devtools/index.js +3 -3
- package/dist/common/devtools/reduxDevtools.d.ts +1 -1
- package/dist/common/devtools/reduxDevtools.js +17 -17
- package/dist/common/devtools/types.d.ts +0 -6
- package/dist/common/options/SharedOptions.d.ts +1 -0
- package/dist/common/options/SharedOptions.js +6 -0
- package/dist/common/options/index.d.ts +1 -1
- package/dist/common/options/index.js +1 -1
- package/dist/common/react/index.d.ts +2 -2
- package/dist/common/react/index.js +2 -2
- package/dist/common/react/useConstant.js +1 -1
- package/dist/common/utils/deepEqual.js +1 -1
- package/dist/common/utils/index.d.ts +3 -3
- package/dist/common/utils/index.js +3 -3
- package/dist/common/utils/shallowEqual.js +1 -1
- package/dist/index.d.ts +8 -7
- package/dist/index.js +8 -7
- package/dist/query/SKIP_TOKEN.js +1 -1
- package/dist/query/api/createCommand.d.ts +1 -1
- package/dist/query/api/createOperation.d.ts +1 -1
- package/dist/query/api/createOperation.js +1 -1
- package/dist/query/api/createResource.d.ts +1 -1
- package/dist/query/api/createResourceDuplicator.d.ts +1 -1
- package/dist/query/core/Command/Command.d.ts +7 -7
- package/dist/query/core/Command/Command.js +2 -2
- package/dist/query/core/Command/CommandAgent.d.ts +1 -1
- package/dist/query/core/Command/index.d.ts +2 -2
- package/dist/query/core/Command/index.js +2 -2
- package/dist/query/core/{Opertation → Operation}/Operation.d.ts +2 -2
- package/dist/query/core/{Opertation → Operation}/Operation.js +1 -1
- package/dist/query/core/{Opertation → Operation}/OperationAgent.d.ts +1 -1
- package/dist/query/core/{Opertation → Operation}/OperationAgent.js +1 -1
- package/dist/query/core/QueriesCache.d.ts +1 -1
- package/dist/query/core/QueriesCache.js +1 -1
- package/dist/query/core/QueriesLifetimeHooks.js +7 -7
- package/dist/query/core/Resource/Resource.d.ts +15 -15
- package/dist/query/core/Resource/Resource.js +7 -7
- package/dist/query/core/Resource/ResourceAgent.d.ts +1 -1
- package/dist/query/core/Resource/ResourceAgent.js +2 -2
- package/dist/query/core/Resource/ResourceDuplicator.d.ts +16 -16
- package/dist/query/core/Resource/ResourceDuplicator.js +18 -20
- package/dist/query/core/Resource/ResourceDuplicatorAgent.d.ts +5 -5
- package/dist/query/core/Resource/ResourceDuplicatorAgent.js +2 -2
- package/dist/query/core/Resource/ResourceRef.d.ts +2 -2
- package/dist/query/core/Resource/ResourceRef.js +12 -12
- package/dist/query/index.d.ts +11 -10
- package/dist/query/index.js +11 -10
- package/dist/query/lib/IndirectMap.js +4 -4
- package/dist/query/react/useCommandAgent.d.ts +2 -2
- package/dist/query/react/useOperationAgent.d.ts +1 -1
- package/dist/query/react/useOperationAgent.js +1 -1
- package/dist/query/react/useResourceAgent.d.ts +3 -3
- package/dist/query/react/useResourceAgent.js +1 -1
- package/dist/query/react/useResourceRef.d.ts +3 -3
- package/dist/query/react/useResourceRef.js +7 -2
- package/dist/query/types/Command.types.d.ts +1 -1
- package/dist/query/types/Operation.types.d.ts +1 -1
- package/dist/query/types/Resource.types.d.ts +7 -5
- package/dist/query/types/index.d.ts +4 -4
- package/dist/query/types/index.js +4 -4
- package/dist/query-v2/api/createApi.d.ts +10 -0
- package/dist/query-v2/api/createApi.js +83 -0
- package/dist/query-v2/core/common/CacheEntry.d.ts +29 -0
- package/dist/query-v2/core/common/CacheEntry.js +71 -0
- package/dist/query-v2/core/common/CacheMap.d.ts +38 -0
- package/dist/query-v2/core/common/CacheMap.js +127 -0
- package/dist/query-v2/core/common/LifecycleHooks.d.ts +22 -0
- package/dist/query-v2/core/common/LifecycleHooks.js +104 -0
- package/dist/query-v2/core/common/index.d.ts +3 -0
- package/dist/query-v2/core/common/index.js +3 -0
- package/dist/query-v2/core/index.d.ts +3 -0
- package/dist/query-v2/core/index.js +3 -0
- package/dist/query-v2/core/machines/Machine.d.ts +14 -0
- package/dist/query-v2/core/machines/Machine.js +33 -0
- package/dist/query-v2/core/machines/MachineError.d.ts +11 -0
- package/dist/query-v2/core/machines/MachineError.js +26 -0
- package/dist/query-v2/core/machines/MachineIdle.d.ts +8 -0
- package/dist/query-v2/core/machines/MachineIdle.js +19 -0
- package/dist/query-v2/core/machines/MachinePending.d.ts +12 -0
- package/dist/query-v2/core/machines/MachinePending.js +29 -0
- package/dist/query-v2/core/machines/MachineRefreshing.d.ts +14 -0
- package/dist/query-v2/core/machines/MachineRefreshing.js +46 -0
- package/dist/query-v2/core/machines/MachineSuccess.d.ts +16 -0
- package/dist/query-v2/core/machines/MachineSuccess.js +42 -0
- package/dist/query-v2/core/machines/MachineWithData.d.ts +18 -0
- package/dist/query-v2/core/machines/MachineWithData.js +40 -0
- package/dist/query-v2/core/machines/Patcher.d.ts +20 -0
- package/dist/query-v2/core/machines/Patcher.js +104 -0
- package/dist/query-v2/core/machines/index.d.ts +8 -0
- package/dist/query-v2/core/machines/index.js +8 -0
- package/dist/query-v2/core/resource/ResourceV2.d.ts +120 -0
- package/dist/query-v2/core/resource/ResourceV2.js +464 -0
- package/dist/query-v2/core/resource/ResourceV2Agent.d.ts +26 -0
- package/dist/query-v2/core/resource/ResourceV2Agent.js +132 -0
- package/dist/query-v2/core/resource/index.d.ts +2 -0
- package/dist/query-v2/core/resource/index.js +2 -0
- package/dist/query-v2/index.d.ts +11 -0
- package/dist/query-v2/index.js +17 -0
- package/dist/query-v2/lib/NO_VALUE.d.ts +2 -0
- package/dist/query-v2/lib/NO_VALUE.js +1 -0
- package/dist/query-v2/lib/SKIP_TOKEN.d.ts +2 -0
- package/dist/query-v2/lib/SKIP_TOKEN.js +1 -0
- package/dist/query-v2/lib/index.d.ts +4 -0
- package/dist/query-v2/lib/index.js +3 -0
- package/dist/query-v2/lib/stableStringify.d.ts +8 -0
- package/dist/query-v2/lib/stableStringify.js +23 -0
- package/dist/query-v2/plugins/ReactHooksPlugin.d.ts +25 -0
- package/dist/query-v2/plugins/ReactHooksPlugin.js +19 -0
- package/dist/query-v2/plugins/types.d.ts +1 -0
- package/dist/query-v2/plugins/types.js +1 -0
- package/dist/query-v2/react/__tests__/helpers.d.ts +12 -0
- package/dist/query-v2/react/__tests__/helpers.js +33 -0
- package/dist/query-v2/react/index.d.ts +2 -0
- package/dist/query-v2/react/index.js +2 -0
- package/dist/query-v2/react/useResourceV2Agent.d.ts +12 -0
- package/dist/query-v2/react/useResourceV2Agent.js +36 -0
- package/dist/query-v2/react/useResourceV2Ref.d.ts +12 -0
- package/dist/query-v2/react/useResourceV2Ref.js +57 -0
- package/dist/query-v2/snapshot/Snapshot.d.ts +13 -0
- package/dist/query-v2/snapshot/Snapshot.js +76 -0
- package/dist/query-v2/types/agent.types.d.ts +54 -0
- package/dist/query-v2/types/agent.types.js +1 -0
- package/dist/query-v2/types/api.types.d.ts +22 -0
- package/dist/query-v2/types/api.types.js +1 -0
- package/dist/query-v2/types/cache.types.d.ts +37 -0
- package/dist/query-v2/types/cache.types.js +1 -0
- package/dist/query-v2/types/index.d.ts +9 -0
- package/dist/query-v2/types/index.js +9 -0
- package/dist/query-v2/types/lifecycle.types.d.ts +25 -0
- package/dist/query-v2/types/lifecycle.types.js +1 -0
- package/dist/query-v2/types/machine.types.d.ts +67 -0
- package/dist/query-v2/types/machine.types.js +1 -0
- package/dist/query-v2/types/plugin.types.d.ts +38 -0
- package/dist/query-v2/types/plugin.types.js +1 -0
- package/dist/query-v2/types/resource.types.d.ts +35 -0
- package/dist/query-v2/types/resource.types.js +1 -0
- package/dist/query-v2/types/shared.types.d.ts +20 -0
- package/dist/query-v2/types/shared.types.js +1 -0
- package/dist/query-v2/types/snapshot.types.d.ts +21 -0
- package/dist/query-v2/types/snapshot.types.js +1 -0
- package/dist/signals/base/Batcher.js +9 -5
- package/dist/signals/base/ComputeCache.js +3 -3
- package/dist/signals/base/DependencyTracker.js +1 -1
- package/dist/signals/base/Devtools.d.ts +3 -2
- package/dist/signals/base/Devtools.js +54 -27
- package/dist/signals/base/Indexer.js +1 -1
- package/dist/signals/base/ReadonlySignal.js +1 -1
- package/dist/signals/base/SyncObservable.d.ts +1 -2
- package/dist/signals/base/SyncObservable.js +2 -5
- package/dist/signals/base/index.d.ts +6 -6
- package/dist/signals/base/index.js +6 -6
- package/dist/signals/index.d.ts +5 -4
- package/dist/signals/index.js +5 -4
- package/dist/signals/operators/index.d.ts +1 -1
- package/dist/signals/operators/index.js +1 -1
- package/dist/signals/react/index.d.ts +1 -1
- package/dist/signals/react/index.js +1 -1
- package/dist/signals/signals/Computed.d.ts +3 -4
- package/dist/signals/signals/Computed.js +18 -10
- package/dist/signals/signals/Effect.js +2 -1
- package/dist/signals/signals/LocalState.d.ts +3 -4
- package/dist/signals/signals/LocalState.js +8 -8
- package/dist/signals/signals/Signal.d.ts +7 -6
- package/dist/signals/signals/Signal.js +4 -1
- package/dist/signals/signals/State.d.ts +4 -5
- package/dist/signals/signals/State.js +23 -9
- package/dist/signals/signals/index.d.ts +5 -5
- package/dist/signals/signals/index.js +5 -6
- package/dist/signals/types/SignalOptions.d.ts +16 -0
- package/dist/signals/types/SignalOptions.js +1 -0
- package/dist/signals/types/index.d.ts +3 -1
- package/dist/signals/types/index.js +3 -1
- package/dist/signals/types/normalizeSignalOptions.d.ts +2 -0
- package/dist/signals/types/normalizeSignalOptions.js +10 -0
- package/dist/signals/types/signals.types.d.ts +2 -3
- package/docs/CHANGELOG.md +111 -90
- package/docs/CONTRIBUTING.md +230 -0
- package/docs/contributing/ai-assisted-development.md +47 -0
- package/docs/contributing/query-v2/README.md +379 -0
- package/docs/{release → contributing/release}/README.md +59 -59
- package/docs/devtools/README.md +228 -228
- package/docs/migrations/0.5.0.md +58 -58
- package/docs/migrations/query-v2.md +171 -0
- package/docs/options/README.md +92 -92
- package/docs/query/README.md +575 -573
- package/docs/query-v2/README.md +280 -0
- package/docs/query-v2/api-reference.md +235 -0
- package/docs/query-v2/optimistic-updates.md +148 -0
- package/docs/query-v2/ssr.md +130 -0
- package/docs/signals/README.md +300 -300
- package/docs/usage/react/README.md +309 -309
- package/package.json +86 -63
|
@@ -1,7 +1,8 @@
|
|
|
1
|
-
import { distinctUntilChanged,
|
|
1
|
+
import { distinctUntilChanged, finalize, map, ReplaySubject, share } from "rxjs";
|
|
2
|
+
import { normalizeSignalOptions } from "../../signals/types";
|
|
2
3
|
import { ComputeCache, DependencyTracker } from "../base";
|
|
3
4
|
import { Effect } from "./Effect";
|
|
4
|
-
import {
|
|
5
|
+
import { State } from "./State";
|
|
5
6
|
export class Computed {
|
|
6
7
|
_computeFn;
|
|
7
8
|
_state$;
|
|
@@ -13,12 +14,19 @@ export class Computed {
|
|
|
13
14
|
_computeCache = new ComputeCache();
|
|
14
15
|
constructor(_computeFn, options) {
|
|
15
16
|
this._computeFn = _computeFn;
|
|
16
|
-
const
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
17
|
+
const opts = normalizeSignalOptions(options);
|
|
18
|
+
const stateOptions = {
|
|
19
|
+
key: opts.key,
|
|
20
|
+
name: opts.name,
|
|
21
|
+
base: opts.base ?? Computed.name,
|
|
22
|
+
isDisabled: opts.isDisabled,
|
|
23
|
+
beforeDevtoolsPush: (value, push) => {
|
|
24
|
+
if (value !== Computed._EMPTY) {
|
|
25
|
+
push(value);
|
|
26
|
+
}
|
|
27
|
+
},
|
|
20
28
|
};
|
|
21
|
-
this._state$ =
|
|
29
|
+
this._state$ = State.create(Computed._EMPTY, stateOptions);
|
|
22
30
|
this.obs = this._state$.obs.pipe(map((value) => {
|
|
23
31
|
if (value === Computed._EMPTY) {
|
|
24
32
|
return this._start();
|
|
@@ -36,7 +44,7 @@ export class Computed {
|
|
|
36
44
|
DependencyTracker.track({
|
|
37
45
|
getRang: () => {
|
|
38
46
|
if (!this._effect) {
|
|
39
|
-
throw new Error(
|
|
47
|
+
throw new Error("Effect in not started. Possibly maximum call stack size exceeded.");
|
|
40
48
|
}
|
|
41
49
|
return this._effect._getRang();
|
|
42
50
|
},
|
|
@@ -65,7 +73,7 @@ export class Computed {
|
|
|
65
73
|
});
|
|
66
74
|
this._computeCache.clear();
|
|
67
75
|
if (initialValue === Computed._EMPTY) {
|
|
68
|
-
throw new Error(
|
|
76
|
+
throw new Error("Computed value is not initialized");
|
|
69
77
|
}
|
|
70
78
|
return initialValue;
|
|
71
79
|
}
|
|
@@ -77,7 +85,7 @@ export class Computed {
|
|
|
77
85
|
this._state$.set(Computed._EMPTY);
|
|
78
86
|
}
|
|
79
87
|
// === static ===
|
|
80
|
-
static _EMPTY = Symbol(
|
|
88
|
+
static _EMPTY = Symbol("empty");
|
|
81
89
|
static create(computeFn, options) {
|
|
82
90
|
const lc = new Computed(computeFn, options);
|
|
83
91
|
function computedFn() {
|
|
@@ -15,6 +15,7 @@ export class Effect {
|
|
|
15
15
|
this._rang = 0;
|
|
16
16
|
const legacySubscriptions = this._subscriptions;
|
|
17
17
|
this._subscriptions = new Map();
|
|
18
|
+
// eslint-disable-next-line prefer-const -- assigned after closure capture
|
|
18
19
|
let scheduler;
|
|
19
20
|
// Стабильная функция для планирования выполнения эффекта
|
|
20
21
|
const scheduledFn = () => {
|
|
@@ -52,7 +53,7 @@ export class Effect {
|
|
|
52
53
|
stopTracking();
|
|
53
54
|
isTrackedContext = false;
|
|
54
55
|
// Сохраняем teardown функцию, если она была возвращена
|
|
55
|
-
if (typeof optionalTeardown ===
|
|
56
|
+
if (typeof optionalTeardown === "function") {
|
|
56
57
|
this._teardown = optionalTeardown;
|
|
57
58
|
}
|
|
58
59
|
scheduler = Batcher.scheduler(this._rang);
|
|
@@ -1,7 +1,6 @@
|
|
|
1
|
-
import { ZodType } from "zod/v4";
|
|
2
1
|
import { Observable } from "rxjs";
|
|
3
|
-
import {
|
|
4
|
-
import { type
|
|
2
|
+
import { ZodType } from "zod/v4";
|
|
3
|
+
import { type SignalOptionsOrKey, type StatefulSignalFn } from "../../signals/types";
|
|
5
4
|
type StorageLike = {
|
|
6
5
|
getItem(key: string): string | null;
|
|
7
6
|
setItem(key: string, value: string): void;
|
|
@@ -18,7 +17,7 @@ type Options<T> = {
|
|
|
18
17
|
checkEffect?: (value: T) => boolean;
|
|
19
18
|
driver?: StorageLike;
|
|
20
19
|
defaultValue: T;
|
|
21
|
-
devtoolsOptions?:
|
|
20
|
+
devtoolsOptions?: SignalOptionsOrKey;
|
|
22
21
|
};
|
|
23
22
|
export declare class LocalState<T = string | null | number | undefined> {
|
|
24
23
|
private _state$;
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import { z } from "zod/v4";
|
|
2
2
|
import { signalize } from "../operators";
|
|
3
3
|
import { Computed } from "./Computed";
|
|
4
|
-
import { State } from "
|
|
5
|
-
const NONE = Symbol(
|
|
4
|
+
import { State } from "./State";
|
|
5
|
+
const NONE = Symbol("NONE");
|
|
6
6
|
export class LocalState {
|
|
7
7
|
_state$;
|
|
8
8
|
_computed;
|
|
@@ -59,7 +59,7 @@ export class LocalState {
|
|
|
59
59
|
console.warn(`Invalid value for key "${options.key}" in localStorage`, parsed.error);
|
|
60
60
|
return NONE;
|
|
61
61
|
}
|
|
62
|
-
const subKey = options.userId ? `user:${options.userId}` :
|
|
62
|
+
const subKey = options.userId ? `user:${options.userId}` : "common";
|
|
63
63
|
if (!(subKey in parsed.data)) {
|
|
64
64
|
return NONE;
|
|
65
65
|
}
|
|
@@ -67,14 +67,14 @@ export class LocalState {
|
|
|
67
67
|
}
|
|
68
68
|
_setStorageValue(options, value) {
|
|
69
69
|
const storageKey = `${LocalState.KEY_PREFIX}:${options.key}`;
|
|
70
|
-
const item = this._driver.getItem(storageKey) ||
|
|
70
|
+
const item = this._driver.getItem(storageKey) || "{}";
|
|
71
71
|
const schema = z.record(z.string(), options.zodSchema || z.any());
|
|
72
72
|
const parsed = schema.safeParse(JSON.parse(item));
|
|
73
73
|
let data = parsed.data ?? {};
|
|
74
74
|
if (!parsed.success) {
|
|
75
75
|
data = {};
|
|
76
76
|
}
|
|
77
|
-
const subKey = options.userId ? `user:${options.userId}` :
|
|
77
|
+
const subKey = options.userId ? `user:${options.userId}` : "common";
|
|
78
78
|
data[subKey] = value;
|
|
79
79
|
this._driver.setItem(storageKey, JSON.stringify(data));
|
|
80
80
|
}
|
|
@@ -85,12 +85,12 @@ export class LocalState {
|
|
|
85
85
|
return;
|
|
86
86
|
const schema = z.record(z.string(), options.zodSchema || z.any());
|
|
87
87
|
const parsed = schema.safeParse(JSON.parse(item));
|
|
88
|
-
|
|
88
|
+
const data = parsed.data ?? {};
|
|
89
89
|
if (!parsed.success) {
|
|
90
90
|
this._driver.removeItem(storageKey);
|
|
91
91
|
return;
|
|
92
92
|
}
|
|
93
|
-
const subKey = options.userId ? `user:${options.userId}` :
|
|
93
|
+
const subKey = options.userId ? `user:${options.userId}` : "common";
|
|
94
94
|
if (!data[subKey])
|
|
95
95
|
return;
|
|
96
96
|
delete data[subKey];
|
|
@@ -101,7 +101,7 @@ export class LocalState {
|
|
|
101
101
|
this._driver.setItem(storageKey, JSON.stringify(data));
|
|
102
102
|
}
|
|
103
103
|
// === static ===
|
|
104
|
-
static KEY_PREFIX =
|
|
104
|
+
static KEY_PREFIX = "__LSValue__";
|
|
105
105
|
static DEFAULT_DRIVER = localStorage;
|
|
106
106
|
static create(options) {
|
|
107
107
|
const localState = new LocalState(options);
|
|
@@ -1,12 +1,13 @@
|
|
|
1
|
-
import type {
|
|
1
|
+
import type { SignalOptionsOrKey } from "../../signals/types";
|
|
2
2
|
import { SignalFn } from "../../signals/types";
|
|
3
|
-
import { Effect
|
|
3
|
+
import { Effect } from "./Effect";
|
|
4
|
+
import { State } from "./State";
|
|
4
5
|
export declare class Signal<T> extends State<T> {
|
|
5
6
|
/** @deprecated use `State` instead */
|
|
6
|
-
constructor(initialValue: T, options?:
|
|
7
|
+
constructor(initialValue: T, options?: SignalOptionsOrKey<T>);
|
|
7
8
|
/** @deprecated use `state` instead */
|
|
8
|
-
static create<T>(initialValue: T, options?:
|
|
9
|
-
static state<T>(initialValue: T, options?:
|
|
10
|
-
static compute<T>(computeFn: () => T, options?:
|
|
9
|
+
static create<T>(initialValue: T, options?: SignalOptionsOrKey<T>): SignalFn<T>;
|
|
10
|
+
static state<T>(initialValue: T, options?: SignalOptionsOrKey<T>): SignalFn<T>;
|
|
11
|
+
static compute<T>(computeFn: () => T, options?: SignalOptionsOrKey<T>): import("../../signals/types").ComputeFn<T>;
|
|
11
12
|
static effect(effectFn: () => void): Effect;
|
|
12
13
|
}
|
|
@@ -1,6 +1,9 @@
|
|
|
1
|
-
import { Computed
|
|
1
|
+
import { Computed } from "./Computed";
|
|
2
|
+
import { Effect } from "./Effect";
|
|
3
|
+
import { State } from "./State";
|
|
2
4
|
export class Signal extends State {
|
|
3
5
|
/** @deprecated use `State` instead */
|
|
6
|
+
// eslint-disable-next-line @typescript-eslint/no-useless-constructor
|
|
4
7
|
constructor(initialValue, options) {
|
|
5
8
|
super(initialValue, options);
|
|
6
9
|
}
|
|
@@ -1,15 +1,14 @@
|
|
|
1
1
|
import { BehaviorSubject } from "rxjs";
|
|
2
|
-
import {
|
|
3
|
-
import { SignalFn } from "../../signals/types";
|
|
2
|
+
import { SignalFn, SignalOptionsOrKey } from "../../signals/types";
|
|
4
3
|
export declare class State<T> {
|
|
5
|
-
private readonly
|
|
4
|
+
private readonly _hooks;
|
|
6
5
|
private _rang;
|
|
7
6
|
protected readonly bs$: BehaviorSubject<T>;
|
|
8
7
|
readonly obs: import("rxjs").Observable<T>;
|
|
9
|
-
constructor(initialValue: T, options?:
|
|
8
|
+
constructor(initialValue: T, options?: SignalOptionsOrKey<T>);
|
|
10
9
|
peek(): T;
|
|
11
10
|
set(value: T): void;
|
|
12
11
|
get(): T;
|
|
13
12
|
private static _finalizationRegistry;
|
|
14
|
-
static create<T>(initialValue: T, options?:
|
|
13
|
+
static create<T>(initialValue: T, options?: SignalOptionsOrKey<T>): SignalFn<T>;
|
|
15
14
|
}
|
|
@@ -1,19 +1,27 @@
|
|
|
1
1
|
import { BehaviorSubject } from "rxjs";
|
|
2
|
+
import { normalizeSignalOptions } from "../../signals/types";
|
|
2
3
|
import { Batcher, DependencyTracker, Devtools } from "../base";
|
|
3
4
|
export class State {
|
|
4
|
-
|
|
5
|
+
_hooks;
|
|
5
6
|
_rang = 0;
|
|
6
7
|
bs$;
|
|
7
8
|
obs;
|
|
8
9
|
constructor(initialValue, options) {
|
|
9
10
|
this.bs$ = new BehaviorSubject(initialValue);
|
|
10
11
|
this.obs = this.bs$.asObservable();
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
12
|
+
const opts = normalizeSignalOptions(options);
|
|
13
|
+
const hooks = [];
|
|
14
|
+
const devtoolsHook = Devtools.createSignalHooks(initialValue, {
|
|
15
|
+
...opts,
|
|
16
|
+
base: opts.base ?? State.name,
|
|
14
17
|
});
|
|
15
|
-
if (
|
|
16
|
-
|
|
18
|
+
if (devtoolsHook)
|
|
19
|
+
hooks.push(devtoolsHook);
|
|
20
|
+
if (opts.hooks)
|
|
21
|
+
hooks.push(...opts.hooks);
|
|
22
|
+
this._hooks = hooks.length > 0 ? hooks : null;
|
|
23
|
+
if (this._hooks) {
|
|
24
|
+
State._finalizationRegistry.register(this, this._hooks);
|
|
17
25
|
}
|
|
18
26
|
}
|
|
19
27
|
peek() {
|
|
@@ -24,7 +32,11 @@ export class State {
|
|
|
24
32
|
return;
|
|
25
33
|
}
|
|
26
34
|
Batcher.run(() => {
|
|
27
|
-
this.
|
|
35
|
+
if (this._hooks) {
|
|
36
|
+
for (const hook of this._hooks) {
|
|
37
|
+
hook.onChange?.(value);
|
|
38
|
+
}
|
|
39
|
+
}
|
|
28
40
|
this.bs$.next(value);
|
|
29
41
|
});
|
|
30
42
|
}
|
|
@@ -37,8 +49,10 @@ export class State {
|
|
|
37
49
|
return this.bs$.getValue();
|
|
38
50
|
}
|
|
39
51
|
// === static ===
|
|
40
|
-
static _finalizationRegistry = new FinalizationRegistry((
|
|
41
|
-
|
|
52
|
+
static _finalizationRegistry = new FinalizationRegistry((hooks) => {
|
|
53
|
+
for (const hook of hooks) {
|
|
54
|
+
hook.onDispose?.();
|
|
55
|
+
}
|
|
42
56
|
});
|
|
43
57
|
static create(initialValue, options) {
|
|
44
58
|
const ls = new State(initialValue, options);
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
export * from
|
|
2
|
-
export * from
|
|
3
|
-
export * from
|
|
4
|
-
export * from
|
|
5
|
-
export * from
|
|
1
|
+
export * from "./State";
|
|
2
|
+
export * from "./Computed";
|
|
3
|
+
export * from "./Effect";
|
|
4
|
+
export * from "./LocalState";
|
|
5
|
+
export * from "./Signal";
|
|
@@ -1,6 +1,5 @@
|
|
|
1
|
-
|
|
2
|
-
export * from
|
|
3
|
-
export * from
|
|
4
|
-
export * from
|
|
5
|
-
export * from
|
|
6
|
-
export * from './LocalState';
|
|
1
|
+
export * from "./State";
|
|
2
|
+
export * from "./Computed";
|
|
3
|
+
export * from "./Effect";
|
|
4
|
+
export * from "./LocalState";
|
|
5
|
+
export * from "./Signal";
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
export interface SignalLifecycleHook<T = any> {
|
|
2
|
+
onInit?: (value: T) => void;
|
|
3
|
+
onChange?: (newValue: T) => void;
|
|
4
|
+
onDispose?: () => void;
|
|
5
|
+
}
|
|
6
|
+
export type TBeforeDevtoolsPushFn<T = any> = (newValue: T, push: (v: T) => void) => void;
|
|
7
|
+
export interface SignalOptions<T = any> {
|
|
8
|
+
key?: string;
|
|
9
|
+
/** @deprecated use key */
|
|
10
|
+
name?: string;
|
|
11
|
+
base?: string;
|
|
12
|
+
isDisabled?: boolean;
|
|
13
|
+
beforeDevtoolsPush?: TBeforeDevtoolsPushFn<T>;
|
|
14
|
+
hooks?: SignalLifecycleHook<T>[];
|
|
15
|
+
}
|
|
16
|
+
export type SignalOptionsOrKey<T = any> = SignalOptions<T> | string;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -10,12 +10,11 @@ export interface ReadableSignalFnLike<T> extends ReadableSignalLike<T> {
|
|
|
10
10
|
export interface WriteableSignalLike<T> {
|
|
11
11
|
set(value: T): void;
|
|
12
12
|
}
|
|
13
|
-
export interface ClearableSignalLike<
|
|
13
|
+
export interface ClearableSignalLike<_T> {
|
|
14
14
|
clear(): void;
|
|
15
15
|
}
|
|
16
16
|
export interface StatefulSignalFn<T> extends ReadableSignalFnLike<T>, WriteableSignalLike<T>, ClearableSignalLike<T> {
|
|
17
17
|
}
|
|
18
18
|
export interface SignalFn<T> extends ReadableSignalFnLike<T>, WriteableSignalLike<T> {
|
|
19
19
|
}
|
|
20
|
-
export
|
|
21
|
-
}
|
|
20
|
+
export type ComputeFn<T> = ReadableSignalFnLike<T>;
|
package/docs/CHANGELOG.md
CHANGED
|
@@ -1,90 +1,111 @@
|
|
|
1
|
-
# CHANGELOG
|
|
2
|
-
|
|
3
|
-
## [
|
|
4
|
-
|
|
5
|
-
###
|
|
6
|
-
|
|
7
|
-
- `
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
- `
|
|
11
|
-
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
- `
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
-
|
|
25
|
-
|
|
26
|
-
###
|
|
27
|
-
|
|
28
|
-
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
###
|
|
59
|
-
|
|
60
|
-
-
|
|
61
|
-
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
###
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
-
|
|
84
|
-
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
1
|
+
# CHANGELOG
|
|
2
|
+
|
|
3
|
+
## [Unreleased]
|
|
4
|
+
|
|
5
|
+
### Fixed
|
|
6
|
+
- Fixed `useResourceRef` memoization for object arguments — ref no longer recreated every render
|
|
7
|
+
- Fixed missing type exports from `src/query/` — consumers can now import `ResourceDefinition`, `CommandDefinition`, etc.
|
|
8
|
+
|
|
9
|
+
### Changed
|
|
10
|
+
- `ResourceRefInstanse` renamed to `ResourceRefInstance` (deprecated alias preserved)
|
|
11
|
+
- `FrowardInfo` renamed to `ForwardInfo` (internal type)
|
|
12
|
+
- `Opertation/` directory renamed to `Operation/`
|
|
13
|
+
- Replaced `any` types with proper types in `useResourceAgent` and `ResourceDuplicator`
|
|
14
|
+
|
|
15
|
+
### Added
|
|
16
|
+
- Unit tests for query core modules
|
|
17
|
+
- Smoke tests for React hooks
|
|
18
|
+
- Integration tests for query exports
|
|
19
|
+
|
|
20
|
+
### Deprecated
|
|
21
|
+
- `ResourceRefInstanse` — use `ResourceRefInstance` (will be removed in v0.6.0)
|
|
22
|
+
|
|
23
|
+
|
|
24
|
+
## [0.5.3-rc.2] — 2026-02-23
|
|
25
|
+
|
|
26
|
+
### Added
|
|
27
|
+
|
|
28
|
+
- `createCommand()` — создание команды (мутации/действия), заменяет `createOperation()`
|
|
29
|
+
- `useCommandAgent()` — React-хук для работы с командой
|
|
30
|
+
- `LocalState` — замена `LocalSignal` с новыми возможностями
|
|
31
|
+
- `LocalState.clear()` — метод удаления значения из хранилища и сброса к значению по умолчанию
|
|
32
|
+
- Опция `driver` для `LocalState` — возможность подключить кастомное хранилище (вместо `localStorage`)
|
|
33
|
+
|
|
34
|
+
### Changed
|
|
35
|
+
|
|
36
|
+
- `LocalSignal` переименован в `LocalState`
|
|
37
|
+
- Все вызовы `Signal.create()` в кодовой базе заменены на `Signal.state()` (внутренний рефакторинг)
|
|
38
|
+
|
|
39
|
+
### Deprecated
|
|
40
|
+
|
|
41
|
+
- `createOperation()` → используйте `createCommand()` (будет удалён в v0.6.0)
|
|
42
|
+
- `useOperationAgent()` → используйте `useCommandAgent()` (будет удалён в v0.6.0)
|
|
43
|
+
- Все Operation-типы переименованы в Command-типы: `OperationDefinition` → `CommandDefinition`, `OperationInstance` → `CommandInstance`, `OperationCreateOptions` → `CommandCreateOptions`, `OperationCreateFn` → `CommandCreateFn`, `OperationQueryState` → `CommandQueryState`
|
|
44
|
+
- `OperationAgentInstanse` (с опечаткой) → `CommandAgentInstance` — исправлена опечатка в имени типа
|
|
45
|
+
- `LocalSignal` → используйте `LocalState`
|
|
46
|
+
|
|
47
|
+
### Fixed
|
|
48
|
+
|
|
49
|
+
- Исправления в документации и демо-примерах
|
|
50
|
+
|
|
51
|
+
## [0.5.3-rc.1] — 2026-02-22
|
|
52
|
+
|
|
53
|
+
### Added
|
|
54
|
+
|
|
55
|
+
- Новый примитив **State** — замена `Signal` с идентичным API
|
|
56
|
+
- `Signal.state()` — рекомендуемый статический метод создания сигнала
|
|
57
|
+
|
|
58
|
+
### Deprecated
|
|
59
|
+
|
|
60
|
+
- `Signal` помечен как `@deprecated` — используйте `State` вместо него
|
|
61
|
+
- `Signal.create()` помечен как `@deprecated` — используйте `Signal.state()` / `State.create()`
|
|
62
|
+
|
|
63
|
+
## [0.5.2] — 2025-12-19
|
|
64
|
+
|
|
65
|
+
### Fixed
|
|
66
|
+
|
|
67
|
+
- Исправлена работа `SKIP_TOKEN`
|
|
68
|
+
|
|
69
|
+
## [0.5.1] — 2025-12-19
|
|
70
|
+
|
|
71
|
+
### Fixed
|
|
72
|
+
|
|
73
|
+
- Исправление типизации
|
|
74
|
+
|
|
75
|
+
## [0.5.0] — 2025-12-18
|
|
76
|
+
|
|
77
|
+
[Гайд по миграции с 0.4.x](./migrations/0.5.0.md)
|
|
78
|
+
|
|
79
|
+
### Breaking Changes
|
|
80
|
+
|
|
81
|
+
- Удалены хуки `useObservable` и `useSyncObservable`
|
|
82
|
+
- Сигналы больше не наследуют `Observable` — используйте `.obs` для подписки
|
|
83
|
+
- Удалены `.value`, `.getValue()`, `.next()` — заменены на `signal()`, `.get()`, `.set()`
|
|
84
|
+
- Нет необходимости вызывать `complete()` для Signal и Computed
|
|
85
|
+
|
|
86
|
+
### Added
|
|
87
|
+
|
|
88
|
+
#### Signals
|
|
89
|
+
- **Функциональный API**: `Signal.create()`, `Signal.compute()`, `Signal.effect()`
|
|
90
|
+
- **Ленивый Computed**: вычисление только при наличии подписок
|
|
91
|
+
- Cleanup-функции в `Effect` (возврат teardown)
|
|
92
|
+
|
|
93
|
+
#### Query
|
|
94
|
+
- **Расширенные состояния**: `isInitialLoading`, `isReloading`, `isLocked`
|
|
95
|
+
- **ResourceRef API**: низкоуровневый доступ к кэшу с поддержкой транзакций (patch с commit/abort)
|
|
96
|
+
- **Lifecycle хуки**: `onCacheEntryAdded`, `onQueryStarted`
|
|
97
|
+
- `resetAllQueriesCache()` — сброс всего кэша
|
|
98
|
+
|
|
99
|
+
#### React
|
|
100
|
+
- `useResourceRef` — хук для работы с ResourceRef
|
|
101
|
+
|
|
102
|
+
### Changed
|
|
103
|
+
|
|
104
|
+
- **BatchStrategy**: настройка стратегии обновлений (`'sync'`, `'microtask'`, `'task'`)
|
|
105
|
+
- **DefaultOptions**: расширенная конфигурация (`onQueryError`, `getScopeName`)
|
|
106
|
+
|
|
107
|
+
[0.5.3-rc.2]: https://github.com/fozy-labs/rx-toolkit/compare/v0.5.3-rc.1...v0.5.3-rc.2
|
|
108
|
+
[0.5.3-rc.1]: https://github.com/fozy-labs/rx-toolkit/compare/v0.5.2...v0.5.3-rc.1
|
|
109
|
+
[0.5.2]: https://github.com/fozy-labs/rx-toolkit/compare/v0.5.1...v0.5.2
|
|
110
|
+
[0.5.1]: https://github.com/fozy-labs/rx-toolkit/compare/v0.5.0...v0.5.1
|
|
111
|
+
[0.5.0]: https://github.com/fozy-labs/rx-toolkit/compare/v0.4.18...v0.5.0
|