@reactionary/source 0.0.52 → 0.2.16

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 (293) hide show
  1. package/.env-template +19 -0
  2. package/.github/workflows/pull-request.yml +3 -1
  3. package/.github/workflows/release.yml +9 -0
  4. package/.vscode/extensions.json +0 -2
  5. package/LICENSE +21 -0
  6. package/README.md +175 -23
  7. package/core/package.json +6 -3
  8. package/core/src/cache/cache.interface.ts +1 -0
  9. package/core/src/cache/index.ts +4 -0
  10. package/core/src/cache/memory-cache.ts +30 -2
  11. package/core/src/cache/noop-cache.ts +15 -1
  12. package/core/src/cache/redis-cache.ts +20 -0
  13. package/core/src/client/client-builder.ts +71 -54
  14. package/core/src/client/client.ts +9 -47
  15. package/core/src/client/index.ts +2 -0
  16. package/core/src/decorators/index.ts +1 -0
  17. package/core/src/decorators/reactionary.decorator.ts +203 -34
  18. package/core/src/index.ts +6 -19
  19. package/core/src/initialization.ts +1 -18
  20. package/core/src/metrics/metrics.ts +67 -0
  21. package/core/src/providers/analytics.provider.ts +1 -6
  22. package/core/src/providers/base.provider.ts +5 -69
  23. package/core/src/providers/cart.provider.ts +15 -55
  24. package/core/src/providers/category.provider.ts +7 -11
  25. package/core/src/providers/checkout.provider.ts +17 -15
  26. package/core/src/providers/identity.provider.ts +6 -8
  27. package/core/src/providers/index.ts +2 -1
  28. package/core/src/providers/inventory.provider.ts +15 -5
  29. package/core/src/providers/order-search.provider.ts +29 -0
  30. package/core/src/providers/order.provider.ts +47 -15
  31. package/core/src/providers/price.provider.ts +30 -36
  32. package/core/src/providers/product-search.provider.ts +61 -0
  33. package/core/src/providers/product.provider.ts +71 -12
  34. package/core/src/providers/profile.provider.ts +74 -14
  35. package/core/src/providers/store.provider.ts +3 -5
  36. package/core/src/schemas/capabilities.schema.ts +10 -3
  37. package/core/src/schemas/errors/generic.error.ts +9 -0
  38. package/core/src/schemas/errors/index.ts +4 -0
  39. package/core/src/schemas/errors/invalid-input.error.ts +9 -0
  40. package/core/src/schemas/errors/invalid-output.error.ts +9 -0
  41. package/core/src/schemas/errors/not-found.error.ts +9 -0
  42. package/core/src/schemas/index.ts +7 -0
  43. package/core/src/schemas/models/analytics.model.ts +2 -1
  44. package/core/src/schemas/models/base.model.ts +6 -24
  45. package/core/src/schemas/models/cart.model.ts +5 -8
  46. package/core/src/schemas/models/category.model.ts +4 -9
  47. package/core/src/schemas/models/checkout.model.ts +6 -7
  48. package/core/src/schemas/models/cost.model.ts +4 -3
  49. package/core/src/schemas/models/currency.model.ts +2 -1
  50. package/core/src/schemas/models/identifiers.model.ts +106 -62
  51. package/core/src/schemas/models/identity.model.ts +10 -19
  52. package/core/src/schemas/models/index.ts +2 -1
  53. package/core/src/schemas/models/inventory.model.ts +8 -5
  54. package/core/src/schemas/models/order-search.model.ts +28 -0
  55. package/core/src/schemas/models/order.model.ts +20 -26
  56. package/core/src/schemas/models/payment.model.ts +14 -17
  57. package/core/src/schemas/models/price.model.ts +11 -11
  58. package/core/src/schemas/models/product-search.model.ts +42 -0
  59. package/core/src/schemas/models/product.model.ts +64 -22
  60. package/core/src/schemas/models/profile.model.ts +19 -22
  61. package/core/src/schemas/models/shipping-method.model.ts +24 -29
  62. package/core/src/schemas/models/store.model.ts +9 -5
  63. package/core/src/schemas/mutations/analytics.mutation.ts +8 -7
  64. package/core/src/schemas/mutations/base.mutation.ts +2 -1
  65. package/core/src/schemas/mutations/cart.mutation.ts +33 -33
  66. package/core/src/schemas/mutations/checkout.mutation.ts +23 -30
  67. package/core/src/schemas/mutations/identity.mutation.ts +4 -3
  68. package/core/src/schemas/mutations/profile.mutation.ts +38 -3
  69. package/core/src/schemas/queries/base.query.ts +2 -1
  70. package/core/src/schemas/queries/cart.query.ts +3 -3
  71. package/core/src/schemas/queries/category.query.ts +18 -18
  72. package/core/src/schemas/queries/checkout.query.ts +7 -9
  73. package/core/src/schemas/queries/identity.query.ts +2 -1
  74. package/core/src/schemas/queries/index.ts +2 -1
  75. package/core/src/schemas/queries/inventory.query.ts +5 -5
  76. package/core/src/schemas/queries/order-search.query.ts +10 -0
  77. package/core/src/schemas/queries/order.query.ts +3 -2
  78. package/core/src/schemas/queries/price.query.ts +10 -4
  79. package/core/src/schemas/queries/product-search.query.ts +16 -0
  80. package/core/src/schemas/queries/product.query.ts +13 -6
  81. package/core/src/schemas/queries/profile.query.ts +5 -2
  82. package/core/src/schemas/queries/store.query.ts +6 -5
  83. package/core/src/schemas/result.ts +107 -0
  84. package/core/src/schemas/session.schema.ts +4 -4
  85. package/core/src/test/reactionary.decorator.spec.ts +249 -0
  86. package/core/src/zod-utils.ts +19 -0
  87. package/core/tsconfig.json +1 -1
  88. package/core/tsconfig.spec.json +2 -26
  89. package/core/vitest.config.ts +14 -0
  90. package/documentation/1-purpose.md +114 -0
  91. package/documentation/2-getting-started.md +229 -0
  92. package/documentation/3-querying-and-changing-data.md +74 -0
  93. package/documentation/4-product-data.md +107 -0
  94. package/documentation/5-cart-and-checkout.md +211 -0
  95. package/documentation/6-product-search.md +143 -0
  96. package/documentation/7-marketing.md +3 -0
  97. package/eslint.config.mjs +1 -0
  98. package/examples/node/eslint.config.mjs +1 -4
  99. package/examples/node/package.json +10 -3
  100. package/examples/node/project.json +4 -1
  101. package/examples/node/src/basic/basic-node-provider-model-extension.spec.ts +22 -23
  102. package/examples/node/src/basic/basic-node-provider-query-extension.spec.ts +15 -11
  103. package/examples/node/src/basic/basic-node-setup.spec.ts +44 -28
  104. package/examples/node/src/basic/client-creation.spec.ts +53 -0
  105. package/examples/node/src/capabilities/cart.spec.ts +255 -0
  106. package/examples/node/src/capabilities/category.spec.ts +193 -0
  107. package/examples/node/src/capabilities/checkout.spec.ts +341 -0
  108. package/examples/node/src/capabilities/identity.spec.ts +93 -0
  109. package/examples/node/src/capabilities/inventory.spec.ts +66 -0
  110. package/examples/node/src/capabilities/order-search.spec.ts +265 -0
  111. package/examples/node/src/capabilities/order.spec.ts +91 -0
  112. package/examples/node/src/capabilities/price.spec.ts +51 -0
  113. package/examples/node/src/capabilities/product-search.spec.ts +293 -0
  114. package/examples/node/src/capabilities/product.spec.ts +122 -0
  115. package/examples/node/src/capabilities/profile.spec.ts +316 -0
  116. package/examples/node/src/capabilities/store.spec.ts +26 -0
  117. package/examples/node/src/utils.ts +147 -0
  118. package/examples/node/tsconfig.json +9 -12
  119. package/examples/node/tsconfig.lib.json +1 -2
  120. package/examples/node/tsconfig.spec.json +2 -14
  121. package/examples/node/vitest.config.ts +14 -0
  122. package/migrations.json +22 -5
  123. package/nx.json +8 -47
  124. package/package.json +24 -96
  125. package/providers/algolia/README.md +39 -2
  126. package/providers/algolia/package.json +2 -1
  127. package/providers/algolia/src/core/initialize.ts +7 -14
  128. package/providers/algolia/src/index.ts +2 -4
  129. package/providers/algolia/src/providers/index.ts +1 -0
  130. package/providers/algolia/src/providers/product-search.provider.ts +241 -0
  131. package/providers/algolia/src/schema/capabilities.schema.ts +2 -3
  132. package/providers/algolia/src/schema/index.ts +3 -0
  133. package/providers/algolia/src/schema/search.schema.ts +8 -8
  134. package/providers/algolia/tsconfig.json +1 -1
  135. package/providers/algolia/tsconfig.lib.json +1 -1
  136. package/providers/algolia/tsconfig.spec.json +2 -14
  137. package/providers/algolia/vitest.config.ts +14 -0
  138. package/providers/commercetools/README.md +30 -3
  139. package/providers/commercetools/package.json +2 -1
  140. package/providers/commercetools/src/core/client.ts +178 -99
  141. package/providers/commercetools/src/core/initialize.ts +130 -74
  142. package/providers/commercetools/src/core/token-cache.ts +45 -0
  143. package/providers/commercetools/src/index.ts +3 -2
  144. package/providers/commercetools/src/providers/cart.provider.ts +281 -341
  145. package/providers/commercetools/src/providers/category.provider.ts +223 -138
  146. package/providers/commercetools/src/providers/checkout.provider.ts +631 -449
  147. package/providers/commercetools/src/providers/identity.provider.ts +50 -29
  148. package/providers/commercetools/src/providers/index.ts +2 -2
  149. package/providers/commercetools/src/providers/inventory.provider.ts +76 -74
  150. package/providers/commercetools/src/providers/order-search.provider.ts +220 -0
  151. package/providers/commercetools/src/providers/order.provider.ts +96 -61
  152. package/providers/commercetools/src/providers/price.provider.ts +147 -117
  153. package/providers/commercetools/src/providers/product-search.provider.ts +528 -0
  154. package/providers/commercetools/src/providers/product.provider.ts +249 -74
  155. package/providers/commercetools/src/providers/profile.provider.ts +445 -28
  156. package/providers/commercetools/src/providers/store.provider.ts +54 -40
  157. package/providers/commercetools/src/schema/capabilities.schema.ts +3 -1
  158. package/providers/commercetools/src/schema/commercetools.schema.ts +17 -3
  159. package/providers/commercetools/src/schema/configuration.schema.ts +1 -0
  160. package/providers/commercetools/src/schema/session.schema.ts +7 -0
  161. package/providers/commercetools/src/test/caching.spec.ts +82 -0
  162. package/providers/commercetools/src/test/identity.spec.ts +109 -0
  163. package/providers/commercetools/src/test/test-utils.ts +21 -19
  164. package/providers/commercetools/tsconfig.json +1 -1
  165. package/providers/commercetools/tsconfig.lib.json +1 -1
  166. package/providers/commercetools/tsconfig.spec.json +2 -14
  167. package/providers/commercetools/vitest.config.ts +15 -0
  168. package/providers/fake/README.md +20 -4
  169. package/providers/fake/package.json +2 -1
  170. package/providers/fake/src/core/initialize.ts +47 -49
  171. package/providers/fake/src/providers/analytics.provider.ts +5 -7
  172. package/providers/fake/src/providers/cart.provider.ts +163 -92
  173. package/providers/fake/src/providers/category.provider.ts +78 -50
  174. package/providers/fake/src/providers/checkout.provider.ts +254 -0
  175. package/providers/fake/src/providers/identity.provider.ts +57 -65
  176. package/providers/fake/src/providers/index.ts +6 -2
  177. package/providers/fake/src/providers/inventory.provider.ts +40 -36
  178. package/providers/fake/src/providers/order-search.provider.ts +78 -0
  179. package/providers/fake/src/providers/order.provider.ts +106 -0
  180. package/providers/fake/src/providers/price.provider.ts +93 -41
  181. package/providers/fake/src/providers/product-search.provider.ts +206 -0
  182. package/providers/fake/src/providers/product.provider.ts +56 -41
  183. package/providers/fake/src/providers/profile.provider.ts +147 -0
  184. package/providers/fake/src/providers/store.provider.ts +30 -20
  185. package/providers/fake/src/schema/capabilities.schema.ts +5 -1
  186. package/providers/fake/src/test/cart.provider.spec.ts +59 -80
  187. package/providers/fake/src/test/category.provider.spec.ts +145 -87
  188. package/providers/fake/src/test/checkout.provider.spec.ts +222 -0
  189. package/providers/fake/src/test/order-search.provider.spec.ts +50 -0
  190. package/providers/fake/src/test/order.provider.spec.ts +44 -0
  191. package/providers/fake/src/test/price.provider.spec.ts +50 -45
  192. package/providers/fake/src/test/product.provider.spec.ts +15 -7
  193. package/providers/fake/src/test/profile.provider.spec.ts +167 -0
  194. package/providers/fake/tsconfig.json +1 -1
  195. package/providers/fake/tsconfig.lib.json +1 -1
  196. package/providers/fake/tsconfig.spec.json +2 -12
  197. package/providers/fake/vitest.config.ts +14 -0
  198. package/providers/medusa/README.md +30 -0
  199. package/providers/medusa/TESTING.md +98 -0
  200. package/providers/medusa/eslint.config.mjs +19 -0
  201. package/providers/medusa/package.json +22 -0
  202. package/providers/medusa/project.json +34 -0
  203. package/providers/medusa/src/core/client.ts +370 -0
  204. package/providers/medusa/src/core/initialize.ts +78 -0
  205. package/providers/medusa/src/index.ts +13 -0
  206. package/providers/medusa/src/providers/cart.provider.ts +575 -0
  207. package/providers/medusa/src/providers/category.provider.ts +247 -0
  208. package/providers/medusa/src/providers/checkout.provider.ts +636 -0
  209. package/providers/medusa/src/providers/identity.provider.ts +137 -0
  210. package/providers/medusa/src/providers/inventory.provider.ts +173 -0
  211. package/providers/medusa/src/providers/order-search.provider.ts +202 -0
  212. package/providers/medusa/src/providers/order.provider.ts +226 -0
  213. package/providers/medusa/src/providers/price.provider.ts +140 -0
  214. package/providers/medusa/src/providers/product-search.provider.ts +243 -0
  215. package/providers/medusa/src/providers/product.provider.ts +261 -0
  216. package/providers/medusa/src/providers/profile.provider.ts +392 -0
  217. package/providers/medusa/src/schema/capabilities.schema.ts +18 -0
  218. package/providers/medusa/src/schema/configuration.schema.ts +11 -0
  219. package/providers/medusa/src/schema/medusa.schema.ts +31 -0
  220. package/providers/medusa/src/test/cart.provider.spec.ts +240 -0
  221. package/providers/medusa/src/test/category.provider.spec.ts +231 -0
  222. package/providers/medusa/src/test/checkout.spec.ts +349 -0
  223. package/providers/medusa/src/test/identity.provider.spec.ts +122 -0
  224. package/providers/medusa/src/test/inventory.provider.spec.ts +88 -0
  225. package/providers/medusa/src/test/large-cart.provider.spec.ts +103 -0
  226. package/providers/medusa/src/test/price.provider.spec.ts +104 -0
  227. package/providers/medusa/src/test/product.provider.spec.ts +146 -0
  228. package/providers/medusa/src/test/search.provider.spec.ts +203 -0
  229. package/providers/medusa/src/test/test-utils.ts +13 -0
  230. package/providers/medusa/src/utils/medusa-helpers.ts +89 -0
  231. package/providers/medusa/tsconfig.json +21 -0
  232. package/providers/medusa/tsconfig.lib.json +9 -0
  233. package/providers/medusa/tsconfig.spec.json +4 -0
  234. package/providers/medusa/vitest.config.ts +15 -0
  235. package/providers/meilisearch/README.md +48 -0
  236. package/providers/meilisearch/eslint.config.mjs +22 -0
  237. package/providers/meilisearch/package.json +13 -0
  238. package/providers/meilisearch/project.json +34 -0
  239. package/providers/meilisearch/src/core/initialize.ts +21 -0
  240. package/providers/meilisearch/src/index.ts +6 -0
  241. package/providers/meilisearch/src/providers/index.ts +1 -0
  242. package/providers/meilisearch/src/providers/order-search.provider.ts +222 -0
  243. package/providers/meilisearch/src/providers/product-search.provider.ts +251 -0
  244. package/providers/meilisearch/src/schema/capabilities.schema.ts +10 -0
  245. package/providers/meilisearch/src/schema/configuration.schema.ts +11 -0
  246. package/providers/meilisearch/src/schema/index.ts +3 -0
  247. package/providers/meilisearch/src/schema/search.schema.ts +14 -0
  248. package/providers/meilisearch/tsconfig.json +24 -0
  249. package/providers/meilisearch/tsconfig.lib.json +10 -0
  250. package/providers/meilisearch/tsconfig.spec.json +4 -0
  251. package/providers/meilisearch/vitest.config.ts +14 -0
  252. package/providers/posthog/package.json +2 -1
  253. package/providers/posthog/tsconfig.json +1 -1
  254. package/tsconfig.base.json +5 -0
  255. package/vitest.config.ts +10 -0
  256. package/core/src/providers/search.provider.ts +0 -18
  257. package/core/src/schemas/models/search.model.ts +0 -36
  258. package/core/src/schemas/queries/search.query.ts +0 -9
  259. package/examples/next/.swcrc +0 -30
  260. package/examples/next/eslint.config.mjs +0 -21
  261. package/examples/next/index.d.ts +0 -6
  262. package/examples/next/next-env.d.ts +0 -5
  263. package/examples/next/next.config.js +0 -31
  264. package/examples/next/project.json +0 -9
  265. package/examples/next/public/.gitkeep +0 -0
  266. package/examples/next/public/favicon.ico +0 -0
  267. package/examples/next/src/app/global.css +0 -0
  268. package/examples/next/src/app/layout.tsx +0 -18
  269. package/examples/next/src/app/page.module.scss +0 -2
  270. package/examples/next/src/app/page.tsx +0 -47
  271. package/examples/next/src/instrumentation.ts +0 -9
  272. package/examples/next/tsconfig.json +0 -44
  273. package/examples/node/jest.config.ts +0 -10
  274. package/jest.config.ts +0 -6
  275. package/jest.preset.js +0 -3
  276. package/providers/algolia/jest.config.ts +0 -10
  277. package/providers/algolia/src/providers/product.provider.ts +0 -66
  278. package/providers/algolia/src/providers/search.provider.ts +0 -106
  279. package/providers/algolia/src/test/search.provider.spec.ts +0 -91
  280. package/providers/commercetools/jest.config.cjs +0 -10
  281. package/providers/commercetools/src/providers/search.provider.ts +0 -96
  282. package/providers/commercetools/src/test/cart.provider.spec.ts +0 -199
  283. package/providers/commercetools/src/test/category.provider.spec.ts +0 -168
  284. package/providers/commercetools/src/test/checkout.provider.spec.ts +0 -312
  285. package/providers/commercetools/src/test/identity.provider.spec.ts +0 -88
  286. package/providers/commercetools/src/test/inventory.provider.spec.ts +0 -41
  287. package/providers/commercetools/src/test/price.provider.spec.ts +0 -81
  288. package/providers/commercetools/src/test/product.provider.spec.ts +0 -80
  289. package/providers/commercetools/src/test/profile.provider.spec.ts +0 -49
  290. package/providers/commercetools/src/test/search.provider.spec.ts +0 -61
  291. package/providers/commercetools/src/test/store.provider.spec.ts +0 -37
  292. package/providers/fake/jest.config.cjs +0 -10
  293. package/providers/fake/src/providers/search.provider.ts +0 -132
