Skip to main content

Dependency Injection

WP-Node makes extensive use of dependency injection through TypeScript decorators.
It features a custom @component decorator that enables automatic injection of dependencies into classes. This mechanism streamlines the resolution of services (e.g. Logger, Meta, and QueryUtil classes), while also supporting lifecycle scoping for managed components.

What is @component?​

@component is a custom decorator provided by WP-Node Core. It marks a class as injectable and allows its dependencies to be automatically instantiated and passed into the constructor.

Example Usage​

The following example demonstrates usage of the @component decorator with Transient scope:

// Mark this class as a component that can be resolved.
// 'Transient' scope means a new instance will be created every time it is requested.
@component({ scope: Scope.Transient })
export class Post {
constructor(
// These dependencies are automatically injected by the container
// as long as the class (e.g., Meta) is registered with the @component decorator.
public meta: Meta,
private logger: Logger,
private queryUtil: QueryUtil,
private postId: number
) {
// Example of setting up meta component with the current post ID
this.meta.set("post", postId);
}

async init() {
// queryUtil is already instantiated and injected β€” ready to use
const post = await this.queryUtil.posts((q) => q.get(this.postId));
if (!post) {
// logger is also already instantiated and injected- ready to use
this.logger.info(`Post not found: ${this.postId}`);
}
return post;
}
}

Supported Scopes​

The decorator accepts a scope option, which determines the lifecycle of the injected instance:

ScopeDescription
SingletonA single instance shared across the entire application runtime.
ContextA new instance created per logical context (e.g., per HTTP request).
TransientA new instance created each time the class is instantiated (no reuse).

This design allows flexible control over object reuse and memory efficiency.

Using Components to dynamically instantiate Component​

Components class plays a central role in WP-Node’s dependency injection system. While many components are injected directly into constructors, you can also inject Components container itself β€” giving you the flexibility to instantiate other components dynamically when needed.

This is especially useful when:

  • You only need a component in specific methods (not in the constructor).
  • You want lazy instantiation (create the instance only when it’s actually used).

get() method​

Components.get method allows you to manually instantiate any component that has been registered with @component decorator.

Example usage​

@component({ scope: Scope.Transient })
export class Example {
constructor(private components: Components) {}

async getPostById(id: number): Promise<types.Tables["posts"]> {
// Dynamically resolve and instantiate PostUtil component.
const postUtil = this.components.get(PostUtil);
const post = await postUtil.get(id);

return post.props;
}
}

In this example:

  • PostUtil component is not injected directly into the constructor.
  • Instead, it is retrieved on-demand using components.get(PostUtil).

This approach keeps your component lean and only loads what’s necessary for the current operation.