const { createContainer } = require('cerise');
// or:
import { createContainer } from 'cerise';
Create a container, and optionally register services.
container(name)
: retrieve a registered service.container.scope()
: create a new scoped container that inherits this one.container.registry
: directly access registered service factories. Not unlike the Wu-Tang Clan, this ain't nuthing ta fuck wit. This is an internal property that may break without notice; use at your own risk.container.cache
: directly access cached services. This is an internal property that may break without notice; use at your own risk.container.register(name, serviceFactory)
: register a service using a service factory (i.e something returned byconstant
,factory
orservice
).container.proxy(name)
: retrieve a registered service -- alias forcontainer(name)
.container.proxy[name]
: retrieve a registered service -- alias forcontainer(name)
.container.save()
: save the container state. Useful for testing before registering test values. Not available on child containers!container.restore()
: restore the latest saved state.
const container = createContainer();
const container = createContainer({
name: constant('cerise'),
});
const { constant } = require('cerise');
// or:
import { constant } from 'cerise';
Define a service without any dependency. Sugar for factory(() => x).scoped()
.
container.register('db', constant(new Database(':memory:')));
const { factory } = require('cerise');
// or:
import { factory } from 'cerise';
Takes a callback and defines a lazy-loaded service with optional dependencies. Can be qualified with .scoped()
or .singleton()
.
upperCaseName
will get called everytime NAME
is retrieved.
const upperCaseName = ({ name }) => name.toUpperCase();
container.register('NAME', factory(upperCaseName));
upperCaseName
will get called once for each scope that retrieves it.
const upperCaseName = ({ name }) => name.toUpperCase();
container.register('NAME', factory(upperCaseName).scoped());
upperCaseName
will get called once (if ever).
const upperCaseName = ({ name }) => name.toUpperCase();
container.register('NAME', factory(upperCaseName).singleton());
const { service } = require('cerise');
// or:
import { service } from 'cerise';
Takes a class and defines a lazy-loaded service with optional dependencies. Can be qualified with .scoped()
or .singleton()
. Sugar for factory(proxy => new T(proxy))
.
NameRepeater
will be instanciated everytime nameRepeater
is retrieved.
class NameRepeater {
constructor({ name }) {
this.name = name;
}
repeat(times) {
return Array(times + 1).join(this.name);
}
}
container.register('nameRepeater', factory(NameRepeater));
NameRepeater
will be instanciated once for each scope that retrieves it.
class NameRepeater {
constructor({ name }) {
this.name = name;
}
repeat(times) {
return Array(times + 1).join(this.name);
}
}
container.register('nameRepeater', factory(NameRepeater).scoped());
NameRepeater
will be instanciated once (if ever).
class NameRepeater {
constructor({ name }) {
this.name = name;
}
repeat(times) {
return Array(times + 1).join(this.name);
}
}
container.register('nameRepeater', factory(NameRepeater).singleton());
const { middleware } = require('cerise');
// or
import { middleware } from 'cerise';
Takes a container and returns an Express / Koa middleware that creates a scope and assigns it to req.scope
(Express) or ctx.state.scope
(Koa).
const express = require('express');
const { createContainer, middleware: cerise } = require('cerise');
const app = express();
const container = createContainer();
// req.scope = container.scope();
app.use(cerise(container));
const Koa = require('koa');
const { createContainer, middleware: cerise } = require('cerise');
const app = new Koa();
const container = createContainer();
// ctx.state.scope = container.scope();
app.use(cerise(container));
const { controller } = require('cerise');
// or
import { controller } from 'cerise';
Returns an Express route handler that wraps a callback. Said callback will be passed req.scope.proxy
, req
, res
and next
as argument.
If you don't end the request yourself (using res.send
, res.end
, res.json
, etc.), whatever you return will be await
-ed for and sent as JSON.
Asynchronous errors will be passed to your application error-handling middleware for better error handling and recovery.
app.get(
'/session',
controller(({ session }, req, res) => {
res.json(session);
}),
);
app.get('/session', controller(({ session }) => session));
// Will trigger your application error handler
app.get(
'/throws',
controller(async () => {
throw new Error('Oops');
}),
);