@@ -1,19 +1,78 @@
1
1
  import type { Product } from '../schemas/models/product.model.js';
2
2
  import { BaseProvider } from './base.provider.js';
3
- import type { RequestContext } from '../schemas/session.schema.js';
4
3
  import type { ProductQueryById, ProductQueryBySKU, ProductQueryBySlug } from '../schemas/queries/product.query.js';
4
+ import type { Result } from '../schemas/result.js';
5
+ import type { NotFoundError } from '../schemas/index.js';
6
+
7
+ export abstract class ProductProvider extends BaseProvider {
8
+
9
+
10
+ /**
11
+ * Get a product by its ID.
12
+ * @param payload The query payload containing the product ID.
13
+ * @param reqCtx The request context.
14
+ *
15
+ * Usecase: Not clear. Maybe if you get a reference from marketing? But that would most likely be a partnumber.
16
+ * But what if the marketing system recommends products instead of variants? A product does not have a partnumber, or gtin.
17
+ * Marketing will TYPICALLY recommend products, and in some cases maybe HeroVariants of a product.
18
+ * In that case, you would need to resolve the product to its hero variant first, and then get the SKU from there.
19
+ */
20
+ public abstract getById(payload: ProductQueryById): Promise<Result<Product>>;
21
+
22
+
23
+ /**
24
+ * Get a product by its slug.
25
+ * @param payload The query payload containing the product slug.
26
+ * @param reqCtx The request context.
27
+ *
28
+ * Usecase: You are rendering a product detail page, and you need to fetch the product by its slug.
29
+ */
30
+ public abstract getBySlug(payload: ProductQueryBySlug): Promise<Result<Product, NotFoundError>>;
31
+
32
+
33
+ /**
34
+ * Get a product by its SKU
35
+ * @param payload
36
+ * @param reqCtx
37
+ *
38
+ * Usecase: you want to look up product details for a cart item. Or you have a SKU from an external system (e.g. ERP, PIM, Marketing, OMS/Order History),
39
+ * and you need to fetch the product details for that SKU. You will get the a Product back, with the variant matching the SKU set as heroSku.
40
+ * It might also be used on a quick-order page, or product recommendations from external system.
41
+ */
42
+ public abstract getBySKU(payload: ProductQueryBySKU): Promise<Result<Product>>;
43
+
44
+ protected createEmptyProduct(id: string): Product {
45
+ // FIXME: We can probably get rid of this once we switch to errors as values, as we shouldn't even
46
+ // be materializing an empty product...
47
+ const product = {
48
+ brand: '',
49
+ description: '',
50
+ identifier: {
51
+ key: id
52
+ },
53
+ longDescription: '',
54
+ mainVariant: {
55
+ barcode: '',
56
+ ean: '',
57
+ gtin: '',
58
+ identifier: {
59
+ sku: ''
60
+ },
61
+ images: [],
62
+ name: '',
63
+ options: [],
64
+ upc: ''
65
+ },
66
+ manufacturer: '',
67
+ name: '',
68
+ options: [],
69
+ parentCategories: [],
70
+ published: false,
71
+ sharedAttributes: [],
72
+ slug: '',
73
+ variants: [],
74
+ } satisfies Product;
5
75
 
6
- export abstract class ProductProvider<
7
- T extends Product = Product
8
- > extends BaseProvider<T> {
9
- public abstract getById(payload: ProductQueryById, reqCtx: RequestContext): Promise<T>;
10
- public abstract getBySlug(payload: ProductQueryBySlug, reqCtx: RequestContext): Promise<T | null>;
11
- public abstract getBySKU(payload: ProductQueryBySKU | ProductQueryBySKU[], reqCtx: RequestContext): Promise<T>;
12
-
13
- protected createEmptyProduct(id: string): T {
14
- const product = this.newModel();
15
- product.identifier = { key: id };
16
- product.meta.placeholder = true;
17
76
  return product;
18
77
  }
19
78
 
@@ -1,20 +1,80 @@
1
+ import type { InvalidInputError, NotFoundError } from '../schemas/index.js';
1
2
  import type { Profile } from '../schemas/models/index.js';
2
- import type { ProfileMutationUpdate } from '../schemas/mutations/index.js';
3
- import type { ProfileQuerySelf } from '../schemas/queries/index.js';
4
- import type { RequestContext } from '../schemas/session.schema.js';
3
+ import type { ProfileMutationAddShippingAddress, ProfileMutationMakeShippingAddressDefault, ProfileMutationRemoveShippingAddress, ProfileMutationSetBillingAddress, ProfileMutationUpdate, ProfileMutationUpdateShippingAddress } from '../schemas/mutations/index.js';
4
+ import type { ProfileQuerySelf as ProfileQueryById } from '../schemas/queries/index.js';
5
+ import type { Result } from '../schemas/result.js';
5
6
  import { BaseProvider } from './base.provider.js';
6
7
 
7
- export abstract class ProfileProvider<
8
- T extends Profile = Profile
9
- > extends BaseProvider<T> {
10
- public abstract getSelf(
11
- payload: ProfileQuerySelf,
12
- reqCtx: RequestContext
13
- ): Promise<T>;
14
- public abstract update(
15
- payload: ProfileMutationUpdate,
16
- reqCtx: RequestContext
17
- ): Promise<T>;
8
+ export abstract class ProfileProvider extends BaseProvider {
9
+
10
+ /**
11
+ * Returns the profile of the currently authenticated (registered) user.
12
+ *
13
+ * Usecase: Fetch the profile of the logged-in user for display in header, or account settings.
14
+ * @param payload
15
+ */
16
+ public abstract getById(payload: ProfileQueryById): Promise<Result<Profile, NotFoundError>>;
17
+
18
+ /**
19
+ * Updates the base profile information of the currently authenticated (registered) user.
20
+ *
21
+ * TODO: This should include first/lastname.
22
+ * TODO: In some systems, updating email/phone may require re-verification.
23
+ * TODO: Handle conflicts if email/phone is already in use by another user.
24
+ * TODO: In some systems the email might not be editable.
25
+ *
26
+ * Usecase: Update the user's name, email, or phone number.
27
+ * @param payload
28
+ */
29
+ public abstract update(payload: ProfileMutationUpdate): Promise<Result<Profile, NotFoundError>>;
30
+
31
+ /**
32
+ * Creates a new shipping address for the currently authenticated (registered) user.
33
+ * Does not set it as default automatically.
34
+ *
35
+ * Usecase: User adds a new shipping address in their profile or during checkout. Ideally, any address manipulation
36
+ * done at checkout should be considered local to that session, unless the addressbook is empty.
37
+ * @param payload
38
+ */
39
+ public abstract addShippingAddress(payload: ProfileMutationAddShippingAddress): Promise<Result<Profile, NotFoundError>>;
40
+
41
+ /**
42
+ * Updates an existing shipping address for the currently authenticated (registered) user.
43
+ *
44
+ * Usecase: User edits an existing shipping address in their profile. Ideally, any address manipulation
45
+ * done at checkout should be considered local to that session/order, unless the addressbook is empty.
46
+ * @param payload
47
+ */
48
+ public abstract updateShippingAddress(payload: ProfileMutationUpdateShippingAddress): Promise<Result<Profile, NotFoundError>>;
49
+
50
+ /**
51
+ * Removes an existing shipping address for the currently authenticated (registered) user.
52
+ *
53
+ * If the removed address was the default shipping address, the default shipping address is set to a random other address.
54
+ *
55
+ * Usecase: User deletes a shipping address from their profile.
56
+ * @param payload
57
+ */
58
+ public abstract removeShippingAddress(payload: ProfileMutationRemoveShippingAddress): Promise<Result<Profile, NotFoundError>>;
59
+
60
+ /**
61
+ * Configures an existing shipping address as the default shipping address for the currently authenticated (registered) user.
62
+ *
63
+ * Usecase: User selects a default shipping address in their profile.
64
+ * @param payload
65
+ */
66
+ public abstract makeShippingAddressDefault(payload: ProfileMutationMakeShippingAddressDefault): Promise<Result<Profile, NotFoundError>>;
67
+
68
+ /**
69
+ * Sets the current/active billing address for the currently authenticated (registered) user.
70
+ *
71
+ * Usecase: User sets or updates their billing address in their profile or during checkout.
72
+ *
73
+ * It was a design decision not to support multiple billing addresses. The billing address represents who you are as the commercial
74
+ * entity being billed, and as such it makes sense to have a single authoritative billing address.
75
+ * @param payload
76
+ */
77
+ public abstract setBillingAddress(payload: ProfileMutationSetBillingAddress): Promise<Result<Profile, NotFoundError>>;
18
78
 
19
79
  protected override getResourceName(): string {
20
80
  return 'profile';
@@ -1,12 +1,10 @@
1
1
  import type { Store } from '../schemas/models/store.model.js';
2
2
  import type { StoreQueryByProximity } from '../schemas/queries/index.js';
3
- import type { RequestContext } from '../schemas/session.schema.js';
3
+ import type { Result } from '../schemas/result.js';
4
4
  import { BaseProvider } from './base.provider.js';
5
5
 
6
- export abstract class StoreProvider<
7
- T extends Store = Store
8
- > extends BaseProvider<T> {
9
- public abstract queryByProximity(payload: StoreQueryByProximity, reqCtx: RequestContext): Promise<Array<T>>;
6
+ export abstract class StoreProvider extends BaseProvider {
7
+ public abstract queryByProximity(payload: StoreQueryByProximity): Promise<Result<Array<Store>>>;
10
8
 
11
9
  protected override getResourceName(): string {
12
10
  return 'store';
@@ -1,17 +1,24 @@
1
1
  import { z } from 'zod';
2
+ import type { InferType } from '../zod-utils.js';
3
+ import type { Client } from '../client/client.js';
2
4
 
3
5
  export const CapabilitiesSchema = z.looseObject({
4
6
  product: z.boolean(),
5
- search: z.boolean(),
7
+ productSearch: z.boolean(),
6
8
  analytics: z.boolean(),
7
9
  identity: z.boolean(),
8
10
  cart: z.boolean(),
9
11
  checkout: z.boolean(),
10
12
  order: z.boolean(),
13
+ orderSearch: z.boolean(),
11
14
  inventory: z.boolean(),
12
15
  price: z.boolean(),
13
16
  category: z.boolean(),
14
- store: z.boolean()
17
+ store: z.boolean(),
18
+ profile: z.boolean()
15
19
  });
16
20
 
17
- export type Capabilities = z.infer<typeof CapabilitiesSchema>;
21
+ export type Capabilities = InferType<typeof CapabilitiesSchema>;
22
+ export type ClientFromCapabilities<C extends Partial<Capabilities>> = {
23
+ [K in keyof C & keyof Client as C[K] extends true ? K : never]: Client[K];
24
+ };
@@ -0,0 +1,9 @@
1
+ import { z } from 'zod';
2
+ import type { InferType } from '../../zod-utils.js';
3
+
4
+ export const GenericErrorSchema = z.looseObject({
5
+ type: z.literal('Generic'),
6
+ message: z.string().nonempty()
7
+ });
8
+
9
+ export type GenericError = InferType<typeof GenericErrorSchema>;
@@ -0,0 +1,4 @@
1
+ export * from './generic.error.js';
2
+ export * from './invalid-input.error.js';
3
+ export * from './invalid-output.error.js';
4
+ export * from './not-found.error.js';
@@ -0,0 +1,9 @@
1
+ import { z } from 'zod';
2
+ import type { InferType } from '../../zod-utils.js';
3
+
4
+ export const InvalidInputErrorSchema = z.looseObject({
5
+ type: z.literal('InvalidInput'),
6
+ error: z.ZodError
7
+ });
8
+
9
+ export type InvalidInputError = InferType<typeof InvalidInputErrorSchema>;
@@ -0,0 +1,9 @@
1
+ import { z } from 'zod';
2
+ import type { InferType } from '../../zod-utils.js';
3
+
4
+ export const InvalidOutputErrorSchema = z.looseObject({
5
+ type: z.literal('InvalidOutput'),
6
+ error: z.ZodError
7
+ });
8
+
9
+ export type InvalidOutputError = InferType<typeof InvalidOutputErrorSchema>;
@@ -0,0 +1,9 @@
1
+ import { z } from 'zod';
2
+ import type { InferType } from '../../zod-utils.js';
3
+
4
+ export const NotFoundErrorSchema = z.looseObject({
5
+ type: z.literal('NotFound'),
6
+ identifier: z.unknown()
7
+ });
8
+
9
+ export type NotFoundError = InferType<typeof NotFoundErrorSchema>;
@@ -0,0 +1,7 @@
1
+ export * from './errors/index.js';
2
+ export * from './models/index.js';
3
+ export * from './mutations/index.js';
4
+ export * from './queries/index.js';
5
+ export * from './capabilities.schema.js';
6
+ export * from './session.schema.js';
7
+ export * from './result.js';
@@ -1,7 +1,8 @@
1
1
  import type { z } from 'zod';
2
2
  import { BaseModelSchema } from './base.model.js';
3
+ import type { InferType } from '../../zod-utils.js';
3
4
 
4
5
  export const AnalyticsEventSchema = BaseModelSchema.extend({
5
6
  });
6
7
 
7
- export type AnalyticsEvent = z.infer<typeof AnalyticsEventSchema>;
8
+ export type AnalyticsEvent = InferType<typeof AnalyticsEventSchema>;
@@ -1,31 +1,14 @@
1
1
  import { z } from 'zod';
2
-
3
- export const CacheInformationSchema = z.looseObject({
4
- hit: z.boolean().default(false),
5
- key: z.string().default('')
6
- })
7
-
8
- export const MetaSchema = z.looseObject({
9
- cache: CacheInformationSchema.default(() => CacheInformationSchema.parse({})),
10
- placeholder: z.boolean().default(false).describe('Whether or not the entity exists in a remote system, or is a default placeholder.')
11
- });
2
+ import type { InferType } from '../../zod-utils.js';
12
3
 
13
4
  export const BaseModelSchema = z.looseObject({
14
- meta: MetaSchema.default(() => MetaSchema.parse({}))
15
5
  });
16
6
 
17
- export type CacheInformation = z.infer<typeof CacheInformationSchema>;
18
- export type Meta = z.infer<typeof MetaSchema>;
19
- export type BaseModel = z.infer<typeof BaseModelSchema>;
20
-
21
-
22
7
  export const PaginationOptionsSchema = z.looseObject({
23
8
  pageNumber: z.number().default(1).describe('Current page number, starting from 1'),
24
- pageSize: z.number().default(20).describe('Number of items per page'),
9
+ pageSize: z.number().min(1).max(50).default(20).describe('Number of items per page'),
25
10
  });
26
11
 
27
- export type PaginationOptions = z.infer<typeof PaginationOptionsSchema>;
28
-
29
12
  /**
30
13
  * This seemed like the right way to do it, but we need to be able to pass in the item schema even later than this
31
14
  *
@@ -34,9 +17,8 @@ export function createPaginatedResponseSchema<ItemType extends z.ZodTypeAny>(
34
17
  itemSchema: ItemType,
35
18
  ) {
36
19
  return z.object({
37
- meta: MetaSchema.default(() => MetaSchema.parse({})),
38
20
  pageNumber: z.number().min(1).describe('Current page number, starting from 1'),
39
- pageSize: z.number().min(1).max(50).describe('Number of items per page'),
21
+ pageSize: z.number().min(1).describe('Number of items per page'),
40
22
  totalCount: z.number().min(0).describe('Total number of items available'),
41
23
  totalPages: z.number().min(0).describe('Total number of pages available'),
42
24
  items: z.array(itemSchema),
@@ -55,6 +37,6 @@ export const ImageSchema = z.looseObject({
55
37
  height: z.number().optional().describe('Height of the original image, in pixels, if known'),
56
38
  });
57
39
 
58
- export type Image = z.infer<typeof ImageSchema>;
59
-
60
-
40
+ export type Image = InferType<typeof ImageSchema>;
41
+ export type PaginationOptions = InferType<typeof PaginationOptionsSchema>;
42
+ export type BaseModel = InferType<typeof BaseModelSchema>;
@@ -1,29 +1,26 @@
1
1
  import { z } from 'zod';
2
- import { CartIdentifierSchema, CartItemIdentifierSchema, IdentityIdentifierSchema, ProductIdentifierSchema, SKUIdentifierSchema } from '../models/identifiers.model.js';
2
+ import { CartIdentifierSchema, CartItemIdentifierSchema, IdentityIdentifierSchema, ProductIdentifierSchema, ProductVariantIdentifierSchema } from '../models/identifiers.model.js';
3
3
  import { CostBreakDownSchema, ItemCostBreakdownSchema } from './cost.model.js';
4
4
  import { BaseModelSchema } from './base.model.js';
5
+ import type { InferType } from '../../zod-utils.js';
5
6
 
6
7
  export const CartItemSchema = z.looseObject({
7
8
  identifier: CartItemIdentifierSchema.default(() => CartItemIdentifierSchema.parse({})),
8
9
  product: ProductIdentifierSchema.default(() => ProductIdentifierSchema.parse({})),
9
- sku: SKUIdentifierSchema.default(() => SKUIdentifierSchema.parse({})),
10
+ variant: ProductVariantIdentifierSchema.default(() => ProductVariantIdentifierSchema.parse({})),
10
11
  quantity: z.number().default(0),
11
12
  price: ItemCostBreakdownSchema.default(() => ItemCostBreakdownSchema.parse({})),
12
13
  });
13
14
 
14
15
  export const CartSchema = BaseModelSchema.extend({
15
16
  identifier: CartIdentifierSchema.default(() => CartIdentifierSchema.parse({})),
16
-
17
17
  userId: IdentityIdentifierSchema.default(() => IdentityIdentifierSchema.parse({})),
18
-
19
18
  items: z.array(CartItemSchema).default(() => []),
20
19
  price: CostBreakDownSchema.default(() => CostBreakDownSchema.parse({})),
21
20
  name: z.string().default(''),
22
21
  description: z.string().default(''),
23
-
24
-
25
22
  });
26
23
 
27
24
 
28
- export type CartItem = z.infer<typeof CartItemSchema>;
29
- export type Cart = z.infer<typeof CartSchema>;
25
+ export type CartItem = InferType<typeof CartItemSchema>;
26
+ export type Cart = InferType<typeof CartSchema>;
@@ -1,13 +1,8 @@
1
- // getBySeoSlug
2
- // getBreadcrumbPathToCategory
3
- // getById
4
- // getByExternalId
5
- // getChildCategories
6
-
7
-
8
1
  import { z } from 'zod';
9
2
  import { BaseModelSchema, createPaginatedResponseSchema, ImageSchema } from './base.model.js';
10
3
  import { CategoryIdentifierSchema } from './identifiers.model.js';
4
+ import type { InferType } from '../../zod-utils.js';
5
+
11
6
  export const CategorySchema = BaseModelSchema.extend({
12
7
  identifier: CategoryIdentifierSchema.default(() => CategoryIdentifierSchema.parse({})),
13
8
  name: z.string().default(''),
@@ -17,7 +12,7 @@ export const CategorySchema = BaseModelSchema.extend({
17
12
  parentCategory: CategoryIdentifierSchema.optional(),
18
13
  });
19
14
 
20
- export type Category = z.infer<typeof CategorySchema>;
15
+ export type Category = InferType<typeof CategorySchema>;
21
16
 
22
17
  export const CategoryPaginatedResultSchema = createPaginatedResponseSchema(CategorySchema);
23
- export type CategoryPaginatedResult = z.infer<typeof CategoryPaginatedResultSchema>;
18
+ export type CategoryPaginatedResult = InferType<typeof CategoryPaginatedResultSchema>;
@@ -1,16 +1,15 @@
1
-
2
-
3
1
  import { z } from 'zod';
4
2
  import { BaseModelSchema } from './base.model.js';
5
- import { CartIdentifierSchema, CheckoutIdentifierSchema, CheckoutItemIdentifierSchema, OrderIdentifierSchema, SKUIdentifierSchema } from './identifiers.model.js';
3
+ import { CartIdentifierSchema, CheckoutIdentifierSchema, CheckoutItemIdentifierSchema, OrderIdentifierSchema, ProductVariantIdentifierSchema } from './identifiers.model.js';
6
4
  import { CostBreakDownSchema, ItemCostBreakdownSchema } from './cost.model.js';
7
5
  import { AddressSchema } from './profile.model.js';
8
6
  import { ShippingInstructionSchema } from './shipping-method.model.js';
9
7
  import { PaymentInstructionSchema } from './payment.model.js';
8
+ import type { InferType } from '../../zod-utils.js';
10
9
 
11
10
  export const CheckoutItemSchema = z.looseObject({
12
11
  identifier: CheckoutItemIdentifierSchema.default(() => CheckoutItemIdentifierSchema.parse({})),
13
- sku: SKUIdentifierSchema.default(() => SKUIdentifierSchema.parse({})),
12
+ variant: ProductVariantIdentifierSchema.default(() => ProductVariantIdentifierSchema.parse({})),
14
13
  quantity: z.number().default(0),
15
14
  price: ItemCostBreakdownSchema.default(() => ItemCostBreakdownSchema.parse({})),
16
15
  });
@@ -43,7 +42,7 @@ export const CheckoutSchema = BaseModelSchema.extend({
43
42
  description: z.string().default(''),
44
43
 
45
44
 
46
- billingAddress: AddressSchema.optional(),
45
+ billingAddress: AddressSchema.optional().nullable(),
47
46
 
48
47
  /**
49
48
  * Shipping and billing details can be changed on the checkout, but not items or quantities.
@@ -62,5 +61,5 @@ export const CheckoutSchema = BaseModelSchema.extend({
62
61
 
63
62
 
64
63
 
65
- export type CheckoutItem = z.infer<typeof CheckoutItemSchema>;
66
- export type Checkout = z.infer<typeof CheckoutSchema>;
64
+ export type CheckoutItem = InferType<typeof CheckoutItemSchema>;
65
+ export type Checkout = InferType<typeof CheckoutSchema>;
@@ -1,5 +1,6 @@
1
- import z from "zod";
1
+ import { z } from "zod";
2
2
  import { MonetaryAmountSchema } from "./price.model.js";
3
+ import type { InferType } from '../../zod-utils.js';
3
4
 
4
5
  export const CostBreakDownSchema = z.looseObject({
5
6
  totalTax: MonetaryAmountSchema.default(() => MonetaryAmountSchema.parse({})).describe('The amount of tax paid on the cart. This may include VAT, GST, sales tax, etc.'),
@@ -17,5 +18,5 @@ export const ItemCostBreakdownSchema = z.looseObject({
17
18
  totalDiscount: MonetaryAmountSchema.default(() => MonetaryAmountSchema.parse({})).describe('The total discount applied to all units of the item.'),
18
19
  });
19
20
 
20
- export type CostBreakDown = z.infer<typeof CostBreakDownSchema>;
21
- export type ItemCostBreakdown = z.infer<typeof ItemCostBreakdownSchema>;
21
+ export type CostBreakDown = InferType<typeof CostBreakDownSchema>;
22
+ export type ItemCostBreakdown = InferType<typeof ItemCostBreakdownSchema>;
@@ -1,4 +1,5 @@
1
1
  import { z } from 'zod';
2
+ import type { InferType } from '../../zod-utils.js';
2
3
 
3
4
  export const CurrencySchema = z.enum([
4
5
  'AED',
@@ -184,4 +185,4 @@ export const CurrencySchema = z.enum([
184
185
  'ZWL',
185
186
  ]);
186
187
 
187
- export type Currency = z.infer<typeof CurrencySchema>;
188
+ export type Currency = InferType<typeof CurrencySchema>;