@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
@@ -17,6 +17,9 @@ import {
17
17
  type ProductSearchResultItemVariant,
18
18
  type FacetIdentifier,
19
19
  type FacetValueIdentifier,
20
+ type ProductSearchFactory,
21
+ type ProductSearchFactoryOutput,
22
+ type ProductSearchFactoryWithOutput,
20
23
  type ProductSearchResultFacet,
21
24
  type ProductSearchResultFacetValue,
22
25
  Reactionary,
@@ -37,20 +40,26 @@ import type {
37
40
  StoreProductListResponse,
38
41
  StoreProductVariant,
39
42
  } from '@medusajs/types';
43
+ import type { MedusaProductSearchFactory } from '../factories/product-search/product-search.factory.js';
40
44
 
41
45
  const debug = createDebug('reactionary:medusa:search');
42
46
 
43
- export class MedusaSearchProvider extends ProductSearchProvider {
47
+ export class MedusaSearchProvider<
48
+ TFactory extends ProductSearchFactory = MedusaProductSearchFactory,
49
+ > extends ProductSearchProvider<ProductSearchFactoryOutput<TFactory>> {
44
50
  protected config: MedusaConfiguration;
51
+ protected factory: ProductSearchFactoryWithOutput<TFactory>;
45
52
 
46
53
  constructor(
47
54
  config: MedusaConfiguration,
48
55
  cache: Cache,
49
56
  context: RequestContext,
50
- public medusaApi: MedusaAPI
57
+ public medusaApi: MedusaAPI,
58
+ factory: ProductSearchFactoryWithOutput<TFactory>,
51
59
  ) {
52
60
  super(cache, context);
53
61
  this.config = config;
62
+ this.factory = factory;
54
63
  }
55
64
 
56
65
  protected async resolveCategoryIdByExternalId(
@@ -114,7 +123,7 @@ export class MedusaSearchProvider extends ProductSearchProvider {
114
123
  })
115
124
  public override async queryByTerm(
116
125
  payload: ProductSearchQueryByTerm
117
- ): Promise<Result<ProductSearchResult>> {
126
+ ): Promise<Result<ProductSearchFactoryOutput<TFactory>>> {
118
127
  const client = await this.medusaApi.getClient();
119
128
 
120
129
  let categoryIdToFind: string | null = null;
@@ -141,22 +150,20 @@ export class MedusaSearchProvider extends ProductSearchProvider {
141
150
 
142
151
  const response = await client.store.product.list(this.queryByTermPayload(payload, categoryIdToFind));
143
152
 
144
- const result = this.parsePaginatedResult(response) as ProductSearchResult;
153
+ const result = this.parsePaginatedResult(response, payload);
145
154
  if (debug.enabled) {
146
155
  debug(
147
156
  `Search for term "${payload.search.term}" returned ${response.products.length} products (page ${payload.search.paginationOptions.pageNumber} of ${result.totalPages})`
148
157
  );
149
158
  }
150
159
 
151
- // Set result metadata
152
- result.identifier = {
153
- ...payload.search,
154
- };
155
-
156
- return success(result);
160
+ return success(this.factory.parseSearchResult(this.context, result, payload));
157
161
  }
158
162
 
159
- protected parsePaginatedResult(remote: StoreProductListResponse) {
163
+ protected parsePaginatedResult(
164
+ remote: StoreProductListResponse,
165
+ query: ProductSearchQueryByTerm,
166
+ ) {
160
167
  // Parse facets
161
168
  // no facets available from Medusa at the moment
162
169
 
@@ -166,13 +173,7 @@ export class MedusaSearchProvider extends ProductSearchProvider {
166
173
 
167
174
  const result = {
168
175
  identifier: {
169
- facets: [],
170
- filters: [],
171
- paginationOptions: {
172
- pageNumber: 1,
173
- pageSize: 0,
174
- },
175
- term: '',
176
+ ...query.search,
176
177
  },
177
178
  pageNumber: (Math.ceil(remote.offset / remote.limit) || 0) + 1,
178
179
  pageSize: remote.limit,
@@ -237,17 +238,4 @@ export class MedusaSearchProvider extends ProductSearchProvider {
237
238
  return success(facetValueIdentifier);
238
239
  }
239
240
 
240
- protected override parseFacetValue(
241
- facetValueIdentifier: FacetValueIdentifier,
242
- label: string,
243
- count: number
244
- ): ProductSearchResultFacetValue {
245
- throw new Error('Method not implemented.');
246
- }
247
- protected override parseFacet(
248
- facetIdentifier: FacetIdentifier,
249
- facetValue: unknown
250
- ): ProductSearchResultFacet {
251
- throw new Error('Method not implemented.');
252
- }
253
241
  }
@@ -1,4 +1,24 @@
1
- import type { Cache, Image, NotFoundError, Product, ProductAttribute, ProductAttributeIdentifier, ProductAttributeValueIdentifier, ProductOptionIdentifier, ProductOptionValueIdentifier, ProductQueryById, ProductQueryBySKU, ProductQueryBySlug, ProductVariant, ProductVariantOption, RequestContext, Result } from '@reactionary/core';
1
+ import type {
2
+ Cache,
3
+ Image,
4
+ NotFoundError,
5
+ Product,
6
+ ProductAttribute,
7
+ ProductAttributeIdentifier,
8
+ ProductAttributeValueIdentifier,
9
+ ProductFactory,
10
+ ProductFactoryOutput,
11
+ ProductFactoryWithOutput,
12
+ ProductOptionIdentifier,
13
+ ProductOptionValueIdentifier,
14
+ ProductQueryById,
15
+ ProductQueryBySKU,
16
+ ProductQueryBySlug,
17
+ ProductVariant,
18
+ ProductVariantOption,
19
+ RequestContext,
20
+ Result,
21
+ } from '@reactionary/core';
2
22
  import {
3
23
  CategoryIdentifierSchema,
4
24
  ProductIdentifierSchema,
@@ -16,16 +36,27 @@ import type { MedusaAPI } from '../core/client.js';
16
36
  import type { MedusaConfiguration } from '../schema/configuration.schema.js';
17
37
 
18
38
  import type { StoreProduct, StoreProductImage, StoreProductVariant } from '@medusajs/types';
39
+ import type { MedusaProductFactory } from '../factories/product/product.factory.js';
19
40
 
20
41
  const debug = createDebug('reactionary:medusa:product');
21
42
 
22
- export class MedusaProductProvider extends ProductProvider {
43
+ export class MedusaProductProvider<
44
+ TFactory extends ProductFactory = MedusaProductFactory,
45
+ > extends ProductProvider<ProductFactoryOutput<TFactory>> {
23
46
  protected config: MedusaConfiguration;
24
- protected alwaysIncludedFields = ["+metadata.*","+categories.metadata.*","+external_id"]
25
-
26
- constructor(config: MedusaConfiguration, cache: Cache, context: RequestContext, public medusaApi: MedusaAPI) {
47
+ protected alwaysIncludedFields = ["+metadata.*","+categories.metadata.*","+external_id"];
48
+ protected factory: ProductFactoryWithOutput<TFactory>;
49
+
50
+ constructor(
51
+ config: MedusaConfiguration,
52
+ cache: Cache,
53
+ context: RequestContext,
54
+ public medusaApi: MedusaAPI,
55
+ factory: ProductFactoryWithOutput<TFactory>,
56
+ ) {
27
57
  super(cache, context);
28
58
  this.config = config;
59
+ this.factory = factory;
29
60
  }
30
61
 
31
62
  protected getByIdPayload(payload: ProductQueryById) {
@@ -45,7 +76,9 @@ export class MedusaProductProvider extends ProductProvider {
45
76
  currencyDependentCaching: false,
46
77
  localeDependentCaching: true
47
78
  })
48
- public override async getById(payload: ProductQueryById): Promise<Result<Product>> {
79
+ public override async getById(
80
+ payload: ProductQueryById,
81
+ ): Promise<Result<ProductFactoryOutput<TFactory>>> {
49
82
  const client = await this.medusaApi.getClient();
50
83
  if (debug.enabled) {
51
84
  debug(`Fetching product by ID: ${payload.identifier.key}`);
@@ -81,7 +114,9 @@ export class MedusaProductProvider extends ProductProvider {
81
114
  currencyDependentCaching: false,
82
115
  localeDependentCaching: true
83
116
  })
84
- public override async getBySlug(payload: ProductQueryBySlug): Promise<Result<Product, NotFoundError>> {
117
+ public override async getBySlug(
118
+ payload: ProductQueryBySlug,
119
+ ): Promise<Result<ProductFactoryOutput<TFactory>, NotFoundError>> {
85
120
  const client = await this.medusaApi.getClient();
86
121
  if (debug.enabled) {
87
122
  debug(`Fetching product by slug: ${payload.slug}`);
@@ -111,7 +146,9 @@ export class MedusaProductProvider extends ProductProvider {
111
146
  currencyDependentCaching: false,
112
147
  localeDependentCaching: true
113
148
  })
114
- public override async getBySKU(payload: ProductQueryBySKU): Promise<Result<Product>> {
149
+ public override async getBySKU(
150
+ payload: ProductQueryBySKU,
151
+ ): Promise<Result<ProductFactoryOutput<TFactory>>> {
115
152
  if (debug.enabled) {
116
153
  debug(`Fetching product by SKU: ${Array.isArray(payload) ? payload.join(', ') : payload}`);
117
154
  }
@@ -129,7 +166,7 @@ export class MedusaProductProvider extends ProductProvider {
129
166
  return success(this.parseSingle(product));
130
167
  }
131
168
 
132
- protected parseSingle(_body: StoreProduct): Product {
169
+ protected parseSingle(_body: StoreProduct): ProductFactoryOutput<TFactory> {
133
170
  const identifier = ProductIdentifierSchema.parse({ key: _body.external_id || _body.id });
134
171
  const name = _body.title;
135
172
  const slug = _body.handle;
@@ -171,7 +208,7 @@ export class MedusaProductProvider extends ProductProvider {
171
208
  variants: otherVariants,
172
209
  } satisfies Product;
173
210
 
174
- return result;
211
+ return this.factory.parseProduct(this.context, result);
175
212
  }
176
213
 
177
214
  protected parseVariant(variant: StoreProductVariant, product: StoreProduct) {
@@ -275,4 +312,3 @@ export class MedusaProductProvider extends ProductProvider {
275
312
  return sharedAttributes;
276
313
  }
277
314
  }
278
-
@@ -24,6 +24,9 @@ import {
24
24
  ProfileMutationSetBillingAddressSchema,
25
25
  success,
26
26
  type Address,
27
+ type ProfileFactory,
28
+ type ProfileFactoryOutput,
29
+ type ProfileFactoryWithOutput,
27
30
  ProfileQueryByIdSchema,
28
31
  error
29
32
  } from '@reactionary/core';
@@ -31,6 +34,7 @@ import type { MedusaConfiguration } from '../schema/configuration.schema.js';
31
34
  import type { MedusaAPI } from '../core/client.js';
32
35
  import createDebug from 'debug';
33
36
  import type { StoreCreateCustomerAddress, StoreCustomer, StoreCustomerAddress } from '@medusajs/types';
37
+ import type { MedusaProfileFactory } from '../factories/profile/profile.factory.js';
34
38
 
35
39
  const debug = createDebug('reactionary:medusa:profile');
36
40
  /**
@@ -43,26 +47,33 @@ const debug = createDebug('reactionary:medusa:profile');
43
47
  * - handle guest user scenarios (if applicable).
44
48
  * - improve error handling and edge cases.
45
49
  */
46
- export class MedusaProfileProvider extends ProfileProvider {
50
+ export class MedusaProfileProvider<
51
+ TFactory extends ProfileFactory = MedusaProfileFactory,
52
+ > extends ProfileProvider<ProfileFactoryOutput<TFactory>> {
47
53
  protected config: MedusaConfiguration;
48
54
  protected includedFields = ['+metadata.*'];
55
+ protected factory: ProfileFactoryWithOutput<TFactory>;
49
56
 
50
57
  constructor(
51
58
  config: MedusaConfiguration,
52
59
  cache: Cache,
53
60
  context: RequestContext,
54
- public medusaApi: MedusaAPI
61
+ public medusaApi: MedusaAPI,
62
+ factory: ProfileFactoryWithOutput<TFactory>,
55
63
  ) {
56
64
  super(cache, context);
57
65
 
58
66
  this.config = config;
67
+ this.factory = factory;
59
68
  }
60
69
 
61
70
  @Reactionary({
62
71
  inputSchema: ProfileQueryByIdSchema,
63
72
  outputSchema: ProfileSchema,
64
73
  })
65
- public async getById(payload: ProfileQueryById): Promise<Result<Profile, NotFoundError>> {
74
+ public async getById(
75
+ payload: ProfileQueryById,
76
+ ): Promise<Result<ProfileFactoryOutput<TFactory>, NotFoundError>> {
66
77
  debug('getById', payload);
67
78
 
68
79
  const client = await this.medusaApi.getClient();
@@ -91,7 +102,9 @@ export class MedusaProfileProvider extends ProfileProvider {
91
102
  inputSchema: ProfileMutationUpdateSchema,
92
103
  outputSchema: ProfileSchema,
93
104
  })
94
- public async update(payload: ProfileMutationUpdate): Promise<Result<Profile, NotFoundError>> {
105
+ public async update(
106
+ payload: ProfileMutationUpdate,
107
+ ): Promise<Result<ProfileFactoryOutput<TFactory>, NotFoundError>> {
95
108
  debug('update', payload);
96
109
 
97
110
  const client = await this.medusaApi.getClient();
@@ -120,7 +133,9 @@ export class MedusaProfileProvider extends ProfileProvider {
120
133
  inputSchema: ProfileMutationAddShippingAddressSchema,
121
134
  outputSchema: ProfileSchema,
122
135
  })
123
- public async addShippingAddress(payload: ProfileMutationAddShippingAddress): Promise<Result<Profile, NotFoundError>> {
136
+ public async addShippingAddress(
137
+ payload: ProfileMutationAddShippingAddress,
138
+ ): Promise<Result<ProfileFactoryOutput<TFactory>, NotFoundError>> {
124
139
  debug('addShippingAddress', payload);
125
140
 
126
141
  const client = await this.medusaApi.getClient();
@@ -162,7 +177,9 @@ export class MedusaProfileProvider extends ProfileProvider {
162
177
  inputSchema: ProfileMutationUpdateShippingAddressSchema,
163
178
  outputSchema: ProfileSchema,
164
179
  })
165
- public async updateShippingAddress(payload: ProfileMutationUpdateShippingAddress): Promise<Result<Profile, NotFoundError>> {
180
+ public async updateShippingAddress(
181
+ payload: ProfileMutationUpdateShippingAddress,
182
+ ): Promise<Result<ProfileFactoryOutput<TFactory>, NotFoundError>> {
166
183
  debug('updateShippingAddress', payload);
167
184
 
168
185
  const client = await this.medusaApi.getClient();
@@ -203,7 +220,9 @@ export class MedusaProfileProvider extends ProfileProvider {
203
220
  inputSchema: ProfileMutationRemoveShippingAddressSchema,
204
221
  outputSchema: ProfileSchema,
205
222
  })
206
- public async removeShippingAddress(payload: ProfileMutationRemoveShippingAddress): Promise<Result<Profile, NotFoundError>> {
223
+ public async removeShippingAddress(
224
+ payload: ProfileMutationRemoveShippingAddress,
225
+ ): Promise<Result<ProfileFactoryOutput<TFactory>, NotFoundError>> {
207
226
  debug('removeShippingAddress', payload);
208
227
  const client = await this.medusaApi.getClient();
209
228
 
@@ -247,7 +266,9 @@ export class MedusaProfileProvider extends ProfileProvider {
247
266
  inputSchema: ProfileMutationMakeShippingAddressDefaultSchema,
248
267
  outputSchema: ProfileSchema,
249
268
  })
250
- public async makeShippingAddressDefault(payload: ProfileMutationMakeShippingAddressDefault): Promise<Result<Profile, NotFoundError>> {
269
+ public async makeShippingAddressDefault(
270
+ payload: ProfileMutationMakeShippingAddressDefault,
271
+ ): Promise<Result<ProfileFactoryOutput<TFactory>, NotFoundError>> {
251
272
  debug('makeShippingAddressDefault', payload);
252
273
 
253
274
  const client = await this.medusaApi.getClient();
@@ -289,7 +310,9 @@ export class MedusaProfileProvider extends ProfileProvider {
289
310
  inputSchema: ProfileMutationSetBillingAddressSchema,
290
311
  outputSchema: ProfileSchema,
291
312
  })
292
- public async setBillingAddress(payload: ProfileMutationSetBillingAddress): Promise<Result<Profile, NotFoundError>> {
313
+ public async setBillingAddress(
314
+ payload: ProfileMutationSetBillingAddress,
315
+ ): Promise<Result<ProfileFactoryOutput<TFactory>, NotFoundError>> {
293
316
  debug('setBillingAddress', payload);
294
317
 
295
318
 
@@ -361,7 +384,7 @@ export class MedusaProfileProvider extends ProfileProvider {
361
384
  }
362
385
  }
363
386
 
364
- protected parseSingle(customer: StoreCustomer): Profile {
387
+ protected parseSingle(customer: StoreCustomer): ProfileFactoryOutput<TFactory> {
365
388
  const email = customer.email;
366
389
  const emailVerified = customer.metadata?.['email_verified'] === 'true';
367
390
 
@@ -386,7 +409,7 @@ export class MedusaProfileProvider extends ProfileProvider {
386
409
 
387
410
  alternateShippingAddresses.push(...addresses.filter(x => ! (x.is_default_billing || x.is_default_shipping)).map( addr => this.parseAddress(addr)));
388
411
 
389
- return {
412
+ const result = {
390
413
  identifier: {
391
414
  userId: customer.id,
392
415
  },
@@ -400,6 +423,7 @@ export class MedusaProfileProvider extends ProfileProvider {
400
423
  createdAt: new Date(customer.created_at || '').toISOString(),
401
424
  updatedAt: new Date(customer.updated_at || '').toISOString()
402
425
  } satisfies Profile;
426
+ return this.factory.parseProfile(this.context, result);
403
427
  }
404
428
 
405
429
 
@@ -1,20 +1,231 @@
1
- import { CapabilitiesSchema } from "@reactionary/core";
2
- import type * as z from 'zod';
1
+ import type {
2
+ CartFactory,
3
+ CartFactoryWithOutput,
4
+ CartProvider,
5
+ CategoryFactory,
6
+ CategoryFactoryWithOutput,
7
+ CategoryProvider,
8
+ CheckoutFactory,
9
+ CheckoutFactoryWithOutput,
10
+ CheckoutProvider,
11
+ IdentityProvider,
12
+ InventoryFactory,
13
+ InventoryFactoryWithOutput,
14
+ InventoryProvider,
15
+ OrderFactory,
16
+ OrderFactoryWithOutput,
17
+ OrderProvider,
18
+ OrderSearchFactory,
19
+ OrderSearchFactoryWithOutput,
20
+ OrderSearchProvider,
21
+ PriceFactory,
22
+ PriceFactoryWithOutput,
23
+ PriceProvider,
24
+ ProductAssociationsFactory,
25
+ ProductAssociationsFactoryWithOutput,
26
+ ProductAssociationsProvider,
27
+ ProductFactory,
28
+ ProductFactoryWithOutput,
29
+ ProductProvider,
30
+ ProductRecommendationsProvider,
31
+ ProductSearchFactory,
32
+ ProductSearchFactoryWithOutput,
33
+ ProductSearchProvider,
34
+ ProfileFactory,
35
+ ProfileFactoryWithOutput,
36
+ ProfileProvider,
37
+ RequestContext,
38
+ Cache,
39
+ } from '@reactionary/core';
40
+ import { CapabilitiesSchema } from '@reactionary/core';
41
+ import type { MedusaConfiguration } from './configuration.schema.js';
42
+ import type { MedusaAPI } from '../core/client.js';
43
+ import * as z from 'zod';
44
+
45
+ const OverridableCapabilitySchema = z.looseObject({
46
+ enabled: z.boolean(),
47
+ factory: z.unknown().optional(),
48
+ provider: z.unknown().optional(),
49
+ });
50
+
51
+ const ProviderCapabilitySchema = z.looseObject({
52
+ enabled: z.boolean(),
53
+ provider: z.unknown().optional(),
54
+ });
3
55
 
4
56
  export const MedusaCapabilitiesSchema = CapabilitiesSchema.pick({
5
- productSearch: true,
6
- productRecommendations: true,
7
- cart: true,
8
- checkout: true,
9
- category: true,
10
- product: true,
11
- price: true,
12
- order: true,
13
- orderSearch: true,
14
- inventory: true,
15
- identity: true,
16
- profile: true,
17
- productAssociations: true
18
- }).partial();
19
-
20
- export type MedusaCapabilities = z.infer<typeof MedusaCapabilitiesSchema>;
57
+ productSearch: true,
58
+ productRecommendations: true,
59
+ cart: true,
60
+ checkout: true,
61
+ category: true,
62
+ product: true,
63
+ price: true,
64
+ order: true,
65
+ orderSearch: true,
66
+ inventory: true,
67
+ identity: true,
68
+ profile: true,
69
+ productAssociations: true,
70
+ })
71
+ .extend({
72
+ product: OverridableCapabilitySchema.optional(),
73
+ productSearch: OverridableCapabilitySchema.optional(),
74
+ cart: OverridableCapabilitySchema.optional(),
75
+ checkout: OverridableCapabilitySchema.optional(),
76
+ category: OverridableCapabilitySchema.optional(),
77
+ price: OverridableCapabilitySchema.optional(),
78
+ order: OverridableCapabilitySchema.optional(),
79
+ orderSearch: OverridableCapabilitySchema.optional(),
80
+ inventory: OverridableCapabilitySchema.optional(),
81
+ identity: ProviderCapabilitySchema.optional(),
82
+ profile: OverridableCapabilitySchema.optional(),
83
+ productAssociations: OverridableCapabilitySchema.optional(),
84
+ productRecommendations: ProviderCapabilitySchema.optional(),
85
+ })
86
+ .partial();
87
+
88
+ export interface MedusaProviderFactoryArgs {
89
+ cache: Cache;
90
+ context: RequestContext;
91
+ config: MedusaConfiguration;
92
+ medusaApi: MedusaAPI;
93
+ }
94
+
95
+ export interface MedusaFactoryProviderArgs<TFactory>
96
+ extends MedusaProviderFactoryArgs {
97
+ factory: TFactory;
98
+ }
99
+
100
+ export interface MedusaCapabilityConfig<TFactory, TProvider> {
101
+ enabled: boolean;
102
+ factory?: TFactory;
103
+ provider?: (args: MedusaFactoryProviderArgs<TFactory>) => TProvider;
104
+ }
105
+
106
+ export interface MedusaProviderOnlyCapabilityConfig<TProvider> {
107
+ enabled: boolean;
108
+ provider?: (args: MedusaProviderFactoryArgs) => TProvider;
109
+ }
110
+
111
+ export type MedusaProductCapabilityConfig = MedusaCapabilityConfig<
112
+ ProductFactoryWithOutput<ProductFactory>,
113
+ ProductProvider
114
+ >;
115
+
116
+ export type MedusaProductSearchCapabilityConfig = MedusaCapabilityConfig<
117
+ ProductSearchFactoryWithOutput<ProductSearchFactory>,
118
+ ProductSearchProvider
119
+ >;
120
+
121
+ export type MedusaCartCapabilityConfig = MedusaCapabilityConfig<
122
+ CartFactoryWithOutput<CartFactory>,
123
+ CartProvider
124
+ >;
125
+
126
+ export type MedusaCheckoutCapabilityConfig = MedusaCapabilityConfig<
127
+ CheckoutFactoryWithOutput<CheckoutFactory>,
128
+ CheckoutProvider
129
+ >;
130
+
131
+ export type MedusaCategoryCapabilityConfig = MedusaCapabilityConfig<
132
+ CategoryFactoryWithOutput<CategoryFactory>,
133
+ CategoryProvider
134
+ >;
135
+
136
+ export type MedusaPriceCapabilityConfig = MedusaCapabilityConfig<
137
+ PriceFactoryWithOutput<PriceFactory>,
138
+ PriceProvider
139
+ >;
140
+
141
+ export type MedusaOrderCapabilityConfig = MedusaCapabilityConfig<
142
+ OrderFactoryWithOutput<OrderFactory>,
143
+ OrderProvider
144
+ >;
145
+
146
+ export type MedusaOrderSearchCapabilityConfig = MedusaCapabilityConfig<
147
+ OrderSearchFactoryWithOutput<OrderSearchFactory>,
148
+ OrderSearchProvider
149
+ >;
150
+
151
+ export type MedusaInventoryCapabilityConfig = MedusaCapabilityConfig<
152
+ InventoryFactoryWithOutput<InventoryFactory>,
153
+ InventoryProvider
154
+ >;
155
+
156
+ export type MedusaIdentityCapabilityConfig =
157
+ MedusaProviderOnlyCapabilityConfig<IdentityProvider>;
158
+
159
+ export type MedusaProfileCapabilityConfig = MedusaCapabilityConfig<
160
+ ProfileFactoryWithOutput<ProfileFactory>,
161
+ ProfileProvider
162
+ >;
163
+
164
+ export type MedusaProductAssociationsCapabilityConfig = MedusaCapabilityConfig<
165
+ ProductAssociationsFactoryWithOutput<ProductAssociationsFactory>,
166
+ ProductAssociationsProvider
167
+ >;
168
+
169
+ export type MedusaProductRecommendationsCapabilityConfig =
170
+ MedusaProviderOnlyCapabilityConfig<ProductRecommendationsProvider>;
171
+
172
+ export type MedusaCapabilities<
173
+ TProductFactory extends ProductFactory = ProductFactory,
174
+ TProductProvider extends ProductProvider = ProductProvider,
175
+ TProductSearchFactory extends ProductSearchFactory = ProductSearchFactory,
176
+ TProductSearchProvider extends ProductSearchProvider = ProductSearchProvider,
177
+ TCartFactory extends CartFactory = CartFactory,
178
+ TCartProvider extends CartProvider = CartProvider,
179
+ TCheckoutFactory extends CheckoutFactory = CheckoutFactory,
180
+ TCheckoutProvider extends CheckoutProvider = CheckoutProvider,
181
+ TCategoryFactory extends CategoryFactory = CategoryFactory,
182
+ TCategoryProvider extends CategoryProvider = CategoryProvider,
183
+ TPriceFactory extends PriceFactory = PriceFactory,
184
+ TPriceProvider extends PriceProvider = PriceProvider,
185
+ TOrderFactory extends OrderFactory = OrderFactory,
186
+ TOrderProvider extends OrderProvider = OrderProvider,
187
+ TOrderSearchFactory extends OrderSearchFactory = OrderSearchFactory,
188
+ TOrderSearchProvider extends OrderSearchProvider = OrderSearchProvider,
189
+ TInventoryFactory extends InventoryFactory = InventoryFactory,
190
+ TInventoryProvider extends InventoryProvider = InventoryProvider,
191
+ TIdentityProvider extends IdentityProvider = IdentityProvider,
192
+ TProfileFactory extends ProfileFactory = ProfileFactory,
193
+ TProfileProvider extends ProfileProvider = ProfileProvider,
194
+ TProductAssociationsFactory extends ProductAssociationsFactory = ProductAssociationsFactory,
195
+ TProductAssociationsProvider extends ProductAssociationsProvider = ProductAssociationsProvider,
196
+ TProductRecommendationsProvider extends ProductRecommendationsProvider = ProductRecommendationsProvider,
197
+ > = {
198
+ product?: MedusaCapabilityConfig<ProductFactoryWithOutput<TProductFactory>, TProductProvider>;
199
+ productSearch?: MedusaCapabilityConfig<
200
+ ProductSearchFactoryWithOutput<TProductSearchFactory>,
201
+ TProductSearchProvider
202
+ >;
203
+ cart?: MedusaCapabilityConfig<CartFactoryWithOutput<TCartFactory>, TCartProvider>;
204
+ checkout?: MedusaCapabilityConfig<
205
+ CheckoutFactoryWithOutput<TCheckoutFactory>,
206
+ TCheckoutProvider
207
+ >;
208
+ category?: MedusaCapabilityConfig<
209
+ CategoryFactoryWithOutput<TCategoryFactory>,
210
+ TCategoryProvider
211
+ >;
212
+ price?: MedusaCapabilityConfig<PriceFactoryWithOutput<TPriceFactory>, TPriceProvider>;
213
+ order?: MedusaCapabilityConfig<OrderFactoryWithOutput<TOrderFactory>, TOrderProvider>;
214
+ orderSearch?: MedusaCapabilityConfig<
215
+ OrderSearchFactoryWithOutput<TOrderSearchFactory>,
216
+ TOrderSearchProvider
217
+ >;
218
+ inventory?: MedusaCapabilityConfig<
219
+ InventoryFactoryWithOutput<TInventoryFactory>,
220
+ TInventoryProvider
221
+ >;
222
+ identity?: MedusaProviderOnlyCapabilityConfig<TIdentityProvider>;
223
+ profile?: MedusaCapabilityConfig<ProfileFactoryWithOutput<TProfileFactory>, TProfileProvider>;
224
+ productAssociations?: MedusaCapabilityConfig<
225
+ ProductAssociationsFactoryWithOutput<TProductAssociationsFactory>,
226
+ TProductAssociationsProvider
227
+ >;
228
+ productRecommendations?: MedusaProviderOnlyCapabilityConfig<TProductRecommendationsProvider>;
229
+ };
230
+
231
+ export type ParsedMedusaCapabilities = z.infer<typeof MedusaCapabilitiesSchema>;
@@ -1,8 +1,18 @@
1
1
 
2
- import { NoOpCache, createInitialRequestContext, unwrapValue, type Cart, type CartMutationItemAdd, type RequestContext } from '@reactionary/core';
2
+ import {
3
+ CartIdentifierSchema,
4
+ CartSchema,
5
+ NoOpCache,
6
+ createInitialRequestContext,
7
+ unwrapValue,
8
+ type Cart,
9
+ type CartMutationItemAdd,
10
+ type RequestContext,
11
+ } from '@reactionary/core';
3
12
  import { assert, beforeEach, describe, expect, it } from 'vitest';
4
13
  import { MedusaAPI } from '../core/client.js';
5
14
  import { MedusaCartProvider } from '../providers/cart.provider.js';
15
+ import { MedusaCartFactory } from '../factories/cart/cart.factory.js';
6
16
  import { getMedusaTestConfiguration } from './test-utils.js';
7
17
 
8
18
 
@@ -19,7 +29,13 @@ describe('Medusa Cart Provider', () => {
19
29
  beforeEach( () => {
20
30
  reqCtx = createInitialRequestContext();
21
31
  const client = new MedusaAPI(getMedusaTestConfiguration(), reqCtx);
22
- provider = new MedusaCartProvider(getMedusaTestConfiguration(), new NoOpCache(), reqCtx, client);
32
+ provider = new MedusaCartProvider(
33
+ getMedusaTestConfiguration(),
34
+ new NoOpCache(),
35
+ reqCtx,
36
+ client,
37
+ new MedusaCartFactory(CartSchema, CartIdentifierSchema),
38
+ );
23
39
  });
24
40
 
25
41
  describe('anonymous sessions', () => {
@@ -1,11 +1,13 @@
1
1
  import 'dotenv/config';
2
2
  import type { RequestContext } from '@reactionary/core';
3
3
  import {
4
+ CategoryPaginatedResultSchema,
4
5
  CategorySchema,
5
6
  NoOpCache,
6
7
  createInitialRequestContext,
7
8
  } from '@reactionary/core';
8
9
  import { MedusaCategoryProvider } from '../providers/category.provider.js';
10
+ import { MedusaCategoryFactory } from '../factories/category/category.factory.js';
9
11
  import { getMedusaTestConfiguration } from './test-utils.js';
10
12
  import { describe, expect, it, beforeEach, assert } from 'vitest';
11
13
  import { MedusaAPI } from '../core/client.js';
@@ -46,7 +48,8 @@ describe('Medusa Category Provider', () => {
46
48
  config,
47
49
  new NoOpCache(),
48
50
  reqCtx,
49
- client
51
+ client,
52
+ new MedusaCategoryFactory(CategorySchema, CategoryPaginatedResultSchema),
50
53
  );
51
54
  });
52
55