@reactionary/source 0.3.18 → 0.6.2

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 (191) hide show
  1. package/README.md +28 -14
  2. package/core/src/client/client-builder.ts +54 -6
  3. package/core/src/factories/cart.factory.ts +40 -0
  4. package/core/src/factories/category.factory.ts +40 -0
  5. package/core/src/factories/checkout.factory.ts +59 -0
  6. package/core/src/factories/identity.factory.ts +26 -0
  7. package/core/src/factories/index.ts +15 -0
  8. package/core/src/factories/inventory.factory.ts +26 -0
  9. package/core/src/factories/order-search.factory.ts +33 -0
  10. package/core/src/factories/order.factory.ts +21 -0
  11. package/core/src/factories/price.factory.ts +29 -0
  12. package/core/src/factories/product-associations.factory.ts +30 -0
  13. package/core/src/factories/product-list.factory.ts +82 -0
  14. package/core/src/factories/product-reviews.factory.ts +58 -0
  15. package/core/src/factories/product-search.factory.ts +31 -0
  16. package/core/src/factories/product.factory.ts +21 -0
  17. package/core/src/factories/profile.factory.ts +23 -0
  18. package/core/src/factories/store.factory.ts +21 -0
  19. package/core/src/index.ts +3 -1
  20. package/core/src/providers/cart.provider.ts +12 -10
  21. package/core/src/providers/category.provider.ts +9 -7
  22. package/core/src/providers/checkout.provider.ts +14 -10
  23. package/core/src/providers/identity.provider.ts +7 -7
  24. package/core/src/providers/inventory.provider.ts +4 -4
  25. package/core/src/providers/order-search.provider.ts +4 -2
  26. package/core/src/providers/order.provider.ts +4 -4
  27. package/core/src/providers/price.provider.ts +5 -5
  28. package/core/src/providers/product-associations.provider.ts +6 -4
  29. package/core/src/providers/product-list.provider.ts +13 -8
  30. package/core/src/providers/product-reviews.provider.ts +8 -4
  31. package/core/src/providers/product-search.provider.ts +15 -28
  32. package/core/src/providers/product.provider.ts +6 -6
  33. package/core/src/providers/profile.provider.ts +8 -8
  34. package/core/src/providers/store.provider.ts +2 -2
  35. package/core/src/test/client-builder.spec.ts +81 -0
  36. package/examples/node/package.json +7 -7
  37. package/examples/node/src/basic/basic-node-provider-model-extension.spec.ts +10 -4
  38. package/examples/node/src/basic/basic-node-provider-query-extension.spec.ts +8 -2
  39. package/examples/node/src/basic/basic-node-setup.spec.ts +5 -1
  40. package/examples/node/src/basic/client-creation.spec.ts +3 -3
  41. package/examples/node/src/utils.ts +41 -41
  42. package/examples/node/tsconfig.lib.json +2 -1
  43. package/package.json +1 -1
  44. package/providers/algolia/src/core/initialize.ts +76 -21
  45. package/providers/algolia/src/core/initialize.types.ts +107 -0
  46. package/providers/algolia/src/factories/index.ts +1 -0
  47. package/providers/algolia/src/factories/product-search/product-search.factory.ts +182 -0
  48. package/providers/algolia/src/index.ts +2 -2
  49. package/providers/algolia/src/providers/analytics.provider.ts +4 -4
  50. package/providers/algolia/src/providers/product-search.provider.ts +67 -184
  51. package/providers/algolia/src/schema/capabilities.schema.ts +81 -7
  52. package/providers/algolia/src/test/analytics.spec.ts +9 -1
  53. package/providers/algolia/src/test/client-builder-product-search-extension.example.ts +85 -0
  54. package/providers/commercetools/src/core/capability-descriptors.ts +324 -0
  55. package/providers/commercetools/src/core/initialize.ts +35 -151
  56. package/providers/commercetools/src/core/initialize.types.ts +174 -0
  57. package/providers/commercetools/src/factories/cart/cart.factory.ts +142 -0
  58. package/providers/commercetools/src/factories/category/category.factory.ts +77 -0
  59. package/providers/commercetools/src/factories/checkout/checkout-initializer-overrides.example.ts +94 -0
  60. package/providers/commercetools/src/factories/checkout/checkout.factory.ts +338 -0
  61. package/providers/commercetools/src/factories/identity/identity.factory.ts +26 -0
  62. package/providers/commercetools/src/factories/inventory/inventory.factory.ts +49 -0
  63. package/providers/commercetools/src/factories/order/order.factory.ts +149 -0
  64. package/providers/commercetools/src/factories/order-search/order-search.factory.ts +108 -0
  65. package/providers/commercetools/src/factories/price/price.factory.ts +76 -0
  66. package/providers/commercetools/src/factories/product/product-factory-baseline.example.ts +14 -0
  67. package/providers/commercetools/src/factories/product/product-factory-schema-and-parse-extension.example.ts +35 -0
  68. package/providers/commercetools/src/factories/product/product-factory-schema-extension.example.ts +23 -0
  69. package/providers/commercetools/src/factories/product/product-initializer-factory-extension.example.ts +41 -0
  70. package/providers/commercetools/src/factories/product/product-provider-custom-method-only.example.ts +47 -0
  71. package/providers/commercetools/src/factories/product/product-provider-schema-signature-extension.example.ts +61 -0
  72. package/providers/commercetools/src/factories/product/product.factory.ts +220 -0
  73. package/providers/commercetools/src/factories/product/utils.example.ts +9 -0
  74. package/providers/commercetools/src/factories/product-associations/product-associations.factory.ts +103 -0
  75. package/providers/commercetools/src/factories/product-list/product-list.factory.ts +122 -0
  76. package/providers/commercetools/src/factories/product-reviews/product-reviews.factory.ts +81 -0
  77. package/providers/commercetools/src/factories/product-search/product-search.factory.ts +182 -0
  78. package/providers/commercetools/src/factories/profile/profile.factory.ts +94 -0
  79. package/providers/commercetools/src/factories/store/store.factory.ts +49 -0
  80. package/providers/commercetools/src/index.ts +15 -0
  81. package/providers/commercetools/src/providers/cart.provider.ts +67 -193
  82. package/providers/commercetools/src/providers/category.provider.ts +24 -64
  83. package/providers/commercetools/src/providers/checkout.provider.ts +50 -322
  84. package/providers/commercetools/src/providers/identity.provider.ts +35 -15
  85. package/providers/commercetools/src/providers/inventory.provider.ts +13 -31
  86. package/providers/commercetools/src/providers/order-search.provider.ts +16 -110
  87. package/providers/commercetools/src/providers/order.provider.ts +13 -144
  88. package/providers/commercetools/src/providers/price.provider.ts +37 -51
  89. package/providers/commercetools/src/providers/product-associations.provider.ts +39 -104
  90. package/providers/commercetools/src/providers/product-list.provider.ts +38 -23
  91. package/providers/commercetools/src/providers/product-reviews.provider.ts +34 -14
  92. package/providers/commercetools/src/providers/product-search.provider.ts +17 -170
  93. package/providers/commercetools/src/providers/product.provider.ts +20 -199
  94. package/providers/commercetools/src/providers/profile.provider.ts +27 -73
  95. package/providers/commercetools/src/providers/store.provider.ts +13 -31
  96. package/providers/commercetools/src/schema/capabilities.schema.ts +258 -20
  97. package/providers/commercetools/src/test/caching.spec.ts +18 -2
  98. package/providers/commercetools/src/test/client-builder-merge-extensions.example.ts +125 -0
  99. package/providers/fake/src/core/initialize.ts +213 -44
  100. package/providers/fake/src/core/initialize.types.ts +164 -0
  101. package/providers/fake/src/factories/cart/cart.factory.ts +34 -0
  102. package/providers/fake/src/factories/category/category.factory.ts +40 -0
  103. package/providers/fake/src/factories/checkout/checkout.factory.ts +53 -0
  104. package/providers/fake/src/factories/identity/identity.factory.ts +25 -0
  105. package/providers/fake/src/factories/index.ts +14 -0
  106. package/providers/fake/src/factories/inventory/inventory.factory.ts +25 -0
  107. package/providers/fake/src/factories/order/order.factory.ts +22 -0
  108. package/providers/fake/src/factories/order-search/order-search.factory.ts +27 -0
  109. package/providers/fake/src/factories/price/price.factory.ts +26 -0
  110. package/providers/fake/src/factories/product/product.factory.ts +22 -0
  111. package/providers/fake/src/factories/product-associations/product-associations.factory.ts +25 -0
  112. package/providers/fake/src/factories/product-reviews/product-reviews.factory.ts +53 -0
  113. package/providers/fake/src/factories/product-search/product-search.factory.ts +27 -0
  114. package/providers/fake/src/factories/profile/profile.factory.ts +22 -0
  115. package/providers/fake/src/factories/store/store.factory.ts +22 -0
  116. package/providers/fake/src/index.ts +2 -0
  117. package/providers/fake/src/providers/cart.provider.ts +23 -14
  118. package/providers/fake/src/providers/category.provider.ts +120 -105
  119. package/providers/fake/src/providers/checkout.provider.ts +39 -20
  120. package/providers/fake/src/providers/identity.provider.ts +40 -34
  121. package/providers/fake/src/providers/inventory.provider.ts +26 -24
  122. package/providers/fake/src/providers/order-search.provider.ts +38 -30
  123. package/providers/fake/src/providers/order.provider.ts +21 -37
  124. package/providers/fake/src/providers/price.provider.ts +42 -34
  125. package/providers/fake/src/providers/product-associations.provider.ts +23 -10
  126. package/providers/fake/src/providers/product-reviews.provider.ts +71 -69
  127. package/providers/fake/src/providers/product-search.provider.ts +43 -70
  128. package/providers/fake/src/providers/product.provider.ts +34 -32
  129. package/providers/fake/src/providers/profile.provider.ts +62 -55
  130. package/providers/fake/src/providers/store.provider.ts +38 -22
  131. package/providers/fake/src/schema/capabilities.schema.ts +175 -18
  132. package/providers/fake/src/test/cart.provider.spec.ts +20 -3
  133. package/providers/fake/src/test/category.provider.spec.ts +4 -1
  134. package/providers/fake/src/test/checkout.provider.spec.ts +12 -2
  135. package/providers/fake/src/test/client-builder-product-extension.example.ts +75 -0
  136. package/providers/fake/src/test/order-search.provider.spec.ts +4 -7
  137. package/providers/fake/src/test/order.provider.spec.ts +4 -6
  138. package/providers/fake/src/test/price.provider.spec.ts +3 -1
  139. package/providers/fake/src/test/product.provider.spec.ts +8 -2
  140. package/providers/fake/src/test/profile.provider.spec.ts +4 -2
  141. package/providers/google-analytics/src/core/initialize.ts +37 -12
  142. package/providers/google-analytics/src/core/initialize.types.ts +47 -0
  143. package/providers/google-analytics/src/index.ts +1 -0
  144. package/providers/google-analytics/src/schema/capabilities.schema.ts +31 -5
  145. package/providers/medusa/src/core/initialize.ts +324 -81
  146. package/providers/medusa/src/core/initialize.types.ts +184 -0
  147. package/providers/medusa/src/factories/cart/cart.factory.ts +34 -0
  148. package/providers/medusa/src/factories/category/category.factory.ts +37 -0
  149. package/providers/medusa/src/factories/checkout/checkout.factory.ts +50 -0
  150. package/providers/medusa/src/factories/identity/identity.factory.ts +22 -0
  151. package/providers/medusa/src/factories/index.ts +12 -0
  152. package/providers/medusa/src/factories/inventory/inventory.factory.ts +25 -0
  153. package/providers/medusa/src/factories/order/order.factory.ts +22 -0
  154. package/providers/medusa/src/factories/order-search/order-search.factory.ts +27 -0
  155. package/providers/medusa/src/factories/price/price.factory.ts +26 -0
  156. package/providers/medusa/src/factories/product/product.factory.ts +22 -0
  157. package/providers/medusa/src/factories/product-associations/product-associations.factory.ts +25 -0
  158. package/providers/medusa/src/factories/product-search/product-search.factory.ts +27 -0
  159. package/providers/medusa/src/factories/profile/profile.factory.ts +22 -0
  160. package/providers/medusa/src/index.ts +2 -0
  161. package/providers/medusa/src/providers/cart.provider.ts +33 -20
  162. package/providers/medusa/src/providers/category.provider.ts +30 -12
  163. package/providers/medusa/src/providers/checkout.provider.ts +42 -17
  164. package/providers/medusa/src/providers/identity.provider.ts +1 -1
  165. package/providers/medusa/src/providers/inventory.provider.ts +21 -7
  166. package/providers/medusa/src/providers/order-search.provider.ts +16 -5
  167. package/providers/medusa/src/providers/order.provider.ts +17 -5
  168. package/providers/medusa/src/providers/price.provider.ts +26 -7
  169. package/providers/medusa/src/providers/product-associations.provider.ts +19 -8
  170. package/providers/medusa/src/providers/product-search.provider.ts +19 -31
  171. package/providers/medusa/src/providers/product.provider.ts +47 -11
  172. package/providers/medusa/src/providers/profile.provider.ts +35 -11
  173. package/providers/medusa/src/schema/capabilities.schema.ts +229 -18
  174. package/providers/medusa/src/test/cart.provider.spec.ts +18 -2
  175. package/providers/medusa/src/test/category.provider.spec.ts +4 -1
  176. package/providers/medusa/src/test/checkout.spec.ts +9 -9
  177. package/providers/medusa/src/test/inventory.provider.spec.ts +3 -1
  178. package/providers/medusa/src/test/large-cart.provider.spec.ts +8 -2
  179. package/providers/medusa/src/test/price.provider.spec.ts +8 -1
  180. package/providers/medusa/src/test/product.provider.spec.ts +3 -1
  181. package/providers/medusa/src/test/search.provider.spec.ts +16 -3
  182. package/providers/meilisearch/src/core/initialize.ts +88 -21
  183. package/providers/meilisearch/src/core/initialize.types.ts +119 -0
  184. package/providers/meilisearch/src/factories/index.ts +2 -0
  185. package/providers/meilisearch/src/factories/order-search/order-search.factory.ts +27 -0
  186. package/providers/meilisearch/src/factories/product-search/product-search.factory.ts +27 -0
  187. package/providers/meilisearch/src/index.ts +2 -0
  188. package/providers/meilisearch/src/providers/index.ts +1 -0
  189. package/providers/meilisearch/src/providers/order-search.provider.ts +21 -6
  190. package/providers/meilisearch/src/providers/product-search.provider.ts +24 -8
  191. package/providers/meilisearch/src/schema/capabilities.schema.ts +95 -8
