@webqit/observer 3.8.12 → 3.8.14
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 +29 -26
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -15,26 +15,26 @@ Observe and intercept operations on arbitrary JavaScript objects and arrays usin
|
|
|
15
15
|
|
|
16
16
|
This API re-explores the unique design of the retired [Object.observe()](https://web.dev/es7-observe/) API and unifies that with the rest of JavaScript's metaprogramming APIs: `Proxies`, `Reflect`, `Object`!
|
|
17
17
|
|
|
18
|
-
|
|
18
|
+
Observer comes as one little API for all things _object observability_. (Only `~5.8KiB min|zip`)
|
|
19
19
|
|
|
20
20
|
```js
|
|
21
|
-
const
|
|
21
|
+
const obj = {};
|
|
22
22
|
|
|
23
23
|
// Observe all property changes
|
|
24
|
-
Observer.observe(
|
|
24
|
+
Observer.observe(obj, (mutations) => {
|
|
25
25
|
mutations.forEach(mutation => {
|
|
26
26
|
console.log(`${mutation.type}: ${mutation.key} = ${mutation.value}`);
|
|
27
27
|
});
|
|
28
28
|
});
|
|
29
29
|
|
|
30
|
-
Observer.set(
|
|
31
|
-
Observer.deleteProperty(
|
|
30
|
+
Observer.set(obj, 'count', 5);
|
|
31
|
+
Observer.deleteProperty(obj, 'oldProp');
|
|
32
32
|
```
|
|
33
33
|
|
|
34
34
|
> [!TIP]
|
|
35
|
-
> Reactivity is anchored on its programmtic APIs like `.set()`, `.deleteProperty()`, but you also get reactivity over literal JavaScript operations
|
|
35
|
+
> Reactivity is anchored on its programmtic APIs like `.set()`, `.deleteProperty()`, but you also get reactivity over literal JavaScript operations — `obj.prop = value`, `delete obj.prop`, etc. — by means of the `accessorize()` and `proxy()` methods covered just ahead.
|
|
36
36
|
>
|
|
37
|
-
> For full-fledged Imperative Reactive Programming, you
|
|
37
|
+
> For full-fledged Imperative Reactive Programming, you want to see the [Quantum JS](https://github.com/webqit/quantum-js) project.
|
|
38
38
|
|
|
39
39
|
---
|
|
40
40
|
|
|
@@ -88,16 +88,18 @@ This limitation in the language has long created a **blindspot** — and a **wea
|
|
|
88
88
|
state = { ...state, items: [...state.items, 'new item 3'] };
|
|
89
89
|
```
|
|
90
90
|
|
|
91
|
-
> Because this is generally hard to follow, frameworks typically enforce immutability
|
|
91
|
+
> Because this is generally hard to follow, frameworks typically enforce immutability by means of strong design constraints.
|
|
92
|
+
>
|
|
93
|
+
> Outside of a framework, you get standalone *immutability* libraries (like Immer, or Immutable.js back in the day) that as well try to simulate an immutable world, where data is never changed, only replaced.
|
|
92
94
|
|
|
93
95
|
+ mutation gets a bad rap
|
|
94
96
|
|
|
95
97
|
**Using the Observer API:**
|
|
96
98
|
|
|
97
|
-
By enabling observability at the object/array level, the Observer API effectively solves reactivity for a mutable world.
|
|
99
|
+
By enabling observability at the object/array level, the Observer API effectively solves reactivity for a **mutable** world. The Result is *mutation-based* reactivity as a first-class concept in JavaScript. Consequently:
|
|
98
100
|
|
|
99
|
-
+ you are able to weild *the
|
|
100
|
-
+ you are able to make sense of a mutable world — and integrate with it — rather than
|
|
101
|
+
+ you are able to weild *the full power* of mutability in programming to your advantage
|
|
102
|
+
+ you are able to make sense of a mutable world — and integrate with it — rather than struggle with it
|
|
101
103
|
|
|
102
104
|
## Quick Start
|
|
103
105
|
|
|
@@ -157,7 +159,8 @@ Observer.set(items, 0, 'grape');
|
|
|
157
159
|
Observer.set(items, 2, 'orange');
|
|
158
160
|
|
|
159
161
|
// Reactive method calls
|
|
160
|
-
Observer.apply(items.push, items, ['new item']);
|
|
162
|
+
Observer.apply(items.push, items, ['new item']);
|
|
163
|
+
Observer.proxy(state.items).push('new item')
|
|
161
164
|
```
|
|
162
165
|
|
|
163
166
|
### Intercepting Operations
|
|
@@ -324,7 +327,7 @@ parentController.abort();
|
|
|
324
327
|
#### Parity Table
|
|
325
328
|
|
|
326
329
|
| | Observer API | Object.observe() (Deprecated) |
|
|
327
|
-
|
|
330
|
+
|:-------------|:--------------|:-------------------------------|
|
|
328
331
|
| **Signature** | `.observe(target, callback, options?)` | `.observe(target, callback, acceptList?)` |
|
|
329
332
|
| **Return Value** | `AbortController` (lifecycle management) | `undefined` (no lifecycle management) |
|
|
330
333
|
| **Additional Features** | AbortSignal integration, path watching, batch/atomic operations, synchronous event model, etc. | Basic object observation, asynchronous event model (deprecated) |
|
|
@@ -424,7 +427,7 @@ Observer.intercept(obj, 'get', (operation, previous, next) => {
|
|
|
424
427
|
#### Parity Table
|
|
425
428
|
|
|
426
429
|
| | Observer API | Proxy Traps |
|
|
427
|
-
|
|
430
|
+
|:-------------|:--------------|:-------------|
|
|
428
431
|
| **Signature** | `.intercept(target, operation, handler, options?)`<br>`.intercept(target, { [operation]: handler[, ...]}, options?)` | `new Proxy(target, { [operation]: handler[, ...] })` |
|
|
429
432
|
| **Return Value** | `undefined` (registration) | `Proxy` (wrapped object) |
|
|
430
433
|
| **Additional Features** | Traps pipeline, composable interceptors | Single trap per operation, no composability |
|
|
@@ -475,7 +478,7 @@ Observer.set(obj, Observer.path('user', 'profile', 'name'), 'Alice');
|
|
|
475
478
|
#### Parity Table
|
|
476
479
|
|
|
477
480
|
| | Observer API | Reflect API |
|
|
478
|
-
|
|
481
|
+
|:-------------|:--------------|:-------------|
|
|
479
482
|
| **Signature** | `.set(target, key, value, options?)` | `.set(target, key, value)` |
|
|
480
483
|
| **Return Value** | `boolean` (success) | `boolean` (success) |
|
|
481
484
|
| **Additional Features** | Triggers observers, interceptable | Standard property setting |
|
|
@@ -509,7 +512,7 @@ Observer.get(obj, 'fullName'); // "John Doe" (computed on-the-fly)
|
|
|
509
512
|
#### Parity Table
|
|
510
513
|
|
|
511
514
|
| | Observer API | Reflect API |
|
|
512
|
-
|
|
515
|
+
|:-------------|:--------------|:-------------|
|
|
513
516
|
| **Signature** | `.get(target, key, options?)` | `.get(target, key)` |
|
|
514
517
|
| **Return Value** | `any` (property value) | `any` (property value) |
|
|
515
518
|
| **Additional Features** | Interceptable for computed values | Standard property access |
|
|
@@ -543,7 +546,7 @@ Observer.has(obj, 'password'); // false (hidden from checks)
|
|
|
543
546
|
#### Parity Table
|
|
544
547
|
|
|
545
548
|
| | Observer API | Reflect API |
|
|
546
|
-
|
|
549
|
+
|:-------------|:--------------|:-------------|
|
|
547
550
|
| **Signature** | `.has(target, key, options?)` | `.has(target, key)` |
|
|
548
551
|
| **Return Value** | `boolean` (exists) | `boolean` (exists) |
|
|
549
552
|
| **Additional Features** | Interceptable for property hiding | Standard property existence check |
|
|
@@ -574,7 +577,7 @@ Observer.ownKeys(obj); // ['name', 'email'] (password filtered out)
|
|
|
574
577
|
#### Parity Table
|
|
575
578
|
|
|
576
579
|
| | Observer API | Reflect API | Object API |
|
|
577
|
-
|
|
580
|
+
|:-------------|:--------------|:-------------|:-------------|
|
|
578
581
|
| **Signature** | `.ownKeys(target, options?)` | `.ownKeys(target)` | `.keys(obj)` |
|
|
579
582
|
| **Return Value** | `string[]` (keys) | `string[]` (keys) | `string[]` (keys) |
|
|
580
583
|
| **Additional Features** | Interceptable for key filtering | Standard key enumeration | Standard key enumeration |
|
|
@@ -592,7 +595,7 @@ Observer.deleteProperty(arr, 0);
|
|
|
592
595
|
#### Parity Table
|
|
593
596
|
|
|
594
597
|
| | Observer API | Reflect API |
|
|
595
|
-
|
|
598
|
+
|:-------------|:--------------|:-------------|
|
|
596
599
|
| **Signature** | `.deleteProperty(target, key, options?)` | `.deleteProperty(target, key)` |
|
|
597
600
|
| **Return Value** | `boolean` (success) | `boolean` (success) |
|
|
598
601
|
| **Additional Features** | Triggers observers, interceptable | Standard property deletion |
|
|
@@ -608,7 +611,7 @@ Observer.deleteProperties(obj, ['oldProp1', 'oldProp2', 'tempProp']);
|
|
|
608
611
|
#### Parity Table
|
|
609
612
|
|
|
610
613
|
| | Observer API | No Direct Equivalent |
|
|
611
|
-
|
|
614
|
+
|:-------------|:--------------|:---------------------|
|
|
612
615
|
| **Signature** | `.deleteProperties(target, keys, options?)` | No batch delete in standard APIs |
|
|
613
616
|
| **Return Value** | `boolean[]` (success array) | N/A |
|
|
614
617
|
| **Additional Features** | Triggers observers, interceptable | N/A |
|
|
@@ -628,7 +631,7 @@ Observer.defineProperty(obj, 'computed', {
|
|
|
628
631
|
#### Parity Table
|
|
629
632
|
|
|
630
633
|
| | Observer API | Reflect API | Object API |
|
|
631
|
-
|
|
634
|
+
|:-------------|:--------------|:-------------|:-------------|
|
|
632
635
|
| **Signature** | `.defineProperty(target, key, descriptor, options?)` | `.defineProperty(target, key, descriptor)` | `.defineProperty(obj, key, descriptor)` |
|
|
633
636
|
| **Return Value** | `boolean` (success) | `boolean` (success) | `object` (modified object) |
|
|
634
637
|
| **Additional Features** | Triggers observers, interceptable | Standard property definition | Standard property definition |
|
|
@@ -648,7 +651,7 @@ Observer.defineProperties(obj, {
|
|
|
648
651
|
#### Parity Table
|
|
649
652
|
|
|
650
653
|
| | Observer API | Object API |
|
|
651
|
-
|
|
654
|
+
|:-------------|:--------------|:-------------|
|
|
652
655
|
| **Signature** | `.defineProperties(target, descriptors, options?)` | `.defineProperties(obj, descriptors)` |
|
|
653
656
|
| **Return Value** | `boolean` (success) | `object` (modified object) |
|
|
654
657
|
| **Additional Features** | Triggers observers, interceptable | Standard property definition |
|
|
@@ -676,7 +679,7 @@ obj.email = 'alice@example.com';
|
|
|
676
679
|
#### Parity Table
|
|
677
680
|
|
|
678
681
|
| | Observer API | No Direct Equivalent |
|
|
679
|
-
|
|
682
|
+
|:-------------|:--------------|:---------------------|
|
|
680
683
|
| **Signature** | `.accessorize(target, properties?, options?)` | No direct equivalent in standard APIs |
|
|
681
684
|
| **Return Value** | `undefined` (modification) | N/A |
|
|
682
685
|
| **Additional Features** | Makes properties reactive for direct assignment | N/A |
|
|
@@ -696,7 +699,7 @@ Observer.unaccessorize(obj);
|
|
|
696
699
|
#### Parity Table
|
|
697
700
|
|
|
698
701
|
| | Observer API | No Direct Equivalent |
|
|
699
|
-
|
|
702
|
+
|:-------------|:--------------|:---------------------|
|
|
700
703
|
| **Signature** | `.unaccessorize(target, properties?, options?)` | No direct equivalent in standard APIs |
|
|
701
704
|
| **Return Value** | `undefined` (modification) | N/A |
|
|
702
705
|
| **Additional Features** | Restores accessorized properties to normal state | N/A |
|
|
@@ -866,7 +869,7 @@ const $obj = Observer.proxy(obj, {}, (traps) => {
|
|
|
866
869
|
#### Parity Table
|
|
867
870
|
|
|
868
871
|
| | Observer API | Proxy API |
|
|
869
|
-
|
|
872
|
+
|:-------------|:--------------|:-----------|
|
|
870
873
|
| **Signature** | `.proxy(target, options?)` | `new Proxy(target, handlers)` |
|
|
871
874
|
| **Return Value** | `Proxy` (reactive proxy) | `Proxy` (standard proxy) |
|
|
872
875
|
| **Additional Features** | Built-in reactivity, membrane, chainable | Manual trap implementation required |
|
|
@@ -883,7 +886,7 @@ const original = Observer.unproxy($obj); // Returns original obj
|
|
|
883
886
|
#### Parity Table
|
|
884
887
|
|
|
885
888
|
| | Observer API | No Direct Equivalent |
|
|
886
|
-
|
|
889
|
+
|:-------------|:--------------|:---------------------|
|
|
887
890
|
| **Signature** | `.unproxy(target)` | No direct equivalent in standard APIs |
|
|
888
891
|
| **Return Value** | `object` (original object) | N/A |
|
|
889
892
|
| **Additional Features** | Extracts original object from Observer proxy | N/A |
|