Cheat notes · Module 04 · The backend plugin
An extension point and a module
A five-minute review for when you have done this module and want it back in your head. Open the full module for the steps and the lab, or the full text to print.
The idea
An extension point turns "please add our check" into "write a module". The plugin offers it during register; modules use it in their init, which always runs before the plugin's init.
Remember
createExtensionPoint<T>({ id }): defined in the-nodepackage (readiness-node), so modules depend on a small, stable contract, never on the plugin's internals.- Offering it: in the plugin's
register,env.registerExtensionPoint(ref, { addCheck(...checks) { list.push(...checks) } }), beforeregisterInit. createBackendModule({ pluginId, moduleId }): extends one plugin and may only use that plugin's extension points.- Start order: all modules of a plugin finish
initbefore the plugin'sinitruns, so every check is in the list in time. - Ownership: the module is team-checkout's code in its own package and folder; they review it.
- Generate it:
yarn new --select backend-plugin-module --option pluginId=readiness --option moduleId=api.
Pitfalls
- A typo in
pluginId(readyness): the backend starts, nothing is red, and the check silently disappears. The module's own test starts the real plugin with the module and expects the check in/checks. - Importing the extension point from
readiness-backend: modules then break whenever the plugin changes inside.
Commands
yarn new --select plugin-node-library --option pluginId=readiness | The -node package for the extension point |
yarn new --select backend-plugin-module --option pluginId=readiness --option moduleId=api --option pluginPackage=@internal/backstage-plugin-readiness-backend | A module for the plugin, wired into the backend |
curl -s -H "Authorization: Bearer $PORTAL_API_TOKEN" localhost:7007/api/readiness/checks | jq -r '.items[].id' | Is the module's check listed? |
A module using the extension point
export const readinessModuleApi = createBackendModule({
pluginId: 'readiness', // must match exactly
moduleId: 'api',
register(reg) {
reg.registerInit({
deps: { checks: readinessChecksExtensionPoint },
async init({ checks }) {
checks.addCheck(providesApiCheck);
},
});
},
});
Test yourself
Answer in your head first, then open the answer.
Why is the extension point in readiness-node and not readiness-backend?
So modules depend on a small package and never on the plugin's internals.
When does the module's init run?
Before the plugin's init, so its check is in the list in time.
Who reviews a change to provides-api?
team-checkout, who own the module.
Where module 04 leaves you: Six checks, one owned by team-checkout in its own package. checkout scores 83. Merged.