@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,22 +1,20 @@
1
1
  import type { z } from 'zod';
2
2
  import { BaseQuerySchema } from './base.query.js';
3
3
  import { CheckoutIdentifierSchema } from '../models/identifiers.model.js';
4
+ import type { InferType } from '../../zod-utils.js';
4
5
 
5
6
  export const CheckoutQueryByIdSchema = BaseQuerySchema.extend({
6
- identifier: CheckoutIdentifierSchema.required()
7
+ identifier: CheckoutIdentifierSchema
7
8
  });
8
9
 
9
-
10
10
  export const CheckoutQueryForAvailableShippingMethodsSchema = BaseQuerySchema.extend({
11
- checkout: CheckoutIdentifierSchema.required()
11
+ checkout: CheckoutIdentifierSchema
12
12
  });
13
13
 
14
14
  export const CheckoutQueryForAvailablePaymentMethodsSchema = BaseQuerySchema.extend({
15
- checkout: CheckoutIdentifierSchema.required()
15
+ checkout: CheckoutIdentifierSchema
16
16
  });
17
17
 
18
-
19
-
20
- export type CheckoutQueryForAvailableShippingMethods = z.infer<typeof CheckoutQueryForAvailableShippingMethodsSchema>;
21
- export type CheckoutQueryForAvailablePaymentMethods = z.infer<typeof CheckoutQueryForAvailablePaymentMethodsSchema>;
22
- export type CheckoutQueryById = z.infer<typeof CheckoutQueryByIdSchema>;
18
+ export type CheckoutQueryForAvailableShippingMethods = InferType<typeof CheckoutQueryForAvailableShippingMethodsSchema>;
19
+ export type CheckoutQueryForAvailablePaymentMethods = InferType<typeof CheckoutQueryForAvailablePaymentMethodsSchema>;
20
+ export type CheckoutQueryById = InferType<typeof CheckoutQueryByIdSchema>;
@@ -1,8 +1,9 @@
1
1
  import type { z } from 'zod';
2
2
  import { BaseQuerySchema } from './base.query.js';
3
+ import type { InferType } from '../../zod-utils.js';
3
4
 
4
5
  export const IdentityQuerySelfSchema = BaseQuerySchema.extend({
5
6
 
6
7
  });
7
8
 
8
- export type IdentityQuerySelf = z.infer<typeof IdentityQuerySelfSchema>;
9
+ export type IdentityQuerySelf = InferType<typeof IdentityQuerySelfSchema>;
@@ -7,7 +7,8 @@ export * from './inventory.query.js';
7
7
  export * from './price.query.js';
8
8
  export * from './product.query.js';
9
9
  export * from './profile.query.js';
10
- export * from './search.query.js';
10
+ export * from './product-search.query.js';
11
11
  export * from './store.query.js';
12
12
  export * from './order.query.js';
13
13
  export * from './checkout.query.js';
14
+ export * from './order-search.query.js'
@@ -1,11 +1,11 @@
1
1
  import type { z } from 'zod';
2
2
  import { BaseQuerySchema } from './base.query.js';
3
- import { FulfillmentCenterIdentifierSchema, ProductIdentifierSchema } from '../models/identifiers.model.js';
3
+ import { FulfillmentCenterIdentifierSchema, ProductVariantIdentifierSchema } from '../models/identifiers.model.js';
4
+ import type { InferType } from '../../zod-utils.js';
4
5
 
5
6
  export const InventoryQueryBySKUSchema = BaseQuerySchema.extend({
6
- sku: ProductIdentifierSchema.default(() => ProductIdentifierSchema.parse({})).nonoptional(),
7
- fulfilmentCenter: FulfillmentCenterIdentifierSchema.default(() => FulfillmentCenterIdentifierSchema.parse({})).nonoptional()
7
+ variant: ProductVariantIdentifierSchema.describe('The unique identifier for the product variant (SKU).'),
8
+ fulfilmentCenter: FulfillmentCenterIdentifierSchema
8
9
  });
9
10
 
