Giter VIP home page Giter VIP logo

proxy-watcher's Introduction

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

proxy-watcher's People

Contributors

fabiospampinato avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar

Forkers

slembit

proxy-watcher's Issues

.min.js

hey post a built .min.js or something us native js'ers can user man,
this ts is not cool.

Problems when functions on arrays f.ex. forEach are used

Hi,
first of all, thanks for the lib and the update!

I updated to the latest store.js and latest proxy-watcher, and now I have a strange problem. It seems the native forEach array function is bound / proxied by store, the following example breaks for me:

const data = store({

})

data.categoryList = [1, 2, 3]
data.objectTypes = [1, 2, 3]

data.categoryList.forEach(id => console.log(id))
data.objectTypes.forEach(id => console.log(id))
Uncaught Error: Duplicate object encountered, the same object is being referenced both at path "categoryList.forEach" and at path "objectTypes.forEach". Duplicate objects in a watched object are not supported.
    at checkChildPathDuplicate (make_traps.js?f91d:25)
    at setChildPath (make_traps.js?f91d:42)
    at eval (make_traps.js?f91d:97)
    at Object.trapWrapper [as get] (make_traps.js?f91d:49)
    at eval (MandatorStore.jsx?d6b7:142)

Versions:
"proxy-watcher": "^3.0.0",
"@fabiospampinato/store": "^1.3.1",

My opinion:
I would ignore functions completly in the store, plain old objects can be proxied, no functions, classes etc.

your ts is not legit js

hey post a built .min.js or something us native js'ers can user man,
this ts shit is not cool.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.