npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2024 – Pkg Stats / Ryan Hefner

proxy-watcher

v3.4.4

Published

A library that recursively watches an object for mutations via Proxies and tells you which paths changed.

Downloads

298

Readme

Proxy Watcher

A library that recursively watches an object for mutations via Proxys and tells you which paths changed.

The following values are fully supported: primitives, functions, getters, setters, Dates, RegExps, Objects, Arrays, ArrayBuffers, TypedArrays, Maps and Sets.

Other values are partially supported: Promises, WeakMaps, WeakSets and custom classes. Basically mutations happening inside them won't be detected, however setting any of these as a value will be detected as a mutation.

Functions

The following functions are provided.

  • watch: starts watching an object for mutations, and returns a proxy object.
  • unwatch: stops watching an object for mutations, and returns the raw object being proxied.
  • record: records and returns an array or map of root paths that have been accessed while executing the provided function.
  • target: returns the raw object being proxied.
  • isProxy: returns a boolean indicating if the provided object is a proxy object or not.

Limitations

  • Mutations happening at locations that need to be reached via a Symbol aren't detected, as a precise string path for them can't be generated (e.g. { [Symbol ()]: { unreachableViaStringPath: true }).
  • Referencing the same object under multiple paths at the same time will throw an error. This is not supported because the library can't lazily deeply watch the watched object safely when duplicate objects are used.
  • Referencing the watched object within itself will thrown an error.
  • A path is a dot-separated string of keys, therefore using only dots as your keys may lead to some weird paths generated that can't be parsed properly (e.g. foo.....bar, is that foo/.../bar or foo/././bar?)
  • Proxys will make certain operations even 100x slower on current engines, however those operations are simple things like property accesses which will almost never be your actual bottleneck, even with this kind of performance hit.
  • Proxys are un-polyfillable, if you have to support platforms that don't support them you can't use this library.
  • It's possible that the callback will be called when nothing actually changed (e.g. it will happen if you to flip a boolean twice synchronously).

Install

npm install --save proxy-watcher

Usage

The following interface is provided:

type Disposer = () => void;

function watch ( object: Object, callback: ( paths: string[] ) => any ): [Proxy, Disposer];
function unwatch ( proxy: Proxy ): Object;
function record ( proxy: Proxy, fn: ( proxy: Proxy ) => void ): string[];
function record ( proxies: Proxy[], fn: ( ...proxies: Proxy[] ) => void ): Map<Proxy, string[]>;
function target ( proxy: Proxy ): Object;
function isProxy ( object: Object | Proxy ): boolean;

Basically you have to pass the watch function an object, which will be watched for any changes, and a callback, which will be called with an array of paths changed whenever changes are detected.

The function will return an array containing a proxy object, always use this object rather than the raw object you pass the watch function, and a disposer function, which when called will stop the watching operation and will return back the original unproxied object.

import {watch, unwatch, record, target, isProxy} from 'proxy-watcher';

/* WATCH */

const [proxy, dispose] = watch ({
  foo: true,
  arr: [1, 2, 3]
}, paths => {
  console.log ( 'Something changed at these paths:', paths );
});

proxy.foo; // => true
proxy.arr; // => [1, 2, 3]

proxy.foo = true; // Nothing actually changed, the callback won't be called
proxy.arr[0] = 1; // Nothing actually changed, the callback won't be called

proxy.foo = false; // Callback called with paths: ['foo']
proxy.bar = true; // Callback called with paths: ['bar']
proxy.arr.push ( 4 ) = true; // Callback called with paths: ['arr.3', 'arr']

/* RECORD */ // Record root keys accessed

record ( proxy, () => {
  console.log ( proxy.foo );
}); // => ['foo']

/* TARGET */ // Return the raw unproxied object

target ( proxy ); // => { foo: false, bar = true, arr: [1, 2, 3, 4] }

/* IS PROXY */

isProxy ( proxy ); // => true
isProxy ( target ( proxy ) ); // => false

/* UNWATCH */

dispose (); // Stop watching
unwatch ( proxy ); // Altertnative way to stop watching

License

MIT © Fabio Spampinato