├── chrome-extension
├── visualize
├── icon.png
├── background.html
├── devtools_background.html
├── devtools_background.js
├── manifest.json
├── background.js
├── panel.js
└── panel.html
├── .gitignore
├── example
├── kitchen
│ ├── electricity.js
│ ├── fridge.js
│ ├── skillet.js
│ ├── grinder.js
│ ├── pump.js
│ ├── heater.js
│ ├── dishwasher.js
│ ├── stove.js
│ ├── coffee_maker.js
│ ├── index.html
│ ├── kitchen.js
│ └── main.js
├── kitchen-di
│ ├── electricity.js
│ ├── skillet.js
│ ├── mock_heater.js
│ ├── fridge.js
│ ├── main.js
│ ├── coffee_maker
│ │ ├── grinder.js
│ │ ├── pump.js
│ │ ├── heater.js
│ │ └── coffee_maker.js
│ ├── dishwasher.js
│ ├── stove.js
│ ├── index.html
│ └── kitchen.js
├── coffee
│ ├── heater.js
│ ├── mock_heater.js
│ ├── coffee_module.js
│ ├── pump.js
│ ├── electric_heater.js
│ └── coffee_maker.js
├── node
│ ├── engine.js
│ ├── test
│ │ ├── mock_engine.js
│ │ └── main.spec.js
│ ├── main.js
│ └── car.js
└── testing
│ ├── mocks.js
│ └── coffee.spec.js
├── visualize
├── injectors
│ ├── kitchen.png
│ ├── Untitled.png
│ ├── coffee_maker.json
│ ├── data.json
│ ├── index.html
│ ├── kitchen.json
│ ├── playground.html
│ ├── style.css
│ ├── kitchen.svg
│ └── app.js
└── dag
│ ├── data.json
│ ├── index.html
│ ├── style.css
│ └── dag.js
├── .npmignore
├── test
├── fixtures
│ ├── shiny_house.js
│ ├── house.js
│ └── car.js
├── coffee.spec.js
├── matchers.js
├── async.spec.js
├── annotations.spec.js
└── injector.spec.js
├── src
├── index.js
├── util.js
├── profiler.js
├── testing.js
├── annotations.js
├── providers.js
└── injector.js
├── index.html
├── node
└── index.js
├── .travis.yml
├── LICENSE
├── docs
├── terminology.md
├── how-can-i-use-it.md
├── interfaces.md
└── di_sl.md
├── karma.conf.js
├── test-main.js
├── dist
├── amd
│ ├── index.js
│ ├── util.js
│ ├── profiler.js
│ ├── testing.js
│ ├── providers.js
│ ├── annotations.js
│ └── injector.js
└── cjs
│ ├── util.js
│ ├── index.js
│ ├── profiler.js
│ ├── testing.js
│ ├── providers.js
│ ├── annotations.js
│ └── injector.js
├── package.json
├── README.md
└── gulpfile.js
/chrome-extension/visualize:
--------------------------------------------------------------------------------
1 | ../visualize
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | node_modules
2 | compiled
3 | sauce_connect.log
4 |
--------------------------------------------------------------------------------
/example/kitchen/electricity.js:
--------------------------------------------------------------------------------
1 |
2 | export class Electricity {}
3 |
--------------------------------------------------------------------------------
/example/kitchen-di/electricity.js:
--------------------------------------------------------------------------------
1 |
2 | export class Electricity {}
3 |
--------------------------------------------------------------------------------
/example/coffee/heater.js:
--------------------------------------------------------------------------------
1 | // This is an interface.
2 | export class Heater {}
3 |
--------------------------------------------------------------------------------
/chrome-extension/icon.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/RackHD/di.js/master/chrome-extension/icon.png
--------------------------------------------------------------------------------
/visualize/injectors/kitchen.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/RackHD/di.js/master/visualize/injectors/kitchen.png
--------------------------------------------------------------------------------
/visualize/injectors/Untitled.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/RackHD/di.js/master/visualize/injectors/Untitled.png
--------------------------------------------------------------------------------
/chrome-extension/background.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/chrome-extension/devtools_background.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/chrome-extension/devtools_background.js:
--------------------------------------------------------------------------------
1 | // Create DI panel.
2 | chrome.devtools.panels.create(
3 | 'DI',
4 | 'icon.png',
5 | 'panel.html'
6 | );
7 |
--------------------------------------------------------------------------------
/example/coffee/mock_heater.js:
--------------------------------------------------------------------------------
1 | import {Provide} from 'di';
2 |
3 | import {Heater} from './heater';
4 |
5 | @Provide(Heater)
6 | export class MockHeater {
7 | on() {}
8 | off() {}
9 | }
10 |
--------------------------------------------------------------------------------
/.npmignore:
--------------------------------------------------------------------------------
1 | test/
2 | visualize/
3 | *.sublime-project
4 | *.sublime-workspace
5 | gulpfile.js
6 | karma.conf.js
7 | /index.html
8 | test-main.js
9 | .*
10 | *.orig
11 | Gruntfile.*
12 | compiled/
13 |
--------------------------------------------------------------------------------
/example/kitchen/fridge.js:
--------------------------------------------------------------------------------
1 |
2 | export class Fridge {
3 | constructor(electricity) {
4 | this.electricity = electricity;
5 | }
6 |
7 | getEggs() {
8 | return '3 eggs';
9 | }
10 | }
11 |
--------------------------------------------------------------------------------
/example/kitchen/skillet.js:
--------------------------------------------------------------------------------
1 |
2 | export class Skillet {
3 | add(item) {
4 | console.log('Adding ' + item + ' to the skillet.');
5 | }
6 |
7 | toString() {
8 | return 'skillet';
9 | }
10 | }
11 |
--------------------------------------------------------------------------------
/example/coffee/coffee_module.js:
--------------------------------------------------------------------------------
1 | import {CoffeeMaker} from './coffee_maker';
2 | import {ElectricHeater} from './electric_heater';
3 | import {Pump} from './pump';
4 |
5 | export var module = [CoffeeMaker, ElectricHeater, Pump];
6 |
--------------------------------------------------------------------------------
/example/kitchen/grinder.js:
--------------------------------------------------------------------------------
1 |
2 | export class Grinder {
3 | constructor(electricity) {
4 | this.electricity = electricity;
5 | }
6 |
7 | grind() {
8 | console.log('Grinding coffee beans...');
9 | }
10 | }
11 |
--------------------------------------------------------------------------------
/example/kitchen-di/skillet.js:
--------------------------------------------------------------------------------
1 |
2 | export class Skillet {
3 | constructor() {}
4 |
5 | add(item) {
6 | console.log('Adding ' + item + ' to the skillet.');
7 | }
8 |
9 | toString() {
10 | return 'skillet';
11 | }
12 | }
13 |
--------------------------------------------------------------------------------
/example/kitchen/pump.js:
--------------------------------------------------------------------------------
1 |
2 | export class Pump {
3 | constructor(heater, electricity) {
4 | this.heater = heater;
5 | this.electricity = electricity;
6 | }
7 |
8 | pump() {
9 | console.log('Pumping the water...');
10 | }
11 | }
12 |
--------------------------------------------------------------------------------
/visualize/dag/data.json:
--------------------------------------------------------------------------------
1 | [
2 | {
3 | "source": "CoffeeMaker",
4 | "target": "Heater"
5 | },
6 | {
7 | "source": "CoffeeMaker",
8 | "target": "Pump"
9 | },
10 | {
11 | "source": "Pump",
12 | "target": "Heater"
13 | }
14 | ]
15 |
--------------------------------------------------------------------------------
/example/node/engine.js:
--------------------------------------------------------------------------------
1 | var Engine = function() {
2 | this.state = 'stopped';
3 | };
4 |
5 | Engine.prototype = {
6 | start: function() {
7 | console.log('Starting engine...');
8 | this.state = 'running';
9 | }
10 | };
11 |
12 | module.exports = Engine;
13 |
--------------------------------------------------------------------------------
/test/fixtures/shiny_house.js:
--------------------------------------------------------------------------------
1 | import {Inject, Provide} from '../../src/annotations';
2 |
3 | @Provide('House')
4 | @Inject('Kitchen')
5 | export class ShinyHouse {
6 | constructor(kitchen) {}
7 |
8 | nothing() {}
9 | }
10 |
11 | export var module = [ShinyHouse];
12 |
--------------------------------------------------------------------------------
/visualize/dag/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
12 |
--------------------------------------------------------------------------------
/example/node/test/mock_engine.js:
--------------------------------------------------------------------------------
1 | var di = require('di');
2 | var Engine = require('../engine');
3 |
4 | var MockEngine = function() {};
5 | MockEngine.prototype = {
6 | state: 'running'
7 | };
8 |
9 | di.annotate(MockEngine, new di.Provide(Engine));
10 |
11 | module.exports = MockEngine;
12 |
--------------------------------------------------------------------------------
/example/kitchen-di/mock_heater.js:
--------------------------------------------------------------------------------
1 | import {Provide} from 'di';
2 | import {Heater} from './coffee_maker/heater';
3 |
4 | @Provide(Heater)
5 | export class MockHeater {
6 | constructor() {}
7 |
8 | on() {
9 | console.log('Turning on the MOCK heater...');
10 | }
11 |
12 | off() {}
13 | }
14 |
--------------------------------------------------------------------------------
/example/kitchen-di/fridge.js:
--------------------------------------------------------------------------------
1 | import {Inject} from 'di';
2 | import {Electricity} from './electricity';
3 |
4 | @Inject(Electricity)
5 | export class Fridge {
6 | constructor(electricity) {
7 | this.electricity = electricity;
8 | }
9 |
10 | getEggs() {
11 | return '3 eggs';
12 | }
13 | }
14 |
--------------------------------------------------------------------------------
/example/coffee/pump.js:
--------------------------------------------------------------------------------
1 | import {Inject} from 'di';
2 |
3 | import {Heater} from './heater';
4 |
5 | @Inject(Heater)
6 | export class Pump {
7 | constructor(heater) {
8 | this.heater = heater;
9 | }
10 |
11 | pump() {
12 | this.heater.on();
13 | // console.log('Pumping...');
14 | }
15 | }
16 |
--------------------------------------------------------------------------------
/example/kitchen/heater.js:
--------------------------------------------------------------------------------
1 |
2 | export class Heater {
3 | constructor(electricity) {
4 | this.electricity = electricity;
5 | }
6 |
7 | on() {
8 | console.log('Turning on the coffee heater...');
9 | }
10 |
11 | off() {
12 | console.log('Turning off the coffee heater...');
13 | }
14 | }
15 |
--------------------------------------------------------------------------------
/src/index.js:
--------------------------------------------------------------------------------
1 | // PUBLIC API
2 |
3 | export {Injector} from './injector';
4 | export {
5 | annotate,
6 | Inject,
7 | InjectLazy,
8 | InjectPromise,
9 | Provide,
10 | ProvidePromise,
11 | SuperConstructor,
12 | TransientScope,
13 | ClassProvider,
14 | FactoryProvider
15 | } from './annotations';
16 |
--------------------------------------------------------------------------------
/example/kitchen/dishwasher.js:
--------------------------------------------------------------------------------
1 |
2 | export class Dishwasher {
3 | constructor(electricity) {
4 | this.electricity = electricity;
5 | }
6 |
7 | add(item) {
8 | console.log('Putting ' + item + ' into the dishwasher...');
9 | }
10 | wash() {
11 | console.log('Running the dishwasher...');
12 | }
13 | }
14 |
--------------------------------------------------------------------------------
/chrome-extension/manifest.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "DI visualizer",
3 | "version": "0.0.1",
4 | "description": "",
5 | "background": {
6 | "page": "background.html"
7 | },
8 | "devtools_page": "devtools_background.html",
9 | "manifest_version": 2,
10 | "permissions": [
11 | "tabs",
12 | ""
13 | ]
14 | }
15 |
--------------------------------------------------------------------------------
/example/kitchen-di/main.js:
--------------------------------------------------------------------------------
1 | import {Injector} from 'di';
2 | import {Kitchen} from './kitchen';
3 | import {MockHeater} from './mock_heater';
4 |
5 |
6 | function main() {
7 | var injector = new Injector([MockHeater]);
8 | var kitchen = injector.get(Kitchen);
9 |
10 | kitchen.makeBreakfast();
11 | }
12 |
13 | main();
14 |
15 |
16 |
--------------------------------------------------------------------------------
/example/kitchen-di/coffee_maker/grinder.js:
--------------------------------------------------------------------------------
1 | import {Inject} from 'di';
2 | import {Electricity} from '../electricity';
3 |
4 | @Inject(Electricity)
5 | export class Grinder {
6 | constructor(electricity) {
7 | this.electricity = electricity;
8 | }
9 |
10 | grind() {
11 | console.log('Grinding coffee beans...');
12 | }
13 | }
14 |
--------------------------------------------------------------------------------
/example/coffee/electric_heater.js:
--------------------------------------------------------------------------------
1 | import {Provide} from 'di';
2 |
3 | import {Heater} from './heater';
4 |
5 | @Provide(Heater)
6 | export class ElectricHeater {
7 | constructor() {}
8 |
9 | on() {
10 | // console.log('Turning on electric heater...');
11 | }
12 |
13 | off() {
14 | // console.log('Turning off electric heater...');
15 | }
16 | }
17 |
--------------------------------------------------------------------------------
/example/node/main.js:
--------------------------------------------------------------------------------
1 | var di = require('di');
2 | var Car = require('./car');
3 |
4 |
5 | var injector = new di.Injector([]);
6 |
7 | console.log('Getting in the car...');
8 | var car = injector.get(Car);
9 |
10 | car.run();
11 |
12 | if (car.isRunning()) {
13 | console.log('The car is running');
14 | } else {
15 | console.log('The car is stopped');
16 | }
17 |
--------------------------------------------------------------------------------
/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 | DI v2
4 |
5 |
6 |
11 |
12 |
13 |
14 |
--------------------------------------------------------------------------------
/example/kitchen/stove.js:
--------------------------------------------------------------------------------
1 |
2 | export class Stove {
3 | constructor(electricity) {
4 | this.electricity = electricity;
5 | }
6 |
7 | add(item) {
8 | console.log('Adding ' + item + ' onto the stove.');
9 | }
10 |
11 | on() {
12 | console.log('Turning on the stove...');
13 | }
14 |
15 | off() {
16 | console.log('Turning off the stove...');
17 | }
18 | }
19 |
--------------------------------------------------------------------------------
/example/kitchen-di/coffee_maker/pump.js:
--------------------------------------------------------------------------------
1 | import {Inject} from 'di';
2 | import {Heater} from './heater';
3 | import {Electricity} from '../electricity';
4 |
5 | @Inject(Heater, Electricity)
6 | export class Pump {
7 | constructor(heater, electricity) {
8 | this.heater = heater;
9 | this.electricity = electricity;
10 | }
11 |
12 | pump() {
13 | console.log('Pumping the water...');
14 | }
15 | }
16 |
--------------------------------------------------------------------------------
/example/node/test/main.spec.js:
--------------------------------------------------------------------------------
1 | var di = require('di');
2 | var Car = require('../car');
3 | var MockEngine = require('./mock_engine');
4 |
5 | describe('Car', function() {
6 | beforeEach(function() {
7 | var injector = new di.Injector([MockEngine]);
8 | this.car = injector.get(Car);
9 | });
10 |
11 | it('is running', function() {
12 | expect(this.car.isRunning()).toBe(true);
13 | });
14 | });
15 |
--------------------------------------------------------------------------------
/example/coffee/coffee_maker.js:
--------------------------------------------------------------------------------
1 | import {Inject} from 'di';
2 |
3 | import {Heater} from './heater';
4 | import {Pump} from './pump';
5 |
6 | @Inject(Heater, Pump)
7 | export class CoffeeMaker {
8 | constructor(heater, pump) {
9 | this.heater = heater;
10 | this.pump = pump;
11 | }
12 |
13 | brew() {
14 | this.pump.pump();
15 | this.heater.on();
16 | // console.log('Brewing...')
17 | }
18 | }
19 |
--------------------------------------------------------------------------------
/example/node/car.js:
--------------------------------------------------------------------------------
1 | var di = require('di');
2 | var Engine = require('./engine');
3 |
4 | var Car = function(engine) {
5 | this.engine = engine;
6 | };
7 |
8 | Car.prototype = {
9 | run: function() {
10 | this.engine.start();
11 | },
12 | isRunning: function() {
13 | return this.engine.state === 'running';
14 | }
15 | };
16 |
17 | di.annotate(Car, new di.Inject(Engine));
18 |
19 | module.exports = Car;
20 |
--------------------------------------------------------------------------------
/example/testing/mocks.js:
--------------------------------------------------------------------------------
1 | import {Provide} from '../../src/annotations';
2 | import {Heater} from '../coffee/heater';
3 |
4 | class MockHeater {
5 | constructor() {
6 | this.on = jasmine.createSpy('on');
7 | this.off = jasmine.createSpy('off');
8 | }
9 | }
10 |
11 | @Provide(Heater)
12 | class DummyHeater {
13 | constructor() {}
14 | on() {}
15 | off() {}
16 | }
17 |
18 | export {MockHeater, DummyHeater}
19 |
--------------------------------------------------------------------------------
/example/kitchen-di/coffee_maker/heater.js:
--------------------------------------------------------------------------------
1 | import {Inject} from 'di';
2 | import {Electricity} from '../electricity';
3 |
4 | @Inject(Electricity)
5 | export class Heater {
6 | constructor(electricity) {
7 | this.electricity = electricity;
8 | }
9 |
10 | on() {
11 | console.log('Turning on the coffee heater...');
12 | }
13 |
14 | off() {
15 | console.log('Turning off the coffee heater...');
16 | }
17 | }
18 |
--------------------------------------------------------------------------------
/example/kitchen-di/dishwasher.js:
--------------------------------------------------------------------------------
1 | import {Inject} from 'di';
2 | import {Electricity} from './electricity';
3 |
4 | @Inject(Electricity)
5 | export class Dishwasher {
6 | constructor(electricity) {
7 | this.electricity = electricity;
8 | }
9 |
10 | add(item) {
11 | console.log('Putting ' + item + ' into the dishwasher...');
12 | }
13 | wash() {
14 | console.log('Running the dishwasher...');
15 | }
16 | }
17 |
--------------------------------------------------------------------------------
/example/kitchen/coffee_maker.js:
--------------------------------------------------------------------------------
1 |
2 | export class CoffeeMaker {
3 | constructor(grinder, pump, heater) {
4 | this.grinder = grinder;
5 | this.pump = pump;
6 | this.heater = heater;
7 | }
8 |
9 | brew() {
10 | console.log('Brewing a coffee...');
11 | this.grinder.grind();
12 | this.heater.on();
13 | this.pump.pump();
14 | this.heater.off();
15 | console.log('A coffee is ready.');
16 | }
17 | }
18 |
--------------------------------------------------------------------------------
/example/kitchen-di/stove.js:
--------------------------------------------------------------------------------
1 | import {Inject} from 'di';
2 | import {Electricity} from './electricity';
3 |
4 | @Inject(Electricity)
5 | export class Stove {
6 | constructor(electricity) {
7 | this.electricity = electricity;
8 | }
9 |
10 | add(item) {
11 | console.log('Adding ' + item + ' onto the stove.');
12 | }
13 |
14 | on() {
15 | console.log('Turning on the stove...');
16 | }
17 |
18 | off() {
19 | console.log('Turning off the stove...');
20 | }
21 | }
22 |
--------------------------------------------------------------------------------
/node/index.js:
--------------------------------------------------------------------------------
1 | // This is the file that gets included when you use "di" module in Node.js.
2 |
3 | // Include Traceur runtime.
4 | require('traceur/bin/traceur-runtime');
5 |
6 | // Node.js has to be run with --harmony_collections to support ES6 Map.
7 | // If not defined, include a polyfill.
8 | if (typeof Map === 'undefined') {
9 | require('es6-shim');
10 | }
11 |
12 | if (!global.__di) {
13 | global.__di = require('../dist/cjs/index');
14 | }
15 |
16 | module.exports = global.__di;
17 |
--------------------------------------------------------------------------------
/.travis.yml:
--------------------------------------------------------------------------------
1 | language: node_js
2 |
3 | node_js:
4 | - 0.10
5 |
6 | env:
7 | global:
8 | - SAUCE_USERNAME=angular-ci
9 | - SAUCE_ACCESS_KEY=9b988f434ff8-fbca-8aa4-4ae3-35442987
10 |
11 | install:
12 | - npm install
13 | - npm install -g gulp
14 | - npm install -g karma-cli
15 | - npm install -g jasmine-node
16 |
17 | before_script:
18 |
19 | script:
20 | - karma start --single-run --browsers SL_Chrome --reporters dots
21 | - jasmine-node example/node/test
22 |
23 | after_script:
24 |
--------------------------------------------------------------------------------
/visualize/dag/style.css:
--------------------------------------------------------------------------------
1 | .link {
2 | fill: none;
3 | stroke: #666;
4 | stroke-width: 1.5px;
5 | }
6 |
7 | #licensing {
8 | fill: green;
9 | }
10 |
11 | .link.licensing {
12 | stroke: green;
13 | }
14 |
15 | .link.resolved {
16 | stroke-dasharray: 0,2 1;
17 | }
18 |
19 | circle {
20 | fill: #ccc;
21 | stroke: #333;
22 | stroke-width: 1.5px;
23 | }
24 |
25 | text {
26 | font: 10px sans-serif;
27 | pointer-events: none;
28 | text-shadow: 0 1px 0 #fff, 1px 0 0 #fff, 0 -1px 0 #fff, -1px 0 0 #fff;
29 | }
30 |
--------------------------------------------------------------------------------
/example/kitchen/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 | Kitchen example
4 |
5 |
6 | Kitchen example, transpiled on the server into RequireJS, without DI.
7 |
8 |
9 |
10 |
18 |
19 |
20 |
--------------------------------------------------------------------------------
/test/fixtures/house.js:
--------------------------------------------------------------------------------
1 | import {Inject, Provide} from '../../src/annotations';
2 |
3 | // This is an example of using string as tokens.
4 |
5 | @Provide('House')
6 | @Inject('Kitchen')
7 | export class House {
8 | constructor(kitchen) {
9 |
10 | }
11 |
12 | nothing() {}
13 | }
14 |
15 | @Provide('Kitchen')
16 | @Inject('Sink')
17 | export class Kitchen {
18 | constructor(sink) {
19 |
20 | }
21 |
22 | nothing() {}
23 | }
24 |
25 | // Sink is missing.
26 | // @Provide('Sink')
27 | // export class Sink {
28 | // nothing() {}
29 | // }
30 |
31 | export var module = [House, Kitchen];
32 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | Copyright 2014 Google, Inc. http://angularjs.org
2 |
3 | Licensed under the Apache License, Version 2.0 (the "License");
4 | you may not use this file except in compliance with the License.
5 | You may obtain a copy of the License at
6 |
7 | http://www.apache.org/licenses/LICENSE-2.0
8 |
9 | Unless required by applicable law or agreed to in writing, software
10 | distributed under the License is distributed on an "AS IS" BASIS,
11 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 | See the License for the specific language governing permissions and
13 | limitations under the License.
14 |
--------------------------------------------------------------------------------
/test/coffee.spec.js:
--------------------------------------------------------------------------------
1 | import {Injector} from '../src/injector';
2 |
3 | import {module as coffeeModule} from '../example/coffee/coffee_module';
4 | import {CoffeeMaker} from '../example/coffee/coffee_maker';
5 | import {MockHeater} from '../example/coffee/mock_heater';
6 |
7 |
8 | describe('coffee example', function() {
9 | it('should work', function() {
10 | var i = new Injector(coffeeModule);
11 |
12 | i.get(CoffeeMaker).brew();
13 | });
14 |
15 |
16 | it('should work with mocked heater', function() {
17 | var i = new Injector([MockHeater]);
18 |
19 | i.get(CoffeeMaker).brew();
20 | });
21 | });
22 |
--------------------------------------------------------------------------------
/example/kitchen-di/coffee_maker/coffee_maker.js:
--------------------------------------------------------------------------------
1 | import {Inject} from 'di';
2 |
3 | import {Grinder} from './grinder';
4 | import {Pump} from './pump';
5 | import {Heater} from './heater';
6 |
7 | @Inject(Grinder, Pump, Heater)
8 | export class CoffeeMaker {
9 | constructor(grinder, pump, heater) {
10 | this.grinder = grinder;
11 | this.pump = pump;
12 | this.heater = heater;
13 | }
14 |
15 | brew() {
16 | console.log('Brewing a coffee...');
17 | this.grinder.grind();
18 | this.heater.on();
19 | this.pump.pump();
20 | this.heater.off();
21 | console.log('A coffee is ready.');
22 | }
23 | }
24 |
--------------------------------------------------------------------------------
/chrome-extension/background.js:
--------------------------------------------------------------------------------
1 | // TODO(vojta): Make refresh work
2 | // notify of page refreshes
3 | chrome.extension.onConnect.addListener(function(port) {
4 | port.onMessage.addListener(function (msg) {
5 | if (msg.action === 'register') {
6 | var respond = function (tabId, changeInfo, tab) {
7 | if (tabId !== msg.inspectedTabId) {
8 | return;
9 | }
10 | port.postMessage('refresh');
11 | };
12 |
13 | chrome.tabs.onUpdated.addListener(respond);
14 | port.onDisconnect.addListener(function () {
15 | chrome.tabs.onUpdated.removeListener(respond);
16 | });
17 | }
18 | });
19 | });
20 |
--------------------------------------------------------------------------------
/docs/terminology.md:
--------------------------------------------------------------------------------
1 | # Terminology
2 |
3 | **Injector** - a container, capable of instantiating objects.
4 |
5 | **Provider** - a recipe for constructing an object, typically a class or a factory function. A provider is typically annotated with Tokens, which tells Injector what dependencies particular provider needs.
6 |
7 | **Token** - a contract, an identifier of a dependency. Typically a class or a string.
8 |
9 |
10 | ## An example
11 |
12 | ```js
13 | @Provide(Heater)
14 | class MockHeater {
15 | // ...
16 | }
17 |
18 | @Provide(Heater)
19 | function createElectricHeater() {
20 | // ...
21 | }
22 | ```
23 |
24 | - Heater class is a token.
25 | - MockHeater is a provider.
26 | - createElectricHeater function is a provider.
27 |
--------------------------------------------------------------------------------
/test/fixtures/car.js:
--------------------------------------------------------------------------------
1 | import {annotate, Inject, Provide} from '../../src/annotations';
2 |
3 | export class Engine {}
4 |
5 | export class Car {
6 | constructor(engine) {
7 | this.engine = engine;
8 | }
9 |
10 | start() {}
11 | }
12 |
13 | export function createEngine() {
14 | return 'strong engine';
15 | }
16 |
17 | export class CyclicEngine {
18 | constructor(car) {}
19 | }
20 |
21 | // This is an example of using annotate helper, instead of annotations.
22 |
23 | // @Inject(Engine)
24 | annotate(Car, new Inject(Engine));
25 |
26 | // @Provide(Engine)
27 | annotate(createEngine, new Provide(Engine));
28 |
29 | // @Inject(Car)
30 | annotate(CyclicEngine, new Inject(Car));
31 | // @Provide(Engine)
32 | annotate(CyclicEngine, new Provide(Engine));
33 |
--------------------------------------------------------------------------------
/example/kitchen-di/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 | Kitchen example
4 |
5 |
6 | Kitchen example, transpiled on the server into RequireJS.
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
28 |
29 |
30 |
--------------------------------------------------------------------------------
/example/kitchen/kitchen.js:
--------------------------------------------------------------------------------
1 |
2 | export class Kitchen {
3 | constructor(coffeeMaker, skillet, stove, fridge, dishwasher) {
4 | this.coffeeMaker = coffeeMaker;
5 | this.skillet = skillet;
6 | this.stove = stove;
7 | this.fridge = fridge;
8 | this.dishwasher = dishwasher;
9 | }
10 |
11 | makeScrambledEggs() {
12 | console.log('Making some eggs...');
13 | this.skillet.add(this.fridge.getEggs());
14 | this.stove.add(this.skillet);
15 | this.stove.on();
16 | this.stove.off();
17 | console.log('Scrambled eggs are ready.');
18 | }
19 |
20 | makeBreakfast() {
21 | // make a cofee
22 | this.coffeeMaker.brew();
23 |
24 | // make some eggs
25 | this.makeScrambledEggs();
26 |
27 | // clean the dishes
28 | this.dishwasher.add(this.skillet);
29 | this.dishwasher.wash();
30 | }
31 | }
32 |
--------------------------------------------------------------------------------
/chrome-extension/panel.js:
--------------------------------------------------------------------------------
1 | function evalInInspectedWindow(fn, args, cb) {
2 | var code = '(' + fn.toString() + ')(window, ' + JSON.stringify(args) + ')';
3 | chrome.devtools.inspectedWindow.eval(code, cb);
4 | }
5 |
6 | app.factory('data', function($q) {
7 | var d = $q.defer();
8 |
9 | evalInInspectedWindow(function(window) {
10 | var injectors = window.__di_dump__.injectors;
11 | var tokens = Object.create(null);
12 |
13 | // Serialize the map so that we can pass it back to the console panel.
14 | window.__di_dump__.tokens.forEach(function(id, token) {
15 | tokens[id] = token.name;
16 | });
17 |
18 | return {
19 | injectors: injectors,
20 | tokens: tokens
21 | };
22 | }, [], function(dump) {
23 | d.resolve(dump);
24 | });
25 |
26 | d.promise.success = d.promise.then;
27 | return d.promise;
28 | });
29 |
--------------------------------------------------------------------------------
/visualize/injectors/coffee_maker.json:
--------------------------------------------------------------------------------
1 | {
2 | "injectors": [{
3 | "id": 1,
4 | "parent_id": null,
5 | "providers": {
6 | "CoffeeMaker": {
7 | "name": "CoffeeMaker",
8 | "dependencies": [
9 | "Grinder",
10 | "Pump",
11 | "Heater"
12 | ]
13 | },
14 | "Grinder": {
15 | "name": "Grinder",
16 | "dependencies": [
17 | "Electricity"
18 | ]
19 | },
20 | "Electricity": {
21 | "name": "Electricity",
22 | "dependencies": []
23 | },
24 | "Pump": {
25 | "name": "Pump",
26 | "dependencies": [
27 | "Heater",
28 | "Electricity"
29 | ]
30 | },
31 | "Heater": {
32 | "name": "Heater",
33 | "dependencies": [
34 | "Electricity"
35 | ]
36 | }
37 | }
38 | }]
39 | }
40 |
--------------------------------------------------------------------------------
/visualize/injectors/data.json:
--------------------------------------------------------------------------------
1 | {
2 | "injectors": [
3 | {
4 | "id": "1",
5 | "parent_id": null,
6 | "providers": {
7 | "CoffeMaker": {"name": "CoffeMaker", "dependencies": ["Heater", "Pump"]},
8 | "Heater": {"name": "Heater", "dependencies": []},
9 | "Pump": {"name": "Pump", "dependencies": ["Heater"]},
10 | "Extra": {"name": "Extra", "dependencies": ["Pump"]}
11 | }
12 | },
13 | {
14 | "id": "2",
15 | "parent_id": "1",
16 | "providers": {
17 | "Heater": {"name": "Heater", "dependencies": []},
18 | "Extra": {"name": "Extra", "dependencies": []}
19 | }
20 | },
21 | {
22 | "id": "3",
23 | "parent_id": "1",
24 | "providers": {
25 | "Heater": {"name": "Heater", "dependencies": ["Pump", "Extra"]},
26 | "Pump": {"name": "Pump", "dependencies": []}
27 | }
28 | }
29 | ]
30 | }
31 |
--------------------------------------------------------------------------------
/karma.conf.js:
--------------------------------------------------------------------------------
1 | var sharedConfig = require('pipe/karma');
2 |
3 | module.exports = function(config) {
4 | sharedConfig(config);
5 |
6 | config.set({
7 | // list of files / patterns to load in the browser
8 | files: [
9 | 'test-main.js',
10 |
11 | {pattern: 'src/**/*.js', included: false},
12 | {pattern: 'test/**/*.js', included: false},
13 | {pattern: 'example/coffee/*.js', included: false},
14 | {pattern: 'example/testing/*.js', included: false},
15 | {pattern: 'node_modules/es6-shim/es6-shim.js', included: false},
16 | {pattern: 'node_modules/rtts-assert/src/**/*.js', included: false}
17 | ],
18 |
19 | preprocessors: {
20 | 'src/**/*.js': ['traceur'],
21 | 'test/**/*.js': ['traceur'],
22 | 'example/**/*.js': ['traceur'],
23 | 'node_modules/rtts-assert/src/**/*.js': ['traceur']
24 | }
25 | });
26 |
27 | config.sauceLabs.testName = 'di.js';
28 | };
29 |
--------------------------------------------------------------------------------
/docs/how-can-i-use-it.md:
--------------------------------------------------------------------------------
1 | # How can I use it?
2 |
3 | ## In the browser
4 | See the [kitchen-di example](../example/kitchen-di/index.html) on how to use the DI with [RequireJS].
5 |
6 | You will need:
7 | - a browser that supports `Map`, or include a polyfill,
8 | - include the [Traceur runtime].
9 |
10 | ## In Node.js
11 | ```bash
12 | npm install di --tag v2
13 | ```
14 |
15 | See the [node example] on how to use the DI in regular ES5.
16 |
17 | ## Using ES6
18 | If you decide to write your project in ES6, you can consume the ES6 source code in [`src/`] and compile it with [Traceur] on your own, similar to the [kitchen-di example].
19 |
20 |
21 | [kitchen-di example]: ../example/kitchen-di
22 | [RequireJS]: http://requirejs.org/
23 | [Traceur runtime]: https://github.com/google/traceur-compiler/blob/master/src/runtime/runtime.js
24 | [node example]: ../example/node
25 | [`src/`]: ../src
26 | [Traceur]: https://github.com/google/traceur-compiler
27 |
--------------------------------------------------------------------------------
/test-main.js:
--------------------------------------------------------------------------------
1 | var allTestFiles = [];
2 | var TEST_REGEXP = /\.spec\.js$/;
3 |
4 | var pathToModule = function(path) {
5 | return path.replace(/^\/base\//, '').replace(/\.js$/, '');
6 | };
7 |
8 | Object.keys(window.__karma__.files).forEach(function(file) {
9 | if (TEST_REGEXP.test(file)) {
10 | // Normalize paths to RequireJS module names.
11 | allTestFiles.push(pathToModule(file));
12 | }
13 | });
14 |
15 | require.config({
16 | // Karma serves files under /base, which is the basePath from your config file
17 | baseUrl: '/base',
18 |
19 | paths: {
20 | 'rtts-assert': './node_modules/rtts-assert/src/assert'
21 | },
22 |
23 | map: {
24 | '*': {
25 | 'di': 'src/index'
26 | }
27 | },
28 |
29 | // Dynamically load all test files and ES6 polyfill.
30 | deps: allTestFiles.concat(['node_modules/es6-shim/es6-shim', 'test/matchers']),
31 |
32 | // we have to kickoff jasmine, as it is asynchronous
33 | callback: window.__karma__.start
34 | });
35 |
--------------------------------------------------------------------------------
/src/util.js:
--------------------------------------------------------------------------------
1 | // A bunch of helper functions.
2 |
3 | function isUpperCase(char) {
4 | return char.toUpperCase() === char;
5 | }
6 |
7 | function isFunction(value) {
8 | return typeof value === 'function';
9 | }
10 |
11 |
12 | function isObject(value) {
13 | return typeof value === 'object';
14 | }
15 |
16 |
17 | function toString(token) {
18 | if (typeof token === 'string') {
19 | return token;
20 | }
21 |
22 | if (token === undefined || token === null) {
23 | return '' + token;
24 | }
25 |
26 | if (token.name) {
27 | return token.name;
28 | }
29 |
30 | return token.toString();
31 | }
32 |
33 | var ownKeys = (this.Reflect && Reflect.ownKeys ? Reflect.ownKeys : function ownKeys(O) {
34 | var keys = Object.getOwnPropertyNames(O);
35 | if (Object.getOwnPropertySymbols) return keys.concat(Object.getOwnPropertySymbols(O));
36 | return keys;
37 | });
38 |
39 |
40 | export {
41 | isUpperCase,
42 | isFunction,
43 | isObject,
44 | toString,
45 | ownKeys
46 | };
47 |
--------------------------------------------------------------------------------
/visualize/injectors/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | Visualization of injectors
5 |
6 |
7 |
8 | {{message}}
9 |
10 |
11 |
12 | -
13 | {{provider.name}}
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
--------------------------------------------------------------------------------
/example/kitchen/main.js:
--------------------------------------------------------------------------------
1 | import {Kitchen} from './kitchen';
2 | import {CoffeeMaker} from './coffee_maker';
3 | import {Grinder} from './grinder';
4 | import {Electricity} from './electricity';
5 | import {Pump} from './pump';
6 | import {Heater} from './heater';
7 | import {Skillet} from './skillet';
8 | import {Stove} from './stove';
9 | import {Fridge} from './fridge';
10 | import {Dishwasher} from './dishwasher';
11 |
12 |
13 | function main() {
14 | var electricity = new Electricity();
15 | var skillet = new Skillet();
16 | var stove = new Stove(electricity);
17 | var fridge = new Fridge(electricity);
18 | var dishwasher = new Dishwasher(electricity);
19 |
20 | // assemble the CoffeeMaker
21 | var grinder = new Grinder(electricity);
22 | var heater = new Heater(electricity);
23 | var pump = new Pump(heater, electricity);
24 | var coffeeMaker = new CoffeeMaker(grinder, pump, heater);
25 |
26 | // assemble the Kitchen
27 | var kitchen = new Kitchen(coffeeMaker, skillet, stove, fridge, dishwasher);
28 |
29 | // finally, make the breakfast
30 | kitchen.makeBreakfast();
31 | }
32 |
33 | main();
34 |
--------------------------------------------------------------------------------
/dist/amd/index.js:
--------------------------------------------------------------------------------
1 | define(['./injector', './annotations'], function($__0,$__1) {
2 | "use strict";
3 | if (!$__0 || !$__0.__esModule)
4 | $__0 = {default: $__0};
5 | if (!$__1 || !$__1.__esModule)
6 | $__1 = {default: $__1};
7 | var $__injector__ = $__0;
8 | var $__annotations__ = $__1;
9 | return {
10 | get Injector() {
11 | return $__injector__.Injector;
12 | },
13 | get annotate() {
14 | return $__annotations__.annotate;
15 | },
16 | get Inject() {
17 | return $__annotations__.Inject;
18 | },
19 | get InjectLazy() {
20 | return $__annotations__.InjectLazy;
21 | },
22 | get InjectPromise() {
23 | return $__annotations__.InjectPromise;
24 | },
25 | get Provide() {
26 | return $__annotations__.Provide;
27 | },
28 | get ProvidePromise() {
29 | return $__annotations__.ProvidePromise;
30 | },
31 | get SuperConstructor() {
32 | return $__annotations__.SuperConstructor;
33 | },
34 | get TransientScope() {
35 | return $__annotations__.TransientScope;
36 | },
37 | __esModule: true
38 | };
39 | });
40 |
--------------------------------------------------------------------------------
/example/kitchen-di/kitchen.js:
--------------------------------------------------------------------------------
1 | import {Inject} from 'di';
2 | import {CoffeeMaker} from './coffee_maker/coffee_maker';
3 | import {Skillet} from './skillet';
4 | import {Stove} from './stove';
5 | import {Fridge} from './fridge';
6 | import {Dishwasher} from './dishwasher';
7 |
8 | @Inject(CoffeeMaker, Skillet, Stove, Fridge, Dishwasher)
9 | export class Kitchen {
10 | constructor(coffeeMaker, skillet, stove, fridge, dishwasher) {
11 | this.coffeeMaker = coffeeMaker;
12 | this.skillet = skillet;
13 | this.stove = stove;
14 | this.fridge = fridge;
15 | this.dishwasher = dishwasher;
16 | }
17 |
18 | makeScrambledEggs() {
19 | console.log('Making some eggs...');
20 | this.skillet.add(this.fridge.getEggs());
21 | this.stove.add(this.skillet);
22 | this.stove.on();
23 | this.stove.off();
24 | console.log('Scrambled eggs are ready.');
25 | }
26 |
27 | makeBreakfast() {
28 | // make a cofee
29 | this.coffeeMaker.brew();
30 |
31 | // make some eggs
32 | this.makeScrambledEggs();
33 |
34 | // clean the dishes
35 | this.dishwasher.add(this.skillet);
36 | this.dishwasher.wash();
37 | }
38 | }
39 |
--------------------------------------------------------------------------------
/chrome-extension/panel.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | Visualization of injectors
5 |
6 |
7 |
8 | {{message}}
9 |
10 |
11 |
12 | -
13 | {{provider.name}}
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |