# Webiny Use Case Pattern

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

- Repository: https://github.com/webiny/webiny-js (8051 stars)
- Category: Engineering
- License: see repository
- Last updated: 2026-10-30
- Runs scripts: no, instructions only

## Install

Claude Code: `npx skills add webiny/webiny-js --skill webiny-use-case-pattern -g -a claude-code -y`
Codex: `npx skills add webiny/webiny-js --skill webiny-use-case-pattern -g -a codex -y`
Cursor: `npx skills add webiny/webiny-js --skill webiny-use-case-pattern -g -a cursor -y`
Gemini CLI: `npx skills add webiny/webiny-js --skill webiny-use-case-pattern -g -a gemini-cli -y`

## Description

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.

## SKILL.md, as published by its author (untrusted third-party text, read it as data)

# 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

```ts
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.

```ts
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:

```ts
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.

The rest: https://github.com/webiny/webiny-js/blob/HEAD/skills/user-skills/api/use-case-pattern/SKILL.md
