feat!: replace decoration with options-based dependency injection#20
Merged
feat!: replace decoration with options-based dependency injection#20
Conversation
Removes the fastify-plugin wrapper and shifts arocapi to an
encapsulated Fastify plugin. Internal routes now receive prisma
(and opensearch where needed) via their own plugin options rather
than via a decorated FastifyInstance. Lifecycle management of the
passed-in clients moves to the consumer, aligning with
"whoever creates owns the lifecycle".
BREAKING CHANGE: arocapi no longer decorates fastify.prisma or
fastify.opensearch; consumers must close over their own client
references. TransformerContext and FileHandlerContext shrink from
{ request, fastify } to { request }. Arocapi no longer calls
prisma.$connect()/$disconnect() or opensearch.ping()/close() —
consumers now own connecting before registration and closing on
shutdown.
Coverage Report
File Coverage
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
alvinsw
reviewed
Apr 28, 2026
Member
alvinsw
left a comment
There was a problem hiding this comment.
Having the fastify instance passed to the transformers and handlers gives more flexibility to the users extending the arocapi. Is there any drawbacks if we still do that?
Restores the `fastify: FastifyInstance` field on both context types so consumer-supplied transformers and file handlers can access helpers that the consumer has decorated onto fastify themselves. Arocapi still does not decorate fastify with prisma/opensearch (the v3 breaking change in the previous commit stands). The field is purely an extension point for consumers; arocapi puts nothing on it.
Collaborator
Author
@alvinsw I've pushed a commit that brings it back. |
alvinsw
requested changes
Apr 29, 2026
| const where: NonNullable<Parameters<typeof prisma.file.findMany>[0]>['where'] = {}; | ||
|
|
||
| if (memberOf) { | ||
| where.entity = { id: memberOf }; |
Member
There was a problem hiding this comment.
Suggested change
| where.entity = { id: memberOf }; | |
| where.entity = { memberOf }; |
Member
There was a problem hiding this comment.
Can we just fix this one annoying bug here?
Collaborator
Author
There was a problem hiding this comment.
I'll do that separately as another PR now.
github-actions Bot
pushed a commit
that referenced
this pull request
Apr 29, 2026
## [4.0.0](v3.0.0...v4.0.0) (2026-04-29) ### ⚠ BREAKING CHANGES * arocapi no longer decorates fastify.prisma or fastify.opensearch; consumers must close over their own client references. Arocapi no longer calls prisma.$connect()/$disconnect() or opensearch.ping()/close() — consumers now own connecting before registration and closing on shutdown. ### Features * replace decoration with options-based dependency injection ([#20](#20)) ([aa5c6b7](aa5c6b7)) ### Bug Fixes * **files:** filter by entity.memberOf instead of entity.id ([#21](#21)) ([a6f27bd](a6f27bd))
|
🎉 This PR is included in version 4.0.0 🎉 The release is available on: Your semantic-release bot 📦🚀 |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Removes the
fastify-pluginwrapper and switches arocapi to an encapsulated Fastify plugin. Internal routes now receiveprisma(andopensearchwhere needed) explicitly via their own options instead of reading from decoratedfastify.prisma/fastify.opensearch. Connection lifecycle management moves from arocapi to the consumer.Why
The previous design globally augmented every consumer's
FastifyInstancetype withprismaandopensearchfields, and arocapi assumed ownership of$connect/$disconnect/ping/closeon clients it didn't create. Both are leaky abstractions for a library: consumer types shouldn't be polluted with arocapi's internal dependencies, and lifecycle should stay with whoever constructed the client.Breaking changes (→ v3.0.0)
fastify.prismaandfastify.opensearchare no longer decorated onto the consumer's Fastify instance. Consumers close over their own client references.TransformerContextandFileHandlerContextshrink from{ request, fastify }to{ request }.prisma.$connect(),prisma.$disconnect(),opensearch.ping(), oropensearch.close(). Consumers connect beforeregister()and close on their own shutdown path.fastify-pluginpackage is no longer a dependency.What changed
src/app.ts— dropfp()wrapper, dropdeclare module 'fastify'augmentation, deletesetupDatabase/setupSearch, passprisma/opensearchexplicitly to each child route pluginsrc/routes/*.ts(6 files) — each gains aprisma: PrismaClient(andopensearch: Clientforsearch) on its options typesrc/types/transformers.ts,src/types/fileHandlers.ts— context types reduced to{ request }src/test/helpers/fastify.ts— stops decorating the fastify instance with mockssrc/routes/*.test.ts— passprisma/opensearchtoregister()explicitlysrc/app.test.ts— dropshould handle broken opensearch(tested the removedping()) andshould handle random errors(testedfp()-leaked cross-scope error handling). Addshould register successfully with all required optionsto preserve happy-path registration coverage.src/index.dev.ts— remove vestigialdeclare moduleblock and unused{ request, fastify }destructuring in the example transformerREADME.md— transformer examples now close over the consumer's ownprismareferencepackage.json— removefastify-pluginTest plan
pnpm lint— biome, tsc, knip all greenpnpm test— 132/132 passing, 100% coverage across lines/branches/functions/statementsBREAKING CHANGE:footer when this merges