@mercurjs/docs 2.2.1 → 2.3.0-canary.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/content/home.mdx +107 -0
- package/content/learn/architecture.mdx +168 -83
- package/content/learn/introduction.mdx +161 -56
- package/content/learn/migration-to-2-0.mdx +187 -0
- package/content/learn/why-mercur.mdx +91 -0
- package/content/platform/attribute/concepts/attribute-types.mdx +59 -0
- package/content/platform/attribute/concepts/global-vs-inline.mdx +50 -0
- package/content/platform/attribute/concepts/variant-axes.mdx +61 -0
- package/content/platform/attribute/guides/attach-attributes-to-a-product.mdx +69 -0
- package/content/platform/attribute/guides/create-a-variant-axis.mdx +83 -0
- package/content/platform/attribute/guides/create-an-attribute.mdx +81 -0
- package/content/platform/attribute/overview.mdx +87 -0
- package/content/platform/attribute/reference/data-models.mdx +56 -0
- package/content/platform/attribute/reference/events.mdx +41 -0
- package/content/platform/attribute/reference/links.mdx +45 -0
- package/content/platform/attribute/reference/service.mdx +49 -0
- package/content/platform/attribute/reference/workflows.mdx +45 -0
- package/content/platform/catalog/concepts/master-products.mdx +54 -0
- package/content/platform/catalog/concepts/product-seller-allowlist.mdx +48 -0
- package/content/platform/catalog/concepts/status-lifecycle.mdx +58 -0
- package/content/platform/catalog/concepts/variants-categories-collections.mdx +49 -0
- package/content/platform/catalog/guides/allowlist-stores.mdx +59 -0
- package/content/platform/catalog/guides/create-a-master-product.mdx +70 -0
- package/content/platform/catalog/guides/publish-or-reject-a-product.mdx +79 -0
- package/content/platform/catalog/overview.mdx +90 -0
- package/content/platform/catalog/reference/data-models.mdx +66 -0
- package/content/platform/catalog/reference/events.mdx +41 -0
- package/content/platform/catalog/reference/links.mdx +44 -0
- package/content/platform/catalog/reference/service.mdx +52 -0
- package/content/platform/catalog/reference/workflows.mdx +40 -0
- package/content/platform/commission/concepts/order-commission-lines.mdx +65 -0
- package/content/platform/commission/concepts/rule-matching.mdx +86 -0
- package/content/platform/commission/concepts/rules-and-rates.mdx +84 -0
- package/content/platform/commission/guides/batch-update-rules.mdx +58 -0
- package/content/platform/commission/guides/create-a-rate.mdx +72 -0
- package/content/platform/commission/guides/refresh-order-commission-lines.mdx +55 -0
- package/content/platform/commission/overview.mdx +86 -0
- package/content/platform/commission/reference/data-models.mdx +75 -0
- package/content/platform/commission/reference/events.mdx +58 -0
- package/content/platform/commission/reference/links.mdx +45 -0
- package/content/platform/commission/reference/service.mdx +51 -0
- package/content/platform/commission/reference/workflows.mdx +40 -0
- package/content/platform/offer/concepts/pricing-and-inventory.mdx +72 -0
- package/content/platform/offer/concepts/shipping.mdx +48 -0
- package/content/platform/offer/concepts/what-is-an-offer.mdx +65 -0
- package/content/platform/offer/guides/bulk-create-offers.mdx +84 -0
- package/content/platform/offer/guides/create-an-offer.mdx +83 -0
- package/content/platform/offer/guides/manage-offer-inventory.mdx +53 -0
- package/content/platform/offer/overview.mdx +84 -0
- package/content/platform/offer/reference/data-models.mdx +56 -0
- package/content/platform/offer/reference/events.mdx +39 -0
- package/content/platform/offer/reference/links.mdx +60 -0
- package/content/platform/offer/reference/service.mdx +53 -0
- package/content/platform/offer/reference/workflows.mdx +38 -0
- package/content/platform/order-group/concepts/computed-totals.mdx +59 -0
- package/content/platform/order-group/concepts/order-splitting.mdx +61 -0
- package/content/platform/order-group/concepts/the-order-group.mdx +64 -0
- package/content/platform/order-group/guides/list-order-groups.mdx +67 -0
- package/content/platform/order-group/guides/retrieve-an-order-group.mdx +63 -0
- package/content/platform/order-group/guides/split-a-cart.mdx +58 -0
- package/content/platform/order-group/overview.mdx +83 -0
- package/content/platform/order-group/reference/data-models.mdx +40 -0
- package/content/platform/order-group/reference/events.mdx +37 -0
- package/content/platform/order-group/reference/links.mdx +45 -0
- package/content/platform/order-group/reference/service.mdx +50 -0
- package/content/platform/order-group/reference/workflows.mdx +39 -0
- package/content/platform/payout/concepts/account-lifecycle.mdx +75 -0
- package/content/platform/payout/concepts/accounts-and-onboarding.mdx +70 -0
- package/content/platform/payout/concepts/payout-pipeline.mdx +99 -0
- package/content/platform/payout/guides/create-a-payout-account.mdx +59 -0
- package/content/platform/payout/guides/process-a-provider-webhook.mdx +74 -0
- package/content/platform/payout/guides/start-provider-onboarding.mdx +50 -0
- package/content/platform/payout/overview.mdx +86 -0
- package/content/platform/payout/reference/data-models.mdx +61 -0
- package/content/platform/payout/reference/events.mdx +48 -0
- package/content/platform/payout/reference/links.mdx +36 -0
- package/content/platform/payout/reference/service.mdx +53 -0
- package/content/platform/payout/reference/workflows.mdx +32 -0
- package/content/platform/product-edit/concepts/change-actions.mdx +66 -0
- package/content/platform/product-edit/concepts/change-pipeline.mdx +69 -0
- package/content/platform/product-edit/concepts/status-and-auto-confirm.mdx +66 -0
- package/content/platform/product-edit/guides/confirm-or-decline-a-change.mdx +76 -0
- package/content/platform/product-edit/guides/edit-a-product.mdx +74 -0
- package/content/platform/product-edit/guides/request-a-revision.mdx +54 -0
- package/content/platform/product-edit/overview.mdx +85 -0
- package/content/platform/product-edit/reference/data-models.mdx +65 -0
- package/content/platform/product-edit/reference/events.mdx +47 -0
- package/content/platform/product-edit/reference/links.mdx +39 -0
- package/content/platform/product-edit/reference/service.mdx +43 -0
- package/content/platform/product-edit/reference/workflows.mdx +49 -0
- package/content/platform/review/concepts/product-vs-seller-reviews.mdx +63 -0
- package/content/platform/review/concepts/ratings-and-moderation.mdx +64 -0
- package/content/platform/review/concepts/the-review-model.mdx +56 -0
- package/content/platform/review/guides/compute-aggregate-ratings.mdx +57 -0
- package/content/platform/review/guides/create-a-review.mdx +55 -0
- package/content/platform/review/guides/moderate-a-review.mdx +58 -0
- package/content/platform/review/guides/respond-to-a-review.mdx +61 -0
- package/content/platform/review/overview.mdx +87 -0
- package/content/platform/review/reference/data-models.mdx +36 -0
- package/content/platform/review/reference/events.mdx +61 -0
- package/content/platform/review/reference/links.mdx +43 -0
- package/content/platform/review/reference/service.mdx +54 -0
- package/content/platform/review/reference/workflows.mdx +31 -0
- package/content/platform/store/concepts/lifecycle.mdx +62 -0
- package/content/platform/store/concepts/store-entity.mdx +53 -0
- package/content/platform/store/concepts/team.mdx +50 -0
- package/content/platform/store/guides/create-a-store.mdx +55 -0
- package/content/platform/store/guides/manage-the-team.mdx +55 -0
- package/content/platform/store/guides/moderate-a-store.mdx +59 -0
- package/content/platform/store/overview.mdx +86 -0
- package/content/platform/store/reference/data-models.mdx +89 -0
- package/content/platform/store/reference/events.mdx +43 -0
- package/content/platform/store/reference/links.mdx +71 -0
- package/content/platform/store/reference/service.mdx +51 -0
- package/content/platform/store/reference/workflows.mdx +35 -0
- package/content/references/api/admin/commission-rates/create-commission-rate.mdx +1 -1
- package/content/references/api/admin/commission-rates/list-commission-rates.mdx +2 -2
- package/content/references/api/admin/commission-rates/update-commission-rate.mdx +1 -1
- package/content/references/api/admin/offers/batch-create-offers.mdx +3 -3
- package/content/references/api/admin/order-groups/list-order-groups.mdx +1 -1
- package/content/references/api/admin/product-attributes/create-attribute-value.mdx +2 -2
- package/content/references/api/admin/product-attributes/create-product-attribute.mdx +1 -1
- package/content/references/api/admin/product-attributes/update-product-attribute.mdx +1 -1
- package/content/references/api/admin/product-changes/confirm-product-change.mdx +1 -1
- package/content/references/api/admin/products/batch-product-attributes.mdx +1 -1
- package/content/references/api/admin/products/create-product.mdx +1 -1
- package/content/references/api/admin/products/preview-product.mdx +1 -1
- package/content/references/api/admin.mdx +4 -5
- package/content/references/api/conventions.mdx +9 -7
- package/content/references/api/store/carts/add-line-item.mdx +1 -1
- package/content/references/api/store/offers/list-offers.mdx +1 -1
- package/content/references/api/store/order-groups/list-order-groups.mdx +1 -1
- package/content/references/api/store.mdx +4 -13
- package/content/references/api/vendor/members/accept-member-invite.mdx +1 -1
- package/content/references/api/vendor/offers/batch-create-offers.mdx +4 -0
- package/content/references/api/vendor/offers/batch-offer-inventory-items.mdx +2 -0
- package/content/references/api/vendor/offers/create-offer.mdx +13 -1
- package/content/references/api/vendor/offers/list-offers.mdx +4 -0
- package/content/references/api/vendor/offers/retrieve-offer.mdx +4 -0
- package/content/references/api/vendor/offers/update-offer.mdx +12 -0
- package/content/references/api/vendor/payout-accounts/create-onboarding.mdx +1 -1
- package/content/references/api/vendor/products/batch-product-attributes.mdx +1 -1
- package/content/references/api/vendor/products/create-product-variant.mdx +1 -1
- package/content/references/api/vendor/products/create-product.mdx +1 -1
- package/content/references/api/vendor/products/delete-product.mdx +1 -1
- package/content/references/api/vendor/products/update-product.mdx +1 -1
- package/content/references/api/vendor/sellers/create-seller.mdx +2 -2
- package/content/references/api/vendor/sellers/list-sellers.mdx +1 -1
- package/content/references/api/vendor.mdx +6 -5
- package/content/references/configuration.mdx +16 -33
- package/content/references/overview.mdx +34 -52
- package/content/references/panel-extensions/create-page.mdx +194 -0
- package/content/references/panel-extensions/custom-fields.mdx +256 -0
- package/content/references/panel-extensions/overview.mdx +102 -0
- package/content/references/panel-extensions/widgets.mdx +212 -0
- package/content/resources/ai/mcp.mdx +2 -2
- package/content/resources/ai/overview.mdx +21 -16
- package/content/resources/ai/skills.mdx +67 -0
- package/content/resources/best-practices/api-routes.mdx +55 -43
- package/content/resources/best-practices/custom-fields.mdx +116 -92
- package/content/resources/best-practices/frontend.mdx +62 -50
- package/content/resources/best-practices/module-links.mdx +48 -34
- package/content/resources/best-practices/modules.mdx +53 -27
- package/content/resources/best-practices/overview.mdx +45 -17
- package/content/resources/best-practices/subscribers-and-jobs.mdx +37 -24
- package/content/resources/best-practices/types.mdx +38 -23
- package/content/resources/best-practices/workflows.mdx +33 -21
- package/content/resources/customization/custom-fields.mdx +15 -15
- package/content/resources/customization/extend-a-workflow.mdx +7 -4
- package/content/resources/customization/extending-panels.mdx +55 -52
- package/content/resources/deployment/medusa-cloud.mdx +21 -20
- package/content/resources/deployment/self-host.mdx +123 -0
- package/content/resources/integrations/overview.mdx +38 -0
- package/content/resources/integrations/stripe-connect.mdx +39 -38
- package/content/resources/tutorials/add-a-block.mdx +25 -18
- package/content/resources/tutorials/add-a-widget.mdx +32 -23
- package/content/resources/tutorials/add-order-detail-button.mdx +33 -20
- package/content/resources/tutorials/attributes-and-variant-axes.mdx +28 -27
- package/content/resources/tutorials/build-a-block.mdx +26 -15
- package/content/resources/tutorials/custom-api-route.mdx +32 -20
- package/content/resources/tutorials/custom-panel-page.mdx +21 -12
- package/content/resources/tutorials/customize-navigation.mdx +30 -23
- package/content/resources/tutorials/extend-forms-and-tables.mdx +36 -28
- package/content/resources/tutorials/extend-onboarding.mdx +38 -35
- package/content/resources/tutorials/master-products-and-offers.mdx +28 -23
- package/content/telemetry.mdx +3 -3
- package/content/user-guide/admin/attributes/how-tos/create-an-attribute.mdx +64 -0
- package/content/user-guide/admin/attributes/how-tos/manage-possible-values.mdx +40 -0
- package/content/user-guide/admin/attributes/overview.mdx +22 -0
- package/content/user-guide/admin/commissions/how-tos/create-a-commission-rule.mdx +63 -0
- package/content/user-guide/admin/commissions/how-tos/edit-the-global-commission.mdx +48 -0
- package/content/user-guide/admin/commissions/how-tos/manage-a-commission-rule.mdx +45 -0
- package/content/user-guide/admin/commissions/overview.mdx +25 -0
- package/content/user-guide/admin/overview.mdx +20 -12
- package/content/user-guide/admin/product-requests/how-tos/review-a-new-product.mdx +58 -0
- package/content/user-guide/admin/product-requests/how-tos/review-a-product-edit.mdx +48 -0
- package/content/user-guide/admin/product-requests/overview.mdx +25 -0
- package/content/user-guide/vendor/offers/how-tos/create-an-offer.mdx +59 -0
- package/content/user-guide/vendor/offers/how-tos/update-prices-and-stock.mdx +40 -0
- package/content/user-guide/vendor/offers/overview.mdx +22 -0
- package/content/user-guide/vendor/onboarding.mdx +79 -0
- package/content/user-guide/vendor/orders/how-tos/fulfill-an-order.mdx +49 -0
- package/content/user-guide/vendor/orders/how-tos/mark-an-order-as-delivered.mdx +33 -0
- package/content/user-guide/vendor/orders/how-tos/process-a-return.mdx +42 -0
- package/content/user-guide/vendor/orders/how-tos/refund-an-order.mdx +38 -0
- package/content/user-guide/vendor/orders/how-tos/ship-an-order.mdx +40 -0
- package/content/user-guide/vendor/orders/overview.mdx +31 -0
- package/content/user-guide/vendor/overview.mdx +23 -12
- package/content/user-guide/vendor/products/how-tos/edit-a-product.mdx +44 -0
- package/content/user-guide/vendor/products/how-tos/submit-a-product.mdx +63 -0
- package/content/user-guide/vendor/products/overview.mdx +22 -0
- package/llms.txt +176 -142
- package/package.json +1 -1
- package/content/learn/concepts.mdx +0 -84
- package/content/learn/installation.mdx +0 -117
- package/content/learn/mirakl-alternative.mdx +0 -86
- package/content/migration/from-1-x-to-2-0.mdx +0 -152
- package/content/migration/from-2-0-to-2-1.mdx +0 -105
- package/content/migration/overview.mdx +0 -58
- package/content/references/api/store/search/search.mdx +0 -136
- package/content/references/modules/commission.mdx +0 -106
- package/content/references/modules/custom-fields.mdx +0 -45
- package/content/references/modules/media.mdx +0 -55
- package/content/references/modules/offer.mdx +0 -64
- package/content/references/modules/payout.mdx +0 -121
- package/content/references/modules/product-attribute.mdx +0 -111
- package/content/references/modules/product-edit.mdx +0 -80
- package/content/references/modules/search.mdx +0 -112
- package/content/references/modules/seller.mdx +0 -175
- package/content/references/panel-extension-api.mdx +0 -337
- package/content/references/workflows/cart/add-seller-shipping-method-to-cart.mdx +0 -48
- package/content/references/workflows/cart/complete-cart-with-split-orders.mdx +0 -36
- package/content/references/workflows/cart/list-seller-shipping-options-for-cart.mdx +0 -39
- package/content/references/workflows/cart/update-cart-seller-promotions.mdx +0 -42
- package/content/references/workflows/commission/batch-commission-rules.mdx +0 -49
- package/content/references/workflows/commission/create-commission-rates.mdx +0 -41
- package/content/references/workflows/commission/delete-commission-rates.mdx +0 -34
- package/content/references/workflows/commission/refresh-order-commission-lines.mdx +0 -30
- package/content/references/workflows/commission/update-commission-rates.mdx +0 -35
- package/content/references/workflows/media/set-category-images.mdx +0 -41
- package/content/references/workflows/media/set-collection-images.mdx +0 -41
- package/content/references/workflows/member/accept-member-invite.mdx +0 -33
- package/content/references/workflows/member/add-seller-member.mdx +0 -30
- package/content/references/workflows/member/create-member-invites.mdx +0 -34
- package/content/references/workflows/member/delete-member-invite.mdx +0 -24
- package/content/references/workflows/member/remove-seller-member.mdx +0 -28
- package/content/references/workflows/member/resend-member-invite.mdx +0 -28
- package/content/references/workflows/member/update-member-role.mdx +0 -28
- package/content/references/workflows/member/update-member.mdx +0 -35
- package/content/references/workflows/offer/batch-offer-inventory-items.mdx +0 -62
- package/content/references/workflows/offer/create-offers.mdx +0 -65
- package/content/references/workflows/offer/delete-offers.mdx +0 -35
- package/content/references/workflows/offer/update-offers.mdx +0 -53
- package/content/references/workflows/order/cancel-order-fulfillment.mdx +0 -34
- package/content/references/workflows/order/confirm-claim-request.mdx +0 -25
- package/content/references/workflows/order/confirm-exchange-request.mdx +0 -25
- package/content/references/workflows/order/confirm-order-edit-request.mdx +0 -25
- package/content/references/workflows/order/confirm-return-receive.mdx +0 -25
- package/content/references/workflows/order/create-order-fulfillment.mdx +0 -45
- package/content/references/workflows/order-group/get-order-group-detail.mdx +0 -29
- package/content/references/workflows/order-group/get-order-groups-list.mdx +0 -38
- package/content/references/workflows/overview.mdx +0 -72
- package/content/references/workflows/payout/create-onboarding.mdx +0 -36
- package/content/references/workflows/payout/create-payout-account.mdx +0 -33
- package/content/references/workflows/payout/create-payout.mdx +0 -30
- package/content/references/workflows/payout/process-payout-for-webhook.mdx +0 -34
- package/content/references/workflows/product/confirm-products.mdx +0 -48
- package/content/references/workflows/product/create-products.mdx +0 -63
- package/content/references/workflows/product/link-sellers-to-product-category.mdx +0 -40
- package/content/references/workflows/product/link-sellers-to-product.mdx +0 -40
- package/content/references/workflows/product/reject-product.mdx +0 -48
- package/content/references/workflows/product/request-product-change.mdx +0 -48
- package/content/references/workflows/product-attribute/add-product-attributes-to-product.mdx +0 -49
- package/content/references/workflows/product-attribute/create-and-link-product-attributes-to-product.mdx +0 -46
- package/content/references/workflows/product-attribute/create-product-attribute-values.mdx +0 -43
- package/content/references/workflows/product-attribute/create-product-attributes.mdx +0 -56
- package/content/references/workflows/product-attribute/delete-product-attribute-values.mdx +0 -30
- package/content/references/workflows/product-attribute/delete-product-attributes.mdx +0 -30
- package/content/references/workflows/product-attribute/remove-product-attributes-from-product.mdx +0 -29
- package/content/references/workflows/product-attribute/update-product-attribute-values.mdx +0 -44
- package/content/references/workflows/product-attribute/update-product-attributes-on-product.mdx +0 -41
- package/content/references/workflows/product-attribute/update-product-attributes.mdx +0 -48
- package/content/references/workflows/product-attribute/upsert-product-attribute-values.mdx +0 -43
- package/content/references/workflows/product-edit/auto-confirm-product-change.mdx +0 -39
- package/content/references/workflows/product-edit/cancel-product-change.mdx +0 -49
- package/content/references/workflows/product-edit/confirm-product-change.mdx +0 -57
- package/content/references/workflows/product-edit/create-product-change.mdx +0 -72
- package/content/references/workflows/product-edit/reject-product-change.mdx +0 -54
- package/content/references/workflows/product-edit/stage-product-change.mdx +0 -75
- package/content/references/workflows/seller/approve-seller.mdx +0 -36
- package/content/references/workflows/seller/create-seller-account.mdx +0 -59
- package/content/references/workflows/seller/create-seller-defaults.mdx +0 -22
- package/content/references/workflows/seller/create-sellers.mdx +0 -65
- package/content/references/workflows/seller/delete-seller-professional-details.mdx +0 -37
- package/content/references/workflows/seller/delete-sellers.mdx +0 -24
- package/content/references/workflows/seller/invite-seller.mdx +0 -28
- package/content/references/workflows/seller/suspend-seller.mdx +0 -37
- package/content/references/workflows/seller/terminate-seller.mdx +0 -37
- package/content/references/workflows/seller/unsuspend-seller.mdx +0 -36
- package/content/references/workflows/seller/unterminate-seller.mdx +0 -36
- package/content/references/workflows/seller/update-seller-address.mdx +0 -55
- package/content/references/workflows/seller/update-seller-payment-details.mdx +0 -52
- package/content/references/workflows/seller/update-seller-professional-details.mdx +0 -48
- package/content/references/workflows/seller/update-sellers.mdx +0 -57
- package/content/resources/ai/llms.mdx +0 -74
- package/content/resources/integrations/notifications.mdx +0 -39
- package/content/resources/integrations/search.mdx +0 -122
- package/content/resources/tutorials/configure-commissions.mdx +0 -127
- package/content/resources/tutorials/first-marketplace.mdx +0 -45
- package/content/resources/tutorials/handle-product-requests.mdx +0 -80
- package/content/resources/tutorials/import-export-products.mdx +0 -96
- package/content/resources/tutorials/seller-payouts-stripe.mdx +0 -89
- package/content/resources/tutorials/store-setup-checklist.mdx +0 -214
- package/content/tools/api-client.mdx +0 -155
- package/content/tools/cli.mdx +0 -196
- package/content/tools/dashboard-sdk.mdx +0 -35
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
---
|
|
2
|
+
title: "Variant axes"
|
|
3
|
+
sidebarTitle: "Variant axes"
|
|
4
|
+
description: "How is_variant_axis mirrors a native ProductOption and generates variants."
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
In this document, you'll learn how an attribute becomes the axis a product's
|
|
8
|
+
variants are generated from, and the mirror links that keep the two in sync.
|
|
9
|
+
|
|
10
|
+
## Variant-axis attribute
|
|
11
|
+
|
|
12
|
+
A `multi_select` attribute marked `is_variant_axis` is more than a descriptor.
|
|
13
|
+
It defines a dimension along which a product varies, such as Size or Color. When
|
|
14
|
+
such an attribute is created, the `ProductAttribute` model records the id of a native
|
|
15
|
+
Medusa `ProductOption` in its `product_option_id` field, and each of its
|
|
16
|
+
`ProductAttributeValue`s records the matching `ProductOptionValue` id in
|
|
17
|
+
`product_option_value_id`.
|
|
18
|
+
|
|
19
|
+
```ts
|
|
20
|
+
await createProductAttributesWorkflow(container).run({
|
|
21
|
+
input: {
|
|
22
|
+
attributes: [
|
|
23
|
+
{
|
|
24
|
+
name: "Size",
|
|
25
|
+
type: "multi_select",
|
|
26
|
+
is_variant_axis: true,
|
|
27
|
+
values: [{ name: "S" }, { name: "M" }, { name: "L" }],
|
|
28
|
+
},
|
|
29
|
+
],
|
|
30
|
+
},
|
|
31
|
+
})
|
|
32
|
+
```
|
|
33
|
+
|
|
34
|
+
Because the attribute mirrors a real `ProductOption`, the values a product
|
|
35
|
+
selects along that axis are exactly what Medusa uses to generate its variants.
|
|
36
|
+
|
|
37
|
+
## Mirror links
|
|
38
|
+
|
|
39
|
+
The attribute catalog and Medusa's product options are two separate modules, so
|
|
40
|
+
the relationship is kept as a pair of **read-only mirror links**:
|
|
41
|
+
|
|
42
|
+
| Mirror | FK on the attribute side | Points to |
|
|
43
|
+
| --- | --- | --- |
|
|
44
|
+
| Attribute → option | `ProductAttribute.product_option_id` | `ProductOption` |
|
|
45
|
+
| Value → option value | `ProductAttributeValue.product_option_value_id` | `ProductOptionValue` |
|
|
46
|
+
|
|
47
|
+
Both are 1:1 and have no pivot table. The foreign key lives on the attribute
|
|
48
|
+
record itself.
|
|
49
|
+
|
|
50
|
+
<Note>
|
|
51
|
+
The mirror links are **read-only**. They're resolved from the FK on the
|
|
52
|
+
attribute record; you never write the relationship through the link. The
|
|
53
|
+
workflows keep the option and the attribute in step whenever an axis attribute
|
|
54
|
+
or its values change.
|
|
55
|
+
</Note>
|
|
56
|
+
|
|
57
|
+
<Tip>
|
|
58
|
+
Only `multi_select` attributes can be variant axes. The other four types
|
|
59
|
+
(`single_select`, `text`, `unit`, `toggle`) describe a product but never
|
|
60
|
+
generate variants.
|
|
61
|
+
</Tip>
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
---
|
|
2
|
+
title: "Attach attributes to a product"
|
|
3
|
+
sidebarTitle: "Attach to a product"
|
|
4
|
+
description: "Attach, detach, and update a product's attributes in one batch call."
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
In this guide, you'll learn how to manage all of a product's attributes from
|
|
8
|
+
server code through a single batch workflow.
|
|
9
|
+
|
|
10
|
+
Mercur exposes `createAndLinkProductAttributesToProductWorkflow`, the engine
|
|
11
|
+
behind the product attribute batch endpoint. One call can attach new attributes,
|
|
12
|
+
detach existing ones, and update selections, applied in the order
|
|
13
|
+
**remove → add → update** so a same-call remove and re-add of one attribute
|
|
14
|
+
resolves correctly.
|
|
15
|
+
|
|
16
|
+
## Run the batch workflow
|
|
17
|
+
|
|
18
|
+
```ts title="src/api/custom/products/[id]/attributes/route.ts"
|
|
19
|
+
import type { MedusaRequest, MedusaResponse } from "@medusajs/framework/http"
|
|
20
|
+
import { createAndLinkProductAttributesToProductWorkflow } from "@mercurjs/core/workflows"
|
|
21
|
+
|
|
22
|
+
export async function POST(req: MedusaRequest, res: MedusaResponse) {
|
|
23
|
+
await createAndLinkProductAttributesToProductWorkflow(req.scope).run({
|
|
24
|
+
input: {
|
|
25
|
+
product_id: req.params.id,
|
|
26
|
+
add: [
|
|
27
|
+
// Existing select attribute: link chosen values
|
|
28
|
+
{ id: "pattr_material", value_ids: ["pattrval_cotton"] },
|
|
29
|
+
// Existing text / unit / toggle attribute: set a scalar
|
|
30
|
+
{ id: "pattr_thread_count", value: 400 },
|
|
31
|
+
// Inline attribute created and attached in one step
|
|
32
|
+
{ title: "Gift wrap", type: "toggle", value: true },
|
|
33
|
+
],
|
|
34
|
+
remove: ["pattr_legacy_field"],
|
|
35
|
+
update: [{ id: "pattr_color", add: ["pattrval_blue"], remove: ["pattrval_red"] }],
|
|
36
|
+
},
|
|
37
|
+
})
|
|
38
|
+
|
|
39
|
+
res.sendStatus(200)
|
|
40
|
+
}
|
|
41
|
+
```
|
|
42
|
+
|
|
43
|
+
## The three operations
|
|
44
|
+
|
|
45
|
+
Each entry in `add` is one of the `ProductAttributeBatchAdd` forms:
|
|
46
|
+
|
|
47
|
+
| Form | Shape | Effect |
|
|
48
|
+
| --- | --- | --- |
|
|
49
|
+
| Existing select / axis | `{ id, value_ids }` | Links the referenced values to the product |
|
|
50
|
+
| Existing text / unit / toggle | `{ id, value }` | `text`/`unit` create and link a value; `toggle` links the seeded `true`/`false` value |
|
|
51
|
+
| Inline axis | `{ title, values, is_variant_axis: true }` | Creates an exclusive option, a scoped attribute, and the value mirror |
|
|
52
|
+
| Inline non-axis | `{ title, type, value \| values }` | Creates a scoped attribute plus its value(s) and links them |
|
|
53
|
+
|
|
54
|
+
`remove` takes attribute ids to detach; `update` carries
|
|
55
|
+
`ProductAttributeBatchUpdate` entries adjusting an existing selection.
|
|
56
|
+
|
|
57
|
+
<Note>
|
|
58
|
+
For a variant-axis attribute, `value_ids` is the per-product **subset** of the
|
|
59
|
+
mirror option's values. The product's variants are generated from exactly that
|
|
60
|
+
subset. See [Variant axes](/platform/attribute/concepts/variant-axes).
|
|
61
|
+
</Note>
|
|
62
|
+
|
|
63
|
+
<Tip>
|
|
64
|
+
The batch workflow composes the lower-level
|
|
65
|
+
`addProductAttributesToProductWorkflow`,
|
|
66
|
+
`removeProductAttributesFromProductWorkflow`, and
|
|
67
|
+
`updateProductAttributesOnProductWorkflow`. Reach for those directly when you
|
|
68
|
+
only need one of the three operations.
|
|
69
|
+
</Tip>
|
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
---
|
|
2
|
+
title: "Create a variant axis"
|
|
3
|
+
sidebarTitle: "Create a variant axis"
|
|
4
|
+
description: "Generate product variants from a multi_select axis attribute."
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
In this guide, you'll learn how to create a variant-axis attribute and use it to
|
|
8
|
+
generate a product's variants from server code.
|
|
9
|
+
|
|
10
|
+
A variant axis is a `multi_select` attribute with `is_variant_axis` set. Creating
|
|
11
|
+
one mirrors a native Medusa `ProductOption`, so the values a product selects along
|
|
12
|
+
the axis become the dimensions Medusa uses to generate variants.
|
|
13
|
+
|
|
14
|
+
## Create the axis attribute
|
|
15
|
+
|
|
16
|
+
```ts title="src/api/custom/attributes/route.ts"
|
|
17
|
+
import type { MedusaRequest, MedusaResponse } from "@medusajs/framework/http"
|
|
18
|
+
import { createProductAttributesWorkflow } from "@mercurjs/core/workflows"
|
|
19
|
+
|
|
20
|
+
export async function POST(req: MedusaRequest, res: MedusaResponse) {
|
|
21
|
+
const { result } = await createProductAttributesWorkflow(req.scope).run({
|
|
22
|
+
input: {
|
|
23
|
+
attributes: [
|
|
24
|
+
{
|
|
25
|
+
name: "Size",
|
|
26
|
+
type: "multi_select",
|
|
27
|
+
is_variant_axis: true,
|
|
28
|
+
is_filterable: true,
|
|
29
|
+
values: [{ name: "S" }, { name: "M" }, { name: "L" }],
|
|
30
|
+
},
|
|
31
|
+
],
|
|
32
|
+
},
|
|
33
|
+
})
|
|
34
|
+
|
|
35
|
+
res.status(201).json({ attribute: result[0] })
|
|
36
|
+
}
|
|
37
|
+
```
|
|
38
|
+
|
|
39
|
+
The workflow creates the `ProductAttribute`, a mirror `ProductOption`, and a
|
|
40
|
+
`ProductAttributeValue` for each option value. It wires `product_option_id` and
|
|
41
|
+
`product_option_value_id` behind the scenes.
|
|
42
|
+
|
|
43
|
+
## Attach it to a product
|
|
44
|
+
|
|
45
|
+
Attach the axis to a product and pass the subset of values that product offers.
|
|
46
|
+
Medusa generates a variant for each selected value.
|
|
47
|
+
|
|
48
|
+
```ts
|
|
49
|
+
import { createAndLinkProductAttributesToProductWorkflow } from "@mercurjs/core/workflows"
|
|
50
|
+
|
|
51
|
+
await createAndLinkProductAttributesToProductWorkflow(req.scope).run({
|
|
52
|
+
input: {
|
|
53
|
+
product_id: "prod_shirt",
|
|
54
|
+
add: [{ id: "pattr_size", value_ids: ["pattrval_s", "pattrval_m"] }],
|
|
55
|
+
},
|
|
56
|
+
})
|
|
57
|
+
```
|
|
58
|
+
|
|
59
|
+
<Note>
|
|
60
|
+
Only `multi_select` attributes can be variant axes. The `value_ids` you pass
|
|
61
|
+
are the per-product subset of the axis's values. Only those become variants.
|
|
62
|
+
</Note>
|
|
63
|
+
|
|
64
|
+
## Inline axes
|
|
65
|
+
|
|
66
|
+
To create a product-scoped axis in the same step it's attached, pass the inline
|
|
67
|
+
form instead of an existing id. This creates an exclusive `ProductOption`, a
|
|
68
|
+
scoped attribute (`product_id` set), and the value mirror in one call:
|
|
69
|
+
|
|
70
|
+
```ts
|
|
71
|
+
await createAndLinkProductAttributesToProductWorkflow(req.scope).run({
|
|
72
|
+
input: {
|
|
73
|
+
product_id: "prod_shirt",
|
|
74
|
+
add: [{ title: "Cut", is_variant_axis: true, values: ["Slim", "Regular"] }],
|
|
75
|
+
},
|
|
76
|
+
})
|
|
77
|
+
```
|
|
78
|
+
|
|
79
|
+
<Tip>
|
|
80
|
+
Inline axes are ideal for a one-off dimension a single product needs. Reach for
|
|
81
|
+
a global axis attribute when the same dimension, such as Size or Color, recurs
|
|
82
|
+
across the catalog. See [Global vs inline](/platform/attribute/concepts/global-vs-inline).
|
|
83
|
+
</Tip>
|
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
---
|
|
2
|
+
title: "Create an attribute"
|
|
3
|
+
sidebarTitle: "Create an attribute"
|
|
4
|
+
description: "Create a typed catalog attribute with createProductAttributesWorkflow."
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
In this guide, you'll learn how to create a global catalog attribute from your
|
|
8
|
+
own server code, for example in a seed script, a custom API route, or a catalog
|
|
9
|
+
import.
|
|
10
|
+
|
|
11
|
+
Mercur exposes a `createProductAttributesWorkflow` that creates one or more
|
|
12
|
+
`ProductAttribute` records along with their values. Run it from any place that
|
|
13
|
+
has access to the Medusa container.
|
|
14
|
+
|
|
15
|
+
## Run the workflow
|
|
16
|
+
|
|
17
|
+
```ts title="src/api/custom/attributes/route.ts"
|
|
18
|
+
import type { MedusaRequest, MedusaResponse } from "@medusajs/framework/http"
|
|
19
|
+
import { createProductAttributesWorkflow } from "@mercurjs/core/workflows"
|
|
20
|
+
|
|
21
|
+
export async function POST(req: MedusaRequest, res: MedusaResponse) {
|
|
22
|
+
const { result } = await createProductAttributesWorkflow(req.scope).run({
|
|
23
|
+
input: {
|
|
24
|
+
attributes: [
|
|
25
|
+
{
|
|
26
|
+
name: "Material",
|
|
27
|
+
type: "single_select",
|
|
28
|
+
is_filterable: true,
|
|
29
|
+
values: [{ name: "Cotton" }, { name: "Wool" }, { name: "Linen" }],
|
|
30
|
+
},
|
|
31
|
+
],
|
|
32
|
+
},
|
|
33
|
+
})
|
|
34
|
+
|
|
35
|
+
res.status(201).json({ attribute: result[0] })
|
|
36
|
+
}
|
|
37
|
+
```
|
|
38
|
+
|
|
39
|
+
The workflow creates the attribute, its `ProductAttributeValue` records, and,
|
|
40
|
+
for a `multi_select` axis, the mirror `ProductOption`. It also emits the
|
|
41
|
+
`product-attribute.created` event.
|
|
42
|
+
|
|
43
|
+
<Note>
|
|
44
|
+
Leaving `product_id` unset creates a **global** attribute reusable across the
|
|
45
|
+
catalog. Passing a `product_id` creates an **inline** attribute scoped to a
|
|
46
|
+
single product. See [Global vs inline](/platform/attribute/concepts/global-vs-inline).
|
|
47
|
+
</Note>
|
|
48
|
+
|
|
49
|
+
## Associate categories
|
|
50
|
+
|
|
51
|
+
Pass `category_ids` on an attribute to associate it with product categories
|
|
52
|
+
through the category link in the same call:
|
|
53
|
+
|
|
54
|
+
```ts
|
|
55
|
+
await createProductAttributesWorkflow(req.scope).run({
|
|
56
|
+
input: {
|
|
57
|
+
attributes: [
|
|
58
|
+
{
|
|
59
|
+
name: "Thread count",
|
|
60
|
+
type: "unit",
|
|
61
|
+
category_ids: ["pcat_bedding"],
|
|
62
|
+
},
|
|
63
|
+
],
|
|
64
|
+
},
|
|
65
|
+
})
|
|
66
|
+
```
|
|
67
|
+
|
|
68
|
+
## Attach custom data
|
|
69
|
+
|
|
70
|
+
The workflow accepts an `additional_data` payload passed to its
|
|
71
|
+
`productAttributesCreated` hook, letting you persist marketplace-specific data
|
|
72
|
+
alongside the attribute without forking the workflow.
|
|
73
|
+
|
|
74
|
+
```ts
|
|
75
|
+
await createProductAttributesWorkflow(req.scope).run({
|
|
76
|
+
input: {
|
|
77
|
+
attributes: [{ name: "Material", type: "single_select" }],
|
|
78
|
+
additional_data: { imported_from: "legacy-pim" },
|
|
79
|
+
},
|
|
80
|
+
})
|
|
81
|
+
```
|
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
---
|
|
2
|
+
title: "Attribute"
|
|
3
|
+
sidebarTitle: "Overview"
|
|
4
|
+
description: "An operator-managed, typed attribute catalog for describing and filtering the shared product catalog."
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
Use Mercur to define a typed vocabulary for your products, such as colors,
|
|
8
|
+
materials, sizes, capacities, or warranty toggles, and reuse it across the whole
|
|
9
|
+
marketplace.
|
|
10
|
+
|
|
11
|
+
The Attribute domain is an operator-managed catalog of typed fields that attach
|
|
12
|
+
to products in the shared master catalog. Attributes describe products
|
|
13
|
+
consistently and drive storefront filters. For variant axes, they generate the
|
|
14
|
+
product variants shoppers pick between. Every attribute is one of five types.
|
|
15
|
+
Each one is either a global catalog entry reused everywhere or an inline field
|
|
16
|
+
scoped to a single product.
|
|
17
|
+
|
|
18
|
+
<Note>
|
|
19
|
+
**Attribute = the `ProductAttribute` entity.** The catalog is owned by the
|
|
20
|
+
Product Attribute module (`MercurModules.PRODUCT_ATTRIBUTE`, id prefix
|
|
21
|
+
`pattr`). Products are the shared master catalog. Attributes never belong to a
|
|
22
|
+
store. Sellers list against master products through offers.
|
|
23
|
+
</Note>
|
|
24
|
+
|
|
25
|
+
## Key features
|
|
26
|
+
|
|
27
|
+
- **Five typed forms:** `single_select`, `multi_select`, `text`, `unit`, and `toggle`, each with its own validation and UI shape.
|
|
28
|
+
- **Variant axes:** a `multi_select` attribute marked `is_variant_axis` mirrors a native Medusa `ProductOption` and generates product variants.
|
|
29
|
+
- **Global or inline:** reuse a global catalog attribute across products, or attach a one-off attribute scoped to a single product.
|
|
30
|
+
- **Storefront filtering:** an `is_filterable` flag exposes an attribute as a shopper-facing facet.
|
|
31
|
+
- **Batch attach:** attach, detach, and update all of a product's attributes through a single engine workflow.
|
|
32
|
+
- **Ordered and governed:** `rank`, `is_active`, and `is_required` control ordering, availability, and required-field enforcement.
|
|
33
|
+
|
|
34
|
+
## Get started
|
|
35
|
+
|
|
36
|
+
Learn how the domain fits together.
|
|
37
|
+
|
|
38
|
+
<CardGroup cols={2}>
|
|
39
|
+
<Card title="Attribute types" icon="shapes" href="/platform/attribute/concepts/attribute-types">
|
|
40
|
+
The five attribute types and the values they hold.
|
|
41
|
+
</Card>
|
|
42
|
+
<Card title="Variant axes" icon="sitemap" href="/platform/attribute/concepts/variant-axes">
|
|
43
|
+
How `is_variant_axis` mirrors a `ProductOption` and generates variants.
|
|
44
|
+
</Card>
|
|
45
|
+
<Card title="Global vs inline" icon="layer-group" href="/platform/attribute/concepts/global-vs-inline">
|
|
46
|
+
Catalog-wide attributes, product-scoped attributes, and filtering.
|
|
47
|
+
</Card>
|
|
48
|
+
</CardGroup>
|
|
49
|
+
|
|
50
|
+
## Examples
|
|
51
|
+
|
|
52
|
+
Build against the Attribute domain in your own code.
|
|
53
|
+
|
|
54
|
+
<CardGroup cols={2}>
|
|
55
|
+
<Card title="Create an attribute" icon="plus" href="/platform/attribute/guides/create-an-attribute">
|
|
56
|
+
Run `createProductAttributesWorkflow` from a route or seed script.
|
|
57
|
+
</Card>
|
|
58
|
+
<Card title="Attach to a product" icon="link" href="/platform/attribute/guides/attach-attributes-to-a-product">
|
|
59
|
+
Attach, detach, and update attributes in one batch call.
|
|
60
|
+
</Card>
|
|
61
|
+
<Card title="Create a variant axis" icon="sitemap" href="/platform/attribute/guides/create-a-variant-axis">
|
|
62
|
+
Generate variants from a `multi_select` axis attribute.
|
|
63
|
+
</Card>
|
|
64
|
+
</CardGroup>
|
|
65
|
+
|
|
66
|
+
## Resources
|
|
67
|
+
|
|
68
|
+
Data models, links, workflows, service methods, and events for the Attribute
|
|
69
|
+
domain.
|
|
70
|
+
|
|
71
|
+
<CardGroup cols={2}>
|
|
72
|
+
<Card title="Data models" icon="table" href="/platform/attribute/reference/data-models">
|
|
73
|
+
The `ProductAttribute` and `ProductAttributeValue` entities.
|
|
74
|
+
</Card>
|
|
75
|
+
<Card title="Links" icon="link" href="/platform/attribute/reference/links">
|
|
76
|
+
How the Attribute domain links to products, categories, and options.
|
|
77
|
+
</Card>
|
|
78
|
+
<Card title="Workflows" icon="diagram-project" href="/platform/attribute/reference/workflows">
|
|
79
|
+
Catalog and product-attachment workflows.
|
|
80
|
+
</Card>
|
|
81
|
+
<Card title="Service" icon="gear" href="/platform/attribute/reference/service">
|
|
82
|
+
Module service methods for working with records directly.
|
|
83
|
+
</Card>
|
|
84
|
+
<Card title="Events" icon="bell" href="/platform/attribute/reference/events">
|
|
85
|
+
Events emitted as attributes and values change.
|
|
86
|
+
</Card>
|
|
87
|
+
</CardGroup>
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
---
|
|
2
|
+
title: "Data models"
|
|
3
|
+
sidebarTitle: "Data models"
|
|
4
|
+
description: "The data models owned by the Attribute (Product Attribute) domain."
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
The Attribute domain is owned by the **Product Attribute module**. This reference
|
|
8
|
+
lists its data models and their fields. For the full module overview, see the
|
|
9
|
+
[Attribute module overview](/platform/attribute/overview).
|
|
10
|
+
|
|
11
|
+
## ProductAttribute
|
|
12
|
+
|
|
13
|
+
Table `product_attribute`, id prefix `pattr`. A typed catalog attribute.
|
|
14
|
+
|
|
15
|
+
| Field | Type | Notes |
|
|
16
|
+
| --- | --- | --- |
|
|
17
|
+
| `id` | text | Primary key |
|
|
18
|
+
| `name` | text | Searchable |
|
|
19
|
+
| `handle` | text | Nullable; unique when set |
|
|
20
|
+
| `description` | text | Nullable |
|
|
21
|
+
| `type` | enum | `AttributeType`: `single_select`, `multi_select`, `text`, `unit`, `toggle` |
|
|
22
|
+
| `is_required` | boolean | Default `false` |
|
|
23
|
+
| `is_filterable` | boolean | Default `false`; exposes the attribute as a storefront filter |
|
|
24
|
+
| `is_variant_axis` | boolean | Default `false`; `multi_select` axis that generates variants |
|
|
25
|
+
| `rank` | number | Default `0`; ordering |
|
|
26
|
+
| `is_active` | boolean | Default `true` |
|
|
27
|
+
| `created_by` | text | Nullable |
|
|
28
|
+
| `product_id` | text | Nullable; non-null = product-scoped (inline), null = global |
|
|
29
|
+
| `product_option_id` | text | Nullable; FK to the mirror `ProductOption` (axis attributes) |
|
|
30
|
+
| `metadata` | json | Nullable |
|
|
31
|
+
|
|
32
|
+
Relations: `values` (one-to-many `ProductAttributeValue`, deleted with the
|
|
33
|
+
attribute).
|
|
34
|
+
|
|
35
|
+
## ProductAttributeValue
|
|
36
|
+
|
|
37
|
+
Table `product_attribute_value`, id prefix `pattrval`. A selectable value that
|
|
38
|
+
belongs to one attribute.
|
|
39
|
+
|
|
40
|
+
| Field | Type | Notes |
|
|
41
|
+
| --- | --- | --- |
|
|
42
|
+
| `id` | text | Primary key |
|
|
43
|
+
| `name` | text | The value label |
|
|
44
|
+
| `handle` | text | Nullable; unique per attribute when set |
|
|
45
|
+
| `rank` | number | Default `0`; ordering |
|
|
46
|
+
| `is_active` | boolean | Default `true` |
|
|
47
|
+
| `product_option_value_id` | text | Nullable; FK to the mirror `ProductOptionValue` (axis values) |
|
|
48
|
+
| `metadata` | json | Nullable |
|
|
49
|
+
|
|
50
|
+
Relations: `attribute` (belongs to `ProductAttribute` via `attribute_id`).
|
|
51
|
+
|
|
52
|
+
<Note>
|
|
53
|
+
`product_option_id` on the attribute and `product_option_value_id` on the value
|
|
54
|
+
are the foreign keys behind the read-only mirror links to Medusa's product
|
|
55
|
+
options. See [Links](/platform/attribute/reference/links).
|
|
56
|
+
</Note>
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
---
|
|
2
|
+
title: "Event reference"
|
|
3
|
+
sidebarTitle: "Events"
|
|
4
|
+
description: "Events emitted by the Attribute domain, for subscribers and side effects."
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
The Attribute domain emits events as attributes and their values change.
|
|
8
|
+
Subscribe to them to run side effects, such as reindexing storefront filters,
|
|
9
|
+
syncing an external PIM, or kicking off follow-up workflows, instead of polling.
|
|
10
|
+
|
|
11
|
+
```ts title="src/subscribers/attribute-created.ts"
|
|
12
|
+
import type { SubscriberArgs, SubscriberConfig } from "@medusajs/framework"
|
|
13
|
+
|
|
14
|
+
export default async function attributeCreatedHandler({
|
|
15
|
+
event,
|
|
16
|
+
container,
|
|
17
|
+
}: SubscriberArgs<{ id: string }>) {
|
|
18
|
+
const attributeId = event.data.id
|
|
19
|
+
// ...reindex filters, sync to an external system, etc.
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
export const config: SubscriberConfig = {
|
|
23
|
+
event: "product-attribute.created",
|
|
24
|
+
}
|
|
25
|
+
```
|
|
26
|
+
|
|
27
|
+
## Attribute events
|
|
28
|
+
|
|
29
|
+
| Event | Emitted when | Payload |
|
|
30
|
+
| --- | --- | --- |
|
|
31
|
+
| `product-attribute.created` | An attribute is created | `{ id }` |
|
|
32
|
+
| `product-attribute.updated` | An attribute changes | `{ id }` |
|
|
33
|
+
| `product-attribute.deleted` | An attribute is deleted | `{ id }` |
|
|
34
|
+
|
|
35
|
+
## Value events
|
|
36
|
+
|
|
37
|
+
| Event | Emitted when | Payload |
|
|
38
|
+
| --- | --- | --- |
|
|
39
|
+
| `product-attribute-value.created` | A value is created | `{ id }` |
|
|
40
|
+
| `product-attribute-value.updated` | A value changes | `{ id }` |
|
|
41
|
+
| `product-attribute-value.deleted` | A value is deleted | `{ id }` |
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
---
|
|
2
|
+
title: "Links to other modules"
|
|
3
|
+
sidebarTitle: "Links"
|
|
4
|
+
description: "How the Attribute (Product Attribute) domain links to products, categories, and options."
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
Modules in Mercur never reference each other directly. They're connected through
|
|
8
|
+
**module links**. The Product Attribute module links into Medusa's product module
|
|
9
|
+
in several ways: to products, to categories, and, for variant axes, to product
|
|
10
|
+
options through mirror links. Once a link is defined, you retrieve related records
|
|
11
|
+
with `query.graph` using the link alias.
|
|
12
|
+
|
|
13
|
+
```ts
|
|
14
|
+
const { data: products } = await query.graph({
|
|
15
|
+
entity: "product",
|
|
16
|
+
fields: ["id", "title", "scoped_attributes.*"],
|
|
17
|
+
})
|
|
18
|
+
```
|
|
19
|
+
|
|
20
|
+
## Products
|
|
21
|
+
|
|
22
|
+
| Link | Table | Relationship |
|
|
23
|
+
| --- | --- | --- |
|
|
24
|
+
| **Product → attribute** (`scoped_attributes`) | None | Read-only; a product's inline (product-scoped) attributes, resolved from `ProductAttribute.product_id` |
|
|
25
|
+
| **Product ↔ attribute value** | `product_attribute_value_link` | Many-to-many pivot; the values selected on a product |
|
|
26
|
+
|
|
27
|
+
## Categories
|
|
28
|
+
|
|
29
|
+
| Link | Table | Relationship |
|
|
30
|
+
| --- | --- | --- |
|
|
31
|
+
| **Attribute ↔ category** (`categories`) | `product_category_attribute` | Many-to-many; the product categories an attribute is associated with |
|
|
32
|
+
|
|
33
|
+
## Product options (mirror links)
|
|
34
|
+
|
|
35
|
+
| Link | FK | Relationship |
|
|
36
|
+
| --- | --- | --- |
|
|
37
|
+
| **Attribute → option** | `ProductAttribute.product_option_id` | Read-only 1:1; the mirror `ProductOption` for a variant-axis attribute |
|
|
38
|
+
| **Value → option value** | `ProductAttributeValue.product_option_value_id` | Read-only 1:1; the mirror `ProductOptionValue` for an axis value |
|
|
39
|
+
|
|
40
|
+
<Note>
|
|
41
|
+
The mirror links (Attribute → option, Value → option value) and the product
|
|
42
|
+
scope link (`scoped_attributes`) are **read-only**. They're resolved from the
|
|
43
|
+
FK on the owning record and can't be written through the link itself. The
|
|
44
|
+
workflows keep the mirror in sync when axis attributes and values change.
|
|
45
|
+
</Note>
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
---
|
|
2
|
+
title: "Service reference"
|
|
3
|
+
sidebarTitle: "Service"
|
|
4
|
+
description: "The Product Attribute module service, with methods for working with records directly."
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
The Product Attribute module exposes a service you can resolve from the Medusa
|
|
8
|
+
container to read and write records directly, without going through a workflow.
|
|
9
|
+
Use it inside custom services, subscribers, or scheduled jobs.
|
|
10
|
+
|
|
11
|
+
```ts
|
|
12
|
+
import { MercurModules } from "@mercurjs/types"
|
|
13
|
+
|
|
14
|
+
const attributeModuleService = container.resolve(
|
|
15
|
+
MercurModules.PRODUCT_ATTRIBUTE,
|
|
16
|
+
)
|
|
17
|
+
|
|
18
|
+
const [attributes, count] =
|
|
19
|
+
await attributeModuleService.listAndCountProductAttributes({
|
|
20
|
+
type: "single_select",
|
|
21
|
+
})
|
|
22
|
+
```
|
|
23
|
+
|
|
24
|
+
## Generated methods
|
|
25
|
+
|
|
26
|
+
Each data model gets a standard set of auto-generated methods. For
|
|
27
|
+
`ProductAttribute`:
|
|
28
|
+
|
|
29
|
+
| Method | Description |
|
|
30
|
+
| --- | --- |
|
|
31
|
+
| `createProductAttributes(data)` | Create one or more attributes |
|
|
32
|
+
| `retrieveProductAttribute(id, config?)` | Retrieve an attribute by id |
|
|
33
|
+
| `listProductAttributes(filters?, config?)` | List attributes matching filters |
|
|
34
|
+
| `listAndCountProductAttributes(filters?, config?)` | List attributes with a total count |
|
|
35
|
+
| `updateProductAttributes(data)` | Update one or more attributes |
|
|
36
|
+
| `deleteProductAttributes(ids)` | Delete one or more attributes |
|
|
37
|
+
|
|
38
|
+
The same set exists for `ProductAttributeValue`: `createProductAttributeValues`,
|
|
39
|
+
`retrieveProductAttributeValue`, `listProductAttributeValues`,
|
|
40
|
+
`listAndCountProductAttributeValues`, `updateProductAttributeValues`, and
|
|
41
|
+
`deleteProductAttributeValues`.
|
|
42
|
+
|
|
43
|
+
<Warning>
|
|
44
|
+
Prefer [workflows](/platform/attribute/reference/workflows) for anything with
|
|
45
|
+
side effects, such as creating an axis attribute, attaching attributes to a
|
|
46
|
+
product, or keeping the mirror `ProductOption` in sync. The service writes records
|
|
47
|
+
directly and does **not** emit events, maintain the option mirror, or run
|
|
48
|
+
compensation.
|
|
49
|
+
</Warning>
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
---
|
|
2
|
+
title: "Workflows"
|
|
3
|
+
sidebarTitle: "Workflows"
|
|
4
|
+
description: "Attribute catalog and product-attachment workflows."
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
This reference lists the workflows for the Attribute domain. Import them from
|
|
8
|
+
`@mercurjs/core/workflows` and run them against the Medusa container.
|
|
9
|
+
|
|
10
|
+
## Catalog workflows
|
|
11
|
+
|
|
12
|
+
Manage the attribute catalog and its values.
|
|
13
|
+
|
|
14
|
+
| Workflow | Input | Purpose |
|
|
15
|
+
| --- | --- | --- |
|
|
16
|
+
| `createProductAttributesWorkflow` | `{ attributes[], additional_data? }` | Create attributes (+ values, + mirror option for axes) |
|
|
17
|
+
| `updateProductAttributesWorkflow` | `{ selector, update }` | Update attribute fields |
|
|
18
|
+
| `deleteProductAttributesWorkflow` | `{ ids[] }` | Delete attributes (fails if still linked) |
|
|
19
|
+
| `createProductAttributeValuesWorkflow` | `{ values[], additional_data? }` | Add values to attributes |
|
|
20
|
+
| `updateProductAttributeValuesWorkflow` | `{ selector, update }` | Update values |
|
|
21
|
+
| `deleteProductAttributeValuesWorkflow` | `{ ids[] }` | Delete values |
|
|
22
|
+
| `upsertProductAttributeValuesWorkflow` | `{ attribute_id, values[] }` | Create or update an attribute's values in one call |
|
|
23
|
+
|
|
24
|
+
## Product-attachment workflows
|
|
25
|
+
|
|
26
|
+
Attach attributes to products in the shared master catalog.
|
|
27
|
+
|
|
28
|
+
| Workflow | Input | Purpose |
|
|
29
|
+
| --- | --- | --- |
|
|
30
|
+
| `createAndLinkProductAttributesToProductWorkflow` | `{ product_id, add?, remove?, update? }` | Batch engine: attach, detach, and update, applied remove → add → update |
|
|
31
|
+
| `addProductAttributesToProductWorkflow` | `{ product_id, add[] }` | Attach attributes (existing or inline) to a product |
|
|
32
|
+
| `removeProductAttributesFromProductWorkflow` | `{ product_id, ... }` | Detach attributes from a product |
|
|
33
|
+
| `updateProductAttributesOnProductWorkflow` | `{ product_id, ... }` | Update a product's attribute selections |
|
|
34
|
+
|
|
35
|
+
<Note>
|
|
36
|
+
`createAndLinkProductAttributesToProductWorkflow` is the engine behind the
|
|
37
|
+
product attribute batch endpoint; it composes the three single-purpose
|
|
38
|
+
attachment workflows. See
|
|
39
|
+
[Attach attributes to a product](/platform/attribute/guides/attach-attributes-to-a-product).
|
|
40
|
+
</Note>
|
|
41
|
+
|
|
42
|
+
To work with records directly instead of through a workflow, see the
|
|
43
|
+
[Service reference](/platform/attribute/reference/service). To run side effects
|
|
44
|
+
when an attribute changes, see the
|
|
45
|
+
[Event reference](/platform/attribute/reference/events).
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
---
|
|
2
|
+
title: "Master products"
|
|
3
|
+
sidebarTitle: "Master products"
|
|
4
|
+
description: "The shared catalog, why products aren't seller-owned, and submission attribution."
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
In this document, you'll learn how Mercur models products as a single shared
|
|
8
|
+
catalog rather than per-seller listings.
|
|
9
|
+
|
|
10
|
+
## Product
|
|
11
|
+
|
|
12
|
+
A product is a **master product** in a catalog shared by the whole marketplace,
|
|
13
|
+
represented by Medusa's native `Product` data model (table `product`, id prefix
|
|
14
|
+
`prod`). Products carry the usual commerce fields such as `title`, `handle`,
|
|
15
|
+
`description`, `status`, variants, options, and images, and are **not owned by
|
|
16
|
+
any store**. Creating a product adds it to the shared catalog. Multiple stores
|
|
17
|
+
can then sell the same master product.
|
|
18
|
+
|
|
19
|
+
```ts
|
|
20
|
+
const { result } = await createProductsWorkflow(container).run({
|
|
21
|
+
input: {
|
|
22
|
+
products: [
|
|
23
|
+
{
|
|
24
|
+
title: "Aeron Chair",
|
|
25
|
+
status: "proposed",
|
|
26
|
+
seller_ids: ["sel_123"],
|
|
27
|
+
},
|
|
28
|
+
],
|
|
29
|
+
created_by: "usr_123",
|
|
30
|
+
},
|
|
31
|
+
})
|
|
32
|
+
```
|
|
33
|
+
|
|
34
|
+
<Note>
|
|
35
|
+
A store never sells a bare master product directly. It sells against one by
|
|
36
|
+
creating an [offer](/platform/offer/overview). The offer carries the store's
|
|
37
|
+
own SKU, price, inventory, and shipping profile, while the master product
|
|
38
|
+
holds the shared catalog data everyone shares.
|
|
39
|
+
</Note>
|
|
40
|
+
|
|
41
|
+
## Attribution, not ownership
|
|
42
|
+
|
|
43
|
+
Because the catalog is shared, the creator of a product does **not** own it.
|
|
44
|
+
When a store submits a new product, Mercur records the submission as an immutable
|
|
45
|
+
audit entry (a `PRODUCT_ADD` action in the product-change pipeline) so you know
|
|
46
|
+
who proposed it. That attribution is for review and history only. Once
|
|
47
|
+
published, the product belongs to the shared catalog like any other.
|
|
48
|
+
|
|
49
|
+
<Tip>
|
|
50
|
+
Attribution is recorded automatically by `createProductsWorkflow` through its
|
|
51
|
+
`created_by` input. You don't manage it by hand. See the
|
|
52
|
+
[status lifecycle](/platform/catalog/concepts/status-lifecycle) for how a
|
|
53
|
+
submission becomes a published catalog product.
|
|
54
|
+
</Tip>
|