Security News
RubyGems.org Adds New Maintainer Role
RubyGems.org has added a new "maintainer" role that allows for publishing new versions of gems. This new permission type is aimed at improving security for gem owners and the service overall.
TypeScript opiniated dependency injection library. Why another dependency injection library? Most dependency injection libraries target object oriented codebases. Glue is a tiny lightweight library made for FP codebases making extensive use of parti
TypeScript opiniated dependency injection library.
Why another dependency injection library?
Most dependency injection libraries target object oriented codebases.
Glue is a tiny lightweight library made for FP codebases making extensive use of partial application for dependency injection.
Main benefits of Glue include:
If you are in a hurry you can start playing with ts-glue
right away with this demo sandbox
ts-glue
is a TypeScript library that can be installed with any package manager such as npm or yarn:
# with npm
npm i ts-glue
# or yarn
yarn add ts-glue
In order to use ts-glue
, you need to do 3 things:
Glue
object that will hold a descriptions of all the components and functions that might need to be injectedSo let's begin by building a "Glue" object and a description of all the functions and components that it will handle.
Let's say we have a clock function we want to inject in our codebase:
type Clock = () => Date;
const systemClock: Clock = () => new Date();
Our Glue could be set up as shown below:
import { Glue, is } from "ts-glue";
const glue =
Glue.buildFrom(
{
clock: is<Clock>,
}
).registerService('clock', systemClock);
Our glue is now ready for use!
It can be used like a regular glue:
const clock: Clock = glue.getService('clock');
But the ts-glue
sweet spot comes with functions that can be partially applied as shown below:
const doHelloWorld = (clock: Clock) => (name: string) => `Hello world ${name} (${clock()})`;
const helloWorld = glue.inject(doHelloWorld, ['clock']);
helloWorld('Glue');
Our helloWorld() is now ready for use. If we want to inject dependencies into an object instead of a function, we need to use Glue.build() instead of Glue.inject():
const buildHelloWorld = (clock: Clock) => ({
sayHello: (name: string) => `Hello world ${name} (${clock()})`;
}):
const helloWorld = glue.build(buildHelloWorld, ['clock']);
helloWorld.sayHello('Glue');
Glue functions such as registerService() or inject(). This means that if you do a typo, TypeScript will yell at you!
import { Glue, is } from "ts-glue";
const glue =
Glue.buildFrom(
{
clock: is<Clock>,
}
)
const doHelloWorld = (clock: Clock) => (name: string) => `Hello world ${name} (${clock()})`;
glue.registerService('cloq', systemClock); // Compilation error
glue.registerService('clock', () => 'string')); // Compilation error
glue.inject(doHelloWorld, ['cloq']); // compilation error
glue.inject(doHelloWorld, []); // compilation error
You can also ask ts-glue
to check that your configuration is complete:
import { Glue, is } from "ts-glue";
const glue =
Glue.buildFrom(
{
clock: is<Clock>,
dbConfiguration: is<DbConfiguration>
}
).registerService('clock', systemClock);
// compilation error, dbConfiguration is missing
glue.checkAllServicesAreRegistered();
const glue2 = glue.registerService('clock', someDbConfiguration);
// compilation OK
glue2.checkAllServicesAreRegistered();
TODO playground
ts-glue is very lazy :-)
Function dependencies are resolved at the very last moment, which is when they get executed. This means that you do
not have to worry too much ot the sequence order of injections and registrations:
import { Glue, is } from "ts-glue";
type Random = () => number;
const doGiveMeANumber = (random: Random) => `A random number ${random()}`
const glue =
Glue.buildFrom(
{
randomGenerator: is<Random>,
}
).registerService('randomGenerator', Math.random);
const giveMeANumber = glue.inject(doGiveMeANumber, ['randomGenerator']);
glue.registerService('randomGenerator', () => 42);
giveMeANumber(); // A random number 42
In the example above, we first build a glue, we register a first random number generator and we retrieve an injected version of the giveMeANumber() function. Then we override the registered random number generator. Since dependency injection is lazy, since dependencies are resolved each time an injected function get executed, giveMeANumber() calls the very last registered random generator.
ts-glue lazyness is very handy when one part of your codebase is managed by ts-glue
but not everything.
We have included in the example folder an Express express example app that demonstrate how to use components managed by ts-glue
from Express routes that are out of the scoe of ts-glue
.
Any significant codebase is splitted into several modules, packages... well it should be ;)
A big monolythic dependency injection configuration file quickly becomes hard to maintain. Hence ts-glue
allows you to split your configuration in several files, composing your Glue from several sub Glue instances:
// Let's say we have a booking package in our codebase
// booking.ts
export const bookingGlue =
Glue.buildFrom(
{
bookingService: is<BookingService>,
dbConfiguration: is<DbConfiguration>,
...
}
).registerService(
'bookingService',
someBookingServiceImplementation
);
// Let's say we have also a billing package in our codebase
// billing.ts
export const billingGlue =
Glue.buildFrom(
{
billingService: is<BillingService>,
dbConfiguration: is<DbConfiguration>,
...
}
).registerService(
'billingService',
someBillingServiceImplementation
);
// Then at the entry point of our application
// we can gather our two previous glues
const appGlue = Glue.compose(
bookingGlue,
billingGlue
);
// appGlue can inject 'bookingService' and 'billingService'
const megaSagaService =
appGlue.inject(
...,
['bookingService', 'billingService']
)
// at that point line below fails to compile because
// dbConfiguration has not been registered
appGlue
// Now it's ok and the dbConfiguration is registered
// into both bookingGlue and billingGlue
appGlue
.registerService('dbConfiguration', SomeDbConfig)
.checkAllServicesAreRegistered();
TBC
FAQs
TypeScript opinionated dependency injection library. Glue is a tiny lightweight library made for FP codebases making extensive use of partial application for dependency injection.
We found that ts-glue demonstrated a healthy version release cadence and project activity because the last version was released less than a year ago. It has 0 open source maintainers collaborating on the project.
Did you know?
Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.
Security News
RubyGems.org has added a new "maintainer" role that allows for publishing new versions of gems. This new permission type is aimed at improving security for gem owners and the service overall.
Security News
Node.js will be enforcing stricter semver-major PR policies a month before major releases to enhance stability and ensure reliable release candidates.
Security News
Research
Socket's threat research team has detected five malicious npm packages targeting Roblox developers, deploying malware to steal credentials and personal data.