@fozy-labs/simplest-di
v0.2.3
Published
Простейшая система внедрения зависимостей для React-приложений с поддержкой RxJS.
Maintainers
Readme
@fozy-labs/simplest-di
Простейшая система внедрения зависимостей (DI) для TypeScript с поддержкой React и RxJS.
📦 Установка
npm install @fozy-labs/simplest-diPeer-зависимости
| Зависимость | Версия | Обязательность |
|---|---|---|
| rxjs | ^7.0.0 | Обязательна |
| react | ^19.0.0 | Опционально (только для React-интеграции) |
🚀 Быстрый старт
Базовый пример: Singleton-сервис
import { injectable, inject } from '@fozy-labs/simplest-di';
@injectable('SINGLETON')
class ApiClient {
fetch(url: string) { /* ... */ }
}
// Первый вызов создаёт экземпляр
const client1 = inject(ApiClient);
// Второй вызов возвращает тот же экземпляр
const client2 = inject(ApiClient);
// client1 === client2 → trueКонтракты через inject.define
import { inject, injectable } from '@fozy-labs/simplest-di';
interface ChatDataSource {
fetchChatMessages(): Promise<string[]>;
}
@injectable('SINGLETON')
class CloudChatDataSource implements ChatDataSource {
fetchChatMessages() {
return Promise.resolve(['cloud']);
}
}
const ChatDataSource = inject.define<ChatDataSource>('ChatDataSource');
ChatDataSource.bind(CloudChatDataSource);
const dataSource = inject(ChatDataSource);Контрактом является сам объект, возвращённый inject.define(). Имя используется для диагностики, а bind() нужно вызвать до первого inject(contract). Если контракт не привязан, первый inject(contract) завершится ранней ошибкой.
React: DiScopeProvider
import { setupReactDi, DiScopeProvider, injectable, inject } from '@fozy-labs/simplest-di';
// Вызвать один раз при старте приложения
setupReactDi();
@injectable('SCOPED')
class AppStore {
count = 0;
}
function Counter() {
const store = inject(AppStore);
return <div>{store.count}</div>;
}
function App() {
return (
<DiScopeProvider provide={[AppStore]}>
<Counter />
</DiScopeProvider>
);
}✨ Особенности
- 🔄 Три режима жизненного цикла —
SINGLETON,TRANSIENT,SCOPED - 🧩 Контракты интерфейсов —
inject.define<T>(name)для выбора реализации без нового named export - 🌳 Иерархия скоупов — Родительские и дочерние скоупы с наследованием зависимостей
- ⚛️ React-интеграция —
DiScopeProviderдля управления скоупами в React-дереве - 🎨 Stage 3 декораторы — TC39 декораторы, без
experimentalDecorators - 🧪 Изоляция тестов —
resetRegistry()для очистки синглтон-состояния между тестами - 🔷 TypeScript-first — Полная типизация
📚 Документация
- Концепции DI — жизненные циклы, скоупы, контракты, обнаружение циклов
- React-интеграция — setupReactDi, DiScopeProvider, scoped-контракты
- CHANGELOG — история изменений
📖 API
Основные экспорты
| Экспорт | Тип | Описание |
|---|---|---|
| inject | Функция | Разрешение зависимости по токену (классу или контракту) |
| inject.define | Метод | Создание контрактного токена с последующим bind() |
| inject.provide | Метод | Явная регистрация зависимости в скоупе |
| injectable | Декоратор | Помечает класс метаданными DI (lifetime, опции) |
| Scope | Класс | Контейнер скоупа с иерархией и жизненным циклом |
| resetRegistry | Функция | Очистка синглтон-реестра (для тестов) |
| getInjectorName | Функция | Получение имени родительского инжектора (отладка) |
Классы ошибок
| Экспорт | Описание |
|---|---|
| CircularDependencyError | Обнаружена циклическая зависимость |
| NonCompatibleParentError | SCOPED-зависимость в SINGLETON/TRANSIENT-контексте |
| MustBeProvidedError | Зависимость с requireProvide: true не предоставлена |
React-интеграция
| Экспорт | Тип | Описание |
|---|---|---|
| setupReactDi | Функция | Инициализация DI для React (вызвать один раз) |
| DiScopeProvider | React-компонент | Создаёт дочерний скоуп в React-дереве |
Типы
| Экспорт | Описание |
|---|---|
| InjectionLifetime | 'SINGLETON' \| 'TRANSIENT' \| 'SCOPED' |
| InjectableOptions<T> | Опции для @injectable() (строка или объект) |
| InjectableDetailedOptions<T> | Подробные опции: lifetime, onScopeInit, requireProvide |
| InjectOptions<T> | Полный дескриптор для ручной регистрации |
| InjectComputedOptions<T> | Нормализованная форма InjectOptions |
| ProvideOptions<T> | Тип аргумента inject() / inject.provide() |
| Injectable | Тип класса с метаданными @injectable() |
| InjectableOptionsSymbol | Тип символа INJECTABLE_OPTIONS |
| InjectingInstanceSymbol | Тип символа INJECTING_INSTANCE |
| DiScopeProviderProps | Props для DiScopeProvider |
⚙️ Требования TypeScript
- TypeScript ≥ 5.0
- Не включать
experimentalDecorators— библиотека использует TC39 Stage 3 декораторы - В
tsconfig.jsonне нужны дополнительные настройки для декораторов
