Code Monkey home page Code Monkey logo

observable-slim's People

Contributors

backdoortech avatar cdbishop avatar dashersw avatar elliotnb avatar jansivans avatar reda-alaoui avatar rezyan avatar tannerntannern 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  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  avatar  avatar  avatar  avatar  avatar

observable-slim's Issues

How to check if an object is Proxy or not?

I am creating proxy like this:

const proxy = ObservableSlim.create(model, null, (changes) => {
});

Problem:
How can i check the if the proxy variable is ObservableSlim proxy or some type of indication so i will know that we have already created proxy on an Object?

currentPath is not updated when element position in array changes

When an element’s position in the array changes, this change is not reflected in the currentPath and jsonPointer properties of the change object:

Repro

const ObservableSlim = require('observable-slim');
const proxy = ObservableSlim.create([{}, {}]);

ObservableSlim.observe(proxy, changes => changes
  .forEach(change => console.log(change.currentPath, change.type)));

proxy.splice(0, 1);
proxy[0].foo = 'bar';

Before: [{}, {}]
After: [{foo: 'bar'}]

Result

0 update
1 delete
length update
1.foo add

However, it should read 0.foo add, as the object now is the first item of the array.

Consider JSON Pointer

Love the Library But I wonder if the path can be expressed with JSON Pointer rfc6901?

const data = {
  name: "Max",
  age: 27,
  tags: ["a", "b", "c"],
  friends: [
    {
      name: "Adam",
      age: 27,
      tags: ["a", "b", "c"]
    },
    {
      name: "Joe",
      age: 30,
      tags: ["a", "b", "c"]
    }
  ]
}

If I do

p.friends[0].tags.push('j')

The changes looks like:

[
  {
    "type": "add",
    "target": [
      "a",
      "b",
      "c",
      "j"
    ],
    "property": "3",
    "newValue": "j",
    "currentPath": "friends.0.tags",
    "proxy": [
      "a",
      "b",
      "c",
      "j"
    ]
  }
]

Would it be possible that the path could be a json pointer?

Not exact `currentPath` at array pushing

Hi,
your lib is great. I'm trying to use it in my project, but I have a problem. According to changes I want to reproduce the object and I use the currentPath and newValue fields. When I push an item to an array, the currentPath not too exact.

Example

let data = {};

let reproduced = {};

var p = ObservableSlim.create(data, true, function(changes) {
	console.log(JSON.stringify(changes));
	changes.forEach(change => {
	  _.set(reproduced, change.currentPath, change.newValue);
	});
});

p.user = {
	roles: ["admin"]
};

p.user.roles.push("member");


setTimeout(function() {
	console.log("REPRODUCED OBJECT:", JSON.stringify(reproduced));
}, 2000);

Output

[{"type":"add","target":{"user":{"roles":["admin","member"]}},"property":"user","newValue":{"roles":["admin","member"]},"currentPath":"user","proxy":{"user":{"roles":["admin","member"]}}}]
[{"type":"add","target":["admin","member"],"property":"1","newValue":"member","currentPath":"user.roles","proxy":["admin","member"]}]
REPRODUCED OBJECT: {"user":{"roles":"member"}}

So when I use the roles.push the currentPath doesn't contain the index, just the property. But when I update object, the currentPath contains the property field too. I think the correct currentPath should be user.roles.1. What do you think?

Reproduce jsFiddle: https://jsfiddle.net/icebob/rtvcn685/

Thanks,
Icebob

Observe changes on a nested object set after initialization across multiple observables

We already have a test (see test 24 in test\test.js) and a solution for this issue, but the test is skipped and the solution is commented out because the solution causes IE11 performance to suffer greatly when processing very large objects.

Need to investigate whether it is possible to resolve this issue without comprising IE11 performance. We could also implement the existing solution as-is and live with the fact that IE11 will be slow for very large objects.

Deep observe

This advice on hardcoded nested observers will not work for my use case:
https://github.com/ElliotNB/observable-slim#nested-objects

The schema of the observed object is not known at compile-time.

Need a solution to automatically observe all changes to all properties of deep object whose schema is unknown.

Can this lib do it? Can you please provide sample?

Remove added observer

Good day! Thanks for awesome work. Trying to use it as state manager. I have a global proxy object - state and local states that observe global proxy object and render they logic.

//Global state
const state = ObservableSlim.create(STATE, true);

//Local observer
ObservableSlim.observe(state, function(changes) {
	renderComponent(changes)
});

//Remove all observers but i want to stop only local observer
ObservableSlim.remove(state)

I would like to have a option to remove only specific observer. Its not possible right?

Clear all Observables?

As my title. I know your lib store all Proxies into an array.
How to clear all of them?

Add helpful hint in the README about avoiding infinite recursion

With regular Proxy objects you can trigger an infinite loop by modifying an object that was just modified within the set handler:

