Skills

Webiny Use Case Pattern

UseCase implementation pattern, DI, Result handling, error types, decorators, CMS...

Install

npx skills add webiny/webiny-js --skill webiny-use-case-pattern -g -a claude-code -y
Repository
webiny/webiny-js8.1k
Category
Engineering
Updated
5d ago
License
See repository
Context cost
Mediumabout 3,000 tokens
Runs scripts
No, instructions only

What it does

UseCase implementation pattern, DI, Result handling, error types, decorators, CMS repositories, entry mappers, and schema-based permissions. Use this skill to implement, inject, override, or decorate any Webiny UseCase, or to build repositories that persist data via CMS.

UseCase Pattern

What It Is

A UseCase is a single-method orchestrator that encapsulates one business operation (e.g., CreateTenantUseCase, PublishEntryUseCase). Each UseCase is a DI abstraction with an execute method that returns Result<T, E>.

Interface Shape

interface SomeUseCase.Interface {
    execute(input: Input): Promise<Result<ReturnType, ErrorType>>;
}
  • Input, a typed object specific to the use case
  • Result, always returns Result<T, E> from webiny/api
  • Error, extends BaseError with a unique code

How to Use a UseCase

UseCases are injected as dependencies into EventHandlers, other UseCases, or GraphQL resolvers via DI.

import { SomeUseCase } from "webiny/api/<category>";
import { SomeEventHandler } from "webiny/api/<category>";

class MyHandler implements SomeEventHandler.Interface {
  constructor(private someUseCase: SomeUseCase.Interface) {}

  async handle(event: SomeEventHandler.Event) {
    const result = await this.someUseCase.execute({/* input */});

    if (result.isFail()) {
      console.error(result.error.message);
      return;
    }

    const value = result.value;
    // ... use value
  }
}

export default SomeEventHandler.createImplementation({
  implementation: MyHandler,
  dependencies: [SomeUseCase]
});

How to Override a UseCase

To replace the default implementation, register your own:

import { SomeUseCase } from "webiny/api/<category>";

class CustomImplementation implements SomeUseCase.Interface {
  async execute(input) {
    // Custom logic
    return Result.ok(/* ... */);
  }
}

export default SomeUseCase.createImplementation({
  implementation: CustomImplementation,
  dependencies: []
});

Registration

YOU MUST include the full file path with the .ts extension in the src prop. For example, use src={"@/extensions/my-extension.ts"}, NOT src={"@/extensions/my-extension"}. Omitting the file extension will cause a build failure.

Read the whole SKILL.md on GitHub

More in Engineering