@fozy-labs/rx-toolkit 0.4.14 → 0.4.16

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 (33) hide show
  1. package/dist/common/devtools/reduxDevtools.js +29 -2
  2. package/dist/common/options/SharedOptions.d.ts +5 -3
  3. package/dist/common/options/SharedOptions.js +4 -2
  4. package/dist/common/utils/deepEqual.d.ts +1 -0
  5. package/dist/common/utils/deepEqual.js +21 -0
  6. package/dist/common/utils/index.d.ts +2 -0
  7. package/dist/common/utils/index.js +2 -0
  8. package/dist/index.d.ts +2 -0
  9. package/dist/index.js +2 -0
  10. package/dist/query/api/cleanAllResources.d.ts +1 -0
  11. package/dist/query/api/cleanAllResources.js +4 -0
  12. package/dist/query/core/CleanAllResourcesSignal.d.ts +6 -0
  13. package/dist/query/core/CleanAllResourcesSignal.js +11 -0
  14. package/dist/query/core/QueriesCache.d.ts +3 -1
  15. package/dist/query/core/QueriesCache.js +11 -17
  16. package/dist/query/core/Resource/Resource.d.ts +2 -1
  17. package/dist/query/core/Resource/Resource.js +14 -4
  18. package/dist/query/core/Resource/ResourceAgent.d.ts +3 -1
  19. package/dist/query/core/Resource/ResourceAgent.js +39 -20
  20. package/dist/query/index.d.ts +1 -0
  21. package/dist/query/index.js +1 -0
  22. package/dist/query/lib/IndirectMap.d.ts +1 -0
  23. package/dist/query/lib/IndirectMap.js +4 -1
  24. package/dist/query/lib/ReactiveCache.d.ts +1 -0
  25. package/dist/query/lib/ReactiveCache.js +4 -0
  26. package/dist/query/react/useResourceAgent.js +1 -2
  27. package/dist/query/types/Resource.types.d.ts +6 -0
  28. package/dist/signals/signals/Effect.d.ts +2 -1
  29. package/dist/signals/signals/Effect.js +13 -2
  30. package/dist/signals/signals/Signal.js +2 -2
  31. package/package.json +1 -1
  32. /package/dist/{query/lib → common/utils}/shallowEqual.d.ts +0 -0
  33. /package/dist/{query/lib → common/utils}/shallowEqual.js +0 -0
