@csbeker/medusa-product-attributes 2.2.0

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.
Files changed (237) hide show
  1. package/.medusa/server/src/admin/index.js +9012 -0
  2. package/.medusa/server/src/admin/index.mjs +9010 -0
  3. package/.medusa/server/src/api/admin/middlewares.js +10 -0
  4. package/.medusa/server/src/api/admin/plugin/attribute-set/[id]/attributes/route.js +17 -0
  5. package/.medusa/server/src/api/admin/plugin/attribute-set/[id]/route.js +33 -0
  6. package/.medusa/server/src/api/admin/plugin/attribute-set/middlewares.js +44 -0
  7. package/.medusa/server/src/api/admin/plugin/attribute-set/query-config.js +22 -0
  8. package/.medusa/server/src/api/admin/plugin/attribute-set/route.js +25 -0
  9. package/.medusa/server/src/api/admin/plugin/attribute-set/validators.js +37 -0
  10. package/.medusa/server/src/api/admin/plugin/attributes/[id]/route.js +68 -0
  11. package/.medusa/server/src/api/admin/plugin/attributes/[id]/values/[valueId]/route.js +37 -0
  12. package/.medusa/server/src/api/admin/plugin/attributes/[id]/values/route.js +31 -0
  13. package/.medusa/server/src/api/admin/plugin/attributes/middlewares.js +103 -0
  14. package/.medusa/server/src/api/admin/plugin/attributes/query-config.js +41 -0
  15. package/.medusa/server/src/api/admin/plugin/attributes/route.js +28 -0
  16. package/.medusa/server/src/api/admin/plugin/attributes/validators.js +69 -0
  17. package/.medusa/server/src/api/admin/plugin/route.js +7 -0
  18. package/.medusa/server/src/api/middlewares.js +12 -0
  19. package/.medusa/server/src/api/store/middlewares.js +8 -0
  20. package/.medusa/server/src/api/store/plugin/attributes/middlewares.js +64 -0
  21. package/.medusa/server/src/api/store/plugin/attributes/products/middlewares.js +100 -0
  22. package/.medusa/server/src/api/store/plugin/attributes/products/query-config.js +20 -0
  23. package/.medusa/server/src/api/store/plugin/attributes/products/route.js +48 -0
  24. package/.medusa/server/src/api/store/plugin/attributes/products/validators.js +39 -0
  25. package/.medusa/server/src/api/store/plugin/attributes/query-config.js +21 -0
  26. package/.medusa/server/src/api/store/plugin/attributes/route.js +15 -0
  27. package/.medusa/server/src/api/store/plugin/attributes/validators.js +14 -0
  28. package/.medusa/server/src/api/store/plugin/route.js +7 -0
  29. package/.medusa/server/src/api/utils/common-validators.js +23 -0
  30. package/.medusa/server/src/api/utils/constants.js +6 -0
  31. package/.medusa/server/src/api/utils/middlewares.js +34 -0
  32. package/.medusa/server/src/links/attribute-product-category.js +16 -0
  33. package/.medusa/server/src/links/attribute-value-product.js +16 -0
  34. package/.medusa/server/src/modules/attribute/events/index.js +8 -0
  35. package/.medusa/server/src/modules/attribute/index.js +13 -0
  36. package/.medusa/server/src/modules/attribute/migrations/Migration20250319161229.js +24 -0
  37. package/.medusa/server/src/modules/attribute/migrations/Migration20250320182643.js +16 -0
  38. package/.medusa/server/src/modules/attribute/migrations/Migration20250321162638.js +14 -0
  39. package/.medusa/server/src/modules/attribute/migrations/Migration20250505144933.js +23 -0
  40. package/.medusa/server/src/modules/attribute/migrations/Migration20250505201747.js +21 -0
  41. package/.medusa/server/src/modules/attribute/migrations/Migration20250506162300.js +14 -0
  42. package/.medusa/server/src/modules/attribute/migrations/Migration20250611160552.js +14 -0
  43. package/.medusa/server/src/modules/attribute/migrations/Migration20250611173345.js +16 -0
  44. package/.medusa/server/src/modules/attribute/migrations/Migration20250612192857.js +16 -0
  45. package/.medusa/server/src/modules/attribute/models/attribute-possible-value.js +24 -0
  46. package/.medusa/server/src/modules/attribute/models/attribute-set.js +22 -0
  47. package/.medusa/server/src/modules/attribute/models/attribute-value.js +17 -0
  48. package/.medusa/server/src/modules/attribute/models/attribute.js +27 -0
  49. package/.medusa/server/src/modules/attribute/service.js +84 -0
  50. package/.medusa/server/src/modules/attribute/types/attribute/common.js +13 -0
  51. package/.medusa/server/src/modules/attribute/types/attribute/index.js +18 -0
  52. package/.medusa/server/src/modules/attribute/types/attribute-set/index.js +18 -0
  53. package/.medusa/server/src/modules/attribute/types/attribute-set/mutations.js +3 -0
  54. package/.medusa/server/src/modules/attribute/types/attribute-value/index.js +18 -0
  55. package/.medusa/server/src/modules/attribute/types/attribute-value/mutations.js +3 -0
  56. package/.medusa/server/src/modules/attribute/types/index.js +20 -0
  57. package/.medusa/server/src/types/attribute/common.js +3 -0
  58. package/.medusa/server/src/types/attribute/http/attribute/admin/index.js +3 -0
  59. package/.medusa/server/src/types/attribute/http/attribute/index.js +18 -0
  60. package/.medusa/server/src/types/attribute/http/attribute-set/index.js +3 -0
  61. package/.medusa/server/src/types/attribute/http/index.js +19 -0
  62. package/.medusa/server/src/types/attribute/index.js +19 -0
  63. package/.medusa/server/src/utils/index.js +18 -0
  64. package/.medusa/server/src/utils/products-created-handler.js +22 -0
  65. package/.medusa/server/src/utils/products-updated-handler.js +58 -0
  66. package/.medusa/server/src/utils/validate-attribute-values-to-link.js +43 -0
  67. package/.medusa/server/src/workflows/attribute/index.js +19 -0
  68. package/.medusa/server/src/workflows/attribute/steps/create-attribute-possible-values.js +18 -0
  69. package/.medusa/server/src/workflows/attribute/steps/create-attributes.js +27 -0
  70. package/.medusa/server/src/workflows/attribute/steps/delete-attribute.js +31 -0
  71. package/.medusa/server/src/workflows/attribute/steps/index.js +21 -0
  72. package/.medusa/server/src/workflows/attribute/steps/update-attributes.js +34 -0
  73. package/.medusa/server/src/workflows/attribute/workflows/create-attribute-possible-values.js +11 -0
  74. package/.medusa/server/src/workflows/attribute/workflows/create-attributes.js +46 -0
  75. package/.medusa/server/src/workflows/attribute/workflows/delete-attribute.js +10 -0
  76. package/.medusa/server/src/workflows/attribute/workflows/index.js +20 -0
  77. package/.medusa/server/src/workflows/attribute/workflows/update-attributes.js +73 -0
  78. package/.medusa/server/src/workflows/attribute-set/steps/batch-link-attribute-set-attributes.js +66 -0
  79. package/.medusa/server/src/workflows/attribute-set/steps/create-attribute-set.js +24 -0
  80. package/.medusa/server/src/workflows/attribute-set/steps/index.js +20 -0
  81. package/.medusa/server/src/workflows/attribute-set/steps/update-attribute-set.js +22 -0
  82. package/.medusa/server/src/workflows/attribute-set/workflows/batch-link-attribute-set-attributes.js +10 -0
  83. package/.medusa/server/src/workflows/attribute-set/workflows/create-attribute-set.js +11 -0
  84. package/.medusa/server/src/workflows/attribute-set/workflows/index.js +20 -0
  85. package/.medusa/server/src/workflows/attribute-set/workflows/update-attribute-set.js +10 -0
  86. package/.medusa/server/src/workflows/attribute-value/steps/create-attribute-value.js +18 -0
  87. package/.medusa/server/src/workflows/attribute-value/steps/delete-attribute-value.js +18 -0
  88. package/.medusa/server/src/workflows/attribute-value/steps/index.js +20 -0
  89. package/.medusa/server/src/workflows/attribute-value/steps/validate-attribute-value.js +53 -0
  90. package/.medusa/server/src/workflows/attribute-value/workflow/create-attribute-value.js +28 -0
  91. package/.medusa/server/src/workflows/attribute-value/workflow/delete-attribute-value.js +38 -0
  92. package/.medusa/server/src/workflows/attribute-value/workflow/index.js +19 -0
  93. package/.medusa/server/src/workflows/attribute_possible_value/index.js +19 -0
  94. package/.medusa/server/src/workflows/attribute_possible_value/steps/index.js +18 -0
  95. package/.medusa/server/src/workflows/attribute_possible_value/steps/update-attribute-possible-value.js +18 -0
  96. package/.medusa/server/src/workflows/attribute_possible_value/workflows/index.js +18 -0
  97. package/.medusa/server/src/workflows/attribute_possible_value/workflows/update-attribute-possible-value.js +11 -0
  98. package/.medusa/server/src/workflows/index.js +18 -0
  99. package/CHANGELOG.md +104 -0
  100. package/README.md +86 -0
  101. package/package.json +90 -0
  102. package/src/admin/README.md +31 -0
  103. package/src/admin/components/metadata-editor/index.tsx +101 -0
  104. package/src/admin/components/section-row.tsx +41 -0
  105. package/src/admin/hooks/api/attribute-set.ts +122 -0
  106. package/src/admin/hooks/api/attributes.ts +126 -0
  107. package/src/admin/hooks/table/columns/index.ts +1 -0
  108. package/src/admin/hooks/table/columns/use-attribute-table-columns.tsx +280 -0
  109. package/src/admin/layouts/single-column.tsx +11 -0
  110. package/src/admin/lib/config.ts +8 -0
  111. package/src/admin/lib/query-key-factory.ts +53 -0
  112. package/src/admin/routes/attributes/[id]/edit/page.tsx +133 -0
  113. package/src/admin/routes/attributes/[id]/edit-possible-value/page.tsx +174 -0
  114. package/src/admin/routes/attributes/[id]/page.tsx +127 -0
  115. package/src/admin/routes/attributes/components/AttributeForm.tsx +301 -0
  116. package/src/admin/routes/attributes/components/AttributeSetTable.tsx +108 -0
  117. package/src/admin/routes/attributes/components/category-selection-modal.tsx +82 -0
  118. package/src/admin/routes/attributes/components/possible-values-table.tsx +119 -0
  119. package/src/admin/routes/attributes/create/components/MultiSelectCategory.tsx +148 -0
  120. package/src/admin/routes/attributes/create/components/PossibleValuesList.tsx +151 -0
  121. package/src/admin/routes/attributes/create/page.tsx +123 -0
  122. package/src/admin/routes/attributes/create-set/page.tsx +110 -0
  123. package/src/admin/routes/attributes/page.tsx +346 -0
  124. package/src/admin/routes/attributes/set/[id]/attributes/page.tsx +35 -0
  125. package/src/admin/routes/attributes/set/[id]/components/AttributeSetAttributesSection.tsx +114 -0
  126. package/src/admin/routes/attributes/set/[id]/components/AttributeSetGeneralSection.tsx +42 -0
  127. package/src/admin/routes/attributes/set/[id]/components/attribute-set-attributes-form.tsx +143 -0
  128. package/src/admin/routes/attributes/set/[id]/components/index.ts +2 -0
  129. package/src/admin/routes/attributes/set/[id]/edit/page.tsx +119 -0
  130. package/src/admin/routes/attributes/set/[id]/page.tsx +45 -0
  131. package/src/admin/tsconfig.json +27 -0
  132. package/src/admin/types/global.d.ts +3 -0
  133. package/src/admin/vite-env.d.ts +1 -0
  134. package/src/api/README.md +133 -0
  135. package/src/api/admin/middlewares.ts +8 -0
  136. package/src/api/admin/plugin/attribute-set/[id]/attributes/route.ts +17 -0
  137. package/src/api/admin/plugin/attribute-set/[id]/route.ts +41 -0
  138. package/src/api/admin/plugin/attribute-set/middlewares.ts +42 -0
  139. package/src/api/admin/plugin/attribute-set/query-config.ts +20 -0
  140. package/src/api/admin/plugin/attribute-set/route.ts +34 -0
  141. package/src/api/admin/plugin/attribute-set/validators.ts +45 -0
  142. package/src/api/admin/plugin/attributes/[id]/route.ts +85 -0
  143. package/src/api/admin/plugin/attributes/[id]/values/[valueId]/route.ts +41 -0
  144. package/src/api/admin/plugin/attributes/[id]/values/route.ts +39 -0
  145. package/src/api/admin/plugin/attributes/middlewares.ts +91 -0
  146. package/src/api/admin/plugin/attributes/query-config.ts +42 -0
  147. package/src/api/admin/plugin/attributes/route.ts +33 -0
  148. package/src/api/admin/plugin/attributes/validators.ts +91 -0
  149. package/src/api/admin/plugin/route.ts +8 -0
  150. package/src/api/middlewares.ts +10 -0
  151. package/src/api/store/middlewares.ts +6 -0
  152. package/src/api/store/plugin/attributes/middlewares.ts +33 -0
  153. package/src/api/store/plugin/attributes/products/middlewares.ts +73 -0
  154. package/src/api/store/plugin/attributes/products/query-config.ts +19 -0
  155. package/src/api/store/plugin/attributes/products/route.ts +68 -0
  156. package/src/api/store/plugin/attributes/products/validators.ts +55 -0
  157. package/src/api/store/plugin/attributes/query-config.ts +19 -0
  158. package/src/api/store/plugin/attributes/route.ts +13 -0
  159. package/src/api/store/plugin/attributes/validators.ts +14 -0
  160. package/src/api/store/plugin/route.ts +8 -0
  161. package/src/api/utils/common-validators.ts +24 -0
  162. package/src/api/utils/constants.ts +2 -0
  163. package/src/api/utils/middlewares.ts +31 -0
  164. package/src/jobs/README.md +36 -0
  165. package/src/links/README.md +26 -0
  166. package/src/links/attribute-product-category.ts +14 -0
  167. package/src/links/attribute-value-product.ts +14 -0
  168. package/src/modules/README.md +116 -0
  169. package/src/modules/attribute/events/index.ts +4 -0
  170. package/src/modules/attribute/index.ts +8 -0
  171. package/src/modules/attribute/migrations/.snapshot-medusa-attribute.json +624 -0
  172. package/src/modules/attribute/migrations/Migration20250319161229.ts +27 -0
  173. package/src/modules/attribute/migrations/Migration20250320182643.ts +15 -0
  174. package/src/modules/attribute/migrations/Migration20250321162638.ts +13 -0
  175. package/src/modules/attribute/migrations/Migration20250505144933.ts +26 -0
  176. package/src/modules/attribute/migrations/Migration20250505201747.ts +23 -0
  177. package/src/modules/attribute/migrations/Migration20250506162300.ts +13 -0
  178. package/src/modules/attribute/migrations/Migration20250611160552.ts +13 -0
  179. package/src/modules/attribute/migrations/Migration20250611173345.ts +17 -0
  180. package/src/modules/attribute/migrations/Migration20250612192857.ts +17 -0
  181. package/src/modules/attribute/models/attribute-possible-value.ts +20 -0
  182. package/src/modules/attribute/models/attribute-set.ts +18 -0
  183. package/src/modules/attribute/models/attribute-value.ts +13 -0
  184. package/src/modules/attribute/models/attribute.ts +23 -0
  185. package/src/modules/attribute/service.ts +102 -0
  186. package/src/modules/attribute/types/attribute/common.ts +94 -0
  187. package/src/modules/attribute/types/attribute/index.ts +1 -0
  188. package/src/modules/attribute/types/attribute-set/index.ts +1 -0
  189. package/src/modules/attribute/types/attribute-set/mutations.ts +7 -0
  190. package/src/modules/attribute/types/attribute-value/index.ts +1 -0
  191. package/src/modules/attribute/types/attribute-value/mutations.ts +5 -0
  192. package/src/modules/attribute/types/index.ts +3 -0
  193. package/src/providers/README.md +30 -0
  194. package/src/subscribers/README.md +59 -0
  195. package/src/types/attribute/common.ts +173 -0
  196. package/src/types/attribute/http/attribute/admin/index.ts +0 -0
  197. package/src/types/attribute/http/attribute/index.ts +42 -0
  198. package/src/types/attribute/http/attribute-set/index.ts +10 -0
  199. package/src/types/attribute/http/index.ts +2 -0
  200. package/src/types/attribute/index.ts +2 -0
  201. package/src/utils/index.ts +1 -0
  202. package/src/utils/products-created-handler.ts +35 -0
  203. package/src/utils/products-updated-handler.ts +74 -0
  204. package/src/utils/validate-attribute-values-to-link.ts +67 -0
  205. package/src/workflows/README.md +79 -0
  206. package/src/workflows/attribute/index.ts +2 -0
  207. package/src/workflows/attribute/steps/create-attribute-possible-values.ts +29 -0
  208. package/src/workflows/attribute/steps/create-attributes.ts +35 -0
  209. package/src/workflows/attribute/steps/delete-attribute.ts +41 -0
  210. package/src/workflows/attribute/steps/index.ts +4 -0
  211. package/src/workflows/attribute/steps/update-attributes.ts +45 -0
  212. package/src/workflows/attribute/workflows/create-attribute-possible-values.ts +17 -0
  213. package/src/workflows/attribute/workflows/create-attributes.ts +56 -0
  214. package/src/workflows/attribute/workflows/delete-attribute.ts +15 -0
  215. package/src/workflows/attribute/workflows/index.ts +3 -0
  216. package/src/workflows/attribute/workflows/update-attributes.ts +103 -0
  217. package/src/workflows/attribute-set/steps/batch-link-attribute-set-attributes.ts +82 -0
  218. package/src/workflows/attribute-set/steps/create-attribute-set.ts +34 -0
  219. package/src/workflows/attribute-set/steps/index.ts +3 -0
  220. package/src/workflows/attribute-set/steps/update-attribute-set.ts +32 -0
  221. package/src/workflows/attribute-set/workflows/batch-link-attribute-set-attributes.ts +12 -0
  222. package/src/workflows/attribute-set/workflows/create-attribute-set.ts +17 -0
  223. package/src/workflows/attribute-set/workflows/index.ts +3 -0
  224. package/src/workflows/attribute-set/workflows/update-attribute-set.ts +14 -0
  225. package/src/workflows/attribute-value/steps/create-attribute-value.ts +26 -0
  226. package/src/workflows/attribute-value/steps/delete-attribute-value.ts +26 -0
  227. package/src/workflows/attribute-value/steps/index.ts +3 -0
  228. package/src/workflows/attribute-value/steps/validate-attribute-value.ts +95 -0
  229. package/src/workflows/attribute-value/workflow/create-attribute-value.ts +36 -0
  230. package/src/workflows/attribute-value/workflow/delete-attribute-value.ts +46 -0
  231. package/src/workflows/attribute-value/workflow/index.ts +2 -0
  232. package/src/workflows/attribute_possible_value/index.ts +2 -0
  233. package/src/workflows/attribute_possible_value/steps/index.ts +1 -0
  234. package/src/workflows/attribute_possible_value/steps/update-attribute-possible-value.ts +25 -0
  235. package/src/workflows/attribute_possible_value/workflows/index.ts +1 -0
  236. package/src/workflows/attribute_possible_value/workflows/update-attribute-possible-value.ts +15 -0
  237. package/src/workflows/index.ts +1 -0
