WHAT YOU'LL LEARN
  • How to create an abstraction in Webiny?
  • How to create an implementation of an abstraction?
  • How to declare dependencies?
  • How to use the decorator pattern?

Overview
anchor

Webiny uses @webiny/di, a type-safe dependency injection container built for SOLID principles. The core concept is Abstraction<T>, which unifies tokens and types for compile-time safety. As a developer, you create implementations using createImplementation() and export them.

Creating an Abstraction
anchor

An abstraction is a type-safe token that represents an interface. Use createAbstraction() to create one:

Naming Convention:

  • The abstraction name typically matches the interface name without the I prefix
  • Use a prefix to organize abstractions by domain (e.g., Library/BookRepository, Store/CreateOrder)

Namespace Pattern: Use a namespace with the same name as the abstraction to export related types. Export everything implementers will need - the interface, domain types, input/output types, etc. This allows consumers to use BookRepository.Interface and BookRepository.Book without additional imports.

Advanced Namespace Pattern
anchor

For more complex abstractions like use cases, you can organize additional types in the namespace:

This pattern allows consumers to reference all related types through the abstraction:

  • CreateBookUseCase.Interface - for implementing the use case
  • CreateBookUseCase.Input - for the input parameters
  • CreateBookUseCase.Error - for error types
  • CreateBookUseCase.Return - for the return type
  • CreateBookUseCase.Book, CreateBookUseCase.Author, CreateBookUseCase.Category - domain types needed by implementers

Key Principle: Export everything an implementer needs. This creates a complete, self-contained abstraction where consumers only need to import the abstraction itself.

Creating an Implementation
anchor

Use createImplementation() from the abstraction to bind your class to it. This method is available on every abstraction and requires three properties:

With Dependencies
anchor

Dependencies are declared in the constructor and must match the dependencies array order:

Using Decorators
anchor

Decorators extend behavior without modifying the original implementation. Use createDecorator() from the abstraction to wrap existing functionality:

Key Point: The decorator’s last constructor parameter must be the type being decorated. The decoratee is automatically injected - you only list other dependencies in the dependencies array.

Key Points
anchor

Dependency Order Matters
anchor

The order in the dependencies array must exactly match the constructor parameter order:

Always Use .Interface Types
anchor

Constructor parameters should use the .Interface type from the abstraction:

Export the Implementation
anchor

Always export the result of createImplementation() or createDecorator():