Skip to content
This repository has been archived by the owner on Oct 20, 2022. It is now read-only.

Latest commit

History

History
127 lines (110 loc) 路 3.91 KB

managers.md

File metadata and controls

127 lines (110 loc) 路 3.91 KB

Managers

Why use managers?

Let's start with an example of the problem that managers seek to solve. For simplicity, I'm going to use ESModules syntax.

// a.js
import gardens from 'gardens'
const garden = gardens.createScope( 'project', {
  scopeStyle: {
    color: '#43c872',
    fontDecoration: 'underline'
  }
}).createScope( 'a' )

// b.js
import gardens from 'gardens'
const garden = gardens.createScope( 'project', {
  scopeStyle: {
    color: '#43c872',
    fontDecoration: 'underline'
  }
}).createScope( 'a' )

// c/index.js
import gardens from 'gardens'
const garden = gardens.createScope( 'project', {
  scopeStyle: {
    color: '#43c872',
    fontDecoration: 'underline'
  }
}).createScope( 'c', {
  scopeStyle: {
    color: '#35c4b7',
    fontDecoration: 'underline'
  }
})

// c/d.js
import gardens from 'gardens'
const garden = gardens.createScope( 'project', {
  scopeStyle: {
    color: '#43c872',
    fontDecoration: 'underline'
  }
}).createScope( 'c', {
  scopeStyle: {
    color: '#35c4b7',
    fontDecoration: 'underline'
  }
}).createScope( 'd' )

By default, gardens takes a vary safe approach to scope naming, and assumes that each call to createScope is supposed to actually create a scope. No caching, no scope sharing, just freshly instantiated gardens. In the above code we create multiple nested scopes in order to organize our code. The problem is that we have now created four separate scopes named project and two nested scopes named c on two separate parents. If we want to apply a custom color, output stream, or change any other configuration options, we would have to do that four times to every single one of the 'project' scopes. The lines above already feel long and laborious for what they do, and are inefficient to maintain. If we needed to change the output stream of style we would need to change it several times, or do various trickery to pass the options or the gardens themselves between files. If you use a build system like Babel or Rollup then things get complicated even further.

So, let's look at how we could fix the problem by using a manager.

// scopes.js
import gardens from 'gardens'
const manager = gardens.createManager( 'project', {
  scopeStyle: {
    color: '#43c872',
    fontDecoration: 'underline'
  }
})

manager.scope( 'c' ).options({
  scopeStyle: {
    color: '#35c4b7',
    fontDecoration: 'underline'
  }
})

export default manager

// a.js
import manager from './scopes'
const garden = manager.scope( 'a' )

// b.js
import manager from './scopes'
const garden = manager.scope( 'b' )

// c/index.js
import manager from './scopes'
const garden = manager.scope( 'c' )

// c/d.js
import manager from './scopes'
const garden = manager.scope( 'c', 'd' )

In the above example all of the scopes that you would expect to be the same now match correctly and are shared across files. Any configurations applied in one place will also apply to the same scope in other places. All you need to do is add a file that creates a manager and exposes it for others to use. This avoids any circular dependency work arounds and makes scoping much more concise, readable, and maintainable. You can also set all of your scope options in one consistent place, rather than multiple different files. If you need to set up a complicated custom stream for your output then you do it all in one place.

It's important to note that only scopes created by manager.scope will be managed. Calling createScope from a garden that was created by a manager will result in an unmanaged scope.

Usage

That's it! Managers are a pretty simple feature. They just have a single method that takes a list of names.

const m = gardens.createManager( 'project', options ) // Same options as any other garden
const garden = m.scope() // Returns the root 'project' scope
const gardena = m.scope( 'a' ) // Returns the nested scope 'a'
const gardenabcd = m.scope( 'a', 'b', 'c', 'd' ) // I think you get the idea