10
- //export type InventoryQuery = z.infer<typeof InventoryQuerySchema>;
11
- export type InventoryQueryBySKU = z.infer<typeof InventoryQueryBySKUSchema>;
11
+ export type InventoryQueryBySKU = InferType<typeof InventoryQueryBySKUSchema>;
@@ -0,0 +1,10 @@
1
+ import type { InferType } from "../../zod-utils.js";
2
+ import { OrderSearchIdentifierSchema } from "../models/identifiers.model.js";
3
+ import { BaseQuerySchema } from "./base.query.js";
4
+
5
+ export const OrderSearchQueryByTermSchema = BaseQuerySchema.extend({
6
+ search: OrderSearchIdentifierSchema
7
+ });
8
+
9
+
10
+ export type OrderSearchQueryByTerm = InferType<typeof OrderSearchQueryByTermSchema>;
@@ -1,9 +1,10 @@
1
1
  import type { z } from 'zod';
2
2
  import { BaseQuerySchema } from './base.query.js';
3
3
  import { OrderIdentifierSchema } from '../models/identifiers.model.js';
4
+ import type { InferType } from '../../zod-utils.js';
4
5
 
5
6
  export const OrderQueryByIdSchema = BaseQuerySchema.extend({
6
- order: OrderIdentifierSchema.required()
7
+ order: OrderIdentifierSchema
7
8
  });
8
9
 
9
- export type OrderQueryById = z.infer<typeof OrderQueryByIdSchema>;
10
+ export type OrderQueryById = InferType<typeof OrderQueryByIdSchema>;
@@ -1,9 +1,15 @@
1
1
  import type { z } from 'zod';
2
2
  import { BaseQuerySchema } from './base.query.js';
3
- import { SKUIdentifierSchema } from '../models/identifiers.model.js';
3
+ import { ProductVariantIdentifierSchema } from '../models/identifiers.model.js';
4
+ import type { InferType } from '../../zod-utils.js';
4
5
 