@@ -0,0 +1,56 @@
1
+ import { createWorkflow, transform, when, WorkflowData, WorkflowResponse } from "@medusajs/framework/workflows-sdk";
2
+ import { CreateAttributesWorkflowInput } from "../../../modules/attribute/types/attribute/common";
3
+ import { createAttributesStep } from "../steps/create-attributes";
4
+ import { ATTRIBUTE_MODULE } from "../../../modules/attribute";
5
+ import { Modules } from "@medusajs/framework/utils";
6
+ import { LinkDefinition } from "@medusajs/framework/types";
7
+ import { createRemoteLinkStep, emitEventStep } from "@medusajs/medusa/core-flows";
8
+ import { AttributeWorkflowsEvents } from "../../../modules/attribute/events";
9
+
10
+ export const createAttributesWorkflowId = 'create-attributes'
11
+
12
+ export const createAttributesWorkflow = createWorkflow(
13
+ createAttributesWorkflowId,
14
+ (input: WorkflowData<CreateAttributesWorkflowInput>) => {
15
+ const attributesWithoutExternalRelations = transform(input, ({ attributes }) => {
16
+ return attributes.map(attribute => {
17
+ const { product_category_ids, ...result } = attribute
18
+ return result
19
+ })
20
+ })
21
+
22
+ const createdAttributes = createAttributesStep(attributesWithoutExternalRelations)
23
+
24
+ const productCategoryLinks: LinkDefinition[] = transform({ input, createdAttributes }, ({ input, createdAttributes }) => {
25
+ return createdAttributes.map((attribute, idx) => {
26
+ const inputAttribute = input.attributes[idx]
27
+ return inputAttribute.product_category_ids?.map(productCategoryId => ({
28
+ [ATTRIBUTE_MODULE]: {
29
+ attribute_id: attribute.id
30
+ },
31
+ [Modules.PRODUCT]: {
32
+ product_category_id: productCategoryId
33
+ }
34
+ })) || []
35
+ }).flat()
36
+ })
37
+
38
+ when({ productCategoryLinks }, ({ productCategoryLinks }) => {
39
+ return productCategoryLinks.length > 0
40
+ }).then(() => {
41
+ createRemoteLinkStep(productCategoryLinks)
42
+ })
43
+
44
+
45
+ const attributeEventData = transform({ createdAttributes }, ({ createdAttributes }) => {
46
+ return createdAttributes.map(attribute => attribute.id)
47
+ }) as string[]
48
+
49
+ emitEventStep({
50
+ eventName: AttributeWorkflowsEvents.CREATED,
51
+ data: attributeEventData
52
+ })
53
+
54
+ return new WorkflowResponse(createdAttributes)
55
+ }
56
+ )
@@ -0,0 +1,15 @@
1
+ import { createWorkflow, WorkflowResponse } from "@medusajs/framework/workflows-sdk"
2
+ import { deleteAttributeStep } from "../steps"
3
+
4
+ export const deleteAttributeWorkflowId = 'delete-attribute-worklfow'
5
+
6
+ type DeleteAttributeWorkflowInput = {
7
+ id: string
8
+ }
9
+
10
+ export const deleteAttributeWorkflow = createWorkflow(
11
+ deleteAttributeWorkflowId,
12
+ (input: DeleteAttributeWorkflowInput) => {
13
+ return new WorkflowResponse(deleteAttributeStep(input))
14
+ }
15
+ )
@@ -0,0 +1,3 @@
1
+ export * from './create-attributes'
2
+ export * from './update-attributes'
3
+ export * from './create-attribute-possible-values'
@@ -0,0 +1,103 @@
1
+ import {
2
+ createWorkflow,
3
+ parallelize,
4
+ transform,
5
+ WorkflowResponse,
6
+ } from "@medusajs/framework/workflows-sdk";
7
+ import { UpdateAttributeDTO } from "../../../modules/attribute/types/attribute/common";
8
+ import { updateAttributesStep } from "../steps";
9
+ import { LinkDefinition } from "@medusajs/framework/types";
10
+ import { ATTRIBUTE_MODULE } from "../../../modules/attribute";
11
+ import { arrayDifference, Modules } from "@medusajs/framework/utils";
12
+ import { createRemoteLinkStep, dismissRemoteLinkStep, emitEventStep, useQueryGraphStep, useRemoteQueryStep } from "@medusajs/medusa/core-flows";
13
+ import attributeProductCategory from "../../../links/attribute-product-category";
14
+ import { AttributeWorkflowsEvents } from "../../../modules/attribute/events";
15
+
16
+ const updateAttributesWorkflowId = "update-attributes";
17
+
18
+ export type UpdateAttributesWorkflowInput = {
19
+ attributes: UpdateAttributeDTO[];
20
+ };
21
+
22
+ export const updateAttributesWorkflow = createWorkflow(
23
+ updateAttributesWorkflowId,
24
+ (input: UpdateAttributesWorkflowInput) => {
25
+ const toUpdateInput = transform({ input }, ({ input: { attributes } }) => {
26
+ return attributes.map((attribute) => ({
27
+ ...attribute,
28
+ product_category_ids: undefined,
29
+ }));
30
+ });
31
+
32
+ const updatedAttributes = updateAttributesStep(toUpdateInput);
33
+
34
+ const attributesIdsWithCategories = transform({ input, updatedAttributes }, ({ input, updatedAttributes }) => {
35
+ const updatedAttributeIds = updatedAttributes.map(attr => attr.id)
36
+ const attributeIdsWithoutCategories = input.attributes
37
+ .filter(attr => !attr.product_category_ids)
38
+ .map(attr => attr.id)
39
+ return arrayDifference(updatedAttributeIds, attributeIdsWithoutCategories)
40
+ })
41
+
42
+ const currentCategoriesLinksResult = useQueryGraphStep({
43
+ entity: attributeProductCategory.entryPoint,
44
+ fields: ["attribute_id", "product_category_id"],
45
+ filters: {
46
+ attribute_id: attributesIdsWithCategories,
47
+ },
48
+ });
49
+
50
+ const currentCategoriesLinks = transform({ currentCategoriesLinksResult }, ({ currentCategoriesLinksResult }) => {
51
+ return currentCategoriesLinksResult.data
52
+ })
53
+
54
+ const toDeleteCategoriesLinks = transform({ currentCategoriesLinks }, ({ currentCategoriesLinks }) => {
55
+ if (!currentCategoriesLinks.length) {
56
+ return []
57
+ }
58
+
59
+ return currentCategoriesLinks.map(({ attribute_id, product_category_id }) => ({
60
+ [ATTRIBUTE_MODULE]: {
61
+ attribute_id
62
+ },
63
+ [Modules.PRODUCT]: {
64
+ product_category_id
65
+ }
66
+ }))
67
+ })
68
+
69
+ dismissRemoteLinkStep(toDeleteCategoriesLinks)
70
+
71
+ const toCreateCategoryLinks: LinkDefinition[] = transform(
72
+ { input },
73
+ ({ input: { attributes }}) => {
74
+ return attributes
75
+ .filter((attribute) => attribute.product_category_ids)
76
+ .flatMap((attribute) =>
77
+ attribute.product_category_ids!.map((attrCat) => ({
78
+ [ATTRIBUTE_MODULE]: {
79
+ attribute_id: attribute.id,
80
+ },
81
+ [Modules.PRODUCT]: {
82
+ product_category_id: attrCat,
83
+ },
84
+ }))
85
+ );
86
+ }
87
+ )
88
+
89
+ const updatedAttributesEventData = transform({ updatedAttributes }, ({ updatedAttributes }) =>
90
+ updatedAttributes.map(attr => attr.id)
91
+ )
92
+
93
+ parallelize(
94
+ createRemoteLinkStep(toCreateCategoryLinks),
95
+ emitEventStep({
96
+ eventName: AttributeWorkflowsEvents.UPDATED,
97
+ data: updatedAttributesEventData
98
+ })
99
+ )
100
+
101
+ return new WorkflowResponse(updatedAttributes)
102
+ }
103
+ );
@@ -0,0 +1,82 @@
1
+ import { createStep, StepResponse } from "@medusajs/framework/workflows-sdk"
2
+ import { AdminBatchLinkAttributeSetAttributesType } from "../../../api/admin/plugin/attribute-set/validators"
3
+ import AttributeModuleService from "../../../modules/attribute/service"
4
+ import { ATTRIBUTE_MODULE } from "../../../modules/attribute"
5
+ import { LinkWorkflowInput } from "@medusajs/framework/types"
6
+
7
+ export const batchLinkAttributeSetAttributesStepId = 'batch-link-attribute-set-attributes'
8
+
9
+ export const batchLinkAttributeSetAttributesStep = createStep(
10
+ batchLinkAttributeSetAttributesStepId,
11
+ async (data: LinkWorkflowInput, { container }) => {
12
+ if (!data.add?.length && !data.remove?.length) {
13
+ return new StepResponse(void 0, null)
14
+ }
15
+
16
+ const service = container.resolve<AttributeModuleService>(ATTRIBUTE_MODULE)
17
+
18
+ const toRemoveAttributesSet = new Set(data.remove?.map(id => id))
19
+ const targetAttributes = await service.listAttributes({
20
+ id: [...(data?.add ?? []), ...(data?.remove ?? [])]
21
+ }, {
22
+ select: ['id'],
23
+ relations: ['sets']
24
+ })
25
+
26
+ const attributesWithUpdateSets = targetAttributes.map(attribute => {
27
+ if (toRemoveAttributesSet.has(attribute.id)) {
28
+ return {
29
+ id: attribute.id,
30
+ sets: (attribute.sets ?? [])
31
+ .filter(attrSet => attrSet.id !== data.id)
32
+ .map(attrSet => attrSet.id)
33
+ }
34
+ }
35
+
36
+ return {
37
+ id: attribute.id,
38
+ sets: [...(attribute.sets ?? []).map(attrSet => attrSet.id), data.id]
39
+ }
40
+ }) as { id: string, sets: string[]}[]
41
+
42
+ await service.updateAttributes(attributesWithUpdateSets)
43
+
44
+ return new StepResponse(void 0, {
45
+ ...data,
46
+ attribute_ids: attributesWithUpdateSets.map(attr => attr.id)
47
+ })
48
+ },
49
+ async (data: (LinkWorkflowInput & { attribute_ids: string[] }) | null, { container }) => {
50
+ if(!data?.add || !data?.remove) {
51
+ return
52
+ }
53
+
54
+ const service = container.resolve<AttributeModuleService>(ATTRIBUTE_MODULE)
55
+
56
+ const toRevertAttributeSet = new Set(data?.remove?.map(id => id))
57
+ const targetAttributes = await service.listAttributes({
58
+ id: data.attribute_ids,
59
+ }, {
60
+ select: ['id'],
61
+ relations: ['sets']
62
+ })
63
+
64
+ const attributesWithRevertedSets = targetAttributes.map(attribute => {
65
+ if (toRevertAttributeSet.has(attribute.id)) {
66
+ return {
67
+ id: attribute.id,
68
+ sets: [...(attribute.sets ?? []).map(attrSet => attrSet.id), data.id]
69
+ }
70
+ }
71
+
72
+ return {
73
+ id: attribute.id,
74
+ sets: (attribute.sets ?? [])
75
+ .filter(attrSet => attrSet.id !== data.id)
76
+ .map(attrSet => attrSet.id)
77
+ }
78
+ }) as { id:string, sets: string[]}[]
79
+
80
+ await service.updateAttributes(attributesWithRevertedSets)
81
+ }
82
+ )
@@ -0,0 +1,34 @@
1
+ import { StepResponse, createStep } from "@medusajs/framework/workflows-sdk"
2
+
3
+ import { ATTRIBUTE_MODULE } from "../../../modules/attribute"
4
+ import AttributeModuleService from "../../../modules/attribute/service"
5
+ import { CreateAttributeSetDTO } from "../../../modules/attribute/types"
6
+ import { kebabCase, toHandle } from "@medusajs/framework/utils"
7
+
8
+ export const createAttributeSetStepId = 'create-attribute-set'
9
+
10
+ export const createAttributeSetStep = createStep(
11
+ createAttributeSetStepId,
12
+ async (input: CreateAttributeSetDTO | CreateAttributeSetDTO[], { container }) => {
13
+ const attributeModuleService = container.resolve<AttributeModuleService>(ATTRIBUTE_MODULE)
14
+
15
+ const normalizedInput = Array.isArray(input) ? input : [input]
16
+
17
+ const toCreate = normalizedInput.map(attributeSet => ({
18
+ ...attributeSet,
19
+ handle: attributeSet.handle?.length ? attributeSet.handle : toHandle(attributeSet.name)
20
+ }))
21
+
22
+ const created = await attributeModuleService.createAttributeSets(toCreate)
23
+
24
+ return new StepResponse(created, created.map(set => set.id))
25
+ },
26
+ async (ids: string[] | undefined, { container }) => {
27
+ if (!ids?.length) {
28
+ return
29
+ }
30
+
31
+ const attributeModuleService = container.resolve<AttributeModuleService>(ATTRIBUTE_MODULE)
32
+ await attributeModuleService.deleteAttributeSets(ids)
33
+ }
34
+ )
@@ -0,0 +1,3 @@
1
+ export * from './create-attribute-set'
2
+ export * from './batch-link-attribute-set-attributes'
3
+ export * from './update-attribute-set'
@@ -0,0 +1,32 @@
1
+ import { createStep, StepResponse } from "@medusajs/framework/workflows-sdk"
2
+ import { AdminUpdateAttributeSetType } from "../../../api/admin/plugin/attribute-set/validators"
3
+ import AttributeModuleService from "../../../modules/attribute/service"
4
+ import { ATTRIBUTE_MODULE } from "../../../modules/attribute"
5
+
6
+ export const updateAttributeStepId = 'update-attribute-set'
7
+
8
+ type UpdateAttributeStepInput = AdminUpdateAttributeSetType & { id: string }
9
+
10
+ export const updateAttributeSetStep = createStep(
11
+ updateAttributeStepId,
12
+ async (data: UpdateAttributeStepInput, { container }) => {
13
+ const service = container.resolve<AttributeModuleService>(ATTRIBUTE_MODULE)
14
+
15
+ const prev = await service.retrieveAttributeSet(data.id)
16
+ const updated = await service.updateAttributeSets(data)
17
+
18
+ return new StepResponse(updated, prev)
19
+ },
20
+ async (prev, { container }) => {
21
+ if (!prev) {
22
+ return
23
+ }
24
+
25
+ const service = container.resolve<AttributeModuleService>(ATTRIBUTE_MODULE)
26
+
27
+ await service.updateAttributeSets({
28
+ ...prev,
29
+ attributes: prev.attributes.map(attr => attr.id)
30
+ })
31
+ }
32
+ )
@@ -0,0 +1,12 @@
1
+ import { LinkWorkflowInput } from "@medusajs/framework/types"
2
+ import { createWorkflow, WorkflowResponse } from "@medusajs/framework/workflows-sdk"
3
+ import { batchLinkAttributeSetAttributesStep } from "../steps"
4
+
5
+ export const batchLinkAttributeSetAttributesWorkflowId = 'batch-link-attribute-set-attributes'
6
+
7
+ export const batchLinkAttributeSetAttributesWorkflow = createWorkflow(
8
+ batchLinkAttributeSetAttributesWorkflowId,
9
+ (input: LinkWorkflowInput) => {
10
+ return new WorkflowResponse(batchLinkAttributeSetAttributesStep(input))
11
+ }
12
+ )
@@ -0,0 +1,17 @@
1
+ import { WorkflowResponse, createWorkflow, transform } from "@medusajs/framework/workflows-sdk"
2
+
3
+ import { CreateAttributeSetDTO } from "../../../modules/attribute/types"
4
+ import { createAttributeSetStep } from "../steps"
5
+
6
+ export const createAttributeSetWorkflowId = 'create-attribute-set'
7
+
8
+ export type CreateAttributeSetWorkflowInput = CreateAttributeSetDTO[]
9
+
10
+ export const createAttributeSetWorkflow = createWorkflow(
11
+ createAttributeSetWorkflowId,
12
+ (input: CreateAttributeSetWorkflowInput) => {
13
+ const created = createAttributeSetStep(input)
14
+
15
+ return new WorkflowResponse(created)
16
+ }
17
+ )
@@ -0,0 +1,3 @@
1
+ export * from './batch-link-attribute-set-attributes'
2
+ export * from './create-attribute-set'
3
+ export * from './update-attribute-set'
@@ -0,0 +1,14 @@
1
+ import { createWorkflow, WorkflowResponse } from "@medusajs/framework/workflows-sdk"
2
+ import { AdminUpdateAttributeSetType } from "../../../api/admin/plugin/attribute-set/validators"
3
+ import { updateAttributeSetStep } from "../steps"
4
+
5
+ export const updateAttributeWorkflowId = 'update-attribute-set'
6
+
7
+ type UpdateAttributeSetWorkflowInput = AdminUpdateAttributeSetType & { id: string }
8
+
9
+ export const updateAttributeSetWorkflow = createWorkflow(
10
+ updateAttributeWorkflowId,
11
+ (input: UpdateAttributeSetWorkflowInput) => {
12
+ return new WorkflowResponse(updateAttributeSetStep(input))
13
+ }
14
+ )
@@ -0,0 +1,26 @@
1
+ import { StepResponse, createStep } from "@medusajs/framework/workflows-sdk"
2
+
3
+ import { ATTRIBUTE_MODULE } from "../../../modules/attribute";
4
+ import AttributeModuleService from "../../../modules/attribute/service";
5
+ import { CreateProductAttributeValueDTO } from "../../../modules/attribute/types"
6
+
7
+ export const createAttributeValueStepId = 'create-attribute-value'
8
+
9
+ export const createAttributeValueStep = createStep(
10
+ createAttributeValueStepId,
11
+ async (input: Omit<CreateProductAttributeValueDTO, 'product_id'>, { container }) => {
12
+ const attributeModuleService = container.resolve<AttributeModuleService>(ATTRIBUTE_MODULE)
13
+
14
+ const created = await attributeModuleService.createAttributeValues(input)
15
+
16
+ return new StepResponse(created, created.id)
17
+ },
18
+ async (id: string | undefined, { container }) => {
19
+ if (!id) {
20
+ return;
21
+ }
22
+
23
+ const attributeModuleService = container.resolve<AttributeModuleService>(ATTRIBUTE_MODULE)
24
+ await attributeModuleService.deleteAttributeValues(id)
25
+ }
26
+ )
@@ -0,0 +1,26 @@
1
+ import { StepResponse, createStep } from "@medusajs/framework/workflows-sdk"
2
+
3
+ import { ATTRIBUTE_MODULE } from "../../../modules/attribute"
4
+ import AttributeModuleService from "../../../modules/attribute/service"
5
+
6
+ export const deleteAttributeValueStepId = 'delete-attribute-value'
7
+
8
+ export const deleteAttributeValueStep = createStep(
9
+ deleteAttributeValueStepId,
10
+ async (ids: string[], { container }) => {
11
+ const attributeModuleService = container.resolve<AttributeModuleService>(ATTRIBUTE_MODULE)
12
+
13
+ await attributeModuleService.softDeleteAttributeValues(ids)
14
+
15
+ return new StepResponse(ids, ids)
16
+ },
17
+ async (ids: string[] | undefined, { container }) => {
18
+ if (!ids?.length) {
19
+ return
20
+ }
21
+
22
+ const attributeModuleService = container.resolve<AttributeModuleService>(ATTRIBUTE_MODULE)
23
+
24
+ await attributeModuleService.restoreAttributeValues(ids)
25
+ },
26
+ )
@@ -0,0 +1,3 @@
1
+ export * from './create-attribute-value'
2
+ export * from './validate-attribute-value'
3
+ export * from './delete-attribute-value'
@@ -0,0 +1,95 @@
1
+ import {
2
+ ContainerRegistrationKeys,
3
+ MedusaError,
4
+ MedusaErrorTypes,
5
+ } from "@medusajs/framework/utils";
6
+ import { StepResponse, createStep } from "@medusajs/framework/workflows-sdk";
7
+
8
+ import { CreateProductAttributeValueDTO } from "../../../modules/attribute/types";
9
+ import attributeValueProductLink from "../../../links/attribute-value-product";
10
+
11
+ export const validateAttributeValueStepId = "validate-attribute-value";
12
+
13
+ export const validateAttributeValueStep = createStep(
14
+ validateAttributeValueStepId,
15
+ async (input: CreateProductAttributeValueDTO, { container }) => {
16
+ const query = container.resolve(ContainerRegistrationKeys.QUERY);
17
+
18
+ const {
19
+ data: [attribute],
20
+ } = await query.graph({
21
+ entity: "attribute",
22
+ fields: ["product_categories.id", "possible_values.value"],
23
+ filters: {
24
+ id: input.attribute_id,
25
+ },
26
+ });
27
+
28
+ const allowedValues = attribute.possible_values?.map(
29
+ (posVal) => posVal.value
30
+ );
31
+
32
+ if (allowedValues?.length && !allowedValues.includes(input.value)) {
33
+ throw new MedusaError(
34
+ MedusaErrorTypes.INVALID_DATA,
35
+ `Attribute ${input.attribute_id} doesn't define ${input.value} as a possible_value`
36
+ );
37
+ }
38
+
39
+ const attributeCategoryIds = attribute.product_categories.map(
40
+ (cat) => cat.id
41
+ );
42
+
43
+ // If all attributes are global, we don't enforce for product.categories to include the attribute.product_categories, since there are none
44
+ if (attributeCategoryIds.length) {
45
+ const {
46
+ data: [product],
47
+ } = await query.graph({
48
+ entity: "product",
49
+ fields: ["categories.id"],
50
+ filters: {
51
+ id: input.product_id,
52
+ },
53
+ });
54
+
55
+ const productCategoryIds = product.categories?.map((cat) => cat.id);
56
+ if (
57
+ !productCategoryIds?.some((prodCatId) =>
58
+ attributeCategoryIds.includes(prodCatId)
59
+ )
60
+ ) {
61
+ throw new MedusaError(
62
+ MedusaErrorTypes.INVALID_DATA,
63
+ `Product ${input.product_id} isn't linked to any category from the requested attributes.`
64
+ );
65
+ }
66
+ }
67
+
68
+ const { data: attributeValuesProduct } = await query.graph({
69
+ entity: attributeValueProductLink.entryPoint,
70
+ fields: ["attribute_value.value", "attribute_value.attribute_id"],
71
+ filters: {
72
+ product_id: input.product_id,
73
+ },
74
+ });
75
+
76
+ const attributeValues = attributeValuesProduct.map(
77
+ (element) => element.attribute_value
78
+ );
79
+
80
+ if (
81
+ attributeValues.some(
82
+ (value) =>
83
+ value.attribute_id === input.attribute_id &&
84
+ value.value === input.value
85
+ )
86
+ ) {
87
+ throw new MedusaError(
88
+ MedusaErrorTypes.DUPLICATE_ERROR,
89
+ `Attribute value ${input.value} for attribute ${input.attribute_id} already exists for product ${input.product_id}`
90
+ );
91
+ }
92
+
93
+ return new StepResponse();
94
+ }
95
+ );
@@ -0,0 +1,36 @@
1
+ import { WorkflowResponse, createWorkflow, transform } from "@medusajs/framework/workflows-sdk"
2
+ import { createAttributeValueStep, validateAttributeValueStep } from "../steps"
3
+
4
+ import { ATTRIBUTE_MODULE } from "../../../modules/attribute"
5
+ import { CreateProductAttributeValueDTO } from "../../../modules/attribute/types"
6
+ import { Modules } from "@medusajs/framework/utils"
7
+ import { createRemoteLinkStep, } from "@medusajs/medusa/core-flows"
8
+
9
+ export const createAttributeValueWorkflowId = 'create-attribute-value'
10
+
11
+ export const createAttributeValueWorkflow = createWorkflow(
12
+ createAttributeValueWorkflowId,
13
+ (input: CreateProductAttributeValueDTO) => {
14
+ const attributeValueWithoutExternalRelations = transform({ input }, ({ input }) => {
15
+ const { product_id, ...attributeValue } = input
16
+ return attributeValue
17
+ })
18
+
19
+ validateAttributeValueStep(input)
20
+
21
+ const attributeValue = createAttributeValueStep(attributeValueWithoutExternalRelations)
22
+
23
+ const link = transform({ input, attributeValue }, ({ input, attributeValue }) => ([{
24
+ [ATTRIBUTE_MODULE]: {
25
+ attribute_value_id: attributeValue.id,
26
+ },
27
+ [Modules.PRODUCT]: {
28
+ product_id: input.product_id
29
+ }
30
+ }]))
31
+
32
+ createRemoteLinkStep(link)
33
+
34
+ return new WorkflowResponse(attributeValue)
35
+ }
36
+ )
@@ -0,0 +1,46 @@
1
+ import { WorkflowResponse, createWorkflow, transform } from "@medusajs/framework/workflows-sdk"
2
+ import { dismissRemoteLinkStep, useQueryGraphStep } from "@medusajs/medusa/core-flows"
3
+
4
+ import { ATTRIBUTE_MODULE } from "../../../modules/attribute"
5
+ import { Modules } from "@medusajs/framework/utils"
6
+ import attributeValueProduct from "../../../links/attribute-value-product"
7
+ import { deleteAttributeValueStep } from "../steps"
8
+
9
+ export const deleteAttributeValueWorkflowId = 'delete-attribute-value'
10
+
11
+ export type DeleteAttributeValueWorkflowInput = string | string[]
12
+
13
+ export const deleteAttributeValueWorkflow = createWorkflow(
14
+ deleteAttributeValueWorkflowId,
15
+ (input: DeleteAttributeValueWorkflowInput) => {
16
+ const normalizedInput = transform({ input }, ({ input }) =>
17
+ Array.isArray(input) ? input : [input]
18
+ )
19
+
20
+ const attributeValueProductQuery = useQueryGraphStep({
21
+ entity: attributeValueProduct.entryPoint,
22
+ fields: ['product_id', 'attribute_value_id'],
23
+ filters: {
24
+ attribute_value_id: normalizedInput
25
+ }
26
+ })
27
+
28
+ const deleted = deleteAttributeValueStep(normalizedInput)
29
+
30
+ const links = transform({ attributeValueProductQuery }, ({ attributeValueProductQuery }) => {
31
+ const { data } = attributeValueProductQuery;
32
+ return data.map(element => ({
33
+ [ATTRIBUTE_MODULE]: {
34
+ attribute_value_id: element.attribute_value_id,
35
+ },
36
+ [Modules.PRODUCT]: {
37
+ product_id: element.product_id
38
+ }
39
+ }))
40
+ })
41
+
42
+ dismissRemoteLinkStep(links)
43
+
44
+ return new WorkflowResponse(deleted)
45
+ }
46
+ )
@@ -0,0 +1,2 @@
1
+ export * from './create-attribute-value'
2
+ export * from './delete-attribute-value'
@@ -0,0 +1,2 @@
1
+ export * from './steps'
2
+ export * from './workflows'
@@ -0,0 +1 @@
1
+ export * from './update-attribute-possible-value'
@@ -0,0 +1,25 @@
1
+ import { createStep, StepResponse } from "@medusajs/framework/workflows-sdk"
2
+ import { UpdateAttributeValueDTO } from "../../../modules/attribute/types"
3
+ import { ATTRIBUTE_MODULE } from "../../../modules/attribute"
4
+ import AttributeModuleService from "../../../modules/attribute/service"
5
+
6
+ export const updateAttributePossibleValueStepId = 'update-attribute-possible-value'
7
+
8
+ type StepInput = UpdateAttributeValueDTO
9
+
10
+ export const updateAttributePossibleValueStep = createStep(
11
+ updateAttributePossibleValueStepId,
12
+ async (payload: StepInput, { container }) => {
13
+ const attributeModuleService = container.resolve(ATTRIBUTE_MODULE) as AttributeModuleService
14
+ const updated = await attributeModuleService.updateAttributePossibleValues(payload)
15
+ return new StepResponse(updated, payload.id)
16
+ },
17
+ async (id: string | undefined, { container }) => {
18
+ if (!id) {
19
+ return
20
+ }
21
+
22
+ const attributeModuleService = container.resolve(ATTRIBUTE_MODULE) as AttributeModuleService
23
+ await attributeModuleService.deleteAttributePossibleValues(id)
24
+ }
25
+ )
@@ -0,0 +1 @@
1
+ export * from './update-attribute-possible-value'