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.
- package/MIGRATION.md +410 -0
- package/README.md +204 -67
- package/package.json +1 -1
- package/repo/evg_observable.js +1 -1
- package/src/outLib/AbstractSwitchCase.d.ts +2 -2
- package/src/outLib/AbstractSwitchCase.js +3 -3
- package/src/outLib/FilterCollection.d.ts +3 -3
- package/src/outLib/FilterCollection.js +4 -4
- package/src/outLib/Observable.d.ts +2 -1
- package/src/outLib/Observable.js +12 -1
- package/src/outLib/OrderedObservable.d.ts +2 -2
- package/src/outLib/OrderedObservable.js +2 -2
- package/src/outLib/OrderedSubscribeObject.d.ts +1 -1
- package/src/outLib/OrderedSubscribeObject.js +2 -2
- package/src/outLib/Pipe.d.ts +10 -8
- package/src/outLib/Pipe.js +14 -8
- package/src/outLib/SubscribeObject.d.ts +4 -1
- package/src/outLib/SubscribeObject.js +76 -6
- package/src/outLib/Types.d.ts +37 -24
- package/BREAKING_CHANGES.md +0 -70
package/MIGRATION.md
ADDED
|
@@ -0,0 +1,410 @@
|
|
|
1
|
+
# Migration Guide: v2.x → v3.0.0
|
|
2
|
+
|
|
3
|
+
This is a **breaking change** release. All operator names have been updated for better clarity and RxJS alignment.
|
|
4
|
+
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
## Quick Start
|
|
8
|
+
|
|
9
|
+
### Automated Migration (Recommended)
|
|
10
|
+
|
|
11
|
+
Use this command to automatically update your codebase:
|
|
12
|
+
|
|
13
|
+
```bash
|
|
14
|
+
find src -name "*.ts" -exec sed -i \
|
|
15
|
+
-e 's/\.stream(/\.of(/g' \
|
|
16
|
+
-e 's/\.refine(/\.and(/g' \
|
|
17
|
+
-e 's/\.then(/\.map(/g' \
|
|
18
|
+
-e 's/\.setOnce(/\.once(/g' \
|
|
19
|
+
-e 's/\.serialize(/\.toJson(/g' \
|
|
20
|
+
-e 's/\.deserialize(/\.fromJson(/g' \
|
|
21
|
+
-e 's/\.switch(/\.choice(/g' \
|
|
22
|
+
-e 's/\.case(/\.or(/g' \
|
|
23
|
+
-e 's/\.pushRefiners(/\.allOf(/g' \
|
|
24
|
+
-e 's/\.pushFilters(/\.allOf(/g' \
|
|
25
|
+
-e 's/\.pushCases(/\.anyOf(/g' \
|
|
26
|
+
-e 's/\.setAscendingSort(/\.ascendingSort(/g' \
|
|
27
|
+
-e 's/\.setDescendingSort(/\.descendingSort(/g' \
|
|
28
|
+
{} \;
|
|
29
|
+
```
|
|
30
|
+
|
|
31
|
+
**Note:** Test your code after migration to ensure correct behavior.
|
|
32
|
+
|
|
33
|
+
---
|
|
34
|
+
|
|
35
|
+
## Manual Migration Table
|
|
36
|
+
|
|
37
|
+
### Pipe Operators (Outbound Transformations)
|
|
38
|
+
|
|
39
|
+
| v2.x Method | v3.0.0 Method | Description |
|
|
40
|
+
|-------------|---------------|-------------|
|
|
41
|
+
| `.stream(values)` | `.of(values)` | Emit array elements one by one |
|
|
42
|
+
| `.refine(condition)` | `.and(condition)` | Filter values (AND logic) |
|
|
43
|
+
| `.then<K>(fn)` | `.map<K>(fn)` | Transform value type |
|
|
44
|
+
| `.setOnce()` | `.once()` | Receive one value then unsubscribe |
|
|
45
|
+
| `.serialize()` | `.toJson()` | Convert to JSON string |
|
|
46
|
+
| `.deserialize<K>()` | `.fromJson<K>()` | Parse from JSON string |
|
|
47
|
+
| `.switch()` | `.choice()` | Begin OR-logic branching |
|
|
48
|
+
| `.case(condition)` | `.or(condition)` | Add OR condition |
|
|
49
|
+
| `.pushRefiners(arr)` | `.allOf(arr)` | Add multiple AND filters |
|
|
50
|
+
| `.pushCases(arr)` | `.anyOf(arr)` | Add multiple OR conditions |
|
|
51
|
+
|
|
52
|
+
### FilterCollection Operators (Inbound Filters)
|
|
53
|
+
|
|
54
|
+
| v2.x Method | v3.0.0 Method | Description |
|
|
55
|
+
|-------------|---------------|-------------|
|
|
56
|
+
| `.filter(condition)` | `.and(condition)` | Add inbound filter (AND logic) |
|
|
57
|
+
| `.pushFilters(arr)` | `.allOf(arr)` | Add multiple inbound filters |
|
|
58
|
+
| `.switch()` | `.choice()` | Begin OR-logic branching |
|
|
59
|
+
| `.case(condition)` | `.or(condition)` | Add OR condition |
|
|
60
|
+
| `.pushCases(arr)` | `.anyOf(arr)` | Add multiple OR conditions |
|
|
61
|
+
|
|
62
|
+
### OrderedObservable Operators
|
|
63
|
+
|
|
64
|
+
| v2.x Method | v3.0.0 Method | Description |
|
|
65
|
+
|-------------|---------------|-------------|
|
|
66
|
+
| `.setAscendingSort()` | `.ascendingSort()` | Sort subscribers ascending by order |
|
|
67
|
+
| `.setDescendingSort()` | `.descendingSort()` | Sort subscribers descending by order |
|
|
68
|
+
|
|
69
|
+
---
|
|
70
|
+
|
|
71
|
+
## Migration Examples
|
|
72
|
+
|
|
73
|
+
### Example 1: Basic Pipe Chain
|
|
74
|
+
|
|
75
|
+
**Before (v2.x):**
|
|
76
|
+
```typescript
|
|
77
|
+
observable$
|
|
78
|
+
.pipe()
|
|
79
|
+
.refine(x => x > 0)
|
|
80
|
+
.then(x => x * 2)
|
|
81
|
+
.setOnce()
|
|
82
|
+
.subscribe(result => console.log(result));
|
|
83
|
+
```
|
|
84
|
+
|
|
85
|
+
**After (v3.0.0):**
|
|
86
|
+
```typescript
|
|
87
|
+
observable$
|
|
88
|
+
.pipe()
|
|
89
|
+
.and(x => x > 0) // refine → and
|
|
90
|
+
.map(x => x * 2) // then → map
|
|
91
|
+
.once() // setOnce → once
|
|
92
|
+
.subscribe(result => console.log(result));
|
|
93
|
+
```
|
|
94
|
+
|
|
95
|
+
---
|
|
96
|
+
|
|
97
|
+
### Example 2: Batch Emission
|
|
98
|
+
|
|
99
|
+
**Before (v2.x):**
|
|
100
|
+
```typescript
|
|
101
|
+
observable$.stream([1, 2, 3, 4, 5]);
|
|
102
|
+
```
|
|
103
|
+
|
|
104
|
+
**After (v3.0.0):**
|
|
105
|
+
```typescript
|
|
106
|
+
observable$.of([1, 2, 3, 4, 5]); // stream → of
|
|
107
|
+
```
|
|
108
|
+
|
|
109
|
+
---
|
|
110
|
+
|
|
111
|
+
### Example 3: JSON Serialization
|
|
112
|
+
|
|
113
|
+
**Before (v2.x):**
|
|
114
|
+
```typescript
|
|
115
|
+
const jsonPipe = observable$
|
|
116
|
+
.pipe()
|
|
117
|
+
.serialize()
|
|
118
|
+
.subscribe(jsonString => { /* ... */ });
|
|
119
|
+
|
|
120
|
+
const objPipe = jsonObservable$
|
|
121
|
+
.pipe()
|
|
122
|
+
.deserialize<MyType>()
|
|
123
|
+
.subscribe(obj => { /* ... */ });
|
|
124
|
+
```
|
|
125
|
+
|
|
126
|
+
**After (v3.0.0):**
|
|
127
|
+
```typescript
|
|
128
|
+
const jsonPipe = observable$
|
|
129
|
+
.pipe()
|
|
130
|
+
.toJson() // serialize → toJson
|
|
131
|
+
.subscribe(jsonString => { /* ... */ });
|
|
132
|
+
|
|
133
|
+
const objPipe = jsonObservable$
|
|
134
|
+
.pipe()
|
|
135
|
+
.fromJson<MyType>() // deserialize → fromJson
|
|
136
|
+
.subscribe(obj => { /* ... */ });
|
|
137
|
+
```
|
|
138
|
+
|
|
139
|
+
---
|
|
140
|
+
|
|
141
|
+
### Example 4: OR Logic (Switch/Case)
|
|
142
|
+
|
|
143
|
+
**Before (v2.x):**
|
|
144
|
+
```typescript
|
|
145
|
+
observable$
|
|
146
|
+
.pipe()
|
|
147
|
+
.switch()
|
|
148
|
+
.case(x => x === 'red')
|
|
149
|
+
.case(x => x === 'blue')
|
|
150
|
+
.subscribe(color => { /* ... */ });
|
|
151
|
+
```
|
|
152
|
+
|
|
153
|
+
**After (v3.0.0):**
|
|
154
|
+
```typescript
|
|
155
|
+
observable$
|
|
156
|
+
.pipe()
|
|
157
|
+
.choice() // switch → choice
|
|
158
|
+
.or(x => x === 'red') // case → or
|
|
159
|
+
.or(x => x === 'blue')
|
|
160
|
+
.subscribe(color => { /* ... */ });
|
|
161
|
+
```
|
|
162
|
+
|
|
163
|
+
---
|
|
164
|
+
|
|
165
|
+
### Example 5: Batch Filters
|
|
166
|
+
|
|
167
|
+
**Before (v2.x):**
|
|
168
|
+
```typescript
|
|
169
|
+
const filters = [
|
|
170
|
+
(x: Person) => x.age > 18,
|
|
171
|
+
(x: Person) => x.name.length > 0,
|
|
172
|
+
(x: Person) => x.email.includes('@')
|
|
173
|
+
];
|
|
174
|
+
|
|
175
|
+
observable$
|
|
176
|
+
.pipe()
|
|
177
|
+
.pushRefiners(filters)
|
|
178
|
+
.subscribe(person => { /* ... */ });
|
|
179
|
+
```
|
|
180
|
+
|
|
181
|
+
**After (v3.0.0):**
|
|
182
|
+
```typescript
|
|
183
|
+
const filters = [
|
|
184
|
+
(x: Person) => x.age > 18,
|
|
185
|
+
(x: Person) => x.name.length > 0,
|
|
186
|
+
(x: Person) => x.email.includes('@')
|
|
187
|
+
];
|
|
188
|
+
|
|
189
|
+
observable$
|
|
190
|
+
.pipe()
|
|
191
|
+
.allOf(filters) // pushRefiners → allOf
|
|
192
|
+
.subscribe(person => { /* ... */ });
|
|
193
|
+
```
|
|
194
|
+
|
|
195
|
+
---
|
|
196
|
+
|
|
197
|
+
### Example 6: Inbound Filters
|
|
198
|
+
|
|
199
|
+
**Before (v2.x):**
|
|
200
|
+
```typescript
|
|
201
|
+
men$.addFilter()
|
|
202
|
+
.filter(person => person.age > 17)
|
|
203
|
+
.filter(person => person.age < 60);
|
|
204
|
+
```
|
|
205
|
+
|
|
206
|
+
**After (v3.0.0):**
|
|
207
|
+
```typescript
|
|
208
|
+
men$.addFilter()
|
|
209
|
+
.and(person => person.age > 17) // filter → and
|
|
210
|
+
.and(person => person.age < 60);
|
|
211
|
+
```
|
|
212
|
+
|
|
213
|
+
---
|
|
214
|
+
|
|
215
|
+
## New Features in v3.0.0
|
|
216
|
+
|
|
217
|
+
### 1. `in<K,V>()` Operator - Object Iteration
|
|
218
|
+
|
|
219
|
+
Iterate over object properties and emit `[key, value]` tuples:
|
|
220
|
+
|
|
221
|
+
```typescript
|
|
222
|
+
const stats = {
|
|
223
|
+
users: 1500,
|
|
224
|
+
sessions: 4200,
|
|
225
|
+
errors: 12
|
|
226
|
+
};
|
|
227
|
+
|
|
228
|
+
observable$.in(stats);
|
|
229
|
+
// Emits: ['users', 1500], ['sessions', 4200], ['errors', 12]
|
|
230
|
+
|
|
231
|
+
// Usage with pipe:
|
|
232
|
+
observable$
|
|
233
|
+
.pipe()
|
|
234
|
+
.subscribe(([metric, count]) => {
|
|
235
|
+
console.log(`${metric}: ${count}`);
|
|
236
|
+
});
|
|
237
|
+
|
|
238
|
+
observable$.in(stats);
|
|
239
|
+
```
|
|
240
|
+
|
|
241
|
+
**Use cases:**
|
|
242
|
+
- Iterating over configuration objects
|
|
243
|
+
- Processing key-value data structures
|
|
244
|
+
- Converting objects to streams
|
|
245
|
+
|
|
246
|
+
---
|
|
247
|
+
|
|
248
|
+
### 2. `group()` Operator - Multi-Listener Optimization
|
|
249
|
+
|
|
250
|
+
Optimize performance when multiple listeners need the same pipe transformations:
|
|
251
|
+
|
|
252
|
+
```typescript
|
|
253
|
+
const group = observable$
|
|
254
|
+
.pipe()
|
|
255
|
+
.and(x => x > 0)
|
|
256
|
+
.map(x => x * 2)
|
|
257
|
+
.group(); // Type finalizer - prevents further chaining
|
|
258
|
+
|
|
259
|
+
// All listeners share single pipe execution
|
|
260
|
+
group.add(listener1);
|
|
261
|
+
group.add(listener2);
|
|
262
|
+
group.add(listener3);
|
|
263
|
+
|
|
264
|
+
// Performance: 1x pipe execution instead of 3x
|
|
265
|
+
```
|
|
266
|
+
|
|
267
|
+
**Key benefits:**
|
|
268
|
+
- **Performance:** Single pipe execution for all listeners (up to 54,000x faster in benchmarks)
|
|
269
|
+
- **Type safety:** TypeScript prevents adding operators after `.group()`
|
|
270
|
+
- **Convenience:** Fluent API for adding multiple listeners
|
|
271
|
+
|
|
272
|
+
**Use cases:**
|
|
273
|
+
- Multiple UI components listening to same data stream
|
|
274
|
+
- Event broadcasting to multiple handlers
|
|
275
|
+
- Optimizing high-frequency emissions with many subscribers
|
|
276
|
+
|
|
277
|
+
---
|
|
278
|
+
|
|
279
|
+
## Breaking Changes
|
|
280
|
+
|
|
281
|
+
### API Changes
|
|
282
|
+
|
|
283
|
+
1. **All 14 operator names changed** - See migration table above
|
|
284
|
+
2. **Semantic consistency:** `and()` for AND logic, `or()` for OR logic, `allOf()`/`anyOf()` for batch operations
|
|
285
|
+
3. **RxJS alignment:** `map()`, `of()` match RxJS naming for easier migration
|
|
286
|
+
|
|
287
|
+
### Type Signatures
|
|
288
|
+
|
|
289
|
+
**No changes** - All type signatures remain the same. Only method names changed.
|
|
290
|
+
|
|
291
|
+
### Bundle Size
|
|
292
|
+
|
|
293
|
+
**Increased:** 6.4 kB → 7.2 kB (+12.5%)
|
|
294
|
+
- **Reason:** New operators (`in()`, `group()`) add functionality
|
|
295
|
+
- **Trade-off:** Still **12.2x smaller** than RxJS (88 kB)
|
|
296
|
+
|
|
297
|
+
### Performance
|
|
298
|
+
|
|
299
|
+
**Improved or maintained:**
|
|
300
|
+
- Emit performance: +7% faster than v2.x
|
|
301
|
+
- Multiple subscribers (10): +10% faster than v2.x
|
|
302
|
+
- Still **2-7x faster** than RxJS across all operations
|
|
303
|
+
|
|
304
|
+
---
|
|
305
|
+
|
|
306
|
+
## Compatibility
|
|
307
|
+
|
|
308
|
+
### Requirements
|
|
309
|
+
|
|
310
|
+
- **Node.js:** 16.x or higher (unchanged from v2.x)
|
|
311
|
+
- **TypeScript:** 4.4+ (required for `Object.hasOwn` support)
|
|
312
|
+
- **ES Target:** ES2022 or higher (updated from ES2020)
|
|
313
|
+
|
|
314
|
+
### Supported Environments
|
|
315
|
+
|
|
316
|
+
- ✅ Node.js 16+
|
|
317
|
+
- ✅ Modern browsers (Chrome 94+, Firefox 92+, Safari 15.4+)
|
|
318
|
+
- ✅ TypeScript 4.4+
|
|
319
|
+
- ⚠️ Legacy browsers: May need polyfill for `Object.hasOwn`
|
|
320
|
+
|
|
321
|
+
---
|
|
322
|
+
|
|
323
|
+
## Common Migration Issues
|
|
324
|
+
|
|
325
|
+
### Issue 1: TypeScript Compilation Errors
|
|
326
|
+
|
|
327
|
+
**Symptom:**
|
|
328
|
+
```
|
|
329
|
+
error TS2339: Property 'refine' does not exist on type 'ISetup<T>'
|
|
330
|
+
```
|
|
331
|
+
|
|
332
|
+
**Solution:**
|
|
333
|
+
Update method name: `.refine()` → `.and()`
|
|
334
|
+
|
|
335
|
+
---
|
|
336
|
+
|
|
337
|
+
### Issue 2: Runtime Errors After Migration
|
|
338
|
+
|
|
339
|
+
**Symptom:**
|
|
340
|
+
```
|
|
341
|
+
TypeError: observable$.stream is not a function
|
|
342
|
+
```
|
|
343
|
+
|
|
344
|
+
**Solution:**
|
|
345
|
+
Ensure all method names are updated. Run automated migration script again.
|
|
346
|
+
|
|
347
|
+
---
|
|
348
|
+
|
|
349
|
+
### Issue 3: Test Failures
|
|
350
|
+
|
|
351
|
+
**Symptom:**
|
|
352
|
+
Tests fail after migration with method not found errors.
|
|
353
|
+
|
|
354
|
+
**Solution:**
|
|
355
|
+
Update test files as well:
|
|
356
|
+
```bash
|
|
357
|
+
find test -name "*.test.ts" -exec sed -i -e 's/\.refine(/\.and(/g' {} \;
|
|
358
|
+
```
|
|
359
|
+
|
|
360
|
+
---
|
|
361
|
+
|
|
362
|
+
## Rollback Plan
|
|
363
|
+
|
|
364
|
+
If you need to rollback to v2.x:
|
|
365
|
+
|
|
366
|
+
1. **Revert package version:**
|
|
367
|
+
```bash
|
|
368
|
+
npm install evg_observable@2.x
|
|
369
|
+
```
|
|
370
|
+
|
|
371
|
+
2. **Revert code changes:**
|
|
372
|
+
```bash
|
|
373
|
+
git revert <migration-commit-hash>
|
|
374
|
+
```
|
|
375
|
+
|
|
376
|
+
3. **Or use reverse migration script:**
|
|
377
|
+
```bash
|
|
378
|
+
find src -name "*.ts" -exec sed -i \
|
|
379
|
+
-e 's/\.of(/\.stream(/g' \
|
|
380
|
+
-e 's/\.and(/\.refine(/g' \
|
|
381
|
+
-e 's/\.map(/\.then(/g' \
|
|
382
|
+
-e 's/\.once(/\.setOnce(/g' \
|
|
383
|
+
{} \;
|
|
384
|
+
```
|
|
385
|
+
|
|
386
|
+
---
|
|
387
|
+
|
|
388
|
+
## Need Help?
|
|
389
|
+
|
|
390
|
+
- **Documentation:** [README.md](./README.md)
|
|
391
|
+
- **Issues:** https://github.com/your-repo/issues
|
|
392
|
+
- **Examples:** See `test/*.test.ts` for v3.0.0 usage patterns
|
|
393
|
+
|
|
394
|
+
---
|
|
395
|
+
|
|
396
|
+
## Changelog Summary
|
|
397
|
+
|
|
398
|
+
See [CHANGELOG.md](./CHANGELOG.md) for detailed changes.
|
|
399
|
+
|
|
400
|
+
**Major Changes:**
|
|
401
|
+
- 14 operators renamed for consistency and RxJS alignment
|
|
402
|
+
- New `in<K,V>()` operator for object iteration
|
|
403
|
+
- New `group()` operator for multi-listener optimization
|
|
404
|
+
- Performance improvements (+7% emit, +10% multi-subscriber)
|
|
405
|
+
- Bundle size increased to 7.2 kB (+12.5%) for new features
|
|
406
|
+
|
|
407
|
+
**No Breaking Changes:**
|
|
408
|
+
- All type signatures preserved
|
|
409
|
+
- No behavioral changes to existing operators
|
|
410
|
+
- Full backward compatibility in logic (only names changed)
|