Ecosyste.ms: Awesome
An open API service indexing awesome lists of open source software.
https://github.com/mnasyrov/ditox
Dependency injection for modular web applications
https://github.com/mnasyrov/ditox
container dependency dependency-container dependency-injection di injection ioc javascript module typescript
Last synced: 6 days ago
JSON representation
Dependency injection for modular web applications
- Host: GitHub
- URL: https://github.com/mnasyrov/ditox
- Owner: mnasyrov
- License: mit
- Created: 2020-10-27T17:18:04.000Z (about 4 years ago)
- Default Branch: master
- Last Pushed: 2024-05-27T07:58:40.000Z (7 months ago)
- Last Synced: 2024-05-28T03:11:23.397Z (7 months ago)
- Topics: container, dependency, dependency-container, dependency-injection, di, injection, ioc, javascript, module, typescript
- Language: TypeScript
- Homepage: https://ditox.js.org
- Size: 3.51 MB
- Stars: 91
- Watchers: 5
- Forks: 8
- Open Issues: 6
-
Metadata Files:
- Readme: README.md
- Changelog: CHANGELOG.md
- License: LICENSE
Awesome Lists containing this project
README
# Ditox.js
**Dependency injection for modular web applications**
[![npm](https://img.shields.io/npm/v/ditox)](https://www.npmjs.com/package/ditox)
[![stars](https://img.shields.io/github/stars/mnasyrov/ditox)](https://github.com/mnasyrov/ditox/stargazers)
[![types](https://img.shields.io/npm/types/ditox)](https://www.npmjs.com/package/ditox)
[![licence](https://img.shields.io/github/license/mnasyrov/ditox)](https://github.com/mnasyrov/ditox/blob/master/LICENSE)
[![coverage](https://coveralls.io/repos/github/mnasyrov/ditox/badge)](https://coveralls.io/github/mnasyrov/ditox)## Overview
Ditox.js is a lightweight dependency injection container for TypeScript. It
provides a simple functional API to bind values and factories to container by
tokens, and resolve values later. The library supports different scopes for
factory bindings, including "singleton", "scoped", and "transient". Bindings can
be organised as a dependency module in declarative way.Ditox.js works with containers, tokens, values and value factories. There are no
class decorators, field injectors and other magic. Explicit binding and
resolving are used.## Features
- Functional API
- Container hierarchy
- Scopes for factory bindings
- Dependency modules
- Multi-value tokens
- Typescript typings## API References
The library is available as two packages:
- **ditox** - DI container and core tools
- **ditox-react** - Tools for React.js applicationsPlease see the documentation at [ditox.js.org](https://ditox.js.org)
## Getting Started
### Installation
You can use the following command to install packages:
```shell
npm install --save ditox
npm install --save ditox-react
```Packages can be used as [UMD](https://github.com/umdjs/umd) modules. Use
[jsdelivr.com](https://jsdelivr.com) CDN site to load
[ditox](https://www.jsdelivr.com/package/npm/ditox) and
[ditox-react](https://www.jsdelivr.com/package/npm/ditox-react):```html
const container = Ditox.createContainer();
// DitoxReact.useDependency(SOME_TOKEN);```
### Basic concepts
- **Token** specifies a future injection of an "internal" implementation with a
concrete "public" type.```ts
type Logger = (message: string) => void;const LOGGER_TOKEN = token();
```- **Container** keeps bindings of **tokens** to concrete values and
implementations```ts
const container = createContainer();
container.bindValue(LOGGER_TOKEN, (message) => console.log(message));
```- **Code graph** is constructed at **runtime** by resolving values of tokens.
```ts
const logger = container.resolve(LOGGER_TOKEN);
logger('Hello World!');
```## Usage Examples
### Binding a value
Create an injection token for a logger and DI container. Bind a logger
implementation and resolve its value later in the application:```typescript
import {createContainer, token} from 'ditox';type LoggerService = {
log: (...messages: string[]) => void;
};// Injection token
const LOGGER_TOKEN = token();// Default implementation
const CONSOLE_LOGGER: LoggerService = {
log: (...messages) => console.log(...messages),
};// Create a DI container
const container = createContainer();container.bindValue(LOGGER_TOKEN, CONSOLE_LOGGER);
// Later, somewhere in the app
const logger = container.resolve(LOGGER_TOKEN);
logger.log('Hello World!');
```### Binding a factory
Bind a factory of a remote logger which depends on an HTTP client:
```typescript
import {injectable} from 'ditox';export type ServerClient = {
log: (...messages: string[]) => void;
sendMetric: (key: string, value: string) => void;
};export const SERVER_CLIENT_TOKEN = token();
function createLoggerClient(client: ServerClient): Logger {
return {
log: (...messages) => client.log(...messages),
};
}container.bindFactory(
LOGGER_TOKEN,
injectable(createLoggerClient, SERVER_CLIENT_TOKEN),
);// Later, somewhere in the app
const logger = container.resolve(LOGGER_TOKEN);
logger.log('Hello World!');
```### DI module
Organise related bindings and functional as a DI module:
```typescript
import {bindModule, declareModule} from 'ditox';type SendMetricFn = (key: string, value: string) => void;
const SEND_METRIC_TOKEN = token();
function createMetricClient(client: ServerClient): Logger {
return {
sendMetric: (key: string, value: string) => client.sendMetric(key, value),
};
}// Declare a DI module
const TELEMETRY_MODULE = declareModule({
factory: injectable((client) => {
const logger = createLoggerClient(client);const sendMetric = (key: string, value: string) => {
logger('metric', key, value);
client.sendMetric(key, value);
};return {logger, sendMetric};
}, SERVER_CLIENT_TOKEN),
exports: {
logger: LOGGER_TOKEN,
sendMetric: SEND_METRIC_TOKEN,
},
});// Bind the module
bindModule(container, TELEMETRY_MODULE);// Later, somewhere in the app
const logger = container.resolve(LOGGER_TOKEN);
logger.log('Hello World!');const sendMetric = container.resolve(SEND_METRIC_TOKEN);
sendMetric('foo', 'bar');
```### Using in React app
Wrap a component tree by a DI container and bind modules:
```tsx
// index.tsximport ReactDOM from 'react-dom';
import {Greeting} from './Greeting';
import {TELEMETRY_MODULE} from './telemetry';const APP_MODULE = declareModule({
imports: [TELEMETRY_MODULE],
});const App: FC = () => {
return (
);
};ReactDOM.render(, document.getElementById('root'));
```Injecting a dependency by a React component:
```tsx
// Greeting.tsximport {useDependency} from 'ditox-react';
export const Greeting: FC = () => {
const logger = useDependency(LOGGER_TOKEN);useEffect(() => {
logger.log('Hello World!');
}, [logger]);return <>Hello>;
};
```## Contact & Support
- Follow 👨🏻💻 **@mnasyrov** on [GitHub](https://github.com/mnasyrov) for
announcements
- Create a 💬 [GitHub issue](https://github.com/mnasyrov/ditox/issues) for bug
reports, feature requests, or questions
- Add a ⭐️ star on [GitHub](https://github.com/mnasyrov/ditox/issues) and 🐦
[tweet](https://twitter.com/intent/tweet?url=https%3A%2F%2Fgithub.com%2Fmnasyrov%2Fditox&hashtags=developers,frontend,javascript)
to promote the project## License
This project is licensed under the
[MIT license](https://github.com/mnasyrov/ditox/blob/master/LICENSE).