evg_observable 2.15.8 → 3.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -6,5 +6,5 @@ export declare class OrderedSubscribeObject<T> extends SubscribeObject<T> implem
6
6
  get order(): number;
7
7
  set order(value: number);
8
8
  subscribe(observer: IListener<T> | ISetObservableValue, errorHandler?: IErrorCallback): IOrderedSubscriptionLike;
9
- setOnce(): IOrderedSubscribe<T>;
9
+ once(): IOrderedSubscribe<T>;
10
10
  }
@@ -22,8 +22,8 @@ class OrderedSubscribeObject extends SubscribeObject_1.SubscribeObject {
22
22
  super.subscribe(observer, errorHandler);
23
23
  return this;
24
24
  }
25
- setOnce() {
26
- return super.setOnce();
25
+ once() {
26
+ return super.once();
27
27
  }
28
28
  }
29
29
  exports.OrderedSubscribeObject = OrderedSubscribeObject;
@@ -1,20 +1,22 @@
1
- import { ICallback, IChainCallback, IErrorCallback, IListener, IPipeCase, IPipePayload, ISetObservableValue, ISetup, ISubscribe, ISubscriptionLike } from "./Types";
1
+ import { ICallback, IChainCallback, IErrorCallback, IGroupSubscription, IListener, IPipeCase, IPipePayload, ISetObservableValue, ISetup, ISubscribe, ISubscriptionLike } from "./Types";
2
2
  import { SwitchCase } from "./AbstractSwitchCase";
3
3
  export declare abstract class Pipe<T> implements ISubscribe<T> {
4
4
  chain: IChainCallback[];
5
5
  flow: IPipePayload;
6
6
  abstract subscribe(listener: IListener<T> | ISetObservableValue, errorHandler?: IErrorCallback): ISubscriptionLike | undefined;
7
7
  private push;
8
- setOnce(): ISubscribe<T>;
8
+ once(): ISubscribe<T>;
9
9
  unsubscribeBy(condition: ICallback<T>): ISetup<T>;
10
- refine(condition: ICallback<T>): ISetup<T>;
11
- pushRefiners(conditions: ICallback<any>[]): ISetup<T>;
12
- switch(): PipeSwitchCase<T>;
13
- then<K>(condition: ICallback<T>): ISetup<K>;
14
- serialize(): ISetup<string>;
15
- deserialize<K>(): ISetup<K>;
10
+ and(condition: ICallback<T>): ISetup<T>;
11
+ allOf(conditions: ICallback<any>[]): ISetup<T>;
12
+ choice(): PipeSwitchCase<T>;
13
+ map<K>(condition: ICallback<T>): ISetup<K>;
14
+ toJson(): ISetup<string>;
15
+ fromJson<K>(): ISetup<K>;
16
+ group(): IGroupSubscription<T>;
16
17
  processChain(listener: IListener<T>): void;
17
18
  }
18
19
  export declare class PipeSwitchCase<T> extends SwitchCase<T, Pipe<T>, IPipeCase<T>> implements ISubscribe<T> {
19
20
  subscribe(listener: IListener<T> | ISetObservableValue, errorHandler?: IErrorCallback): ISubscriptionLike | undefined;
21
+ group(): IGroupSubscription<T>;
20
22
  }
@@ -9,7 +9,7 @@ class Pipe {
9
9
  this.chain.push(callback);
10
10
  return this;
11
11
  }
