@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
@@ -23,15 +23,15 @@ function createMedusaClient(config: MedusaConfiguration, reqCtx: RequestContext)
23
23
  .withCache(new NoOpCache())
24
24
  .withCapability(
25
25
  withMedusaCapabilities(config, {
26
- cart: true,
27
- product: true,
28
- category: true,
29
- checkout: true,
30
- identity: true,
31
- inventory: true,
32
- order: true,
33
- price: true,
34
- productSearch: true,
26
+ cart: { enabled: true },
27
+ product: { enabled: true },
28
+ category: { enabled: true },
29
+ checkout: { enabled: true },
30
+ identity: { enabled: true },
31
+ inventory: { enabled: true },
32
+ order: { enabled: true },
33
+ price: { enabled: true },
34
+ productSearch: { enabled: true },
35
35
  })
36
36
  );
37
37
 
@@ -8,6 +8,7 @@ import {
8
8
  } from '@reactionary/core';
9
9
  import { getMedusaTestConfiguration } from './test-utils.js';
10
10
  import { MedusaAPI } from '../core/client.js';
11
+ import { MedusaInventoryFactory } from '../factories/inventory/inventory.factory.js';
11
12
 
12
13
  const testData = {
13
14
  skuInStock: ' 4007249524126',
@@ -29,7 +30,8 @@ describe('Medusa Inventory Provider', () => {
29
30
  config,
30
31
  new NoOpCache(),
31
32
  reqCtx,
32
- client
33
+ client,
34
+ new MedusaInventoryFactory(InventorySchema),
33
35
  );
34
36
  });
35
37
 
