object-observer

Migrating from v6 to v7

object-observer v7 is a major release. The core API — Observable.from, Observable.observe, Observable.unobserve, Observable.isObservable, ObjectObserver — keeps its shape and semantics. The change event model (type, path, value, oldValue, object) is unchanged.

The only API break is the observation options shape: the old path-based options have been replaced with a single filters array of Filter instances. A handful of smaller, mostly incidental adjustments are listed at the end for completeness.

Observation options — path-based options replaced by filters

What changed

In v6, Observable.observe(observable, callback, options) accepted one of three mutually exclusive path options:

v6 option Meaning
path observe one exact path
pathsOf observe direct children of a path
pathsFrom observe a path and everything below it

In v7 these three options are removed. In their place, options.filters accepts a non-empty array of Filter instances. When multiple filters are provided they compose as logical AND — each narrows the output of the previous one. Filter is a new named export; instances are created via static factory methods (the constructor is private).

Mapping table

v6 v7
{ path: 'a.b' } { filters: [Filter.exactPaths(['a.b'])] }
{ path: ['a.b', 'a.c'] } (if ever used) { filters: [Filter.exactPaths(['a.b', 'a.c'])] }
{ pathsOf: 'a' } { filters: [Filter.directChildrenOf('a')] }
{ pathsOf: '' } { filters: [Filter.directChildrenOf('')] } (root direct children)
{ pathsFrom: 'a' } { filters: [Filter.pathsStartWith('a')] }
(no v6 equivalent) { filters: [Filter.custom(cs => cs.filter(...))] }

Before / after

//  v6
import { Observable } from '@gullerya/object-observer';

Observable.observe(obs, cb, { path: 'address.city' });
Observable.observe(obs, cb, { pathsOf: 'address' });
Observable.observe(obs, cb, { pathsFrom: 'address' });
//  v7
import { Observable, Filter } from '@gullerya/object-observer';

Observable.observe(obs, cb, { filters: [Filter.exactPaths(['address.city'])] });
Observable.observe(obs, cb, { filters: [Filter.directChildrenOf('address')] });
Observable.observe(obs, cb, { filters: [Filter.pathsStartWith('address')] });

Behavior notes

See docs/filters.md for the full Filter API.

Other breaking changes

Change objects are read-only

In v6 the Change class exposed its fields as plain writable properties. In v7, type, path, value, oldValue, and object are read-only getters backed by private fields. Code that read change properties is unaffected. Code that wrote to change objects — e.g. change.type = 'custom' or attaching ad-hoc properties to a change — will throw in strict mode (and silently fail in sloppy mode). This is very rarely done in practice; if you were using change objects as a scratch space, copy the fields into your own object instead.

A new pathAsString getter is available (lazy, dot-joined). Additive, not breaking.

Runtime and browser matrix

The officially supported matrix has been refreshed:

This is the matrix the library is actively tested against — it is not a hard runtime requirement. The library does not use any v7-specific new language or platform features, so older Node.js versions and older browsers will most likely continue to work just fine. We simply don’t run CI against them anymore, so regressions there won’t be caught by us.

What did not change

New in v7 (non-breaking, for awareness)