From 0084adf7dea99482247f14b13016e84bec026563 Mon Sep 17 00:00:00 2001 From: Tom Van Herreweghe Date: Mon, 31 Aug 2026 15:11:53 +0200 Subject: [PATCH] Give the external layer a plugin, so the directory exists in a clone src/plugins/external/ was empty, and git does not track empty directories. Every clone and every template of this repo therefore arrived without it, and @fastify/autoload threw ENOENT before any route was registered: 15 of the 22 checks that should be green on a fresh clone never ran at all. The plugin itself is lifted from the service this scaffold mirrors. It uses fastify-plugin, which was already a dependency and until now unused, and it gives the documented dependency arrow something to point at. --- src/plugins/external/jsonContentType.ts | 30 +++++++++++++++++++++++++ 1 file changed, 30 insertions(+) create mode 100644 src/plugins/external/jsonContentType.ts diff --git a/src/plugins/external/jsonContentType.ts b/src/plugins/external/jsonContentType.ts new file mode 100644 index 0000000..a9d80b9 --- /dev/null +++ b/src/plugins/external/jsonContentType.ts @@ -0,0 +1,30 @@ +import { fastifyPlugin } from 'fastify-plugin'; +import type { FastifyPluginAsync } from 'fastify'; + +// The infrastructure layer, and the bottom of the dependency arrow: +// +// routes/ tools/ -> plugins/app/ -> plugins/external/ +// +// Nothing in here knows anything about discounts. It is where the plumbing +// lives — anything that wraps the outside world, or reaches across every +// response the way this hook does. Your own external concerns go beside it. +// +// This one is lifted from the service this test mirrors: it normalises the +// `content-type` on JSON responses, which Fastify otherwise sends with a +// charset appended. + +const JSON_CONTENT_TYPE = 'application/json'; + +const jsonContentType: FastifyPluginAsync = async (fastify) => { + fastify.addHook('onSend', (_request, reply, payload, done) => { + const contentType = reply.getHeader('content-type'); + + if (typeof contentType === 'string' && contentType.startsWith(JSON_CONTENT_TYPE)) { + reply.header('content-type', JSON_CONTENT_TYPE); + } + + done(null, payload); + }); +}; + +export default fastifyPlugin(jsonContentType, { name: 'jsonContentType' });