5
- export const PriceQueryBySkuSchema = BaseQuerySchema.extend({
6
- sku: SKUIdentifierSchema.required(),
6
+ export const ListPriceQuerySchema = BaseQuerySchema.extend({
7
+ variant: ProductVariantIdentifierSchema
7
8
  });
8
9
 
9
- export type PriceQueryBySku = z.infer<typeof PriceQueryBySkuSchema>;
10
+ export const CustomerPriceQuerySchema = BaseQuerySchema.extend({
11
+ variant: ProductVariantIdentifierSchema
12
+ });
13
+
14
+ export type ListPriceQuery = InferType<typeof ListPriceQuerySchema>;
15
+ export type CustomerPriceQuery = InferType<typeof CustomerPriceQuerySchema>;
@@ -0,0 +1,16 @@
1
+ import { z } from 'zod';
2
+ import type { InferType } from '../../zod-utils.js';
3
+ import { CategorySchema } from '../models/category.model.js';
4
+ import { ProductSearchIdentifierSchema } from '../models/identifiers.model.js';
5
+ import { BaseQuerySchema } from './base.query.js';
6
+
7
+ export const ProductSearchQueryByTermSchema = BaseQuerySchema.extend({
8
+ search: ProductSearchIdentifierSchema
9
+ });
10
+
11
+ export const ProductSearchQueryCreateNavigationFilterSchema = z.looseObject({
12
+ categoryPath: z.array(CategorySchema).describe('An array representing the breadcrumb path to a category, from root to the specific category.')
13
+ }).describe('Payload to create a category navigation filter from a breadcrumb path.');
14
+
15
+ export type ProductSearchQueryByTerm = InferType<typeof ProductSearchQueryByTermSchema>;
16
+ export type ProductSearchQueryCreateNavigationFilter = InferType<typeof ProductSearchQueryCreateNavigationFilterSchema>;
@@ -1,20 +1,27 @@
1
1
  import { z } from 'zod';
2
2
  import { BaseQuerySchema } from './base.query.js';
3
- import { SKUIdentifierSchema } from '../models/index.js';
3
+ import { PaginationOptionsSchema, ProductIdentifierSchema, ProductVariantIdentifierSchema } from '../models/index.js';
4
+ import type { InferType } from '../../zod-utils.js';
4
5
 
5
6
  export const ProductQueryBySlugSchema = BaseQuerySchema.extend({
6
7
  slug: z.string()
7
8
  });
8
9
 
9
10
  export const ProductQueryByIdSchema = BaseQuerySchema.extend({
10
- id: z.string()
11
+ identifier: ProductIdentifierSchema
11
12
  });
12
13
 
13
14
  export const ProductQueryBySKUSchema = BaseQuerySchema.extend({
14
- sku: SKUIdentifierSchema.default(() => SKUIdentifierSchema.parse({})),
15
+ variant: ProductVariantIdentifierSchema,
16
+ });
17
+
18
+ export const ProductQueryVariantsSchema = BaseQuerySchema.extend({
19
+ parentId: ProductIdentifierSchema,
20
+ paginationOptions: PaginationOptionsSchema,
15
21
  });
16
22
 
17
23
 
18
- export type ProductQueryBySlug = z.infer<typeof ProductQueryBySlugSchema>;
19
- export type ProductQueryById = z.infer<typeof ProductQueryByIdSchema>;
20
- export type ProductQueryBySKU = z.infer<typeof ProductQueryBySKUSchema>;
24
+ export type ProductQueryBySlug = InferType<typeof ProductQueryBySlugSchema>;
25
+ export type ProductQueryById = InferType<typeof ProductQueryByIdSchema>;
26
+ export type ProductQueryBySKU = InferType<typeof ProductQueryBySKUSchema>;
27
+ export type ProductQueryVariants = InferType<typeof ProductQueryVariantsSchema>;
@@ -1,7 +1,10 @@
1
1
  import type { z } from 'zod';
2
2
  import { BaseQuerySchema } from './base.query.js';
3
+ import type { InferType } from '../../zod-utils.js';
4
+ import { IdentityIdentifierSchema } from '../models/identifiers.model.js';
3
5
 
4
- export const ProfileQuerySelfSchema = BaseQuerySchema.extend({
6
+ export const ProfileQueryByIdSchema = BaseQuerySchema.extend({
7
+ identifier: IdentityIdentifierSchema,
5
8
  });
6
9
 
7
- export type ProfileQuerySelf = z.infer<typeof ProfileQuerySelfSchema>;
10
+ export type ProfileQuerySelf = InferType<typeof ProfileQueryByIdSchema>;
@@ -1,11 +1,12 @@
1
1
  import { z } from 'zod';
2
2
  import { BaseQuerySchema } from './base.query.js';
3
+ import type { InferType } from '../../zod-utils.js';
3
4
 
4
5
  export const StoreQueryByProximitySchema = BaseQuerySchema.extend({
5
- longitude: z.number().default(0),
6
- latitude: z.number().default(0),
7
- distance: z.number().default(0),
8
- limit: z.number().default(10)
6
+ longitude: z.number(),
7
+ latitude: z.number(),
8
+ distance: z.number(),
9
+ limit: z.number(),
9
10
  });
10
11
 
11
- export type StoreQueryByProximity = z.infer<typeof StoreQueryByProximitySchema>;
12
+ export type StoreQueryByProximity = InferType<typeof StoreQueryByProximitySchema>;
@@ -0,0 +1,107 @@
1
+ import { trace } from "@opentelemetry/api";
2
+ import type { GenericError } from "./errors/generic.error.js";
3
+ import type { InvalidInputError } from "./errors/invalid-input.error.js";
4
+ import type { InvalidOutputError } from "./errors/invalid-output.error.js";
5
+
6
+ export type Ok<T> = {
7
+ success: true;
8
+ value: T;
9
+ meta: {
10
+ trace: string;
11
+ cache: {
12
+ hit: boolean,
13
+ key: string
14
+ }
15
+ }
16
+ };
17
+
18
+ export type Fail<E> = {
19
+ success: false;
20
+ error: E | GenericError | InvalidInputError | InvalidOutputError;
21
+ meta: {
22
+ trace: string
23
+ }
24
+ };
25
+
26
+ export type Result<T, E = { type: string }> = Ok<T> | Fail<E>;
27
+
28
+ /**
29
+ * Utility function for asserting and unwrapping the value of a success.
30
+ * It is an assert, so treat it as such (similar to any unwrap, assert or similar function).
31
+ * You are guaranteeing that this will ALWAYS succeed, and can expect a runtime error if
32
+ * that assertion ever fails.
33
+ *
34
+ * This is primarily useful for cases where you KNOW that it shouldn't fail, or where failure
35
+ * has no known mechanism of recovery besides simply crashing.
36
+ */
37
+ export function assertSuccess<T, E = Error>(
38
+ result: Result<T, E>
39
+ ): asserts result is Ok<T> {
40
+ if (!result.success) {
41
+ throw new Error(
42
+ `Expected Result.success = true, but got false. Error: ${result.error}`
43
+ );
44
+ }
45
+ }
46
+
47
+ /**
48
+ * Utility function for asserting an error. This is primarily useful for testing scenarios
49
+ * that trigger errors as part of their validation.
50
+ */
51
+ export function assertError<T, E = Error>(
52
+ result: Result<T, E>
53
+ ): asserts result is Fail<E> {
54
+ if (result.success) {
55
+ throw new Error(`Expected failure but got success: ${result.value}`);
56
+ }
57
+ }
58
+
59
+ /**
60
+ * Utility function for unwrapping a value from a result. Internally this
61
+ * WILL assert success, so the caller needs to guarantee that this will
62
+ * always be a valid operation, or expect a thrown exception.
63
+ */
64
+ export function unwrapValue<T, E = Error>(result: Result<T, E>): T {
65
+ assertSuccess(result);
66
+ return result.value;
67
+ }
68
+
69
+ /**
70
+ * Utility function for unwrapping an error. Primarily useful for testing.
71
+ */
72
+ export function unwrapError<T, E>(
73
+ result: Result<T, E>
74
+ ): Fail<E>['error'] {
75
+ assertError(result);
76
+ return result.error;
77
+ }
78
+
79
+ /**
80
+ * Helper function for wrapping a success as an Ok<T> type
81
+ */
82
+ export function success<T>(value: T): Ok<T> {
83
+ return {
84
+ success: true,
85
+ value,
86
+ meta: {
87
+ trace: trace.getActiveSpan()?.spanContext().traceId || '',
88
+ cache: {
89
+ hit: false,
90
+ key: ''
91
+ }
92
+ }
93
+ }
94
+ }
95
+
96
+ /**
97
+ * Helper function for wrapping an error as a Fail<E> type
98
+ */
99
+ export function error<E>(error: E): Fail<E> {
100
+ return {
101
+ success: false,
102
+ error,
103
+ meta: {
104
+ trace: trace.getActiveSpan()?.spanContext().traceId || '',
105
+ }
106
+ }
107
+ }
@@ -1,5 +1,4 @@
1
1
  import { z } from 'zod';
2
- import { IdentitySchema } from './models/identity.model.js';
3
2
  import { WebStoreIdentifierSchema } from './models/identifiers.model.js';
4
3
  import { CurrencySchema } from './models/currency.model.js';
5
4
 
@@ -11,7 +10,7 @@ export const LanguageContextSchema = z.looseObject( {
11
10
  currencyCode: CurrencySchema.default(() => CurrencySchema.parse({})),
12
11
  })
13
12
 
14
- export const SessionSchema = z.record( z.string(), z.any());
13
+ export const SessionSchema = z.record(z.string(), z.any());
15
14
 
16
15
  export const TaxJurisdictionSchema = z.object( {
17
16
  countryCode: z.string().default('US'),
@@ -21,7 +20,6 @@ export const TaxJurisdictionSchema = z.object( {
21
20
  });
22
21
 
23
22
  export const RequestContextSchema = z.looseObject( {
24
- identity: IdentitySchema.default(() => IdentitySchema.parse({})).describe('Read/Write. The identity of the current user. Caller is responsible for persisting any changes to the identity'),
25
23
  session: SessionSchema.default(() => SessionSchema.parse({})).describe('Read/Write session storage. Caller is responsible for persisting any changes. Providers will prefix own values'),
26
24
 
27
25
  languageContext: LanguageContextSchema.default(() => LanguageContextSchema.parse({})).describe('ReadOnly. The language and locale context for the current request.'),
@@ -34,11 +32,13 @@ export const RequestContextSchema = z.looseObject( {
34
32
  clientIp: z.string().default('').describe('The IP address of the client making the request, if available. Mostly for logging purposes'),
35
33
  userAgent: z.string().default('').describe('The user agent string of the client making the request, if available.'),
36
34
  referrer: z.string().default('').describe('The referrer URL, if available.'),
37
-
38
35
  })
39
36
 
40
37
 
41
38
 
39
+ // Note, for this ONE type (which is effectively a dictionary), we currently don't want
40
+ // to strip [key: string]: unknown, hence the manual zod infer over the helper.
41
+ // Maybe there is a better solution, with a different typing for SessionSchema...
42
42
  export type Session = z.infer<typeof SessionSchema>;
43
43
  export type LanguageContext = z.infer<typeof LanguageContextSchema>;
44
44
  export type RequestContext = z.infer<typeof RequestContextSchema>;
@@ -0,0 +1,249 @@
1
+ import { afterEach, beforeEach, describe, expect, it } from 'vitest';
2
+ import { BaseProvider } from '../providers/base.provider.js';
3
+ import type { RequestContext } from '../schemas/session.schema.js';
4
+ import type { Cache } from '../cache/cache.interface.js';
5
+ import {
6
+ Reactionary,
7
+ type ReactionaryDecoratorOptions,
8
+ } from '../decorators/reactionary.decorator.js';
9
+ import { createInitialRequestContext } from '../initialization.js';
10
+ import { z } from 'zod';
11
+ import { success, MemoryCache, type Result } from '../index.js';
12
+ import { assert } from 'vitest';
13
+ import {
14
+ InMemorySpanExporter,
15
+ SimpleSpanProcessor,
16
+ } from '@opentelemetry/sdk-trace-base';
17
+ import { NodeTracerProvider } from '@opentelemetry/sdk-trace-node';
18
+ import { SpanStatusCode, trace } from '@opentelemetry/api';
19
+ import { hrTimeToMilliseconds } from '@opentelemetry/core';
20
+
21
+ export function createTestableProvider(
22
+ decoratorOptions: Partial<ReactionaryDecoratorOptions>,
23
+ fn?: any
24
+ ) {
25
+ class TestableProvider extends BaseProvider {
26
+ constructor(
27
+ public override cache: Cache,
28
+ public override context: RequestContext
29
+ ) {
30
+ super(cache, context);
31
+ }
32
+
33
+ @Reactionary({
34
+ inputSchema: z.undefined(),
35
+ outputSchema: z.string(),
36
+ ...decoratorOptions,
37
+ })
38
+ public async decoratedFunction(
39
+ ...args: unknown[]
40
+ ): Promise<Result<unknown>> {
41
+ if (fn) {
42
+ return await fn(args);
43
+ }
44
+
45
+ return success('BASE');
46
+ }
47
+
48
+ public override generateCacheKeyForQuery(
49
+ scope: string,
50
+ query: object
51
+ ): string {
52
+ return super.generateCacheKeyForQuery(scope, query);
53
+ }
54
+
55
+ public getResourceName(): string {
56
+ return 'TestableProvider';
57
+ }
58
+ }
59
+
60
+ const cache = new MemoryCache();
61
+ const context = createInitialRequestContext();
62
+
63
+ return new TestableProvider(cache, context);
64
+ }
65
+
66
+ describe('@Reactionary decorator', () => {
67
+ describe('Input validation', () => {
68
+ it('should reject invalid input with a failure', async () => {
69
+ const provider = createTestableProvider({
70
+ cache: false,
71
+ inputSchema: z.string(),
72
+ });
73
+
74
+ const result = await provider.decoratedFunction(42);
75
+
76
+ expect(result.success).toBe(false);
77
+ });
78
+
79
+ it('should allow valid input through with a success', async () => {
80
+ const provider = createTestableProvider({
81
+ cache: false,
82
+ inputSchema: z.string(),
83
+ });
84
+
85
+ const result = await provider.decoratedFunction('42');
86
+
87
+ expect(result.success).toBe(true);
88
+ });
89
+ });
90
+
91
+ describe('Output validation', () => {
92
+ it('should reject invalid output with a failure', async () => {
93
+ const provider = createTestableProvider(
94
+ {
95
+ cache: false,
96
+ outputSchema: z.string(),
97
+ },
98
+ function () {
99
+ return success(42);
100
+ }
101
+ );
102
+
103
+ const result = await provider.decoratedFunction();
104
+
105
+ expect(result.success).toBe(false);
106
+ });
107
+
108
+ it('should allow valid output with a success', async () => {
109
+ const provider = createTestableProvider(
110
+ {
111
+ cache: false,
112
+ outputSchema: z.string(),
113
+ },
114
+ function () {
115
+ return success('42');
116
+ }
117
+ );
118
+
119
+ const result = await provider.decoratedFunction();
120
+
121
+ expect(result.success).toBe(true);
122
+ });
123
+ });
124
+
125
+ describe('Error handling', () => {
126
+ it('will wrap errors thrown by the provider in a GenericError', async () => {
127
+ const provider = createTestableProvider({}, function () {
128
+ throw new Error('42');
129
+ });
130
+
131
+ const result = await provider.decoratedFunction();
132
+
133
+ if (result.success) {
134
+ assert.fail();
135
+ }
136
+
137
+ expect(result.error.type).toBe('Generic');
138
+ });
139
+ });
140
+
141
+ describe('Tracing', () => {
142
+ let exporter: InMemorySpanExporter;
143
+ let provider: NodeTracerProvider;
144
+
145
+ beforeEach(() => {
146
+ exporter = new InMemorySpanExporter();
147
+ provider = new NodeTracerProvider({
148
+ spanProcessors: [new SimpleSpanProcessor(exporter)],
149
+ });
150
+
151
+ provider.register();
152
+ });
153
+
154
+ afterEach(() => {
155
+ exporter.reset();
156
+ trace.disable();
157
+ });
158
+
159
+ it('records a timed span for entering the decorated function', async () => {
160
+ const provider = createTestableProvider({
161
+ cache: false,
162
+ }, async function() {
163
+ await new Promise(resolve => setTimeout(resolve, 200));
164
+
165
+ return "42";
166
+ });
167
+ const result = await provider.decoratedFunction();
168
+ const spans = exporter.getFinishedSpans();
169
+
170
+ expect(spans.length).toBe(1);
171
+
172
+ const span = spans[0];
173
+ const duration = hrTimeToMilliseconds(span.duration);
174
+ const name = span.name;
175
+ const status = span.status;
176
+
177
+ console.log('unset expected: ', status);
178
+
179
+ expect(name).toBe('TestableProvider.decoratedFunction');
180
+ expect(duration).toBeGreaterThanOrEqual(200);
181
+ expect(duration).toBeLessThanOrEqual(300);
182
+ expect(status.code).toBe(SpanStatusCode.UNSET);
183
+ });
184
+
185
+ it('records exceptions as events and marks the span as an error', async () => {
186
+ const provider = createTestableProvider({
187
+ cache: false,
188
+ }, async function() {
189
+ throw new Error('42');
190
+ });
191
+
192
+ const result = await provider.decoratedFunction();
193
+ const spans = exporter.getFinishedSpans();
194
+
195
+ expect(spans.length).toBe(1);
196
+
197
+ const span = spans[0];
198
+ const name = span.name;
199
+ const status = span.status;
200
+
201
+ expect(name).toBe('TestableProvider.decoratedFunction');
202
+ expect(status.code).toBe(SpanStatusCode.ERROR);
203
+ });
204
+ });
205
+
206
+ describe('Caching', () => {
207
+ it('should not cache repeat lookups if the decorator is set to uncached', async () => {
208
+ const provider = createTestableProvider({
209
+ cache: false,
210
+ });
211
+ const result = await provider.decoratedFunction();
212
+
213
+ if (!result.success) {
214
+ assert.fail();
215
+ }
216
+
217
+ expect(result.meta.cache.hit).toBe(false);
218
+
219
+ const secondResult = await provider.decoratedFunction();
220
+
221
+ if (!secondResult.success) {
222
+ assert.fail();
223
+ }
224
+
225
+ expect(secondResult.meta.cache.hit).toBe(false);
226
+ });
227
+
228
+ it('should cache repeat lookups if the decorator is set to cached', async () => {
229
+ const provider = createTestableProvider({
230
+ cache: true,
231
+ });
232
+ const result = await provider.decoratedFunction();
233
+
234
+ if (!result.success) {
235
+ assert.fail();
236
+ }
237
+
238
+ expect(result.meta.cache.hit).toBe(false);
239
+
240
+ const secondResult = await provider.decoratedFunction();
241
+
242
+ if (!secondResult.success) {
243
+ assert.fail();
244
+ }
245
+
246
+ expect(secondResult.meta.cache.hit).toBe(true);
247
+ });
248
+ });
249
+ });
@@ -0,0 +1,19 @@
1
+ import type z from "zod";
2
+
3
+ export type StripIndexSignature<T> =
4
+ T extends (infer U)[] ? StripIndexSignature<U>[] :
5
+ T extends readonly (infer U)[] ? readonly StripIndexSignature<U>[] :
6
+ T extends Set<infer U> ? Set<StripIndexSignature<U>> :
7
+ T extends Map<infer K, infer V> ? Map<StripIndexSignature<K>, StripIndexSignature<V>> :
8
+ T extends Promise<infer U> ? Promise<StripIndexSignature<U>> :
9
+ T extends object ? {
10
+ [K in keyof T as K extends string
11
+ ? string extends K
12
+ ? never
13
+ : K
14
+ : K
15
+ ]: StripIndexSignature<T[K]>
16
+ } :
17
+ T;
18
+
19
+ export type InferType<T extends z.ZodTypeAny> = StripIndexSignature<z.infer<T>>;
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "extends": "../tsconfig.base.json",
3
3
  "compilerOptions": {
4
- "module": "nodenext",
4
+ "module": "NodeNext",
5
5
  "moduleResolution": "nodenext",
6
6
  "forceConsistentCasingInFileNames": true,
7
7
  "strict": true,
@@ -1,28 +1,4 @@
1
1
  {
2
- "extends": "./tsconfig.json",
3
- "compilerOptions": {
4
- "outDir": "../dist/out-tsc",
5
- "types": [
6
- "vitest/globals",
7
- "vitest/importMeta",
8
- "vite/client",
9
- "node",
10
- "vitest"
11
- ]
12
- },
13
- "include": [
14
- "vite.config.ts",
15
- "vite.config.mts",
16
- "vitest.config.ts",
17
- "vitest.config.mts",
18
- "src/**/*.test.ts",
19
- "src/**/*.spec.ts",
20
- "src/**/*.test.tsx",
21
- "src/**/*.spec.tsx",
22
- "src/**/*.test.js",
23
- "src/**/*.spec.js",
24
- "src/**/*.test.jsx",
25
- "src/**/*.spec.jsx",
26
- "src/**/*.d.ts"
27
- ]
2
+ "extends": "./tsconfig.lib.json",
3
+ "exclude": []
28
4
  }
@@ -0,0 +1,14 @@
1
+ import { defineConfig, defineProject } from 'vitest/config';
2
+ import tsconfigPaths from 'vite-tsconfig-paths';
3
+ import { resolve } from 'path';
4
+ import { nxViteTsPaths } from '@nx/vite/plugins/nx-tsconfig-paths.plugin';
5
+
6
+ export default defineProject({
7
+ plugins: [nxViteTsPaths()],
8
+ test: {
9
+ root: resolve(__dirname),
10
+ globals: true,
11
+ environment: 'node',
12
+ include: ['src/**/*.spec.ts', 'src/**/*.test.ts']
13
+ },
14
+ });