Inject the gift-links service into the API controller at boot#28788
Inject the gift-links service into the API controller at boot#28788rob-ghost wants to merge 1 commit into
Conversation
|
Important Review skippedDraft detected. Please check the settings in the CodeRabbit UI or the ⚙️ Run configurationConfiguration used: Path: .coderabbit.yaml Review profile: CHILL Plan: Pro Run ID: You can disable this status message by setting the Use the checkbox below for a quick retry:
✨ Finishing Touches🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
|
| Command | Status | Duration | Result |
|---|---|---|---|
nx run ghost:test:ci:integration:no-coverage |
✅ Succeeded | 2m 33s | View ↗ |
nx run ghost:test:ci:integration |
✅ Succeeded | 2m 20s | View ↗ |
nx build @tryghost/sodo-search |
✅ Succeeded | <1s | View ↗ |
nx build @tryghost/admin-toolbar |
✅ Succeeded | <1s | View ↗ |
nx build @tryghost/signup-form |
✅ Succeeded | <1s | View ↗ |
nx build @tryghost/announcement-bar |
✅ Succeeded | <1s | View ↗ |
nx build @tryghost/activitypub |
✅ Succeeded | 2s | View ↗ |
nx build @tryghost/comments-ui |
✅ Succeeded | <1s | View ↗ |
Additional runs (10) |
✅ Succeeded | ... | View ↗ |
💡 Verify your cache is correct by running tasks in a sandbox. Read docs ↗
☁️ Nx Cloud last updated this comment at 2026-06-22 20:24:05 UTC
Boot constructs the service against the ready DB and passes it straight to the controller factory; the controller closes over a definite instance, so the non-null assertions and the lazy init()/singleton are both gone.
e6d877e to
f60c2fe
Compare

Problem
The gift-links API controller read its service from a mutable module export that is undefined until a boot-time
init()ran, so every handler needed a non-null assertion. The service was also instantiated lazily inside its own module rather than wired by the boot sequence, so a future second dependant couldn't easily share the same instance.Solution
Make boot the composition root: it constructs the service against the ready DB and passes it straight to the controller factory (
createController(service)), which closes over a definite instance. The non-null assertions, theinit()indirection, and the mutable service singleton all go away. The only shared slot is the built controller, which the API endpoints index reads — the framework loads controllers lazily, so the boot-built one has to live somewhere it can find.Verified: typecheck and lint clean, and the e2e-api suite (which boots Ghost through this exact path) passes.