12
- setOnce() {
12
+ once() {
13
13
  return this.push((data) => {
14
14
  this.listener(data.payload);
15
15
  data.isUnsubscribe = true;
@@ -22,37 +22,40 @@ class Pipe {
22
22
  data.isUnsubscribe = true;
23
23
  });
24
24
  }
25
- refine(condition) {
25
+ and(condition) {
26
26
  return this.push((data) => condition(data.payload) && (data.isAvailable = true));
27
27
  }
28
- pushRefiners(conditions) {
28
+ allOf(conditions) {
29
29
  if (!Array.isArray(conditions))
30
30
  return this;
31
31
  for (let i = 0; i < conditions.length; i++)
32
- this.refine(conditions[i]);
32
+ this.and(conditions[i]);
33
33
  return this;
34
34
  }
35
- switch() {
35
+ choice() {
36
36
  return new PipeSwitchCase(this);
37
37
  }
38
- then(condition) {
38
+ map(condition) {
39
39
  return this.push((data) => {
40
40
  data.payload = condition(data.payload);
41
41
  data.isAvailable = true;
42
42
  });
43
43
  }
44
- serialize() {
44
+ toJson() {
45
45
  return this.push((data) => {
46
46
  data.payload = JSON.stringify(data.payload);
47
47
  data.isAvailable = true;
48
48
  });
49
49
  }
50
- deserialize() {
50
+ fromJson() {
51
51
  return this.push((data) => {
52
52
  data.payload = JSON.parse(data.payload);
53
53
  data.isAvailable = true;
54
54
  });
55
55
  }
56
+ group() {
57
+ return this;
58
+ }
56
59
  processChain(listener) {
57
60
  const chain = this.chain;
58
61
  const data = this.flow;
@@ -76,5 +79,8 @@ class PipeSwitchCase extends AbstractSwitchCase_1.SwitchCase {
76
79
  subscribe(listener, errorHandler) {
77
80
  return this.pipe.subscribe(listener, errorHandler);
78
81
  }
82
+ group() {
83
+ return this.pipe;
84
+ }
79
85
  }
80
86
  exports.PipeSwitchCase = PipeSwitchCase;
@@ -1,4 +1,4 @@
1
- import { IErrorCallback, IListener, IObserver, ISubscribeGroup, ISubscribeObject, ISubscriptionLike } from "./Types";
1
+ import { IErrorCallback, IGroupSubscription, IListener, IObserver, ISubscribeGroup, ISubscribeObject, ISubscriptionLike } from "./Types";
2
2
  import { Pipe } from "./Pipe";
3
3
  export declare class SubscribeObject<T> extends Pipe<T> implements ISubscribeObject<T> {
4
4
  observer: IObserver<T> | undefined;
@@ -7,8 +7,11 @@ export declare class SubscribeObject<T> extends Pipe<T> implements ISubscribeObj
7
7
  _order: number;
8
8
  paused: boolean;
9
9
  piped: boolean;
10
+ listeners?: IListener<T>[];
11
+ errorHandlers?: IErrorCallback[];
10
12
  constructor(observable?: IObserver<T>, isPipe?: boolean);
11
13
  subscribe(observer: ISubscribeGroup<T>, errorHandler?: IErrorCallback): ISubscriptionLike;
14
+ add(listener: IListener<T> | IListener<T>[], errorHandler?: IErrorCallback | IErrorCallback[]): IGroupSubscription<T>;
12
15
  unsubscribe(): void;
13
16
  send(value: T): void;
14
17
  resume(): void;
@@ -12,6 +12,8 @@ class SubscribeObject extends Pipe_1.Pipe {
12
12
  _order = 0;
13
13
  paused = false;
14
14
  piped = false;
15
+ listeners;
16
+ errorHandlers;
15
17
  constructor(observable, isPipe) {
16
18
  super();
17
19
  this.observer = observable;
@@ -22,6 +24,29 @@ class SubscribeObject extends Pipe_1.Pipe {
22
24
  errorHandler && (this.errorHandler = errorHandler);
23
25
  return this;
24
26
  }
27
+ add(listener, errorHandler) {
28
+ if (!this.listeners) {
29
+ this.listeners = [];
30
+ this.errorHandlers = [];
31
+ }
32
+ if (Array.isArray(listener)) {
33
+ for (let i = 0; i < listener.length; i++) {
34
+ this.listeners.push(listener[i]);
35
+ const handler = (errorHandler && Array.isArray(errorHandler))
36
+ ? (errorHandler[i] ?? this.errorHandler)
37
+ : (errorHandler || this.errorHandler);
38
+ this.errorHandlers.push(handler);
39
+ }
40
+ }
41
+ else {
42
+ this.listeners.push(listener);
43
+ const handler = (errorHandler && !Array.isArray(errorHandler))
44
+ ? errorHandler
45
+ : this.errorHandler;
46
+ this.errorHandlers.push(handler);
47
+ }
48
+ return this;
49
+ }
25
50
  unsubscribe() {
26
51
  if (!this.observer)
27
52
  return;
@@ -32,25 +57,70 @@ class SubscribeObject extends Pipe_1.Pipe {
32
57
  }
33
58
  send(value) {
34
59
  const listener = this.listener;
35
- if (!listener) {
60
+ const hasGroupListeners = this.listeners && this.listeners.length > 0;
61
+ if (!listener && !hasGroupListeners) {
36
62
  this.unsubscribe();
37
63
  return;
38
64
  }
39
65
  if (!this.observer || this.paused)
40
66
  return;
41
67
  if (!this.piped) {
42
- try {
43
- listener(value);
68
+ if (listener) {
69
+ try {
70
+ listener(value);
71
+ }
72
+ catch (err) {
73
+ this.errorHandler(value, err);
74
+ }
44
75
  }
45
- catch (err) {
46
- this.errorHandler(value, err);
76
+ if (hasGroupListeners) {
77
+ for (let i = 0; i < this.listeners.length; i++) {
78
+ try {
79
+ this.listeners[i](value);
80
+ }
81
+ catch (err) {
82
+ this.errorHandlers[i](value, err);
83
+ }
84
+ }
47
85
  }
48
86
  return;
49
87
  }
50
88
  try {
51
89
  this.flow.payload = value;
52
90
  this.flow.isBreak = false;
53
- this.processChain(listener);
91
+ if (listener) {
92
+ this.processChain(listener);
93
+ }
94
+ else {
95
+ const chain = this.chain;
96
+ const data = this.flow;
97
+ const len = chain.length;
98
+ data.isAvailable = len === 0;
99
+ for (let i = 0; i < len; i++) {
100
+ data.isUnsubscribe = false;
101
+ data.isAvailable = false;
102
+ chain[i](data);
103
+ if (data.isUnsubscribe) {
104
+ this.unsubscribe();
105
+ return;
106
+ }
107
+ if (!data.isAvailable)
108
+ return;
109
+ if (data.isBreak)
110
+ break;
111
+ }
112
+ }
113
+ if (hasGroupListeners) {
114
+ const processedValue = this.flow.payload;
115
+ for (let i = 0; i < this.listeners.length; i++) {
116
+ try {
117
+ this.listeners[i](processedValue);
118
+ }
119
+ catch (err) {
120
+ this.errorHandlers[i](processedValue, err);
121
+ }
122
+ }
123
+ }
54
124
  }
55
125
  catch (err) {
56
126
  this.errorHandler(value, err);
@@ -14,16 +14,22 @@ export type IOrder = {
14
14
  order: number;
15
15
  };
16
16
  export type ISwitch<T> = {
17
- switch(): PipeSwitchCase<T>;
17
+ choice(): PipeSwitchCase<T>;
18
18
  };
19
19
  export type IOrderedSwitch<T> = {
20
- switch(): PipeSwitchCase<T>;
20
+ choice(): PipeSwitchCase<T>;
21
+ };
22
+ export type IGroup<T> = {
23
+ group(): IGroupSubscription<T>;
24
+ };
25
+ export type IOrderedGroup<T> = {
26
+ group(): IGroupSubscription<T>;
21
27
  };
22
28
  export type IOnce<T> = {
23
- setOnce(): ISubscribe<T>;
29
+ once(): ISubscribe<T>;
24
30
  };
25
31
  export type IOrderedOnce<T> = {
26
- setOnce(): IOrderedSubscribe<T>;
32
+ once(): IOrderedSubscribe<T>;
27
33
  };
28
34
  export type ISetObservableValue = {
29
35
  next(value: any): void;
@@ -31,8 +37,11 @@ export type ISetObservableValue = {
31
37
  export type ISubscriptionLike = {
32
38
  unsubscribe(): void;
33
39
  };
34
- export type ISetup<T> = IUnsubscribeByPositive<T> & IEmitByPositive<T> & IOnce<T> & ISwitch<T> & ITransform<T> & ISerialisation & ISubscribe<T>;
35
- export type IOrderedSetup<T> = IOrderedUnsubscribeByPositive<T> & IOrderedEmitByPositive<T> & IOrderedOnce<T> & IOrderedSwitch<T> & IOrderedTransform<T> & IOrderedSerialisation & IOrderedSubscribe<T>;
40
+ export type IGroupSubscription<T> = ISubscriptionLike & {
41
+ add(listener: IListener<T> | IListener<T>[], errorHandler?: IErrorCallback | IErrorCallback[]): IGroupSubscription<T>;
42
+ };
43
+ export type ISetup<T> = IUnsubscribeByPositive<T> & IEmitByPositive<T> & IOnce<T> & ISwitch<T> & ITransform<T> & ISerialisation & IGroup<T> & ISubscribe<T>;
44
+ export type IOrderedSetup<T> = IOrderedUnsubscribeByPositive<T> & IOrderedEmitByPositive<T> & IOrderedOnce<T> & IOrderedSwitch<T> & IOrderedTransform<T> & IOrderedSerialisation & IOrderedGroup<T> & IOrderedSubscribe<T>;
36
45
  export type ISubscribeObject<T> = ISubscriptionLike & IPause & IOrder & ISend<T> & ISetup<T>;
37
46
  export type ISubscribeCounter = {
38
47
  size(): number;
@@ -48,7 +57,10 @@ export type IObserver<T> = ISetObservableValue & ISubscriber<T> & IDestroy & ISu
48
57
  enable(): void;
49
58
  };
50
59
  export type IStream<T> = {
51
- stream(value: T[]): void;
60
+ of(value: T[]): void;
61
+ };
62
+ export type IObjectStream<K extends string | number | symbol, V> = {
63
+ in(value: Record<K, V>): void;
52
64
  };
53
65
  export type IPause = {
54
66
  pause(): void;
@@ -82,26 +94,26 @@ export type IOrderedEmitByNegative<T> = {
82
94
  emitByNegative(condition: ICallback<T>): IOrderedSetup<T>;
83
95
  };
84
96
  export type IEmitByPositive<T> = {
85
- refine(condition: ICallback<T>): ISetup<T>;
86
- pushRefiners(conditions: ICallback<T>[]): ISetup<T>;
97
+ and(condition: ICallback<T>): ISetup<T>;
98
+ allOf(conditions: ICallback<T>[]): ISetup<T>;
87
99
  };
88
100
  export type ITransform<T> = {
89
- then<K>(condition: ICallback<T>): ISetup<K>;
101
+ map<K>(condition: ICallback<T>): ISetup<K>;
90
102
  };
91
103
  export type ISerialisation = {
92
- serialize(): ISetup<string>;
93
- deserialize<K>(): ISetup<K>;
104
+ toJson(): ISetup<string>;
105
+ fromJson<K>(): ISetup<K>;
94
106
  };
95
107
  export type IOrderedEmitByPositive<T> = {
96
- refine(condition: ICallback<any>): ISetup<T>;
97
- pushRefiners(conditions: ICallback<any>[]): ISetup<T>;
108
+ and(condition: ICallback<any>): ISetup<T>;
109
+ allOf(conditions: ICallback<any>[]): ISetup<T>;
98
110
  };
99
111
  export type IOrderedTransform<T> = {
100
- then<K>(condition: ICallback<T>): ISetup<K>;
112
+ map<K>(condition: ICallback<T>): ISetup<K>;
101
113
  };
102
114
  export type IOrderedSerialisation = {
103
- serialize(): ISetup<string>;
104
- deserialize<K>(): ISetup<K>;
115
+ toJson(): ISetup<string>;
116
+ fromJson<K>(): ISetup<K>;
105
117
  };
106
118
  export type IEmitMatchCondition<T> = {
107
119
  emitMatch(condition: ICallback<any>): ISetup<T>;
@@ -133,8 +145,9 @@ export type IPipePayload = {
133
145
  };
134
146
  export type IChainCallback = (data: IPipePayload) => void;
135
147
  export type IPipeCase<T> = ISubscribe<T> & {
136
- case(condition: ICallback<any>): IPipeCase<T> & ISubscribe<T>;
137
- pushCases(conditions: ICallback<any>[]): IPipeCase<T> & ISubscribe<T>;
148
+ or(condition: ICallback<any>): IPipeCase<T> & ISubscribe<T>;
149
+ anyOf(conditions: ICallback<any>[]): IPipeCase<T> & ISubscribe<T>;
150
+ group(): IGroupSubscription<T>;
138
151
  };
139
152
  export type ICombinedSubscriber<T> = IListener<T> | ISetObservableValue;
140
153
  export type ISubscribeGroup<T> = ICombinedSubscriber<T> | ICombinedSubscriber<T>[];
@@ -143,15 +156,15 @@ export type IAddFilter<T> = {
143
156
  };
144
157
  export type IFilterSetup<T> = IFilter<T> & IFilterSwitch<T>;
145
158
  export type IFilter<T> = {
146
- filter(condition: ICallback<any>): IFilterSetup<T>;
147
- pushFilters(conditions: ICallback<any>[]): IFilterSetup<T>;
159
+ and(condition: ICallback<any>): IFilterSetup<T>;
160
+ allOf(conditions: ICallback<any>[]): IFilterSetup<T>;
148
161
  };
149
162
  export type IFilterSwitch<T> = {
150
- switch(): FilterSwitchCase<T>;
163
+ choice(): FilterSwitchCase<T>;
151
164
  };
152
165
  export type IFilterCase<T> = {
153
- case(condition: ICallback<any>): IFilterCase<T>;
154
- pushCases(conditions: ICallback<any>[]): IFilterCase<T>;
166
+ or(condition: ICallback<any>): IFilterCase<T>;
167
+ anyOf(conditions: ICallback<any>[]): IFilterCase<T>;
155
168
  };
156
169
  export type IFilterPayload = {
157
170
  isBreak: boolean;
@@ -1,70 +0,0 @@
1
- # Breaking Changes - Performance Optimizations Branch
2
-
3
- ## Version 2.15.0
4
-
5
- ### Internal Field Renaming
6
-
7
- **Affected field:** `value` renamed to `_value`
8
-
9
- The internal field storing the current observable value has been renamed from `value` to `_value` to follow TypeScript conventions for protected/private members.
10
-
11
- **Before:**
12
- ```typescript
13
- export class Observable<T> {
14
- constructor(private value: T) {}
15
- }
16
- ```
17
-
18
- **After:**
19
- ```typescript
20
- export class Observable<T> {
21
- protected _value: T;
22
- constructor(value: T) {
23
- this._value = value;
24
- }
25
- }
26
- ```
27
-
28
- **Migration:**
29
- - If you were extending `Observable` and accessing `this.value`, change to `this._value`
30
- - Use the public `getValue()` method for reading the current value (recommended)
31
-
32
- ### Visibility Changes
33
-
34
- The following fields changed from `private` to `protected` to enable better inheritance:
35
-
36
- | Field | Before | After |
37
- |-------|--------|-------|
38
- | `enabled` | private | protected |
39
- | `filters` | private | protected |
40
- | `_value` (formerly `value`) | private | protected |
41
-
42
- **Impact:** This is not a breaking change for most users, but allows subclasses to access these fields.
43
-
44
- ### Recommended Migration Path
45
-
46
- Instead of accessing internal fields directly, use the public API:
47
-
48
- ```typescript
49
- // Instead of:
50
- // @ts-ignore
51
- const val = observable._value;
52
-
53
- // Use:
54
- const val = observable.getValue();
55
-
56
- // Instead of:
57
- // @ts-ignore
58
- const count = observable.subs.length;
59
-
60
- // Use:
61
- const count = observable.size();
62
- ```
63
-
64
- ### New Behavior
65
-
66
- 1. **`destroy()` now uses `Promise.resolve()`** instead of `setInterval()` for async cleanup when called during emission
67
- 2. **`unsubscribeAll()` is now safe to call during `next()`** - uses deferred cleanup mechanism
68
- 3. **Early exit optimization** - `next()` returns immediately if there are no subscribers
69
-
70
- These behavioral changes improve performance and memory management but should not require code changes.