@@ -26,8 +26,8 @@ export function reduxDevtools(options = {}) {
26
26
  state = applyState(keys, initState, state);
27
27
  scheduler.schedule(createFn());
28
28
  return (newState) => {
29
- if (newState === '$COMPLETE' || newState === '$CLEANED') {
30
- delete state[name];
29
+ if (newState === '$COMPLETED' || newState === '$CLEANED') {
30
+ state = deleteState(keys, state);
31
31
  clearFn();
32
32
  return;
33
33
  }
@@ -51,3 +51,30 @@ function applyState(keys, newState, state) {
51
51
  });
52
52
  return acc;
53
53
  }
54
+ // Идем по ключам и удалаем последний, если оставется пустой объект, удаляем его рекурсивно
55
+ function deleteState(keys, state) {
56
+ if (keys.length === 0)
57
+ return state;
58
+ const acc = { ...state };
59
+ // Рекурсивная функция для удаления с очисткой пустых объектов
60
+ const deleteRecursive = (obj, pathKeys, index) => {
61
+ const key = pathKeys[index];
62
+ if (!obj || !obj.hasOwnProperty(key)) {
63
+ return false;
64
+ }
65
+ if (index === pathKeys.length - 1) {
66
+ delete obj[key];
67
+ }
68
+ else {
69
+ obj[key] = { ...obj[key] };
70
+ deleteRecursive(obj[key], pathKeys, index + 1);
71
+ // Если объект стал пустым, удаляем его
72
+ if (Object.keys(obj[key]).length === 0) {
73
+ delete obj[key];
74
+ }
75
+ }
76
+ return true;
77
+ };
78
+ deleteRecursive(acc, keys, 0);
79
+ return acc;
80
+ }
@@ -1,8 +1,10 @@
1
- import { DevtoolsLike } from "../../common/devtools";
2
1
  import { Observable } from "rxjs";
2
+ import { DevtoolsLike } from "../../common/devtools";
3
+ import { shallowEqual } from "../../common/utils";
3
4
  export declare class SharedOptions {
4
5
  static DEVTOOLS: DevtoolsLike | null;
5
6
  static onQueryError: ((error: unknown) => void) | null;
6
- static getScopeName: () => string | null;
7
- static getScopeDestroyed$: () => Observable<void> | null;
7
+ static getScopeName: (() => string | null) | null;
8
+ static getScopeDestroyed$: (() => Observable<void> | null) | null;
9
+ static defaultCompareArgs: typeof shallowEqual;
8
10
  }
@@ -1,6 +1,8 @@
1
+ import { shallowEqual } from "../../common/utils";
1
2
  export class SharedOptions {
2
3
  static DEVTOOLS = null;
3
4
  static onQueryError = null;
4
- static getScopeName;
5
- static getScopeDestroyed$;
5
+ static getScopeName = null;
6
+ static getScopeDestroyed$ = null;
7
+ static defaultCompareArgs = shallowEqual;
6
8
  }
@@ -0,0 +1 @@
1
+ export declare function deepEqual(a: unknown, b: unknown): boolean;
@@ -0,0 +1,21 @@
1
+ export function deepEqual(a, b) {
2
+ if (a === b) {
3
+ return true;
4
+ }
5
+ if (typeof a !== "object" || a === null || typeof b !== "object" || b === null) {
6
+ return false;
7
+ }
8
+ const keysA = Object.keys(a);
9
+ const keysB = Object.keys(b);
10
+ if (keysA.length !== keysB.length) {
11
+ return false;
12
+ }
13
+ for (let i = 0; i < keysA.length; i++) {
14
+ const key = keysA[i];
15
+ // @ts-ignore
16
+ if (!Object.prototype.hasOwnProperty.call(b, key) || !deepEqual(a[key], b[key])) {
17
+ return false;
18
+ }
19
+ }
20
+ return true;
21
+ }
@@ -1 +1,3 @@
1
1
  export * from './PromiseResolver';
2
+ export * from './deepEqual';
3
+ export * from './shallowEqual';
@@ -1 +1,3 @@
1
1
  export * from './PromiseResolver';
2
+ export * from './deepEqual';
3
+ export * from './shallowEqual';
package/dist/index.d.ts CHANGED
@@ -1,5 +1,7 @@
1
1
  export * from './common/devtools';
2
2
  export * from './common/options';
3
3
  export * from './common/react';
4
+ export * from './common/utils/deepEqual';
5
+ export * from './common/utils/shallowEqual';
4
6
  export * from './query';
5
7
  export * from './signals';
package/dist/index.js CHANGED
@@ -1,5 +1,7 @@
1
1
  export * from './common/devtools';
2
2
  export * from './common/options';
3
3
  export * from './common/react';
4
+ export * from './common/utils/deepEqual';
5
+ export * from './common/utils/shallowEqual';
4
6
  export * from './query';
5
7
  export * from './signals';
@@ -0,0 +1 @@
1
+ export declare function cleanAllResources(): void;
@@ -0,0 +1,4 @@
1
+ import { CleanAllResourcesSignal } from "../core/CleanAllResourcesSignal";
2
+ export function cleanAllResources() {
3
+ CleanAllResourcesSignal.clean();
4
+ }
@@ -0,0 +1,6 @@
1
+ import { Subject } from "rxjs";
2
+ export declare class CleanAllResourcesSignal {
3
+ private static subject$;
4
+ static clean$: Subject<void>;
5
+ static clean(): void;
6
+ }
@@ -0,0 +1,11 @@
1
+ import { Subject } from "rxjs";
2
+ import { Batcher } from "../../signals";
3
+ export class CleanAllResourcesSignal {
4
+ static subject$ = new Subject();
5
+ static clean$ = CleanAllResourcesSignal.subject$;
6
+ static clean() {
7
+ Batcher.batch(() => {
8
+ CleanAllResourcesSignal.subject$.next();
9
+ });
10
+ }
11
+ }
@@ -1,8 +1,10 @@
1
1
  import { ReactiveCache } from "../../query/lib/ReactiveCache";
2
+ import { shallowEqual } from "../../common/utils";
2
3
  export declare class QueriesCache<KEY, VALUE> {
3
4
  private _cacheLifeTime;
4
5
  private readonly _cache;
5
- constructor(_cacheLifeTime?: number | false);
6
+ constructor(_cacheLifeTime?: number | false, compareArgsFn?: typeof shallowEqual);
6
7
  getQueryCache(args: KEY): ReactiveCache<VALUE> | undefined;
7
8
  createQueryCache(args: KEY, initialState: VALUE): ReactiveCache<VALUE>;
9
+ clear(): void;
8
10
  }
@@ -1,10 +1,12 @@
1
1
  import { IndirectMap } from "../../query/lib/IndirectMap";
2
2
  import { ReactiveCache } from "../../query/lib/ReactiveCache";
3
+ import { shallowEqual } from "../../common/utils";
3
4
  export class QueriesCache {
4
5
  _cacheLifeTime;
5
- _cache = new IndirectMap();
6
- constructor(_cacheLifeTime = 60_000) {
6
+ _cache;
7
+ constructor(_cacheLifeTime = 60_000, compareArgsFn = shallowEqual) {
7
8
  this._cacheLifeTime = _cacheLifeTime;
9
+ this._cache = new IndirectMap(compareArgsFn);
8
10
  }
9
11
  getQueryCache(args) {
10
12
  return this._cache.get(args);
@@ -14,25 +16,17 @@ export class QueriesCache {
14
16
  initialState,
15
17
  cacheLifeTime: this._cacheLifeTime,
16
18
  });
17
- // const stateDevtools = SharedOptions.DEVTOOLS?.state;
18
- //
19
- // if (stateDevtools) {
20
- // const key = `${this._logname}:${JSON.stringify(args)}:i=${Indexer.getIndex()}`;
21
- // let devtools = stateDevtools(key, initialState);
22
- //
23
- // cache.spy$.subscribe((state) => {
24
- // if (state === initialState) return;
25
- // devtools(state);
26
- // });
27
- //
28
- // cache.onClean$.subscribe(() => {
29
- // devtools('$CLEANED' as any);
30
- // });
31
- // }
32
19
  cache.onClean$.subscribe(() => {
33
20
  this._cache.delete(args);
34
21
  });
35
22
  this._cache.set(args, cache);
36
23
  return cache;
37
24
  }
25
+ clear() {
26
+ // Делаем именно так, тк при очистке могут синхронно добавляться новые кеши
27
+ const values = Array.from(this._cache.values);
28
+ values.forEach(c => {
29
+ c.complete();
30
+ });
31
+ }
38
32
  }
@@ -4,7 +4,7 @@ import { ResourceAgent } from "./ResourceAgent";
4
4
  export type CoreResourceQueryState<D extends ResourceDefinition> = {
5
5
  transactions: ResourceTransaction[] | null;
6
6
  abortController: AbortController | null;
7
- args: D['Args'] | null;
7
+ args: D['Args'];
8
8
  savedData: D['Data'] | null;
9
9
  data: D['Data'] | null;
10
10
  error: unknown | null;
@@ -47,4 +47,5 @@ export declare class Resource<D extends ResourceDefinition> implements ResourceI
47
47
  initiate(args: D['Args'], options?: {
48
48
  cache?: CoreResourceQueryCache<D>;
49
49
  }): CoreResourceQueryCache<D>;
50
+ compareArgs(args1: D['Args'], args2: D['Args']): boolean;
50
51
  }
@@ -1,14 +1,16 @@
1
1
  import { QueriesCache } from "../QueriesCache";
2
2
  import { QueriesLifetimeHooks } from "../QueriesLifetimeHooks";
3
+ import { CleanAllResourcesSignal } from "../CleanAllResourcesSignal";
3
4
  import { ResourceAgent } from "./ResourceAgent";
4
5
  import { ResourceRef } from "./ResourceRef";
6
+ import { SharedOptions } from "../../../common/options/SharedOptions";
5
7
  class ResourceQueryState {
6
- static create() {
8
+ static create(args) {
7
9
  return {
8
10
  transactions: null,
9
11
  savedData: null,
10
12
  abortController: null,
11
- args: null,
13
+ args,
12
14
  data: null,
13
15
  error: null,
14
16
  isError: false,
@@ -21,7 +23,8 @@ class ResourceQueryState {
21
23
  lockCount: 0
22
24
  };
23
25
  }
24
- static load(state = ResourceQueryState.create(), args) {
26
+ static load(state, args) {
27
+ state = state ?? ResourceQueryState.create(args);
25
28
  return {
26
29
  ...state,
27
30
  abortController: new AbortController(),
@@ -114,6 +117,9 @@ export class Resource {
114
117
  devtoolsName: _options.devtoolsName,
115
118
  });
116
119
  this._queriesCache = new QueriesCache(_options.cacheLifetime ?? this._DEFAULT_CACHE_LIFETIME);
120
+ CleanAllResourcesSignal.clean$.subscribe(() => {
121
+ this._queriesCache.clear();
122
+ });
117
123
  }
118
124
  createAgent = () => {
119
125
  return new ResourceAgent(this);
@@ -124,7 +130,7 @@ export class Resource {
124
130
  getQueryCache(args) {
125
131
  return this._queriesCache.getQueryCache(args);
126
132
  }
127
- createQueryCache(args, state = ResourceQueryState.create()) {
133
+ createQueryCache(args, state = ResourceQueryState.create(args)) {
128
134
  const cache = this._queriesCache.createQueryCache(args, state);
129
135
  const hookResolvers = this._hooks.onCacheEntryAdded(args);
130
136
  const spySub = cache.spy$.subscribe((state) => {
@@ -215,4 +221,8 @@ export class Resource {
215
221
  });
216
222
  return cache;
217
223
  }
224
+ compareArgs(args1, args2) {
225
+ const compareFn = this._options.compareArgsFn ?? SharedOptions.defaultCompareArgs;
226
+ return compareFn(args1, args2);
227
+ }
218
228
  }
@@ -4,6 +4,7 @@ import type { Resource } from "./Resource";
4
4
  export declare class ResourceAgent<D extends ResourceDefinition> implements ResourceAgentInstance<D> {
5
5
  private _resource;
6
6
  private _resources$;
7
+ private _effect;
7
8
  state$: Computed<{
8
9
  isInitiated: boolean;
9
10
  isLoading: boolean;
@@ -30,7 +31,8 @@ export declare class ResourceAgent<D extends ResourceDefinition> implements Reso
30
31
  args: NonNullable<D["Args"]> | undefined;
31
32
  }>;
32
33
  constructor(_resource: Resource<D>);
33
- private _next;
34
34
  initiate(args: D["Args"], force?: boolean): void;
35
+ compareArgs(args: D["Args"], otherArgs: D["Args"]): boolean;
35
36
  complete(): void;
37
+ private _next;
36
38
  }
@@ -1,10 +1,25 @@
1
- import { Computed, Signal } from "../../../signals";
1
+ import { Computed, Effect, Signal } from "../../../signals";
2
2
  export class ResourceAgent {
3
3
  _resource;
4
4
  _resources$ = new Signal({
5
5
  previous$: null,
6
6
  current$: null,
7
7
  }, { isDisabled: true });
8
+ _effect = new Effect(() => {
9
+ const current$ = this._resources$.value.current$;
10
+ const args = current$?.value.args;
11
+ // Если ресурс который мы слушаем очистился, то инициируем его заново с теми же аргументами
12
+ const sub = current$?.onClean$.subscribe(() => {
13
+ this._resources$.next({
14
+ previous$: null,
15
+ current$: null,
16
+ });
17
+ this.initiate(args);
18
+ });
19
+ return () => {
20
+ sub?.unsubscribe();
21
+ };
22
+ });
8
23
  state$ = new Computed(() => {
9
24
  const resources = this._resources$.value;
10
25
  let prevState;
@@ -47,6 +62,29 @@ export class ResourceAgent {
47
62
  constructor(_resource) {
48
63
  this._resource = _resource;
49
64
  }
65
+ initiate(args, force = false) {
66
+ const current = this._resources$.value.current$;
67
+ const cache = this._resource.getQueryCache(args);
68
+ if (!cache) {
69
+ const newCache = this._resource.initiate(args);
70
+ this._next(newCache);
71
+ return;
72
+ }
73
+ if (force || !(cache.value.isDone || cache.value.isLoading)) {
74
+ this._resource.initiate(args, { cache });
75
+ }
76
+ if (current !== cache) {
77
+ this._next(cache);
78
+ }
79
+ }
80
+ compareArgs(args, otherArgs) {
81
+ return this._resource.compareArgs(args, otherArgs);
82
+ }
83
+ complete() {
84
+ this._effect.complete();
85
+ this.state$.complete();
86
+ this._resources$.complete();
87
+ }
50
88
  _next(newCache) {
51
89
  const { previous$, current$ } = this._resources$.value;
52
90
  if (!current$) {
@@ -68,23 +106,4 @@ export class ResourceAgent {
68
106
  current$: newCache,
69
107
  });
70
108
  }
71
- initiate(args, force = false) {
72
- const current = this._resources$.value.current$;
73
- const cache = this._resource.getQueryCache(args);
74
- if (!cache) {
75
- const newCache = this._resource.initiate(args);
76
- this._next(newCache);
77
- return;
78
- }
79
- if (force || !(cache.value.isDone || cache.value.isLoading)) {
80
- this._resource.initiate(args, { cache });
81
- }
82
- if (current !== cache) {
83
- this._next(cache);
84
- }
85
- }
86
- complete() {
87
- this.state$.complete();
88
- this._resources$.complete();
89
- }
90
109
  }
@@ -1,5 +1,6 @@
1
1
  export * from './api/createResource';
2
2
  export * from './api/createOperation';
3
+ export * from './api/cleanAllResources';
3
4
  export * from './SKIP_TOKEN';
4
5
  export * from './react/useResourceAgent';
5
6
  export * from './react/useResourceRef';
@@ -1,5 +1,6 @@
1
1
  export * from './api/createResource';
2
2
  export * from './api/createOperation';
3
+ export * from './api/cleanAllResources';
3
4
  export * from './SKIP_TOKEN';
4
5
  export * from './react/useResourceAgent';
5
6
  export * from './react/useResourceRef';
@@ -14,5 +14,6 @@ export declare class IndirectMap<KEY, VALUE> {
14
14
  */
15
15
  delete(key: KEY): void;
16
16
  has(key: KEY): boolean;
17
+ get values(): IterableIterator<VALUE>;
17
18
  }
18
19
  export {};
@@ -1,4 +1,4 @@
1
- import { shallowEqual } from "./shallowEqual";
1
+ import { shallowEqual } from "../../common/utils";
2
2
  export class IndirectMap {
3
3
  _compareObjectsFn;
4
4
  _compareCache = new WeakMap();
@@ -82,4 +82,7 @@ export class IndirectMap {
82
82
  }
83
83
  return has;
84
84
  }
85
+ get values() {
86
+ return this._map.values();
87
+ }
85
88
  }
@@ -37,6 +37,7 @@ export declare class ReactiveCache<VALUE> {
37
37
  * Subject, уведомляющий об очистке кэша.
38
38
  */
39
39
  onClean$: Subject<VALUE>;
40
+ closed: boolean;
40
41
  /**
41
42
  * Создает новый экземпляр `ReactiveCacheItem`.
42
43
  *
@@ -24,6 +24,7 @@ export class ReactiveCache {
24
24
  * Subject, уведомляющий об очистке кэша.
25
25
  */
26
26
  onClean$ = new Subject();
27
+ closed = false;
27
28
  /**
28
29
  * Создает новый экземпляр `ReactiveCacheItem`.
29
30
  *
@@ -69,6 +70,9 @@ export class ReactiveCache {
69
70
  * Завершает работу кэша, закрывая все потоки и уведомляя об очистке.
70
71
  */
71
72
  complete() {
73
+ if (this.closed)
74
+ return;
75
+ this.closed = true;
72
76
  this._state$.complete();
73
77
  this.onClean$.next(this._state$.value);
74
78
  this.onClean$.complete();
@@ -1,7 +1,6 @@
1
1
  import React from "react";
2
2
  import { useConstant } from "../../common/react";
3
3
  import { useSignal } from "../../signals/react";
4
- import { shallowEqual } from "../../query/lib/shallowEqual";
5
4
  import { SKIP } from "../../query/SKIP_TOKEN";
6
5
  export function useResourceAgent(res, ...argss) {
7
6
  const args = (argss[0] === SKIP ? SKIP : argss[0]);
@@ -13,7 +12,7 @@ export function useResourceAgent(res, ...argss) {
13
12
  }
14
13
  return agent;
15
14
  });
16
- if (args !== SKIP && !shallowEqual(args, prevArgsRef.current)) {
15
+ if (args !== SKIP && !agent.compareArgs(args, prevArgsRef.current)) {
17
16
  prevArgsRef.current = args;
18
17
  agent.initiate(args);
19
18
  }
@@ -35,6 +35,10 @@ export type ResourceCreateOptions<D extends ResourceDefinition> = {
35
35
  * Настройка отображения в devtools
36
36
  */
37
37
  devtoolsName?: string | false;
38
+ /**
39
+ * Сравнение аргументов между собой
40
+ */
41
+ compareArgsFn?: (args1: D["Args"], args2: D["Args"]) => boolean;
38
42
  };
39
43
  /**
40
44
  * Определение типов ресурса
@@ -69,6 +73,8 @@ export type ResourceAgentInstance<D extends ResourceDefinition> = {
69
73
  initiate(args: D["Args"], force?: boolean): void;
70
74
  /** Завершает работу агента, позволяя освободить ресурсы */
71
75
  complete(): void;
76
+ /** Сравнивает аргументы между собой */
77
+ compareArgs(args1: D["Args"], args2: D["Args"]): unknown;
72
78
  };
73
79
  /**
74
80
  * Состояние запроса ресурса
@@ -2,10 +2,11 @@ import { SubscriptionLike } from "rxjs";
2
2
  export declare class Effect implements SubscriptionLike {
3
3
  private _onComplete?;
4
4
  private _subscriptions;
5
+ private _teardown?;
5
6
  protected readonly _scopeDestroyedSub: import("rxjs").Subscription | undefined;
6
7
  closed: boolean;
7
8
  _rang: number;
8
- constructor(effectFn: (ctx: (fn: () => void) => void) => void, _onComplete?: (() => void) | undefined);
9
+ constructor(effectFn: (ctx: (fn: () => void) => void) => void | (() => void), _onComplete?: (() => void) | undefined);
9
10
  /**
10
11
  * Выполняет функцию в tracked-контексте, подписываясь на Tracker.
11
12
  */
@@ -3,7 +3,8 @@ import { SharedOptions } from "../../common/options/SharedOptions";
3
3
  export class Effect {
4
4
  _onComplete;
5
5
  _subscriptions = [];
6
- _scopeDestroyedSub = SharedOptions.getScopeDestroyed$()?.subscribe(() => {
6
+ _teardown;
7
+ _scopeDestroyedSub = SharedOptions.getScopeDestroyed$?.()?.subscribe(() => {
7
8
  this.complete();
8
9
  });
9
10
  closed = false;
@@ -18,6 +19,9 @@ export class Effect {
18
19
  _runInTrackedContext(effectFn, isAsyncRun = false) {
19
20
  let prevSubscriptions;
20
21
  if (!isAsyncRun) {
22
+ // Вызываем teardown перед перезапуском эффекта
23
+ this._teardown?.();
24
+ this._teardown = undefined;
21
25
  this._rang = 0;
22
26
  prevSubscriptions = this._subscriptions;
23
27
  this._subscriptions = [];
@@ -51,9 +55,13 @@ export class Effect {
51
55
  this.complete();
52
56
  },
53
57
  });
54
- effectFn((fn) => {
58
+ const teardown = effectFn((fn) => {
55
59
  this._runInTrackedContext(fn, true);
56
60
  });
61
+ // Сохраняем teardown функцию, если она была возвращена
62
+ if (typeof teardown === 'function') {
63
+ this._teardown = teardown;
64
+ }
57
65
  trackerSub.unsubscribe();
58
66
  isTrackedContext = false;
59
67
  scheduler = Batcher.scheduler(this._rang);
@@ -63,6 +71,9 @@ export class Effect {
63
71
  if (this.closed)
64
72
  return;
65
73
  this.closed = true;
74
+ // Вызываем teardown перед завершением эффекта
75
+ this._teardown?.();
76
+ this._teardown = undefined;
66
77
  this._subscriptions.forEach((sub) => sub.unsubscribe());
67
78
  this._scopeDestroyedSub?.unsubscribe();
68
79
  this._onComplete?.();
@@ -4,7 +4,7 @@ import { SharedOptions } from "../../common/options/SharedOptions";
4
4
  export class Signal extends BehaviorSubject {
5
5
  _stateDevtools;
6
6
  _rang = 0;
7
- _scopeDestroyedSub = SharedOptions.getScopeDestroyed$()?.subscribe(() => {
7
+ _scopeDestroyedSub = SharedOptions.getScopeDestroyed$?.()?.subscribe(() => {
8
8
  this.complete();
9
9
  });
10
10
  constructor(initialValue, options) {
@@ -52,7 +52,7 @@ export class Signal extends BehaviorSubject {
52
52
  return this.next(value);
53
53
  }
54
54
  complete() {
55
- this._stateDevtools?.('$COMPLETE');
55
+ this._stateDevtools?.('$COMPLETED');
56
56
  this._scopeDestroyedSub?.unsubscribe();
57
57
  super.complete();
58
58
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@fozy-labs/rx-toolkit",
3
- "version": "0.4.14",
3
+ "version": "0.4.16",
4
4
  "main": "./dist/index.js",
5
5
  "types": "./dist/index.d.ts",
6
6
  "type": "module",