Ecosyste.ms: Awesome
An open API service indexing awesome lists of open source software.
https://github.com/smonn/container
Easy to use dependency injection container.
https://github.com/smonn/container
dependency-injection javascript nodejs typescript
Last synced: 22 days ago
JSON representation
Easy to use dependency injection container.
- Host: GitHub
- URL: https://github.com/smonn/container
- Owner: smonn
- License: mit
- Created: 2022-03-31T02:08:10.000Z (almost 3 years ago)
- Default Branch: main
- Last Pushed: 2023-03-01T12:59:42.000Z (almost 2 years ago)
- Last Synced: 2024-12-06T10:46:37.959Z (about 2 months ago)
- Topics: dependency-injection, javascript, nodejs, typescript
- Language: TypeScript
- Homepage: https://www.npmjs.com/package/@smonn/container
- Size: 826 KB
- Stars: 2
- Watchers: 2
- Forks: 0
- Open Issues: 13
-
Metadata Files:
- Readme: README.md
- Changelog: CHANGELOG.md
- License: LICENSE.md
Awesome Lists containing this project
README
# @smonn/container
Dependency injection container. Attempts to avoid fixed dependencies via decorators. It also always returns the same instance unless you explicitly ask for a new instance. Instances are lazily created, meaning nothing is created until you request an instance. TypeScript optional, but attempts to infer types as much as possible.
## Install
```sh
npm install @smonn/container
``````sh
yarn add @smonn/container
```## Usage
Example usage. See more examples in the test files.
```ts
import { expect, test } from "vitest";
import { createContainer, createToken, IContainer } from "../src/index";// Interfaces are optional, but can help to ensure you depend on abstractions only.
interface IGreeter {
sayHello(): string;
}
interface IShouter {
shoutHello(): string;
}class Greeter implements IGreeter {
// Can either define tokens along with the class implementation...
static token = createToken("greeter");constructor(private readonly name: string) {}
sayHello(): string {
return `Hello, ${this.name}!`;
}
}class Shouter implements IShouter {
static token = createToken("shouter");constructor(private readonly greeter: IGreeter) {}
shoutHello(): string {
return this.greeter.sayHello().toUpperCase();
}
}class Other {
ping() {
return "pong";
}
}// Or define token types in a central location to help avoid circular imports.
const Tokens = {
// Token type can also be inferred from the function signature
name: createToken("name", String),// Or use explicit type and infer name from class
other: createToken("other", Other),
} as const;// Group together related classes in a single function to avoid a single
// massive function defining hundreds of dependencies. Also note that thanks to
// the token spec, explicitly declaring the generic type is not required.
function provideModule(container: IContainer) {
// Literal/basic values are allowed
container.set(Tokens.name, "Joy");
container.set(Tokens.other, new Other());// Use factory functions to help resolve dependencies
container.set(Greeter.token, (c) => new Greeter(c.get(Tokens.name)));
container.set(Shouter.token, (c) => new Shouter(c.get(Greeter.token)));
}const container = createContainer();
container.register(provideModule);// Here shouter will have the correct type (the IShouter interface)
const shouter = container.get(Shouter.token);test('returns "HELLO, JOY!"', () => {
expect(shouter.shoutHello()).toBe("HELLO, JOY!");
});test("always get the same instance", () => {
expect(container.get(Shouter.token)).toBe(container.get(Shouter.token));
});test("always get a new instance", () => {
expect(container.create(Shouter.token)).not.toBe(
container.create(Shouter.token)
);
});test("other will never create a new instance", () => {
expect(container.create(Tokens.other)).toBe(container.create(Tokens.other));
});
```