---
title: Custom Source Generators
type: concept
created: 2026-09-06
updated: 2026-09-06
sources: [codebase snapshot 2026-09-06]
tags: [generators, artisan, stubs, tooling]
---

# Custom Source Generators

Because the Domain and Application layers live **outside `app/`**, Laravel's built-in `make:*` commands cannot reach them. Project-Board ships five custom Artisan generators that scaffold the DDD skeleton from templates in `stubs/`.

> **Note on provenance:** reflects the code as of 2026-09-06; no written ADR exists. These generators encode the intended conventions and are the fastest way to see what "correct" DDD scaffolding looks like.

## Commands

Registered in `src/Infrastructure/Providers/ConsoleServiceProvider.php` (via `ConsoleServiceProvider`):

| Command                              | Creates                                                                                                                                                       |
| ------------------------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `make:entity {context} {name}`       | `src/Domain/{Context}/Entities/{Name}.php`                                                                                                                    |
| `make:value-object {context} {name}` | `src/Domain/{Context}/ValueObjects/{Name}.php`                                                                                                                |
| `make:repository {context} {name}`   | `src/Domain/{Context}/Repositories/{Name}RepositoryInterface.php` **and** `src/Infrastructure/Persistence/Eloquent/Repositories/Eloquent{Name}Repository.php` |
| `make:command {context} {action}`    | `src/Application/Commands/{Context}/{Action}Command/{Action}.php` (invokable, empty `__invoke()` with a `TODO`)                                               |
| `make:query {context} {action}`      | `src/Application/Queries/{Context}/{Action}Query/{Action}.php` (invokable, empty `__invoke()` with a `TODO`)                                                  |

All commands extend `Infrastructure\Console\Commands\SourceGenerator`, which extends Laravel's `GeneratorCommand` and injects `{context}`/`{name}` placeholders.

## Templates

`stubs/` holds `entity.stub`, `value-object.stub`, `repository-interface.stub`, `eloquent-repository.stub`, `command.stub`, `query.stub`. Each carries the layer's dependency-rule header block, so generated files are self-documenting about the ring they belong to.

Notably, the generated **repository** wires in a mapper (`{{ mapper }}`) and an entity namespace, and the command/query stubs produce invokable handlers with a `TODO` — so a new context starts as a valid skeleton.

## Adding a bounded context

The README documents the workflow, e.g. for an `Invoice` context:

```bash
php artisan make:entity Invoice Invoice
php artisan make:value-object Invoice Amount
php artisan make:repository Invoice Invoice
php artisan make:command Invoice CreateInvoice
php artisan make:query Invoice GetInvoiceDetails
```

Then: register the repository binding in `DomainServiceProvider`, add a migration, add a thin controller in `app/Http/Controllers/{Web,Api/V1}`, and route it.

## Observations / open questions

- The generator scaffolding is the **canonical shape** for new contexts — the template's own contexts were hand-written but follow the same pattern.
- `make:repository` writes two files but only takes one `name` (the aggregate name) and assumes an `{Name}RepositoryInterface` / `Eloquent{Name}Repository` naming.
- There is **no generator for mappers or Eloquent models** yet; those are hand-written per context.

## Related pages

- [ddd-layering](ddd-layering.md) — what the generators scaffold
- [cqrs](cqrs.md) — the command/query shapes the generators emit
- [repository-mapper-pattern](repository-mapper-pattern.md) — the repository/mapper skeleton