@@ -0,0 +1,122 @@
1
+ import type { ShoppingList, ShoppingListLineItem } from '@commercetools/platform-sdk';
2
+ import type {
3
+ ProductListItemPaginatedResultsSchema,
4
+ ProductListItemSchema,
5
+ ProductListPaginatedResultsSchema,
6
+ ProductListSchema} from '@reactionary/core';
7
+ import {
8
+ type AnyProductListItemPaginatedSchema,
9
+ type AnyProductListItemSchema,
10
+ type AnyProductListPaginatedSchema,
11
+ type AnyProductListSchema,
12
+ type ProductList,
13
+ type ProductListFactory,
14
+ type ProductListIdentifier,
15
+ type ProductListItem,
16
+ type ProductListItemPaginatedResult,
17
+ type ProductListPaginatedResult,
18
+ type ProductListType,
19
+ type RequestContext,
20
+ } from '@reactionary/core';
21
+ import type * as z from 'zod';
22
+
23
+ export class CommercetoolsProductListFactory<
24
+ TProductListSchema extends AnyProductListSchema = typeof ProductListSchema,
25
+ TProductListItemSchema extends AnyProductListItemSchema = typeof ProductListItemSchema,
26
+ TProductListPaginatedSchema extends AnyProductListPaginatedSchema = typeof ProductListPaginatedResultsSchema,
27
+ TProductListItemPaginatedSchema extends AnyProductListItemPaginatedSchema = typeof ProductListItemPaginatedResultsSchema,
28
+ > implements
29
+ ProductListFactory<
30
+ TProductListSchema,
31
+ TProductListItemSchema,
32
+ TProductListPaginatedSchema,
33
+ TProductListItemPaginatedSchema
34
+ >
35
+ {
36
+ public readonly productListSchema: TProductListSchema;
37
+ public readonly productListItemSchema: TProductListItemSchema;
38
+ public readonly productListPaginatedSchema: TProductListPaginatedSchema;
39
+ public readonly productListItemPaginatedSchema: TProductListItemPaginatedSchema;
40
+
41
+ constructor(
42
+ productListSchema: TProductListSchema,
43
+ productListItemSchema: TProductListItemSchema,
44
+ productListPaginatedSchema: TProductListPaginatedSchema,
45
+ productListItemPaginatedSchema: TProductListItemPaginatedSchema,
46
+ ) {
47
+ this.productListSchema = productListSchema;
48
+ this.productListItemSchema = productListItemSchema;
49
+ this.productListPaginatedSchema = productListPaginatedSchema;
50
+ this.productListItemPaginatedSchema = productListItemPaginatedSchema;
51
+ }
52
+
53
+ public parseProductList(
54
+ _context: RequestContext,
55
+ data: ProductList,
56
+ ): z.output<TProductListSchema> {
57
+ return this.productListSchema.parse(data);
58
+ }
59
+
60
+ public parseProductListItem(
61
+ _context: RequestContext,
62
+ data: ProductListItem,
63
+ ): z.output<TProductListItemSchema> {
64
+ return this.productListItemSchema.parse(data);
65
+ }
66
+
67
+ public parseProductListPaginatedResult(
68
+ _context: RequestContext,
69
+ data: ProductListPaginatedResult,
70
+ ): z.output<TProductListPaginatedSchema> {
71
+ return this.productListPaginatedSchema.parse(data);
72
+ }
73
+
74
+ public parseProductListItemPaginatedResult(
75
+ _context: RequestContext,
76
+ data: ProductListItemPaginatedResult,
77
+ ): z.output<TProductListItemPaginatedSchema> {
78
+ return this.productListItemPaginatedSchema.parse(data);
79
+ }
80
+
81
+ public parseListFromCommercetools(list: ShoppingList): z.output<TProductListSchema> {
82
+ const listType = (list.custom?.fields['listType'] as ProductListType) || 'favorite';
83
+ const image = list.custom?.fields['imageUrl'] as string | undefined;
84
+ const published = (list.custom?.fields['published'] as boolean) && true;
85
+ const publishDateValue = list.custom?.fields['publishedDate'] as string | undefined;
86
+ const publishDate = publishDateValue ? new Date(publishDateValue).toISOString() : undefined;
87
+
88
+ return this.productListSchema.parse({
89
+ identifier: {
90
+ listType,
91
+ key: list.id,
92
+ },
93
+ type: listType,
94
+ name: list.name['en'] || 'Unnamed List',
95
+ description: list.description?.['en'] || '',
96
+ published,
97
+ publishDate,
98
+ image: {
99
+ sourceUrl: image || '',
100
+ altText: list.name['en'] || 'List Image',
101
+ },
102
+ } satisfies ProductList);
103
+ }
104
+
105
+ public parseListItemFromCommercetools(
106
+ listIdentifier: ProductListIdentifier,
107
+ lineItem: ShoppingListLineItem,
108
+ ): z.output<TProductListItemSchema> {
109
+ return this.productListItemSchema.parse({
110
+ identifier: {
111
+ list: listIdentifier,
112
+ key: lineItem.id,
113
+ },
114
+ variant: {
115
+ sku: lineItem.variant?.sku || '',
116
+ },
117
+ quantity: lineItem.quantity,
118
+ notes: (lineItem.custom?.fields['notes'] as string) || '',
119
+ order: (lineItem.custom?.fields['order'] as number) || 1,
120
+ } satisfies ProductListItem);
121
+ }
122
+ }
@@ -0,0 +1,81 @@
1
+ import type { Review as CTReview } from '@commercetools/platform-sdk';
2
+ import type {
3
+ ProductRatingSummarySchema,
4
+ ProductReviewPaginatedResultSchema,
5
+ ProductReviewSchema} from '@reactionary/core';
6
+ import {
7
+ type AnyProductRatingSummarySchema,
8
+ type AnyProductReviewPaginatedSchema,
9
+ type AnyProductReviewSchema,
10
+ type ProductRatingSummary,
11
+ type ProductReview,
12
+ type ProductReviewPaginatedResult,
13
+ type ProductReviewsFactory,
14
+ type RequestContext,
15
+ } from '@reactionary/core';
16
+ import type * as z from 'zod';
17
+
18
+ export class CommercetoolsProductReviewsFactory<
19
+ TRatingSummarySchema extends AnyProductRatingSummarySchema = typeof ProductRatingSummarySchema,
20
+ TReviewSchema extends AnyProductReviewSchema = typeof ProductReviewSchema,
21
+ TReviewPaginatedSchema extends AnyProductReviewPaginatedSchema = typeof ProductReviewPaginatedResultSchema,
22
+ > implements ProductReviewsFactory<TRatingSummarySchema, TReviewSchema, TReviewPaginatedSchema>
23
+ {
24
+ public readonly ratingSummarySchema: TRatingSummarySchema;
25
+ public readonly reviewSchema: TReviewSchema;
26
+ public readonly reviewPaginatedSchema: TReviewPaginatedSchema;
27
+
28
+ constructor(
29
+ ratingSummarySchema: TRatingSummarySchema,
30
+ reviewSchema: TReviewSchema,
31
+ reviewPaginatedSchema: TReviewPaginatedSchema,
32
+ ) {
33
+ this.ratingSummarySchema = ratingSummarySchema;
34
+ this.reviewSchema = reviewSchema;
35
+ this.reviewPaginatedSchema = reviewPaginatedSchema;
36
+ }
37
+
38
+ public parseRatingSummary(
39
+ _context: RequestContext,
40
+ data: ProductRatingSummary,
41
+ ): z.output<TRatingSummarySchema> {
42
+ return this.ratingSummarySchema.parse(data);
43
+ }
44
+
45
+ public parseReview(
46
+ _context: RequestContext,
47
+ data: ProductReview,
48
+ ): z.output<TReviewSchema> {
49
+ return this.reviewSchema.parse(data);
50
+ }
51
+
52
+ public parseReviewPaginatedResult(
53
+ _context: RequestContext,
54
+ data: ProductReviewPaginatedResult,
55
+ ): z.output<TReviewPaginatedSchema> {
56
+ return this.reviewPaginatedSchema.parse(data);
57
+ }
58
+
59
+ public parseReviewFromCommercetools(
60
+ _context: RequestContext,
61
+ review: CTReview,
62
+ productKey: string,
63
+ ): z.output<TReviewSchema> {
64
+ return this.reviewSchema.parse({
65
+ identifier: {
66
+ key: review.key || '',
67
+ },
68
+ product: {
69
+ key: productKey,
70
+ },
71
+ authorName: review.authorName ?? 'Anonymous',
72
+ authorId: review.customer?.id,
73
+ rating: review.rating ?? 0,
74
+ title: review.title ?? '',
75
+ content: review.text ?? '',
76
+ createdAt: review.createdAt,
77
+ updatedAt: review.lastModifiedAt,
78
+ verified: !!review.customer,
79
+ } satisfies ProductReview);
80
+ }
81
+ }
@@ -0,0 +1,182 @@
1
+ import type {
2
+ ProductPagedSearchResponse,
3
+ ProductProjection,
4
+ ProductSearchFacetResult as CTProductSearchFacetResult,
5
+ ProductSearchFacetResultBucket as CTProductSearchFacetResultBucket,
6
+ ProductVariant as CTProductVariant,
7
+ } from '@commercetools/platform-sdk';
8
+ import type {
9
+ ProductSearchResultSchema} from '@reactionary/core';
10
+ import {
11
+ FacetIdentifierSchema,
12
+ FacetValueIdentifierSchema,
13
+ ImageSchema,
14
+ ProductOptionIdentifierSchema,
15
+ ProductSearchResultFacetSchema,
16
+ ProductSearchResultFacetValueSchema,
17
+ ProductSearchResultItemVariantSchema,
18
+ ProductVariantIdentifierSchema,
19
+ ProductVariantOptionSchema,
20
+ type AnyProductSearchResultSchema,
21
+ type FacetIdentifier,
22
+ type FacetValueIdentifier,
23
+ type ProductOptionIdentifier,
24
+ type ProductSearchFactory,
25
+ type ProductSearchQueryByTerm,
26
+ type ProductSearchResult,
27
+ type ProductSearchResultFacet,
28
+ type ProductSearchResultFacetValue,
29
+ type ProductSearchResultItem,
30
+ type ProductSearchResultItemVariant,
31
+ type ProductVariantIdentifier,
32
+ type ProductVariantOption,
33
+ type RequestContext,
34
+ type SearchIdentifier,
35
+ } from '@reactionary/core';
36
+ import type * as z from 'zod';
37
+
38
+ export class CommercetoolsProductSearchFactory<
39
+ TProductSearchResultSchema extends AnyProductSearchResultSchema = typeof ProductSearchResultSchema,
40
+ > implements ProductSearchFactory<TProductSearchResultSchema>
41
+ {
42
+ public readonly productSearchResultSchema: TProductSearchResultSchema;
43
+
44
+ constructor(productSearchResultSchema: TProductSearchResultSchema) {
45
+ this.productSearchResultSchema = productSearchResultSchema;
46
+ }
47
+
48
+ public parseSearchResult(
49
+ context: RequestContext,
50
+ data: ProductPagedSearchResponse,
51
+ query: ProductSearchQueryByTerm,
52
+ ): z.output<TProductSearchResultSchema> {
53
+ const identifier = {
54
+ ...query.search,
55
+ } satisfies SearchIdentifier;
56
+
57
+ const items: ProductSearchResultItem[] = data.results.map((product) =>
58
+ this.parseSingle(context, product.productProjection!),
59
+ );
60
+ const facets: ProductSearchResultFacet[] = [];
61
+
62
+ for (const facet of data.facets) {
63
+ const facetIdentifier = FacetIdentifierSchema.parse({
64
+ key: facet.name,
65
+ } satisfies Partial<FacetIdentifier>);
66
+
67
+ const candidateFacet = this.parseFacet(facetIdentifier, facet);
68
+ if (candidateFacet.values.length > 0) {
69
+ facets.push(candidateFacet);
70
+ }
71
+ }
72
+
73
+ const result = {
74
+ identifier,
75
+ pageNumber: (Math.ceil(data.offset / data.limit) || 0) + 1,
76
+ pageSize: data.limit,
77
+ totalCount: data.total || 0,
78
+ totalPages: Math.ceil((data.total || 0) / data.limit || 0) + 1,
79
+ items,
80
+ facets,
81
+ } satisfies ProductSearchResult;
82
+
83
+ return this.productSearchResultSchema.parse(result);
84
+ }
85
+
86
+ protected parseSingle(
87
+ context: RequestContext,
88
+ data: ProductProjection,
89
+ ): ProductSearchResultItem {
90
+ const identifier = { key: data.id };
91
+ const name = data.name[context.languageContext.locale] || data.id;
92
+ const slug = data.slug?.[context.languageContext.locale] || data.id;
93
+ const variants = [data.masterVariant, ...data.variants].map((variant) =>
94
+ this.parseVariant(context, variant, data),
95
+ );
96
+
97
+ const result = {
98
+ identifier,
99
+ name,
100
+ slug,
101
+ variants,
102
+ } satisfies ProductSearchResultItem;
103
+
104
+ return result;
105
+ }
106
+
107
+ protected parseFacet(
108
+ facetIdentifier: FacetIdentifier,
109
+ facet: CTProductSearchFacetResult,
110
+ ): ProductSearchResultFacet {
111
+ const result: ProductSearchResultFacet = ProductSearchResultFacetSchema.parse({
112
+ identifier: facetIdentifier,
113
+ name: facet.name,
114
+ values: [],
115
+ });
116
+
117
+ const distinctFacet = facet as CTProductSearchFacetResultBucket;
118
+ for (const bucket of distinctFacet.buckets || []) {
119
+ const facetValueIdentifier = FacetValueIdentifierSchema.parse({
120
+ facet: facetIdentifier,
121
+ key: bucket.key,
122
+ } satisfies Partial<FacetValueIdentifier>);
123
+
124
+ result.values.push(
125
+ this.parseFacetValue(facetValueIdentifier, bucket.key, bucket.count),
126
+ );
127
+ }
128
+
129
+ return result;
130
+ }
131
+
132
+ protected parseFacetValue(
133
+ facetValueIdentifier: FacetValueIdentifier,
134
+ label: string,
135
+ count: number,
136
+ ): ProductSearchResultFacetValue {
137
+ return ProductSearchResultFacetValueSchema.parse({
138
+ identifier: facetValueIdentifier,
139
+ name: label,
140
+ count,
141
+ active: false,
142
+ } satisfies Partial<ProductSearchResultFacetValue>);
143
+ }
144
+
145
+ protected parseVariant(
146
+ context: RequestContext,
147
+ variant: CTProductVariant,
148
+ product: ProductProjection,
149
+ ): ProductSearchResultItemVariant {
150
+ const sourceImage = variant.images?.[0];
151
+
152
+ const image = ImageSchema.parse({
153
+ sourceUrl: sourceImage?.url || '',
154
+ height: sourceImage?.dimensions.h || undefined,
155
+ width: sourceImage?.dimensions.w || undefined,
156
+ altText:
157
+ sourceImage?.label || product.name[context.languageContext.locale] || undefined,
158
+ });
159
+
160
+ const mappedOptions =
161
+ variant.attributes
162
+ ?.filter((attribute) => attribute.name === 'Color')
163
+ .map((option) =>
164
+ ProductVariantOptionSchema.parse({
165
+ identifier: ProductOptionIdentifierSchema.parse({
166
+ key: option.name,
167
+ } satisfies Partial<ProductOptionIdentifier>),
168
+ name: option.value || '',
169
+ } satisfies Partial<ProductVariantOption>),
170
+ ) || [];
171
+
172
+ const mappedOption = mappedOptions?.[0];
173
+
174
+ return ProductSearchResultItemVariantSchema.parse({
175
+ variant: ProductVariantIdentifierSchema.parse({
176
+ sku: variant.sku || '',
177
+ } satisfies ProductVariantIdentifier),
178
+ image,
179
+ options: mappedOption,
180
+ } satisfies Partial<ProductSearchResultItemVariant>);
181
+ }
182
+ }
@@ -0,0 +1,94 @@
1
+ import type { Address as CTAddress, Customer } from '@commercetools/platform-sdk';
2
+ import type {
3
+ ProfileSchema} from '@reactionary/core';
4
+ import {
5
+ type Address,
6
+ type AnyProfileSchema,
7
+ type Profile,
8
+ type ProfileFactory,
9
+ type RequestContext,
10
+ } from '@reactionary/core';
11
+ import type * as z from 'zod';
12
+
13
+ export class CommercetoolsProfileFactory<
14
+ TProfileSchema extends AnyProfileSchema = typeof ProfileSchema,
15
+ > implements ProfileFactory<TProfileSchema>
16
+ {
17
+ public readonly profileSchema: TProfileSchema;
18
+
19
+ constructor(profileSchema: TProfileSchema) {
20
+ this.profileSchema = profileSchema;
21
+ }
22
+
23
+ public parseProfile(
24
+ _context: RequestContext,
25
+ data: Customer,
26
+ ): z.output<TProfileSchema> {
27
+ const email = data.email;
28
+ const emailVerified = data.isEmailVerified;
29
+ let defaultBilling = data.addresses.find((address) => address.id === data.defaultBillingAddressId);
30
+ const phone = defaultBilling?.phone ?? '';
31
+
32
+ if (this.isIncompleteAddress(defaultBilling)) {
33
+ defaultBilling = undefined;
34
+ }
35
+
36
+ const defaultShipping = data.addresses.find(
37
+ (address) => address.id === data.defaultShippingAddressId,
38
+ );
39
+
40
+ const alternateShippingAddresses = data.addresses
41
+ .filter((address) => address.id !== data.defaultBillingAddressId)
42
+ .filter((address) => address.id !== data.defaultShippingAddressId)
43
+ .map((address) => this.parseAddress(address));
44
+
45
+ const billingAddress = defaultBilling ? this.parseAddress(defaultBilling) : undefined;
46
+ const shippingAddress = defaultShipping ? this.parseAddress(defaultShipping) : undefined;
47
+
48
+ const result = {
49
+ identifier: {
50
+ userId: data.id,
51
+ },
52
+ email,
53
+ emailVerified,
54
+ alternateShippingAddresses,
55
+ billingAddress,
56
+ shippingAddress,
57
+ createdAt: data.createdAt,
58
+ phone,
59
+ phoneVerified: false,
60
+ updatedAt: data.lastModifiedAt,
61
+ } satisfies Profile;
62
+
63
+ return this.profileSchema.parse(result);
64
+ }
65
+
66
+ protected parseAddress(address: CTAddress): Address {
67
+ return {
68
+ identifier: {
69
+ nickName: address.key || '',
70
+ },
71
+ firstName: address.firstName || '',
72
+ lastName: address.lastName || '',
73
+ streetAddress: address.streetName || '',
74
+ streetNumber: address.streetNumber || '',
75
+ city: address.city || '',
76
+ region: address.region || '',
77
+ postalCode: address.postalCode || '',
78
+ countryCode: address.country,
79
+ } satisfies Address;
80
+ }
81
+
82
+ protected isIncompleteAddress(address: CTAddress | undefined): boolean {
83
+ if (!address) {
84
+ return false;
85
+ }
86
+ return (
87
+ !address.firstName &&
88
+ !address.lastName &&
89
+ !address.streetName &&
90
+ !address.streetNumber &&
91
+ !address.city
92
+ );
93
+ }
94
+ }
@@ -0,0 +1,49 @@
1
+ import type { Channel } from '@commercetools/platform-sdk';
2
+ import type {
3
+ StoreSchema} from '@reactionary/core';
4
+ import {
5
+ type AnyStoreSchema,
6
+ type FulfillmentCenterIdentifier,
7
+ type RequestContext,
8
+ type Store,
9
+ type StoreFactory,
10
+ type StoreIdentifier,
11
+ } from '@reactionary/core';
12
+ import type * as z from 'zod';
13
+
14
+ export class CommercetoolsStoreFactory<
15
+ TStoreSchema extends AnyStoreSchema = typeof StoreSchema,
16
+ > implements StoreFactory<TStoreSchema>
17
+ {
18
+ public readonly storeSchema: TStoreSchema;
19
+
20
+ constructor(storeSchema: TStoreSchema) {
21
+ this.storeSchema = storeSchema;
22
+ }
23
+
24
+ public parseStore(
25
+ _context: RequestContext,
26
+ data: Channel,
27
+ ): z.output<TStoreSchema> {
28
+ let name = '';
29
+ if (data.name && data.name['la']) {
30
+ name = data.name['la'];
31
+ }
32
+
33
+ const identifier = {
34
+ key: data.key || '',
35
+ } satisfies StoreIdentifier;
36
+
37
+ const fulfillmentCenter = {
38
+ key: data.key || '',
39
+ } satisfies FulfillmentCenterIdentifier;
40
+
41
+ const result = {
42
+ identifier,
43
+ fulfillmentCenter,
44
+ name,
45
+ } satisfies Store;
46
+
47
+ return this.storeSchema.parse(result);
48
+ }
49
+ }
@@ -10,6 +10,21 @@ export * from './providers/product-associations.provider.js';
10
10
  export * from './providers/product.provider.js';
11
11
  export * from './providers/product-reviews.provider.js';
12
12
  export * from './providers/product-search.provider.js';
13
+ export * from './factories/product/product.factory.js';
14
+ export * from './factories/checkout/checkout.factory.js';
15
+ export * from './factories/product-search/product-search.factory.js';
16
+ export * from './factories/inventory/inventory.factory.js';
17
+ export * from './factories/price/price.factory.js';
18
+ export * from './factories/store/store.factory.js';
19
+ export * from './factories/order/order.factory.js';
20
+ export * from './factories/category/category.factory.js';
21
+ export * from './factories/cart/cart.factory.js';
22
+ export * from './factories/profile/profile.factory.js';
23
+ export * from './factories/order-search/order-search.factory.js';
24
+ export * from './factories/product-associations/product-associations.factory.js';
25
+ export * from './factories/product-reviews/product-reviews.factory.js';
26
+ export * from './factories/product-list/product-list.factory.js';
27
+ export * from './factories/identity/identity.factory.js';
13
28
 
14
29
  export * from './schema/capabilities.schema.js';
15
30
  export * from './schema/configuration.schema.js';