@@ -1,6 +1,8 @@
1
1
  import {
2
+ CartIdentifierSchema,
2
3
  CartSchema,
3
4
  NoOpCache,
5
+ ProductSearchResultSchema,
4
6
  ProductSearchQueryByTermSchema,
5
7
  ProductSearchResultItemSchema,
6
8
  createInitialRequestContext,
@@ -12,6 +14,8 @@ import { MedusaCartProvider } from '../providers/cart.provider.js';
12
14
  import { MedusaSearchProvider } from '../providers/product-search.provider.js';
13
15
  import { getMedusaTestConfiguration } from './test-utils.js';
14
16
  import { MedusaAPI } from '../core/client.js';
17
+ import { MedusaCartFactory } from '../factories/cart/cart.factory.js';
18
+ import { MedusaProductSearchFactory } from '../factories/product-search/product-search.factory.js';
15
19
 
16
20
  /**
17
21
  const testData = {
@@ -32,13 +36,15 @@ describe('Medusa Cart Provider - Large Scenarios', () => {
32
36
  getMedusaTestConfiguration(),
33
37
  new NoOpCache(),
34
38
  reqCtx,
35
- client
39
+ client,
40
+ new MedusaCartFactory(CartSchema, CartIdentifierSchema),
36
41
  );
37
42
  searchProvider = new MedusaSearchProvider(
38
43
  getMedusaTestConfiguration(),
39
44
  new NoOpCache(),
40
45
  reqCtx,
41
- client
46
+ client,
47
+ new MedusaProductSearchFactory(ProductSearchResultSchema),
42
48
  );
43
49
  });
44
50
 
@@ -9,6 +9,7 @@ import {
9
9
  } from '@reactionary/core';
10
10
  import { getMedusaTestConfiguration } from './test-utils.js';
11
11
  import { MedusaAPI } from '../core/client.js';
12
+ import { MedusaPriceFactory } from '../factories/price/price.factory.js';
12
13
 
13
14
  const testData = {
14
15
  skuWithoutTiers: '8712581327934',
@@ -25,7 +26,13 @@ describe('Medusa Price Provider', () => {
25
26
  const config = getMedusaTestConfiguration();
26
27
  const client = new MedusaAPI(config, reqCtx);
27
28
 
28
- provider = new MedusaPriceProvider(config, new NoOpCache(), reqCtx, client);
29
+ provider = new MedusaPriceProvider(
30
+ config,
31
+ new NoOpCache(),
32
+ reqCtx,
33
+ client,
34
+ new MedusaPriceFactory(PriceSchema),
35
+ );
29
36
  });
30
37
 
31
38
  it('should be able to get prices for a product without tiers', async () => {
@@ -9,6 +9,7 @@ import { MedusaProductProvider } from '../providers/product.provider.js';
9
9
  import { getMedusaTestConfiguration } from './test-utils.js';
10
10
  import { describe, expect, it, beforeAll, beforeEach, assert } from 'vitest';
11
11
  import { MedusaAPI } from '../index.js';
12
+ import { MedusaProductFactory } from '../factories/product/product.factory.js';
12
13
 
13
14
  const testData = {
14
15
  product: {
@@ -33,7 +34,8 @@ describe('Medusa Product Provider', () => {
33
34
  getMedusaTestConfiguration(),
34
35
  new NoOpCache(),
35
36
  reqCtx,
36
- client
37
+ client,
38
+ new MedusaProductFactory(ProductSchema),
37
39
  );
38
40
  });
39
41
 
@@ -1,10 +1,21 @@
1
1
  import 'dotenv/config';
2
- import { createInitialRequestContext, NoOpCache, ProductSearchQueryByTermSchema, ProductSearchResultItemSchema, type ProductSearchQueryCreateNavigationFilter } from '@reactionary/core';
2
+ import {
3
+ CategoryPaginatedResultSchema,
4
+ CategorySchema,
5
+ createInitialRequestContext,
6
+ NoOpCache,
7
+ ProductSearchQueryByTermSchema,
8
+ ProductSearchResultItemSchema,
9
+ ProductSearchResultSchema,
10
+ type ProductSearchQueryCreateNavigationFilter,
11
+ } from '@reactionary/core';
3
12
  import { assert, describe, expect, it } from 'vitest';
4
13
  import { MedusaSearchProvider } from '../providers/product-search.provider.js';
5
14
  import { getMedusaTestConfiguration } from './test-utils.js';
6
15
  import { MedusaAPI } from '../index.js';
7
16
  import { MedusaCategoryProvider } from '../providers/category.provider.js';
17
+ import { MedusaCategoryFactory } from '../factories/category/category.factory.js';
18
+ import { MedusaProductSearchFactory } from '../factories/product-search/product-search.factory.js';
8
19
 
9
20
  const testData = {
10
21
  searchTerm: 'printer',
@@ -16,14 +27,16 @@ describe('Medusa Search Provider', () => {
16
27
  getMedusaTestConfiguration(),
17
28
  new NoOpCache(),
18
29
  reqCtx,
19
- client
30
+ client,
31
+ new MedusaProductSearchFactory(ProductSearchResultSchema),
20
32
  );
21
33
 
22
34
  const categoryProvider = new MedusaCategoryProvider(
23
35
  getMedusaTestConfiguration(),
24
36
  new NoOpCache(),
25
37
  reqCtx,
26
- client
38
+ client,
39
+ new MedusaCategoryFactory(CategorySchema, CategoryPaginatedResultSchema),
27
40
  );
28
41
 
29
42
  it('should be able to get a result by term', async () => {
@@ -1,27 +1,94 @@
1
- import type { Cache, ClientFromCapabilities, RequestContext } from "@reactionary/core";
2
- import { MeilisearchSearchProvider } from "../providers/product-search.provider.js";
3
- import { MeilisearchProductRecommendationsProvider } from "../providers/product-recommendations.provider.js";
4
- import { MeilisearchOrderSearchProvider } from "../providers/order-search.provider.js";
5
- import type { MeilisearchCapabilities } from "../schema/capabilities.schema.js";
6
- import type { MeilisearchConfiguration } from "../schema/configuration.schema.js";
1
+ import type { Cache, RequestContext } from '@reactionary/core';
2
+ import { OrderSearchResultSchema, ProductSearchResultSchema } from '@reactionary/core';
3
+ import { MeilisearchSearchProvider } from '../providers/product-search.provider.js';
4
+ import { MeilisearchProductRecommendationsProvider } from '../providers/product-recommendations.provider.js';
5
+ import { MeilisearchOrderSearchProvider } from '../providers/order-search.provider.js';
6
+ import {
7
+ MeilisearchCapabilitiesSchema,
8
+ type MeilisearchCapabilities,
9
+ } from '../schema/capabilities.schema.js';
10
+ import type { MeilisearchConfiguration } from '../schema/configuration.schema.js';
11
+ import { MeilisearchOrderSearchFactory } from '../factories/order-search/order-search.factory.js';
12
+ import { MeilisearchProductSearchFactory } from '../factories/product-search/product-search.factory.js';
13
+ import {
14
+ type MeilisearchClientFromCapabilities,
15
+ resolveCapabilityProvider,
16
+ resolveProviderOnlyCapability,
17
+ } from './initialize.types.js';
7
18
 
8
- export function withMeilisearchCapabilities<T extends MeilisearchCapabilities>(configuration: MeilisearchConfiguration, capabilities: T) {
9
- return (cache: Cache, context: RequestContext): ClientFromCapabilities<T> => {
10
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
11
- const client: any = {};
19
+ export function withMeilisearchCapabilities<T extends MeilisearchCapabilities>(
20
+ configuration: MeilisearchConfiguration,
21
+ capabilities: T,
22
+ ) {
23
+ return (
24
+ cache: Cache,
25
+ context: RequestContext,
26
+ ): MeilisearchClientFromCapabilities<T> => {
27
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
28
+ const client: any = {};
29
+ const caps = MeilisearchCapabilitiesSchema.parse(capabilities);
12
30
 
13
- if (capabilities.productSearch) {
14
- client.productSearch = new MeilisearchSearchProvider(configuration, cache, context);
15
- }
31
+ if (caps.productSearch?.enabled) {
32
+ client.productSearch = resolveCapabilityProvider(
33
+ capabilities.productSearch,
34
+ {
35
+ factory: new MeilisearchProductSearchFactory(ProductSearchResultSchema),
36
+ provider: (args) =>
37
+ new MeilisearchSearchProvider(
38
+ args.config,
39
+ args.cache,
40
+ args.context,
41
+ args.factory,
42
+ ),
43
+ },
44
+ (factory) => ({
45
+ cache,
46
+ context,
47
+ config: configuration,
48
+ factory,
49
+ }),
50
+ );
51
+ }
16
52
 
17
- if (capabilities.productRecommendations) {
18
- client.productRecommendations = new MeilisearchProductRecommendationsProvider(configuration, cache, context);
19
- }
53
+ if (caps.orderSearch?.enabled) {
54
+ client.orderSearch = resolveCapabilityProvider(
55
+ capabilities.orderSearch,
56
+ {
57
+ factory: new MeilisearchOrderSearchFactory(OrderSearchResultSchema),
58
+ provider: (args) =>
59
+ new MeilisearchOrderSearchProvider(
60
+ args.config,
61
+ args.cache,
62
+ args.context,
63
+ args.factory,
64
+ ),
65
+ },
66
+ (factory) => ({
67
+ cache,
68
+ context,
69
+ config: configuration,
70
+ factory,
71
+ }),
72
+ );
73
+ }
20
74
 
21
- if (capabilities.orderSearch) {
22
- client.orderSearch = new MeilisearchOrderSearchProvider(configuration, cache, context);
23
- }
75
+ if (caps.productRecommendations?.enabled) {
76
+ client.productRecommendations = resolveProviderOnlyCapability(
77
+ capabilities.productRecommendations,
78
+ (args) =>
79
+ new MeilisearchProductRecommendationsProvider(
80
+ args.config,
81
+ args.cache,
82
+ args.context,
83
+ ),
84
+ {
85
+ cache,
86
+ context,
87
+ config: configuration,
88
+ },
89
+ );
90
+ }
24
91
 
25
- return client;
26
- };
92
+ return client;
93
+ };
27
94
  }
@@ -0,0 +1,119 @@
1
+ import type {
2
+ ClientFromCapabilities,
3
+ OrderSearchFactory,
4
+ ProductSearchFactory,
5
+ } from '@reactionary/core';
6
+ import type { MeilisearchCapabilities } from '../schema/capabilities.schema.js';
7
+ import type { MeilisearchOrderSearchFactory } from '../factories/order-search/order-search.factory.js';
8
+ import type { MeilisearchProductSearchFactory } from '../factories/product-search/product-search.factory.js';
9
+ import type { MeilisearchOrderSearchProvider } from '../providers/order-search.provider.js';
10
+ import type { MeilisearchProductRecommendationsProvider } from '../providers/product-recommendations.provider.js';
11
+ import type { MeilisearchSearchProvider } from '../providers/product-search.provider.js';
12
+
13
+ type EnabledCapability<TCapability> =
14
+ TCapability extends { enabled: true } ? true : false;
15
+
16
+ type NormalizeConfiguredCapabilities<T extends MeilisearchCapabilities> =
17
+ Omit<T, 'productSearch' | 'orderSearch' | 'productRecommendations'> & {
18
+ productSearch?: EnabledCapability<T['productSearch']>;
19
+ orderSearch?: EnabledCapability<T['orderSearch']>;
20
+ productRecommendations?: EnabledCapability<T['productRecommendations']>;
21
+ };
22
+
23
+ type ExtractCapabilityFactory<TCapability, TContract, TDefaultFactory> =
24
+ TCapability extends { enabled: true; factory?: infer TFactory }
25
+ ? TFactory extends TContract
26
+ ? TFactory
27
+ : TDefaultFactory
28
+ : TDefaultFactory;
29
+
30
+ type ExtractCapabilityProvider<TCapability, TDefaultProvider> =
31
+ TCapability extends { enabled: true; provider?: infer TProviderFactory }
32
+ ? TProviderFactory extends (...args: unknown[]) => infer TProvider
33
+ ? TProvider
34
+ : TDefaultProvider
35
+ : TDefaultProvider;
36
+
37
+ type CapabilityOverride<
38
+ TCapability,
39
+ TKey extends string,
40
+ TProvider,
41
+ > = TCapability extends { enabled: true }
42
+ ? { [K in TKey]: TProvider }
43
+ : Record<never, never>;
44
+
45
+ type ProductSearchFactoryFor<T extends MeilisearchCapabilities> =
46
+ ExtractCapabilityFactory<
47
+ T['productSearch'],
48
+ ProductSearchFactory,
49
+ MeilisearchProductSearchFactory
50
+ >;
51
+
52
+ type OrderSearchFactoryFor<T extends MeilisearchCapabilities> =
53
+ ExtractCapabilityFactory<
54
+ T['orderSearch'],
55
+ OrderSearchFactory,
56
+ MeilisearchOrderSearchFactory
57
+ >;
58
+
59
+ type ProductSearchProviderFor<T extends MeilisearchCapabilities> =
60
+ ExtractCapabilityProvider<
61
+ T['productSearch'],
62
+ MeilisearchSearchProvider<ProductSearchFactoryFor<T>>
63
+ >;
64
+
65
+ type OrderSearchProviderFor<T extends MeilisearchCapabilities> =
66
+ ExtractCapabilityProvider<
67
+ T['orderSearch'],
68
+ MeilisearchOrderSearchProvider<OrderSearchFactoryFor<T>>
69
+ >;
70
+
71
+ type ProductRecommendationsProviderFor<T extends MeilisearchCapabilities> =
72
+ ExtractCapabilityProvider<
73
+ T['productRecommendations'],
74
+ MeilisearchProductRecommendationsProvider
75
+ >;
76
+
77
+ export type MeilisearchClientFromCapabilities<T extends MeilisearchCapabilities> = Omit<
78
+ ClientFromCapabilities<NormalizeConfiguredCapabilities<T>>,
79
+ 'productSearch' | 'orderSearch' | 'productRecommendations'
80
+ > &
81
+ CapabilityOverride<T['productSearch'], 'productSearch', ProductSearchProviderFor<T>> &
82
+ CapabilityOverride<T['orderSearch'], 'orderSearch', OrderSearchProviderFor<T>> &
83
+ CapabilityOverride<
84
+ T['productRecommendations'],
85
+ 'productRecommendations',
86
+ ProductRecommendationsProviderFor<T>
87
+ >;
88
+
89
+ export function resolveCapabilityProvider<TFactory, TProvider, TProviderArgs>(
90
+ capability:
91
+ | {
92
+ factory?: TFactory;
93
+ provider?: (args: TProviderArgs) => TProvider;
94
+ }
95
+ | undefined,
96
+ defaults: {
97
+ factory: TFactory;
98
+ provider: (args: TProviderArgs) => TProvider;
99
+ },
100
+ buildProviderArgs: (factory: TFactory) => TProviderArgs,
101
+ ): TProvider {
102
+ const factory = capability?.factory ?? defaults.factory;
103
+ const provider = capability?.provider ?? defaults.provider;
104
+
105
+ return provider(buildProviderArgs(factory));
106
+ }
107
+
108
+ export function resolveProviderOnlyCapability<TProvider, TProviderArgs>(
109
+ capability:
110
+ | {
111
+ provider?: (args: TProviderArgs) => TProvider;
112
+ }
113
+ | undefined,
114
+ defaultProvider: (args: TProviderArgs) => TProvider,
115
+ args: TProviderArgs,
116
+ ): TProvider {
117
+ const provider = capability?.provider ?? defaultProvider;
118
+ return provider(args);
119
+ }
@@ -0,0 +1,2 @@
1
+ export * from './order-search/order-search.factory.js';
2
+ export * from './product-search/product-search.factory.js';
@@ -0,0 +1,27 @@
1
+ import type {
2
+ AnyOrderSearchResultSchema,
3
+ OrderSearchFactory,
4
+ OrderSearchQueryByTerm,
5
+ OrderSearchResultSchema,
6
+ RequestContext,
7
+ } from '@reactionary/core';
8
+ import type * as z from 'zod';
9
+
10
+ export class MeilisearchOrderSearchFactory<
11
+ TOrderSearchResultSchema extends AnyOrderSearchResultSchema = typeof OrderSearchResultSchema,
12
+ > implements OrderSearchFactory<TOrderSearchResultSchema>
13
+ {
14
+ public readonly orderSearchResultSchema: TOrderSearchResultSchema;
15
+
16
+ constructor(orderSearchResultSchema: TOrderSearchResultSchema) {
17
+ this.orderSearchResultSchema = orderSearchResultSchema;
18
+ }
19
+
20
+ public parseOrderSearchResult(
21
+ _context: RequestContext,
22
+ data: unknown,
23
+ _query: OrderSearchQueryByTerm,
24
+ ): z.output<TOrderSearchResultSchema> {
25
+ return this.orderSearchResultSchema.parse(data);
26
+ }
27
+ }
@@ -0,0 +1,27 @@
1
+ import type {
2
+ AnyProductSearchResultSchema,
3
+ ProductSearchFactory,
4
+ ProductSearchQueryByTerm,
5
+ ProductSearchResultSchema,
6
+ RequestContext,
7
+ } from '@reactionary/core';
8
+ import type * as z from 'zod';
9
+
10
+ export class MeilisearchProductSearchFactory<
11
+ TProductSearchResultSchema extends AnyProductSearchResultSchema = typeof ProductSearchResultSchema,
12
+ > implements ProductSearchFactory<TProductSearchResultSchema>
13
+ {
14
+ public readonly productSearchResultSchema: TProductSearchResultSchema;
15
+
16
+ constructor(productSearchResultSchema: TProductSearchResultSchema) {
17
+ this.productSearchResultSchema = productSearchResultSchema;
18
+ }
19
+
20
+ public parseSearchResult(
21
+ _context: RequestContext,
22
+ data: unknown,
23
+ _query: ProductSearchQueryByTerm,
24
+ ): z.output<TProductSearchResultSchema> {
25
+ return this.productSearchResultSchema.parse(data);
26
+ }
27
+ }
@@ -1,4 +1,6 @@
1
1
  export * from './core/initialize.js';
2
+ export * from './core/initialize.types.js';
3
+ export * from './factories/index.js';
2
4
  export * from './providers/product-search.provider.js';
3
5
  export * from './providers/product-recommendations.provider.js';
4
6
  export * from './providers/order-search.provider.js';
@@ -1,2 +1,3 @@
1
1
  export * from './product-search.provider.js';
2
2
  export * from './product-recommendations.provider.js';
3
+ export * from './order-search.provider.js';
@@ -19,9 +19,13 @@ import {
19
19
  AddressIdentifierSchema,
20
20
  type AddressIdentifier,
21
21
  type OrderInventoryStatus,
22
+ type OrderSearchFactory,
23
+ type OrderSearchFactoryOutput,
24
+ type OrderSearchFactoryWithOutput,
22
25
  } from '@reactionary/core';
23
26
  import { MeiliSearch, type SearchParams, type SearchResponse } from 'meilisearch';
24
27
  import type { MeilisearchConfiguration } from '../schema/configuration.schema.js';
28
+ import type { MeilisearchOrderSearchFactory } from '../factories/order-search/order-search.factory.js';
25
29
 
26
30
  interface MeilisearchNativeOrderAddress {
27
31
  address1: string;
@@ -44,12 +48,21 @@ interface MeilisearchNativeOrderRecord {
44
48
  currency: string;
45
49
  }
46
50
 
47
- export class MeilisearchOrderSearchProvider extends OrderSearchProvider {
51
+ export class MeilisearchOrderSearchProvider<
52
+ TFactory extends OrderSearchFactory = MeilisearchOrderSearchFactory,
53
+ > extends OrderSearchProvider<OrderSearchFactoryOutput<TFactory>> {
48
54
  protected config: MeilisearchConfiguration;
49
-
50
- constructor(config: MeilisearchConfiguration, cache: Cache, context: RequestContext) {
55
+ protected factory: OrderSearchFactoryWithOutput<TFactory>;
56
+
57
+ constructor(
58
+ config: MeilisearchConfiguration,
59
+ cache: Cache,
60
+ context: RequestContext,
61
+ factory: OrderSearchFactoryWithOutput<TFactory>,
62
+ ) {
51
63
  super(cache, context);
52
64
  this.config = config;
65
+ this.factory = factory;
53
66
  }
54
67
 
55
68
  protected queryByTermPayload(payload: OrderSearchQueryByTerm): SearchParams {
@@ -100,7 +113,9 @@ export class MeilisearchOrderSearchProvider extends OrderSearchProvider {
100
113
  inputSchema: OrderSearchQueryByTermSchema,
101
114
  outputSchema: OrderSearchResultSchema,
102
115
  })
103
- public async queryByTerm(payload: OrderSearchQueryByTerm): Promise<Result<OrderSearchResult>> {
116
+ public async queryByTerm(
117
+ payload: OrderSearchQueryByTerm,
118
+ ): Promise<Result<OrderSearchFactoryOutput<TFactory>>> {
104
119
  const client = new MeiliSearch({
105
120
  host: this.config.apiUrl,
106
121
  apiKey: this.config.apiKey,
@@ -114,9 +129,9 @@ export class MeilisearchOrderSearchProvider extends OrderSearchProvider {
114
129
  this.queryByTermPayload(payload)
115
130
  );
116
131
 
117
- const result = this.parsePaginatedResult(remote, payload) as OrderSearchResult;
132
+ const result = this.parsePaginatedResult(remote, payload);
118
133
 
119
- return success(result);
134
+ return success(this.factory.parseOrderSearchResult(this.context, result, payload));
120
135
  }
121
136
 
122
137
  protected mapOrderStatus(status: OrderStatus): string {
@@ -6,6 +6,9 @@ import {
6
6
  FacetValueIdentifierSchema,
7
7
  ImageSchema,
8
8
  ProductSearchProvider,
9
+ type ProductSearchFactory,
10
+ type ProductSearchFactoryOutput,
11
+ type ProductSearchFactoryWithOutput,
9
12
  type ProductSearchQueryByTerm,
10
13
  ProductSearchQueryByTermSchema,
11
14
  type ProductSearchQueryCreateNavigationFilter,
@@ -25,15 +28,25 @@ import {
25
28
  } from '@reactionary/core';
26
29
  import { MeiliSearch, type SearchParams, type SearchResponse } from 'meilisearch';
27
30
  import type { MeilisearchConfiguration } from '../schema/configuration.schema.js';
28
- import type { MeilisearchNativeRecord, MeilisearchNativeVariant, MeilisearchProductSearchResult } from '../schema/search.schema.js';
31
+ import type { MeilisearchNativeRecord, MeilisearchNativeVariant } from '../schema/search.schema.js';
32
+ import type { MeilisearchProductSearchFactory } from '../factories/product-search/product-search.factory.js';
29
33
 
30
34
 
31
- export class MeilisearchSearchProvider extends ProductSearchProvider {
35
+ export class MeilisearchSearchProvider<
36
+ TFactory extends ProductSearchFactory = MeilisearchProductSearchFactory,
37
+ > extends ProductSearchProvider<ProductSearchFactoryOutput<TFactory>> {
32
38
  protected config: MeilisearchConfiguration;
33
-
34
- constructor(config: MeilisearchConfiguration, cache: Cache, context: RequestContext) {
39
+ protected factory: ProductSearchFactoryWithOutput<TFactory>;
40
+
41
+ constructor(
42
+ config: MeilisearchConfiguration,
43
+ cache: Cache,
44
+ context: RequestContext,
45
+ factory: ProductSearchFactoryWithOutput<TFactory>,
46
+ ) {
35
47
  super(cache, context);
36
48
  this.config = config;
49
+ this.factory = factory;
37
50
  }
38
51
 
39
52
  protected queryByTermPayload(payload: ProductSearchQueryByTerm) {
@@ -85,7 +98,7 @@ export class MeilisearchSearchProvider extends ProductSearchProvider {
85
98
  })
86
99
  public override async queryByTerm(
87
100
  payload: ProductSearchQueryByTerm
88
- ): Promise<Result<ProductSearchResult>> {
101
+ ): Promise<Result<ProductSearchFactoryOutput<TFactory>>> {
89
102
  const client = new MeiliSearch({
90
103
  host: this.config.apiUrl,
91
104
  apiKey: this.config.apiKey,
@@ -96,7 +109,7 @@ export class MeilisearchSearchProvider extends ProductSearchProvider {
96
109
 
97
110
  const remote = await index.search<MeilisearchNativeRecord>(payload.search.term, this.queryByTermPayload(payload) as SearchParams);
98
111
 
99
- const result = this.parsePaginatedResult(remote, payload) as MeilisearchProductSearchResult;
112
+ const result = this.parsePaginatedResult(remote, payload);
100
113
 
101
114
  // mark selected facets as active
102
115
  for (const selectedFacet of payload.search.facets) {
@@ -109,7 +122,7 @@ export class MeilisearchSearchProvider extends ProductSearchProvider {
109
122
  }
110
123
  }
111
124
 
112
- return success(result);
125
+ return success(this.factory.parseSearchResult(this.context, result, payload));
113
126
  }
114
127
 
115
128
  public override async createCategoryNavigationFilter(payload: ProductSearchQueryCreateNavigationFilter): Promise<Result<FacetValueIdentifier>> {
@@ -136,7 +149,10 @@ export class MeilisearchSearchProvider extends ProductSearchProvider {
136
149
  return product;
137
150
  }
138
151
 
139
- protected override parseVariant(variant: MeilisearchNativeVariant, product: MeilisearchNativeRecord): ProductSearchResultItemVariant {
152
+ protected parseVariant(
153
+ variant: MeilisearchNativeVariant,
154
+ product: MeilisearchNativeRecord,
155
+ ): ProductSearchResultItemVariant {
140
156
  const result = ProductSearchResultItemVariantSchema.parse({
141
157
  variant: {
142
158
  sku: variant.sku