ProductAttribute and ProductAttributeValue records directly. Use it for reads in routes, subscribers, and scheduled jobs. For writes, prefer the workflows, because the service doesn’t emit events, update the mirror ProductOption, or link values to products.
Resolve the service
Resolve the service from the container withMercurModules.PRODUCT_ATTRIBUTE, whose value is "product_attribute".
src/api/admin/catalog-import/facets/route.ts
Generated methods
The service extendsMedusaService, so each data model gets the standard methods. For ProductAttribute:
ProductAttributeValue gets the same set: retrieveProductAttributeValue, listProductAttributeValues, listAndCountProductAttributeValues, createProductAttributeValues, updateProductAttributeValues, deleteProductAttributeValues, softDeleteProductAttributeValues, and restoreProductAttributeValues.
Overridden methods
Five methods add behavior on top of the generated ones.createProductAttributes
handle from name for any global attribute created without one. After creating, it seeds a "true" value (rank 0) and a "false" value (rank 1) for every toggle attribute. It doesn’t create any other values, so add them with createProductAttributeValues.
updateProductAttributes
INVALID_DATA when an update sets a type that differs from the attribute’s current type. Every other field passes through.
listProductAttributes and listAndCountProductAttributes
config.relations or config.select asks for values, the service loads them in a separate query. Only single_select, multi_select, and toggle attributes get their values. text and unit attributes come back with values: [], because their values belong to individual products.
createProductAttributeValues
handle from name for values of global single_select and multi_select attributes. Values of inline attributes and of text, unit, and toggle attributes keep a null handle.