Bottlejs
A powerful dependency injection micro container for JavaScript applications
Install / Use
/learn @young-steveo/BottlejsREADME

BottleJS
A powerful dependency injection micro container
Introduction
BottleJS is a tiny, powerful dependency injection container. It features lazy loading, middleware hooks, decorators and a clean api inspired by the AngularJS Module API and the simple PHP library Pimple. You'll like BottleJS if you enjoy:
- building a stack from components rather than a kitchen-sink framework.
- uncoupled objects and dependency injection.
- an API that makes sense.
- lazily loaded objects.
- trying cool stuff :smile:
Browser Support
BottleJS supports IE9+ and other ECMAScript 5 compliant browsers.
Installation
BottleJS can be used in a browser or in a nodejs app. It can be installed via bower or npm:
$ bower install bottlejs
$ npm install bottlejs
BottleJS is also available on cdnjs:
<script src="https://cdnjs.cloudflare.com/ajax/libs/bottlejs/2.0.1/bottle.min.js"></script>
Simple Example
The simplest recipe to get started with is Bottle#service. Say you have a constructor for a service object:
var Beer = function() { /* A beer service, :yum: */ };
You can register the constructor with Bottle#service:
var bottle = new Bottle();
bottle.service('Beer', Beer);
Later, when you need the constructed service, you just access the Beer property like this:
bottle.container.Beer;
A lot happened behind the scenes:
- Bottle created a provider containing a factory function when you registered the Beer service.
- When the
bottle.container.Beerproperty was accessed, Bottle looked up the provider and executed the factory to build and return the Beer service. - The provider and factory were deleted, and the
bottle.container.Beerproperty was set to be the Beer service instance. Accessingbottle.container.Beerin the future becomes a simple property lookup.
Injecting Dependencies
The above example is simple. But, what if the Beer service had dependencies? For example:
var Barley = function() {};
var Hops = function() {};
var Water = function() {};
var Beer = function(barley, hops, water) { /* A beer service, :yum: */ };
You can register services with Bottle#service and include dependencies like this:
var bottle = new Bottle();
bottle.service('Barley', Barley);
bottle.service('Hops', Hops);
bottle.service('Water', Water);
bottle.service('Beer', Beer, 'Barley', 'Hops', 'Water');
Now, when you access bottle.container.Beer, Bottle will lazily load all of the dependencies and inject them into your Beer service before returning it.
Service Factory
If you need more complex logic when generating a service, you can register a factory instead. A factory function receives the container as an argument, and should return your constructed service:
var bottle = new Bottle();
bottle.service('Barley', Barley);
bottle.service('Hops', Hops);
bottle.service('Water', Water);
bottle.factory('Beer', function(container) {
var barley = container.Barley;
var hops = container.Hops;
var water = container.Water;
barley.halved();
hops.doubled();
water.spring();
return new Beer(barley, hops, water);
});
Service Provider
This is the meat of the Bottle library. The above methods Bottle#service and Bottle#factory are just shorthand for the provider function. You usually can get by with the simple functions above, but if you really need more granular control of your services in different environments, register them as a provider. To use it, pass a constructor for the provider that exposes a $get function. The $get function is used as a factory to build your service.
var bottle = new Bottle();
bottle.service('Barley', Barley);
bottle.service('Hops', Hops);
bottle.service('Water', Water);
bottle.provider('Beer', function() {
// This environment may not support water.
// We should polyfill it.
if (waterNotSupported) {
Beer.polyfillWater();
}
// this is the service factory.
this.$get = function(container) {
var barley = container.Barley;
var hops = container.Hops;
var water = container.Water;
barley.halved();
hops.doubled();
water.spring();
return new Beer(barley, hops, water);
};
});
Decorators
Bottle supports injecting decorators into the provider pipeline with the Bottle#decorator method. Bottle decorators are just simple functions that intercept a service in the provider phase after it has been created, but before it is accessed for the first time. The function should return the service, or another object to be used as the service instead.
var bottle = new Bottle();
bottle.service('Beer', Beer);
bottle.service('Wine', Wine);
bottle.decorator(function(service) {
// this decorator will be run for both Beer and Wine services.
service.stayCold();
return service;
});
bottle.decorator('Wine', function(wine) {
// this decorator will only affect the Wine service.
wine.unCork();
return wine;
});
Middleware
Bottle middleware are similar to decorators, but they are executed every time a service is accessed from the container. They are passed the service instance and a next function:
var bottle = new Bottle();
bottle.service('Beer', Beer);
bottle.middleware(function(service, next) {
// this middleware will be executed for all services
console.log('A service was accessed!');
next();
});
bottle.middleware('Beer', function(beer, next) {
// this middleware will only affect the Beer service.
console.log('Beer? Nice. Tip your bartender...');
next();
});
Middleware can pass an error object to the next function, and bottle will throw the error:
var bottle = new Bottle();
bottle.service('Beer', Beer);
bottle.middleware('Beer', function(beer, next) {
if (beer.hasGoneBad()) {
return next(new Error('The Beer has gone bad!'));
}
next();
});
// results in Uncaught Error: The Beer has gone bad!(…)
Nested Bottles
Bottle will generate nested containers if dot notation is used in the service name. An isolated sub container will be created for you based on the name given:
var bottle = new Bottle();
var IPA = function() {};
bottle.service('Beer.IPA', IPA);
bottle.container.Beer; // this is a new Bottle.container object
bottle.container.Beer.IPA; // the service
bottle.factory('Beer.DoubleIPA', function (container) {
var IPA = container.IPA; // note the container in here is the nearest parent.
})
Nested Containers Are Isolated
Nested containers are designed to provide isolation between different packages. This means that you cannot access a nested container from a different parent when you are writing a factory.
var bottle = new Bottle();
var IPA = function() {};
var Wort = function() {};
bottle.service('Ingredients.Wort', Wort);
bottle.factory('Beer.IPA', function(container) {
// container is `Beer`, not the root, so:
container.Wort; // undefined
container.Ingredients.Wort; // undefined
});
API
Bottle
pop(name)
Used to get an instance of bottle. If a name is passed, bottle will return the same instance. Calling the Bottle constructor as a function will call and return Bottle.pop, so Bottle.pop('Soda') === Bottle('Soda')
Param | Type | Details
:--------------------------|:-----------|:--------
name<br />(optional) | String | The name of the bottle. If passed, bottle will store the instance internally and return the same instance if Bottle.pop is subsequently called with the same name.
clear(name)
Removes the named instance from bottle's internal store, if it exists. The immediately subsequent call to Bottle.pop(name) will return a new instance. If no name is given, all named instances will be cleared.
In general, this function should only be called in situations where you intend to reset the bottle instance with new providers, decorators, etc. such as test setup.
Param | Type | Details
:--------------------------|:-----------|:--------
name<br />(optional) | String | The name of the bottle. If passed, bottle will remove the internal instance, if such a bottle was created using Bottle.pop. If not passed, all named internal instances will be cleared.
list(container)
prototype.list()
prototype.container.$list()
Used to list the names of all registered constants, values, and services on the container. Must pass a container to the global static version Bottle.list(bottle.container). The instance and container versions return the services that are registered within.
Returns an array of strings.
Param | Type | Details
:-------------------------------|:-----------|:--------
container<br />(optional) | Object | A bottle.container. Only required when using the global, static Bottle.list method. The prototype version uses that instance's container, and the container version uses itself.
config
A global configuration object.
Property | Type | Default | Details
:----------|:----------|:--------|:--------
strict | Boolean | false
Related Skills
node-connect
348.2kDiagnose OpenClaw node connection and pairing failures for Android, iOS, and macOS companion apps
frontend-design
108.9kCreate distinctive, production-grade frontend interfaces with high design quality. Use this skill when the user asks to build web components, pages, or applications. Generates creative, polished code that avoids generic AI aesthetics.
openai-whisper-api
348.2kTranscribe audio via OpenAI Audio Transcriptions API (Whisper).
qqbot-media
348.2kQQBot 富媒体收发能力。使用 <qqmedia> 标签,系统根据文件扩展名自动识别类型(图片/语音/视频/文件)。

