Feature Recipe: Blameable Changes Plugin

This guide provides a recipe for a "blameable changes" plugin that automatically tracks which Administrator creates and updates product variants.
The plugin demonstrates several core Vendure concepts, including the EventBus for reacting to data changes, Custom Fields to extend core entities, and extending the GraphQL API with custom resolvers.
1. Plugin Architecture & Custom Fields
The first step is to define the custom fields that will store the user information.
This is done within the plugin's main configuration.
We will use the Vendure CLI to scaffold the plugin and service.
We add createdBy
and updatedBy
fields of type relation
to the ProductVariant
entity, linking them to the User
entity.
File: src/plugins/blameable-fields/blameable-fields.plugin.ts
2. Service for Event Handling
Next, we create a service that listens for product variant events and populates our new custom fields.
The service subscribes to the ProductVariantEvent
on the EventBus. This is done inside the onModuleInit
method, a lifecycle hook from NestJS (the framework Vendure is built on).
This hook ensures our subscription is set up once the plugin has been initialized.
When an event is received, it checks the event type (created
or updated
). It then updates the corresponding custom field with the ID of the active user.
3. Exposing Data via GraphQL
To make the tracking data easily accessible, we extend the GraphQL schema.
We add createdByIdentifier
and updatedByIdentifier
fields to the ProductVariant
type.
File: src/plugins/blameable-fields/blameable-fields.plugin.ts
A resolver fetches the stored user ID and resolves it to a user identifier, like "superadmin". This approach uses a direct database query for better performance.
File: src/plugins/blameable-fields/resolvers/product-variant.resolver.ts
You could modify the service to track changes on other entities, such as Product
, Customer
, or Order
by subscribing to their respective events. For more detailed auditing, the logic could be extended to store a full history of changes.
Further Reading
Share this article