1. Start
  2. An entity
  3. A source
  4. A rule
  5. A port
  6. A link
  7. A fact
  8. An app
  9. Split

Mail the author, without naming a provider

We mail the author without naming a provider. The handler asks for a mailer, and a class that extends it is enough to provide one.

fronds/blog/handlers/PostHandler.ts
1import { ErrorCode, FougereError, Repository } from '@fougere/core';
2import Post from '../entities/Post.js';
+import Mailer from '../services/Mailer.js';
4
5export default class PostHandler extends Repository<Post> {
+ constructor(private mailer: Mailer) {
+ super();
+ }
+
10 async publish(id: Post['id']): Promise<Post> {
11 const post = await this.findById(id);
12 if (!post) throw new FougereError({ code: ErrorCode.NOT_FOUND, message: 'No such post' });
13 if (post.status === 'published') throw new FougereError({ code: ErrorCode.CONFLICT, message: 'Already published' });
14
+ await this.mailer.send(`Published: ${post.title}`);
+
17 return this.update(id, { status: 'published' });
18 }
19}

point at a lettered line, or tap it, to see what grows from it

The handler names the capability; the config, if ever needed, names who answers.

Try it
$ curl -X POST localhost:4100/api/blog/posts/$ID/publish
mail: Published: Hi

Add FakeMailer extends Mailer and the app refuses to start, naming both classes and the line that settles it: ports: { Mailer: '…' }.

In the docsPort
Built with Fougere and Nuxt, hosted on GitHub Pages.