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

coffee-sweetener

v0.0.3

Published

Small utility component that you can use in your applications to ease the management of dependencies between objects. The idea is simple, you have a factory object (we'll call this the *injector*) where you define some mappings. Each mapping has a unique id that you define. From different modules you can query the *injector* to give you a new instance of a specific mapping. Within classes you can define depenecies which will be satisfied on creation of a new instance of that class.

Downloads

14

Readme

Dependency Injection in CoffeeScript

Table of Contents

coffee-sweetener

This is a small utility component that you can use in your applications to ease the management of dependencies between objects. The idea is simple, you have a factory object (we'll call this the injector) where you define some mappings. Each mapping has a unique id that you define. From different modules you can query the injector to give you a new instance of a specific mapping. Within classes you can define depenecies which will be satisfied on creation of a new instance of that class.

Installation

You can install the latest version through npm: npm install coffee-sweetener

API

Let's start with an example

# define a class
class MyClass
    sayYeah: ->
        console.log "YEAH!"
# get the Injector
CoffeeSweetener = require "coffee-sweetener"
Injector = new CoffeeSweetener()

# map MyClass in the Injector
Injector.map
    klass: MyClass
# ask the Injector to give you a new instance of MyClass
instance = Injector.getInstanceOf "MyClass"
# use the instance
instance.sayYeah() # this print "YEAH!" to the console

Create an Injector

CoffeeSweetener = require "coffee-sweetener"
Injector = new CoffeeSweetener()

Every Injector will automatically create a mapping to itself as a Singleton called "Injector". This is useful if you want to get hold of the injector from within a class, by just specifying it in the list of the injection points.

CoffeeSweetener = require "coffee-sweetener"
Injector = new CoffeeSweetener()

class MyClass
    inject:
        injector: "Injector"

Every new instance of MyClass ( created through Injector.getInstanceOf) will have a property called injector which holds the reference to the Injector that created the class.

.map( mappingObject )

Map a module knowing the path

Just map the module by specifing the path. Be aware that this works only for modules which exports one class.

Injector.map
    modulePath: 'src/yourModule'

where yourModule is:

class YourModule

module.exports = YourModule

Here the name of the mapping will be inferred from the name of the class exported in the module.

Map a Class

class MyClass
    
Injector.map
    klass: MyClass

Here the name of the mapping will be automatically set to the name of the class.

Map a Value

user = "vizio"
Injector.map
    value: user
    name: "user"

A value can be anything, it can also be a function. When mapping a value you should always provide a name for the mapping.

.asSingleton()

Map a Class as a Singleton

class MyClass
    
Injector.map
    klass: MyClass
.asSingleton()

Everytime you then ask the injector for an instance of the class, you'll get back always the same instance.

.as( newName )

Specifing a name for a mapping

This applies for all mapping types.

By passing the name to the mapping:

class MyClass
    
Injector.map
    klass: MyClass
    name: "NewName"

By calling the as() method:

class MyClass
    
Injector.map
    klass: MyClass
.as "NewName"

.getInstanceOf( mappingName )

Once you've created your mappings you can ask the Injector for them:

class MyClass
    
Injector.map
    klass: MyClass

myInstance = Injector.getInstanceOf "MyClass"

For values the injector will always return that same value, it will not return a copy or a new instance of the value.

.getClassOf( mappingName )

For mapped classes you can ask the Injector to get you the class definition object:

class MyClass
    
Injector.map
    klass: MyClass
# getting MyClass definition object
myClass = Injector.getClassOf "MyClass"
# manually creating a new instance of MyClass
myInstance = new myClass

.unmap( mappingName )

Unmaps a mapping.

class MyClass

Injector.map
    klass: MyClass

Injector.unmap "MyClass"
Injector.getInstanceOf "MyClass" # this will throw an exception!

.destroy()

Destroys all the mappings.

Fluent API

You can chain the calls to the different APIs when creating a mapping.

# mapping a class as a Singleton and specifying a new name for the mapping
Injector.map
    modulePath: "yourModulePath"
.asSingleton().as("MySingleton")

Class Injection Points

It is possible, from within a class, to specify a list of dependencies which the Injector will try to satisfy when creating new instances of the class.

# assuming Wheels and Engine have already been mapped in the Injector
class Car
    inject:
        wheels: "Wheels"
        engine: "Engine"
        
Injector.map
    klass: Car

myCar = Injector.getInstanceOf "Car"
console.log myCar.wheels # will print out an instance of the Wheels class
console.log myCar.engine # will print out an instance of the Engine class

This means that there is no need to require Wheels and Engine in the module file where Car is defined.

Instance initialisation

Everytime the Injector creates new instances, it will call the initInstance on the new instance if that method is defined. This is the place you want to put all your initialisation logic, because you can be sure that at that point all the dependencies have been resolved.

References

The API is inspired by SwiftSuspenders which I used while developing Flashy things.