Security News
PyPI Introduces Digital Attestations to Strengthen Python Package Security
PyPI now supports digital attestations, enhancing security and trust by allowing package maintainers to verify the authenticity of Python packages.
dependency-injection-cat
Advanced tools
DI Cat is a truly clean DI-container, which allows you not to pollute your business logic with decorators from DI/IOC libraries!
DI Cat is a truly clean DI-container, which allows you not to pollute your business logic with decorators from DI/IOC libraries!
//ApplicationContext.di.ts
export class ApplicationContext extends CatContext<IBeans> {
useCase = Bean<IUseCase>(UseCase)
mobxRepository = Bean<IRepository>(MobxRepository)
}
//UseCase.ts
export class UseCase implements IUseCase {
constructor(
private repository: IRepository,
) {}
makeBusinessLogic() {}
}
//Your application.tsx
export const UIComponent: React.FC = () => {
const appContext = container.getContext<IBeans>({name: 'ApplicationContext'});
const {useCase} = appContext.getBeans();
return (
<button onClick={useCase.makeBusinessLogic}> Click me! </button>
)
}
yarn add dependency-injection-cat
npm install dependency-injection-cat
//tsconfig.json
{
"compilerOptions": {
"baseUrl": "Base url should be specified!"
}
}
//webpack.config.js
const DiCatWebpackPlugin = require('dependency-injection-cat/plugins/webpack').default;
const DiCatBabelTransformer = require('dependency-injection-cat/transformers/babel');
module.exports = {
//...
module: {
rules: [
{
test: /\.(t|j)sx?$/,
loader: 'babel-loader',
options: {
//Should be false, because babel caching files
//and don't call di-cat babel transformer, if your not *.di.* files was changed
cacheDirectory: false,
plugins: [
[
DiCatBabelTransformer,
{
//Here is configuration options, see below
}
]
]
}
}
]
},
plugins: [
//Without this plugin, a compilation with DI errors will be successful
new DiCatWebpackPlugin(),
]
}
//tsconfig.json
{
"compilerOptions": {
//Should be specified
"baseUrl": "your base url"
}
}
//webpack.config.js
const DiCatWebpackPlugin = require('dependency-injection-cat/plugins/webpack').default;
const diCatTransformer = require('dependency-injection-cat/transformers/typescript').default;
module.exports = {
//...
module: {
rules: [
{
test: /\.(t|j)sx?$/,
use: {
loader: 'ts-loader',
options: {
getCustomTransformers: (program) => ({
before: [diCatTransformer(program, {
//Here is configuration options, see below
})],
}),
}
}
}
]
},
plugins: [
//Without this plugin, a compilation with DI errors will be successful
new DiCatWebpackPlugin(),
]
}
//tsconfig.json
{
"compilerOptions": {
//Should be specified
"baseUrl": "your base url"
}
}
//webpack.config.js
const DiCatWebpackPlugin = require('dependency-injection-cat/plugins/webpack').default;
module.exports = {
//...
module: {
rules: [
{
test: /\.(t|j)sx?$/,
use: {
loader: 'ts-loader',
options: {
compiler: 'ttypescript'
}
}
}
]
},
plugins: [
//Without this plugin, a compilation with DI errors will be successful
new DiCatWebpackPlugin(),
]
}
//tsconfig.json
{
"compilerOptions": {
//Should be specified
"baseUrl": "your base url",
"plugins": [
{
"transform": "dependency-injection-cat/transformers/typescript",
//Here is configuration options, see below
}
]
}
}
//tsconfig.json
{
"compilerOptions": {
//Should be specified
"baseUrl": "your base url",
"plugins": [
{
"transform": "dependency-injection-cat/transformers/typescript",
//Here is configuration options, see below
},
{
"transform": "dependency-injection-cat/plugins/typescript/ReportErrorsTypescriptPlugin"
}
]
}
}
{
diConfigPattern: string | undefined; // Glob pattern, default value. Default: '**/*.di.ts'
ignorePatterns: Array<string> | undefined; // Array of Glob patterns, default value. Default: ['**/node_modules/**']
disableLogoPrint: boolean | undefined; // Disable exposing dependency-injections-cat logo into console
}
Currently correct hot reload supported only with DI-Cat Webpack plugin, and for non-global CatContexts.
CatContext it's a place, where you should define your Beans
class CatContext<TBeans, TConfig = null> {}
Name of context should be unique
Name of context "Global" is preserved for DI container, see GlobalCatContext
TBeans is an interface, of Beans that will be given out of context. Should be the same as in container access calls.
Should be a plain interface without extending, should not have indexed signatures
Should be placed in your source files, not from node_modules
Bean name should not be getBean or getBeans, it's reserved names for di-container
export interface IBeans {
useCase: IUseCase;
//Another beans...
}
If you need to pass additional parameters to your classes, for example ID, or something else, you should specify a type for TConfig (default is null)
export interface IConfig {
id: string;
}
class ApplicationContext extends CatContext<IBeans, IConfig> {
@Bean
useCase(): IUseCase {
const {id} = this.config;
return new UseCase(id);
}
}
Sometimes you want to describe common dependencies that will be used all across your application, for these purposes you should use GlobalCatContext.
//GlobalApplicationContext.di.ts
export class GlobalApplicationContext extends GlobalCatContext {
@Bean
logger(): ILogger {
return new Logger();
}
}
//ApplicationContext.di.ts
export class AppContext extends CatContext<IBeans> {
@Bean
useCase(
//If Bean for ILogger will be defined in current context, bean from current context will be injected
logger: ILogger
): IUseCase {
return new UseCase(logger)
}
}
Using container you can control your contexts. You can't access container inside files where declared contexts.
TBeans is an interface, of Beans that will be given out of context. Should be the same as in CatContext.
InitContext creates instance of context by key (if specified). Also you can pass config to your context using initContext.
container.initContext<TBeans, TConfig>({
key?: any, //Can be any value, you can use it for creating pool of contextMap.
name: string, //It's the name of the class in which you specified the Beans. Should be a string literal.
config?: TConfig, //Config that will be transferred to the context
});
//InitContext without config and keys
import { container } from 'dependency-injection-cat';
import { IBeans } from './IBeans';
const applicationContext = container.initContext<IBeans>({ name: 'ApplicationContext' });
//InitContext with config and keys
import { container } from 'dependency-injection-cat';
import { IBeans } from './IBeans';
import { IConfig } from './IConfig';
const applicationContextBySomeKey = container.initContext<IBeans, IConfig>({
name: 'ApplicationContext',
key: 'userId',
config: { userId: 'userId' },
});
getContext returns instance of context by key (if specified). Can be used only after initialization of context, or error will be thrown.
container.getContext<TBeans>({
key?: any,
name: string, //It's the name of the class in which you specified the Beans. Should be a string literal.
});
//GetContext without keys
import { container } from 'dependency-injection-cat';
const context = container.getContext<TBeans>({ name: 'ApplicationContext' });
//GetContext with keys
import { container } from 'dependency-injection-cat';
const context = container.getContext<TBeans>({
name: 'ApplicationContext',
key: 'userId',
});
clearContext should be used to clear instances of Beans. Can be used, for example when un-mounting components.
container.clearContext({
name: string, //It's the name of the class in which you specified the Beans. Should be a string literal.
key?: any,
})
//ClearContext without keys
import { container } from 'dependency-injection-cat';
container.clearContext({ name: 'ApplicationContext' });
//ClearContext without keys
import { container } from 'dependency-injection-cat';
container.clearContext({
name: 'ApplicationContext',
key: 'userId',
});
A Bean is an object that is instantiated, assembled, and managed by IOC container (Definition from Spring Framework documentation) Beans can have dependencies, and they also should be defined as a beans or passed manually.
interface IBeanConfiguration {
scope?: 'prototype' | 'singleton';
/* Should be a string literal. Default value is 'singleton'. When singleton, will be created only 1 instance of the Bean, when 'prototype', for each getting of Bean will be created a new instance */
}
Property Beans resolving class dependencies automatically from the constructor of a class that passed to Bean.
export class ApplicationContext extends CatContext<IBeans> {
//First argument passed in Bean should be a class, di-container will try to resolve class dependencies
useCase = Bean(UseCaseClass);
//To specify type of Bean you can use Generic parameter, or set type of property
useCase = Bean<IUseCase>(UseCase);
useCase: IUseCase = Bean(UseCase);
useCase: IUseCase = Bean<IUseCase>(UseCase);
//If type is not specified, class will be used as a type
useCase = Bean(UseCaseClass)
//Equivalent to
useCase = Bean<UseCaseClass>(UseCaseClass)
useCase: UseCaseClass = Bean(UseCaseClass)
useCase: UseCaseClass = Bean<UseCaseClass>(UseCaseClass)
//Bean configuration should be passed as a second argument. Should be an object literal.
useCase: IUseCase = Bean(UseCase, {scope: 'prototype'});
}
//UseCaseDependency
export class UseCaseDependency implements IUseCaseDependency {
//...businessLogic
}
//UseCase.ts
export class UseCase implements IUseCase {
constructor(
//Any name can be used
private useCaseDependency: IUseCaseDependency,
) {
}
//...businessLogic
}
//ApplicationContext.di.ts
import { CatContext, Bean } from 'dependency-injection-cat';
export class ApplicationContext extends CatContext<IBeans> {
useCaseDependency = Bean<IUseCaseDependency>(UseCaseDependency);
useCase = Bean<IUseCase>(UseCase);
}
Method Beans are more flexible, for example it allows you to pass configuration values to your class constructor.
export class ApplicationContext extends CatContext<IBeans> {
//Bean don't have any dependencies
@Bean
useCase(): IUseCase {
return new UseCase();
}
//Bean have dependencies
dependency: IUseCaseDependency = Bean(UseCaseDependency);
@Bean
useCase(
useCaseDependency: IUseCaseDependency,
): IUseCase {
return new UseCase(useCaseDependency);
}
//Configure Bean
@Bean({ scope: 'prototype' })
useCase(): IUseCase {
return new UseCase();
}
}
Qualifier needed, when you have 2 or more Beans in the Context with same type. By default, the qualifier is the name of the parameter in the class constructor, or in the Method Bean` Also, you can use qualifier, when injecting Beans from GlobalCatContext
//Implicit declaration of the qualifier
export class ApplicationContext extends CatContext<IBeans> {
httpRequester: IRequester = Bean(HttpRequester);
graphQLRequester: IRequester = Bean(GraphQLRequester);
@Bean
useCase(
graphQLRequester: IRequester, //Will be injected implementation "GraphQLRequester"
): IUseCase {
return new UseCase(graphQLRequester);
}
}
//When Bean placed in current context
export class ApplicationContext extends CatContext<IBeans> {
httpRequester: IRequester = Bean(HttpRequester);
graphQLRequester: IRequester = Bean(GraphQLRequester);
@Bean
useCase(
@Qualifier('graphQLRequester') requester: IRequester,
): IUseCase {
return new UseCase(requester);
}
}
//When Bean placed in Global context
//GlobalApplicationContext.di.ts
export class GlobalApplicationContext extends GlobalCatContext {
graphQLRequester: IRequester = Bean(GraphQLRequester);
httpRequester: IRequester = Bean(HttpRequester);
}
//ApplicationContext.di.ts
export class ApplicationContext extends CatContext<IBeans> {
@Bean
useCase(
@Qualifier('graphQLRequester') requester: IRequester,
): IUseCase {
return new UseCase(requester);
}
}
0.2.0
FAQs
DI Cat is a truly clean DI-container, which allows you not to pollute your business logic with decorators from DI/IOC libraries!
The npm package dependency-injection-cat receives a total of 17 weekly downloads. As such, dependency-injection-cat popularity was classified as not popular.
We found that dependency-injection-cat demonstrated a not healthy version release cadence and project activity because the last version was released a year ago. It has 1 open source maintainer 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
PyPI now supports digital attestations, enhancing security and trust by allowing package maintainers to verify the authenticity of Python packages.
Security News
GitHub removed 27 malicious pull requests attempting to inject harmful code across multiple open source repositories, in another round of low-effort attacks.
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.