canjs / can-connect

Model layer utilities for every JavaScript framework! Assemble real-time, high performance, restful data connections.
https://canjs.com/doc/can-connect.html
MIT License
29 stars 16 forks source link

remove cycle of dependencies with `can-fixture` #412

Closed justinbmeyer closed 6 years ago

justinbmeyer commented 6 years ago

can-connect depends on can-fixture which depends on can-connect. This makes upgrading hard. I'd like to fix this for the next major release. The shared dependency is data/memory-cache.

There are a few options on how to separate memory-cache:

Pull out memory cache as a behavior/mixin

memory-cache is a behavior/mixin defined like:

connect.behavior("data/memory-cache",function(){
  return {
    getListData(){
       this.algebra 
       this.id
    }
  }
});

This means, it expects to have access to other properties and methods up its prototype chain.

If we wanted to keep this the same we would probably make a can-mixin package that would do the same thing as connect.behavior. Then can-memory-cache would be one of these mixins:

var mixin = require("can-mixin");

module.exports = mixin("data/memory-cache",function(){
  return {
    getListData(){
       this.algebra
    }
  }
});

This means to use can-memory-cache, you need to call the mixin like:

var memoryCache = require("can-memory-cache");

var cache = memoryCache({
  algebra: new Algebra()
})

Make the mixin itself

module.exports = function dataMemoryCache(baseObject){
  var obj = Object.create(baseObject);
  Object.assign(obj, {
    getListData(){
       this.algebra
    }
  })
});

Pull out memory-cache as its own thing

Instead of creating memory-cache as a mixin, it could be just a function that must be passed everything it needs:

module.exports = function(options){
  return {
    getListData(){
       options.algebra
    }
  }
});

For this to be used in can-connect, it would effectively need to do something like:

var memoryCache = require("can-memory-cache");

module.exports = mixin("data/memory-cache",function(){

  var THIS;

  var optionsProxyToConnection = new Proxy({},{ 
    get(target, prop, receiver){
      return THIS[prop];
    } , set });

  var underlyingBehavior = memoryCache( optionsProxyToConnection );

  var behaviorProxy = new Proxy({}, { 
    get(target, prop, receiver){
       THIS = receiver;
       return target[prop]
    }, set });

  return behaviorProxy;

});

This basically traps the this of a getListData call, and makes sure that all reads on options read from that this.

bmomberger-bitovi commented 6 years ago

I made a pre-release between can-fixture versions 1.1.1 and 1.1.2 which had a standalone memory connection. It didn't get merged into the mainline versions, but it can be used as a reference point for future work: https://github.com/canjs/can-fixture/blob/v1.1.2-pre.1/memoryConnectionStandalone.js

bmomberger-bitovi commented 6 years ago

Of particular note is the set of utility functions that appear at the top of the file linked above. Those are from can-connect and would also need to be pulled out into a utility library.

justinbmeyer commented 6 years ago

made can-memory-store which is used by can-fixture directly