let validator = {
  set: function(obj, prop, value) {
    if (prop === 'age') {
      if (!Number.isInteger(value)) {
        throw new TypeError('The age is not an integer');
      }
      if (value > 200) {
        throw new RangeError('The age seems invalid');
      }
    }
	console.log('new set');
	person.age = 10;
    // The default behavior to store the value
    obj[prop] = value;

    // Indicate success
    return true;
  }
};

let person = new Proxy({}, validator);
person.age = 15;

A developer is unlikely to make this kind of with a regular Proxy because they are small in scope and easy to understand. However, because Observable-Slim handles this for the user, it can become less clear what's going on if they set a proxy value for the same property within a handler function. If it's not possible to add a more helpful JS error without sacrificing performance, then we should at least include a helpful hint in the README.

Re-execute changes

Hi!

Great lib, I wonder if there is a way to re-execute a change, for example:
[{"type":"add","target":{"hello":"WORLD","testing":{"blah":42},"arr":[]},"property":"arr","newValue":[],"currentPath":"arr","jsonPointer":"/arr","proxy":{"hello":"WORLD","testing":{"blah":42},"arr":[]}}]

Would come as an object and the action would be executed, this could come from anywhere.

Splice method not detecting addition/deletion in changes.

I have this model:

todos: [
          {
            id: "a81823a9-2afa-4427-963f-01693809fe0e", 
            name: "Task1",
            done: true
          },
          {
            id: "1daa7f75-9de9-4925-a94e-0169380a6efa",
            name: "Task2",
            done: false
          }
        ]

Here i am creating ObservableSlim like this:

   const proxy = ObservableSlim.create(model['todos'],  null, function(changes: any) { });
   proxy.splice(0, 1, { { id: "a81823a9-2afa-4427-963f-01693809fe0e",  name: "Task3", done: true }, });

Changes I get:
// change is something like this. But is there any way we can get the deleted and added item?

   [ { type: 'update',
 target: [ [Object], [Object], __length: 2 ],
 property: '0',
 newValue: { name: 'Task3', done: false },
 previousValue: 
  { id: 'a81823a9-2afa-4427-963f-01693809fe0e',
    name: 'Task1',
    done: true },
 currentPath: '0',
 jsonPointer: '/0',
 proxy: [ [Object], [Object], __length: 2 ] } ]

Question:
How will I know which item is deleted and added? The change is of type 'update' only.

What I need:
It should return the deletions/additions when use splice method.

Calling methods on proxied Buffer crashes with error "TypeError: argument must be a buffer"

If you use an object that contains a buffer (for example _id coming from MongoDB), calling methods like toString crash with the error "TypeError: argument must be a buffer".

Here is a test that verifies this:

it("Proxied Buffer.toString outputs the pristine Buffer.toString", async (assert) => {
    const model = { id: Buffer.from("5fea9621e6efdf282752f5ba") };
    const proxy = ObservableSlim.create(model);

    expect(proxy.id.toString()).to.equal(model.id.toString())
});

Getter event

Hey,

First of all, i love how i can get info about add/update on object properties, but.... Is it possible to somehow get notified when an object property is used? Like simple:

console.log(obj.some_prop);

ObservableSlim callback would be called with "read" type, or something like that? Even ugly and hacky way is good enough for my use case.

I had that working with native Proxy but Your lib makes it so much easier to handle all the other cases.

Big arrays: Performance issue in proxy handler get method

Sometimes, when I proxy an array of several multi attribute objects, ObservableSlim proxy cache ends up filled with more than 38000 proxies.
The proxy cache lookup causes performance issues on properties access (get method of the proxy handler).

Could the proxy cache be splitted by scope usages to accelerate the lookup?

Orphan clean-up breaks down when arrays of objects are sorted

Our process for cleaning up orphaned target objects (i.e., objects that are no longer observed underneath an observable -- via deletion or replacement) breaks down when arrays of objects are sorted (e.g., arr.sort()). The clean-up process will need to be essentially re-written.

Vue error when domDelay is set to true, when modifying array.

When using ObservableSlim on a Vue.js data model, I'm running into a vue error when domDelay is enabled & you don't make changes right away.

See this gist for a series of tests: https://gist.github.com/BinarySpike/aa4f82fd024265b72fcde1327c7b0f09

Ultimately I got it working (test7), but it seems ObservableSlim is doing something that Vue doesn't like (test5), even when I've called pauseChanges and don't mutate the object myself (test6).

Below are the three issues I ran into.

  1. ObservableSlim does not respect Vue's reactivity.

pauseChanges and then use Vue.set in the observable (this is the recommended vue way)

  1. Changing a variable to a complex type and then trying to resolve prototypes on it such as Array and Array.push will fail in the same operation/batch

Disabling domDelay fixes this

  1. Some time after the an ObservableSlim is created on a VueJS model, using Array.push will generate a vue error.

Disabling domDelay fixes this, but it's not intuitive why.

