@webqit/observer 2.1.10 → 2.1.12

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 (2) hide show
  1. package/README.md +45 -187
  2. package/package.json +1 -1
package/README.md CHANGED
@@ -6,7 +6,7 @@
6
6
 
7
7
  <!-- /BADGES -->
8
8
 
9
- **[Motivation](#motivation) • [Overview](#an-overview) • [Polyfill](#the-polyfill) • [Design Discussion](#design-discussion) • [Getting Involved](#getting-involved) • [License](#license)**
9
+ **[Motivation](#motivation) • [Overview](#an-overview) • [Documentation](#documentation) • [Polyfill](#the-polyfill) • [Getting Involved](#getting-involved) • [License](#license)**
10
10
 
11
11
  Observe and intercept operations on arbitrary JavaScript objects and arrays using a utility-first, general-purpose reactivity API! This API re-explores the unique design of the [`Object.observe()`](https://web.dev/es7-observe/) API and takes a stab at what could be **a unifying API** over *related but disparate* things like `Object.observe()`, [Reflect](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Reflect) APIs, and the "traps" API (proxy traps)!
12
12
 
@@ -14,7 +14,7 @@ Observer API is an upcoming proposal!
14
14
 
15
15
  ## Motivation
16
16
 
17
- Tracking mutations on JavaScript objects has historically relied on "object wrapping" techniques with [ES6 Proxies](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Proxy), and on "property mangling" techniques with [getters and setters](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/defineProperty). Besides the *object identity* problem of the first and the *object compromissory* nature of the second, there is also the "scalability" issue inherent to the techniques and much "inflexibility" in the programming model they enable!
17
+ Tracking mutations on JavaScript objects has historically relied on "object wrapping" techniques with [ES6 Proxies](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Proxy), and on "property mangling" techniques with [getters and setters](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/defineProperty). Besides how the first poses an *object identity* problem and the second, an *interoperability* problem, there is also much inflexibility in the programming model that the two techniques enable!
18
18
 
19
19
  This is discussed extensively in [the introductory blog post](https://dev.to/oxharris/reinvestigating-reactivity-22e0-temp-slug-5973064?preview=8afd0f8b156bf0b0b1c08058837fe4986054e52a7450f0a28adbaf07dcb7f5659b724166f553fb98ceab3d080748e86b244684f515d579bcd0f48cbb#introducing-the-observer-api)<sup>draft</sup>
20
20
 
@@ -22,69 +22,37 @@ We find a design precedent to object observability in the [`Object.observe()`](h
22
22
 
23
23
  ## An Overview
24
24
 
25
- The Observer API is a set of utility functions.
25
+ The Observer API is a set of utility functions for all things object observability - notably, the `Observer.observe()` and `Observer.intercept()` methods.
26
26
 
27
- <details>
28
- <summary><b>Show Outline</b></summary>
29
-
30
- + [Method: `Observer.observe()`](#method-observerobserve)
31
- + [Usage](#usage)
32
- + [Concept: *Mutation APIs*](#concept-mutation-apis)
33
- + [Concept: *Paths*](#concept-paths)
34
- + [Concept: *Batch Mutations*](#concept-batch-mutations)
35
- + [Concept: *Custom Details*](#concept-custom-details)
36
- + [Concept: *Diffing*](#concept-diffing)
37
- + [Method: `Observer.intercept()`](#method-observerintercept)
38
- + [Usage](#usage-1)
39
- + [API Reference](#api-reference)
40
-
41
- </details>
27
+ <details><summary>This is documentation for Observer@2.x</summary>
42
28
 
43
- > **Note**
44
- > <br>This is documentation for `Observer@2.x`. (Looking for [`Observer@1.x`](https://github.com/webqit/observer/tree/v1.7.6)?)
29
+ Looking for [`Observer@1.x`](https://github.com/webqit/observer/tree/v1.7.6)?
45
30
 
31
+ </details>
32
+
46
33
  ### Method: `Observer.observe()`
47
34
 
48
- Observe mutations on any object or array!
49
-
50
- ```js
51
- // Signature 1
52
- Observer.observe( obj, callback[, options = {} ]);
53
- ```
54
-
55
- ```js
56
- // Signature 2
57
- Observer.observe( obj, [ prop, prop, ... ], callback[, options = {} ]);
58
- ```
59
-
60
- ```js
61
- // Signature 3
62
- Observer.observe( obj, prop, callback[, options = {} ]);
63
- ```
64
-
65
- #### Usage
66
-
67
- Observe arbitrary objects and arrays:
35
+ Observe mutations on arbitrary objects or arrays!
68
36
 
69
37
  ```js
70
38
  // An object
71
39
  const obj = {};
72
40
  // Mtation observer on an object
73
- const abortController = Observer.observe( obj, handleChanges );
41
+ const abortController = Observer.observe( obj, inspect );
74
42
  ```
75
43
 
76
44
  ```js
77
45
  // An array
78
46
  const arr = [];
79
47
  // Mtation observer on an array
80
- const abortController = Observer.observe( arr, handleChanges );
48
+ const abortController = Observer.observe( arr, inspect );
81
49
  ```
82
50
 
83
- └ *Changes are delivered [**synchronously**](https://dev.to/oxharris/reinvestigating-reactivity-22e0-temp-slug-5973064?preview=8afd0f8b156bf0b0b1c08058837fe4986054e52a7450f0a28adbaf07dcb7f5659b724166f553fb98ceab3d080748e86b244684f515d579bcd0f48cbb#timing-and-batching) - as they happen.*
51
+ └ *Changes are delivered [**synchronously**](https://github.com/webqit/observer/wiki/#timing-and-batching) - as they happen.*
84
52
 
85
53
  ```js
86
54
  // The change handler
87
- function handleChanges( mutations ) {
55
+ function inspect( mutations ) {
88
56
  mutations.forEach( mutation => {
89
57
  console.log( mutation.type, mutation.key, mutation.value, mutation.oldValue );
90
58
  } );
@@ -103,7 +71,7 @@ abortController.abort();
103
71
  ```js
104
72
  // Providing an AbortSignal
105
73
  const abortController = new AbortController;
106
- Observer.observe( obj, handleChanges, { signal: abortController.signal } );
74
+ Observer.observe( obj, inspect, { signal: abortController.signal } );
107
75
  ```
108
76
 
109
77
  ```js
@@ -118,12 +86,15 @@ abortController.abort();
118
86
  const abortController = Observer.observe( obj, ( mutations, flags ) => {
119
87
 
120
88
  // Child
121
- Observer.observe( obj, handleChanges, { signal: flags.signal } ); // <<<---- AbortSignal-cascading
89
+ Observer.observe( obj, inspect, { signal: flags.signal } ); // <<<---- AbortSignal-cascading
90
+
91
+ // Child
92
+ Observer.observe( obj, inspect, { signal: flags.signal } ); // <<<---- AbortSignal-cascading
122
93
 
123
94
  } );
124
95
  ```
125
96
 
126
- └ *"Child" gets automatically aborted at parent's "next turn", and at parent's own abortion!*
97
+ └ *"Child" observers get automatically aborted at parent's "next turn", and at parent's own abortion!*
127
98
 
128
99
  #### Concept: *Mutation APIs*
129
100
 
@@ -142,10 +113,9 @@ Observer.set( arr, 0, 'item0' ); // Array [ 'item0' ]
142
113
  Observer.deleteProperty( arr, 0 ); // Array [ <1 empty slot> ]
143
114
  ```
144
115
 
145
- <details>
146
- <summary>Polyfill limitations</summary>
116
+ <details><summary>Polyfill limitations</summary>
147
117
 
148
- *Beware non-reactive operations:*
118
+ In the polyfill, object observability doesn't work with literal operations. **Beware non-reactive operations**:
149
119
 
150
120
  ```js
151
121
  // Literal object operators
@@ -191,10 +161,9 @@ arr.unshift( 'new-item0' );
191
161
  arr.shift();
192
162
  ```
193
163
 
194
- <details>
195
- <summary>Polyfill limitations</summary>
164
+ <details><summary>Polyfill limitations</summary>
196
165
 
197
- *Beware non-reactive operations*:
166
+ In the polyfill, object observability doesn't work with literal operations. **Beware non-reactive operations**:
198
167
 
199
168
  ```js
200
169
  // The delete operator and object properties that haven't been accessorized
@@ -267,7 +236,7 @@ obj = Observer.unproxy( $obj );
267
236
 
268
237
  #### Concept: *Paths*
269
238
 
270
- Observe "the value" at a path in a given tree:
239
+ Observe "a property" at a path in a given tree:
271
240
 
272
241
  ```js
273
242
  const obj = {
@@ -288,8 +257,7 @@ Observer.observe( obj, path, m => {
288
257
  Observer.set( obj.level1, 'level2', 'level2-new-value' );
289
258
  ```
290
259
 
291
- <details>
292
- <summary>Console</summary>
260
+ <details><summary>Console</summary>
293
261
 
294
262
  | type | path | value | isUpdate |
295
263
  | ---- | ---- | ----- | -------- |
@@ -404,69 +372,9 @@ Observer.batch( arr, async () => {
404
372
 
405
373
  > Method calls on a proxied instance - e.g. `Object.proxy( arr ).splice( 0 )` - also follow this strategy.
406
374
 
407
- #### Concept: *Custom Details*
408
-
409
- Pass some custom detail - an arbitrary value - to observers via a `params.detail` property.
410
-
411
- ```js
412
- // A set operation with detail
413
- Observer.set( obj, {
414
- prop2: 'value2',
415
- prop3: 'value3',
416
- }, { detail: 'Certain detail' } );
417
- ```
418
-
419
- └ *Observers recieve this value on their `mutation.detail` property.*
420
-
421
- ```js
422
- // An observer with detail
423
- Observer.observe( obj, 'prop1', mutation => {
424
- console.log( 'A mutation has been made with detail:' + mutation.detail );
425
- } );
426
- ```
427
-
428
- #### Concept: *Diffing*
429
-
430
- Receive notifications only for mutations that actually change property state, and ignore those that don't.
431
-
432
- ```js
433
- // Responding to state changes only
434
- Observer.observe( obj, handleChanges, { diff: true } );
435
- ```
436
-
437
- ```js
438
- // Recieved
439
- Observer.set( obj, 'prop0', 'value' );
440
- ```
441
-
442
- ```js
443
- // Ignored
444
- Observer.set( obj, 'prop0', 'value' );
445
- ```
446
-
447
- <!--
448
- ### Concept: *Live*
449
- descripted
450
- namespace
451
- -->
452
-
453
375
  ### Method: `Observer.intercept()`
454
376
 
455
- Intercept operations on any object or array before they happen!
456
-
457
- ```js
458
- // Signature 1
459
- Observer.intercept( obj, type, handler[, options = {} ]);
460
- ```
461
-
462
- ```js
463
- // Signature 2
464
- Observer.intercept( obj, traps[, options = {} ]);
465
- ```
466
-
467
- #### Usage
468
-
469
- Extend standard operations on an object - `Observer.set()`, `Observer.deleteProperty()`, etc - with custom traps using the [`Observer.intercept()`](https://webqit.io/tooling/observer/docs/api/reactions/intercept) method!
377
+ Intercept operations on any object or array before they happen! This helps you extend standard operations on an object - `Observer.set()`, `Observer.deleteProperty()`, etc - using Proxy-like traps.
470
378
 
471
379
  └ *Below, we intercept all "set" operations for an HTTP URL then transform it to an HTTPS URL.*
472
380
 
@@ -516,91 +424,41 @@ Observer.intercept( obj, {
516
424
  } );
517
425
  ```
518
426
 
519
- ## The Polyfill
427
+ ## Documentation
520
428
 
521
- **_Use as an npm package:_**
429
+ Visit the [docs](https://github.com/webqit/observer/wiki) for all what's possible - including [Reflect APIs](https://github.com/webqit/observer/wiki#featuring-reflect-apis-extended), [Timing and Batching](https://github.com/webqit/observer/wiki#timing-and-batching), [API Reference](https://github.com/webqit/observer/wiki#putting-it-all-together), etc.
522
430
 
523
- ```bash
524
- npm i @webqit/observer
525
- ```
431
+ ## The Polyfill
526
432
 
527
- ```js
528
- // Import
529
- import Observer from '@webqit/observer';;
530
- ```
433
+ The Observer API is being developed as something to be used today - via a polyfill. The polyfill features all of what's documented - with limitations in the area of making mutations: you can only make mutations using the [Mutation APIs](#concept-mutation-apis).
531
434
 
532
- **_Use as a script:_**
435
+ <details><summary>Load from a CDN</summary>
533
436
 
534
437
  ```html
535
438
  <script src="https://unpkg.com/@webqit/observer/dist/main.js"></script>
536
439
  ```
537
440
 
538
- > 4.4 kB min + gz | 13.9 KB min [↗](https://bundlephobia.com/package/@webqit/observer@2.1.4)
441
+ > `4.4` kB min + gz | `13.9` KB min [↗](https://bundlephobia.com/package/@webqit/observer)
539
442
 
540
443
  ```js
541
444
  // Obtain the APIs
542
445
  const Observer = window.webqit.Observer;
543
446
  ```
544
447
 
545
- ## API Reference
546
-
547
- <!--
548
-
549
- | Observer API | Reflect API | Description | Trap |
550
- | -------------- | ------------ | ----------- | --------------- |
551
- | `apply()` | ✓ | Invokes a function [↗](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Reflect/apply) | `apply() {}` |
552
- | `batch()` | `×` | Creates a batching context [↗](https://github.com/webqit/observer#:~:text=use%20the%20observer.batch()%20to%20batch%20multiple%20arbitrary%20mutations%20-%20whether%20related%20or%20not) | `-` |
553
- | `construct()` | ✓ | Initializes a constructor [↗](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Reflect/construct) | `construct() {}` |
554
- | `defineProperties()` [↗]() | `×` | `defineProperty() {}` |
555
- | `defineProperty()` | ✓ | Defines a property [↗](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Reflect/defineProperty) | `defineProperty() {}` |
556
- | `deleteProperties()` [↗]() | `×` | `deleteProperty() {}` |
557
- | `deleteProperty()` | ✓ | Deletes a property [↗](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Reflect/deleteProperty) | `deleteProperty() {}` |
558
- | `get()` | ✓ | Reads a property [↗](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Reflect/get) | `get() {}` |
559
- | `getOwnPropertyDescriptor()` | ✓ | Obtains property descriptor [↗](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Reflect/getOwnPropertyDescriptor) | `getOwnPropertyDescriptor() {}` |
560
- | `getPrototypeOf()` | ✓ | Obtains object prototype [↗](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Reflect/getPrototypeOf) | `getPrototypeOf() {}` |
561
- | `has()` | ✓ | Checks property existence [↗](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Reflect/has) | `has() {}` |
562
- | `intercept()` | `×` | Binds a "traps" object [↗](https://github.com/webqit/observer#method-observerintercept) | `-` |
563
- | `isExtensible()` | ✓ | Checks object extensibility [↗](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Reflect/isExtensible) | `isExtensible() {}` |
564
- | `observe()` | `×` | Binds a mutation observer [↗](https://github.com/webqit/observer#method-observerobserve) | `-` |
565
- | `ownKeys()` | ✓ | Obtains object keys [↗](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Reflect/ownKeys) | `ownKeys() {}` |
566
- | `path()` | `×` | Evaluates a path [↗](#) | `-` |
567
- | `preventExtensions()` | ✓ | Prevents object extensibility [↗](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Reflect/preventExtensions) | `preventExtensions() {}` |
568
- | `set()` | ✓ | Sets a property [↗](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Reflect/set) | `set() {}` |
569
- | `setPrototypeOf()` | ✓ | Sets object prototype [↗](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Reflect/setPrototypeOf) | `setPrototypeOf() {}` |
570
- | . | . | . | . |
571
- | `accessorize()` | `×` | Applies pre-intercepted getters/setters to properties [↗](https://github.com/webqit/observer#:~:text=enable%20reactivity%20on%20specific%20properties%20with%20literal%20object%20accessors%20-%20using%20the%20observer.accessorize()%20method) | `-` |
572
- | `proxy()` | `×` | Creates a pre-intercepted proxy object [↗](https://github.com/webqit/observer#:~:text=enable%20reactivity%20on%20arbitray%20properties%20with%20proxies%20-%20using%20the%20observer.proxy()%20method) | `-` |
573
-
574
- -->
575
-
576
- | Observer API | Reflect API | Trap |
577
- | -------------- | ------------ | ----------- |
578
- | `apply()` [↗](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Reflect/apply) | ✓ | `apply() {}` |
579
- | `batch()` [↗](https://github.com/webqit/observer#concept-batch-mutations) | `×` | `-` |
580
- | `construct()` [↗](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Reflect/construct) | ✓ | `construct() {}` |
581
- | `defineProperties()` [↗]() | `×` | `defineProperty() {}` |
582
- | `defineProperty()` [↗](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Reflect/defineProperty) | ✓ | `defineProperty() {}` |
583
- | `deleteProperties()` [↗]() | `×` | `deleteProperty() {}` |
584
- | `deleteProperty()` [↗](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Reflect/deleteProperty) | ✓ | `deleteProperty() {}` |
585
- | `get()` [↗](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Reflect/get) | ✓ | `get() {}` |
586
- | `getOwnPropertyDescriptor()` [↗](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Reflect/getOwnPropertyDescriptor) | ✓ | `getOwnPropertyDescriptor() {}` |
587
- | `getPrototypeOf()` [↗](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Reflect/getPrototypeOf) | ✓ | `getPrototypeOf() {}` |
588
- | `has()` [↗](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Reflect/has) | ✓ | `has() {}` |
589
- | `intercept()`[↗](https://github.com/webqit/observer#method-observerintercept) | `×` | `-` |
590
- | `isExtensible()` [↗](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Reflect/isExtensible) | ✓ | `isExtensible() {}` |
591
- | `observe()` [↗](https://github.com/webqit/observer#method-observerobserve) | `×` | `-` |
592
- | `ownKeys()` [↗](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Reflect/ownKeys) | ✓ | `ownKeys() {}` |
593
- | `path()` [↗](https://github.com/webqit/observer#concept-paths) | `×` | `-` |
594
- | `preventExtensions()` [↗](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Reflect/preventExtensions) | ✓ | `preventExtensions() {}` |
595
- | `set()` [↗](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Reflect/set) | ✓ | `set() {}` |
596
- | `setPrototypeOf()` [↗](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Reflect/setPrototypeOf) | ✓ | `setPrototypeOf() {}` |
597
- | . | . | . | . |
598
- | `accessorize()` [↗](https://github.com/webqit/observer#:~:text=enable%20reactivity%20on%20specific%20properties%20with%20literal%20object%20accessors%20-%20using%20the%20observer.accessorize()%20method) | `×` | `-` |
599
- | `proxy()` [↗](https://github.com/webqit/observer#:~:text=enable%20reactivity%20on%20arbitray%20properties%20with%20proxies%20-%20using%20the%20observer.proxy()%20method) | `×` | `-` |
600
-
601
- ## Design Discussion
602
-
603
- [See more in the introductory blog post](https://dev.to/oxharris/reinvestigating-reactivity-22e0-temp-slug-5973064?preview=8afd0f8b156bf0b0b1c08058837fe4986054e52a7450f0a28adbaf07dcb7f5659b724166f553fb98ceab3d080748e86b244684f515d579bcd0f48cbb#introducing-the-observer-api)<sup>draft</sup>
448
+ </details>
449
+
450
+ <details><summary>Install from NPM</summary>
451
+
452
+ ```bash
453
+ npm i @webqit/observer
454
+ ```
455
+
456
+ ```js
457
+ // Import
458
+ import Observer from '@webqit/observer';;
459
+ ```
460
+
461
+ </details>
604
462
 
605
463
  ## Getting Involved
606
464
 
package/package.json CHANGED
@@ -12,7 +12,7 @@
12
12
  "events"
13
13
  ],
14
14
  "homepage": "https://webqit.io/tooling/observer",
15
- "version": "2.1.10",
15
+ "version": "2.1.12",
16
16
  "license": "MIT",
17
17
  "repository": {
18
18
  "type": "git",