My troubleshooting and intuition leads me to believe Vue is queuing/batching changes like ObservableSlim. Directly after creating the ObservableSlim, if you make changes, they are performed before Vue "wires-up." However, once Vue completes it's initial operations something is funky. It has something to do with the way ObservableSlim resolves/calls Array.push because direct access (test8) works fine.

I think test7 will work for my immediate needs, but I would like to know if there are solutions to problems 2 and 3.

Report a single high-level mutation when adding/removing non-last array elements

Adding/removing non-last array elements leads to a chain of update changes, before the actual delete/add change is reported on the last array element. I can understand this behaviour from the proxy’s perspective (and I know that you try to be close to the Proxy behaviour), however as a developer I’d prefer to get the high-level perspective of which array element was actually affected.

Library version tested against: 0.0.8

Repro:

const ObservableSlim = require('observable-slim');
const proxy = ObservableSlim.create([0, 1, 2, 3]);

ObservableSlim.observe(proxy, changes => changes
  .forEach(change => console.log(change.currentPath, change.type)));

console.log(proxy);

proxy.splice(0, 1); // delete “0” from index 0
console.log(proxy);

proxy.splice(0, 0, 0); // add “0” at index 0
console.log(proxy);

Result:

[ 0, 1, 2, 3 ]
0 update
1 update
2 update
3 delete
length update
[ 1, 2, 3 ]
3 add
2 update
1 update
0 update
[ 0, 1, 2, 3 ]

Expected:
The library should either report the actual affected index for delete/add changes on arrays or introduce a new (additional) change type addElement/deleteElement that reports the actual index. Interestingly, there seems to be no change fired on the length property when you add items to an array (I tried it with both splice and push).

Events...

there is a way to detect before update or delete? like an event?

Splice method always return last index of array instead of deleted index.

I have this array:

todos: [
          {
            id: "a81823a9-2afa-4427-963f-01693809fe0e", //  Should be called uniqueId
            name: "Task1",
            done: true
          },
          {
            id: "1daa7f75-9de9-4925-a94e-0169380a6efa",
            name: "Task2",
            done: false
          }
        ]

proxy.splice(0, 1);

Changes I got:

 [ { type: 'update',
    target: [ [Object], [Object], __length: 2 ],
    property: '0',
    newValue: 
     { id: '1daa7f75-9de9-4925-a94e-0169380a6efa',
       name: 'Task2',
       done: false },
    previousValue: 
     { id: 'a81823a9-2afa-4427-963f-01693809fe0e',
       name: 'Task1',
       done: true },
    currentPath: '0',
    jsonPointer: '/0',
    proxy: [ [Object], [Object], __length: 2 ] } ] 
 [ { type: 'delete',
    target: [ [Object], , __length: 2 ],
    property: '1',
    newValue: null,
    previousValue: 
     { id: '1daa7f75-9de9-4925-a94e-0169380a6efa',
       name: 'Task2',
       done: false },
    currentPath: '1',
    jsonPointer: '/1',
    proxy: [ [Object], , __length: 2 ] } ] 
 [ { type: 'update',
    target: [ [Object], __length: 1 ],
    property: 'length',
    newValue: 1,
    previousValue: 2,
    currentPath: 'length',
    jsonPointer: '/length',
    proxy: [ [Object], __length: 1 ] } ]

In the change where change type is 'delete', It should return 0 index but it is always returning last index of array.

Conditional recursive watch

Hello and thank you for your work! Is there a way that can watch all properties of an object, recursively, only if a property passes some test.

For instance, say I only want to watch for changes with "public properties", or properties that don't begin with _. I have the following object:

const o = {
    _idcAboutPrivateState: { foo: 0 },
    userModifiableProperty: { bar: 0 }
};

In this case, only o.userModifiableProperty and o.userModifiableProperty.bar should be watched.

Arrays in original target are mutated by library

When you have this code

const item = { numbers: [1, 2] }
ObservableSlim.create(item)

calling Object.keys(item.numbers) yields ['0', '1', '__length'] instead of just ['0', '1'].

This is due to the following change: c69aafd#diff-a882dd68fa93398bef8261d2308d9600efd956dbe6ba6ef1f0fe368aa107225dR64

Expected: Original object should not be mutated.

Of course Object.keys() is not really useful on arrays, but it causes a strange error in jest saying serializes to the same string.

In Typescript, create function returns wrong type

In your type definitions, the ObservableSlim.create() function returns a type ProxyConstructor. I think this is incorrect. ProxyConstructor is just a type defined explicitly for the object Proxy, and all it can do is be constructed, i.e. new Proxy(...).

If I run:

let x = {} as MyState
let state = ObservableSlim.create(x, true, changes => {
    console.log('State changed', changes);
});
x.y = 3;

I would expect state to be of type MyState, or possibly object, but definitely not ProxyConsructor. I get an error on the last line, even if the type MyState has a property x. If you construct a Proxy, it will be of the same type as the first argument, so I think create should world the same way.

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.