@reactionary/source 0.0.48 → 0.0.51

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 (55) hide show
  1. package/core/src/client/client.ts +2 -2
  2. package/core/src/providers/checkout.provider.ts +156 -0
  3. package/core/src/providers/index.ts +3 -2
  4. package/core/src/providers/order.provider.ts +31 -0
  5. package/core/src/providers/product.provider.ts +2 -2
  6. package/core/src/schemas/capabilities.schema.ts +2 -1
  7. package/core/src/schemas/models/cart.model.ts +1 -20
  8. package/core/src/schemas/models/checkout.model.ts +68 -0
  9. package/core/src/schemas/models/cost.model.ts +21 -0
  10. package/core/src/schemas/models/identifiers.model.ts +23 -2
  11. package/core/src/schemas/models/identity.model.ts +6 -3
  12. package/core/src/schemas/models/index.ts +5 -1
  13. package/core/src/schemas/models/order.model.ts +47 -0
  14. package/core/src/schemas/models/payment.model.ts +3 -10
  15. package/core/src/schemas/models/product.model.ts +6 -3
  16. package/core/src/schemas/models/shipping-method.model.ts +32 -1
  17. package/core/src/schemas/mutations/checkout.mutation.ts +50 -0
  18. package/core/src/schemas/mutations/index.ts +1 -1
  19. package/core/src/schemas/queries/checkout.query.ts +22 -0
  20. package/core/src/schemas/queries/index.ts +3 -2
  21. package/core/src/schemas/queries/order.query.ts +9 -0
  22. package/core/src/schemas/queries/product.query.ts +8 -1
  23. package/otel/src/trace-decorator.ts +8 -8
  24. package/package.json +3 -1
  25. package/providers/algolia/src/providers/product.provider.ts +7 -1
  26. package/providers/commercetools/package.json +1 -0
  27. package/providers/commercetools/src/core/client.ts +62 -31
  28. package/providers/commercetools/src/core/initialize.ts +11 -7
  29. package/providers/commercetools/src/providers/cart.provider.ts +10 -1
  30. package/providers/commercetools/src/providers/checkout.provider.ts +644 -0
  31. package/providers/commercetools/src/providers/identity.provider.ts +6 -6
  32. package/providers/commercetools/src/providers/index.ts +4 -1
  33. package/providers/commercetools/src/providers/order.provider.ts +165 -0
  34. package/providers/commercetools/src/providers/price.provider.ts +1 -1
  35. package/providers/commercetools/src/providers/product.provider.ts +24 -1
  36. package/providers/commercetools/src/schema/capabilities.schema.ts +2 -1
  37. package/providers/commercetools/src/schema/commercetools.schema.ts +7 -5
  38. package/providers/commercetools/src/schema/configuration.schema.ts +2 -0
  39. package/providers/commercetools/src/test/cart.provider.spec.ts +21 -1
  40. package/providers/commercetools/src/test/checkout.provider.spec.ts +312 -0
  41. package/providers/commercetools/src/test/price.provider.spec.ts +1 -1
  42. package/providers/commercetools/src/test/product.provider.spec.ts +19 -2
  43. package/providers/commercetools/src/test/test-utils.ts +14 -0
  44. package/providers/fake/src/providers/category.provider.ts +6 -2
  45. package/providers/fake/src/providers/product.provider.ts +9 -3
  46. package/providers/fake/src/test/product.provider.spec.ts +7 -7
  47. package/trpc/src/server.ts +1 -1
  48. package/trpc/src/transparent-client.spec.ts +4 -5
  49. package/.claude/settings.local.json +0 -28
  50. package/core/src/providers/cart-payment.provider.ts +0 -57
  51. package/core/src/schemas/mutations/cart-payment.mutation.ts +0 -21
  52. package/core/src/schemas/queries/cart-payment.query.ts +0 -12
  53. package/providers/commercetools/src/providers/cart-payment.provider.ts +0 -193
  54. package/providers/commercetools/src/test/cart-payment.provider.spec.ts +0 -145
  55. package/trpc/src/test-utils.ts +0 -31
@@ -8,7 +8,7 @@ import type { InventoryProvider } from "../providers/inventory.provider";
8
8
  import type { Cache } from "../cache/cache.interface";
9
9
  import { RedisCache } from "../cache/redis-cache";
10
10
  import type { CategoryProvider } from "../providers/category.provider";
11
- import type { CartPaymentProvider } from "../providers";
11
+ import type { CheckoutProvider } from "../providers";
12
12
 
13
13
  export interface Client {
14
14
  product: ProductProvider,
@@ -16,7 +16,7 @@ export interface Client {
16
16
  identity: IdentityProvider,
17
17
  cache: Cache,
18
18
  cart: CartProvider,
19
- cartPayment: CartPaymentProvider,
19
+ checkout: CheckoutProvider,
20
20
  analytics: Array<AnalyticsProvider>,
21
21
  price: PriceProvider,
22
22
  inventory: InventoryProvider,
@@ -0,0 +1,156 @@
1
+ import type { Checkout, PaymentMethod, ShippingMethod } from "../schemas/models";
2
+ import type { RequestContext } from "../schemas/session.schema";
3
+ import { BaseProvider } from "./base.provider";
4
+ import type { CheckoutMutationFinalizeCheckout, CheckoutMutationInitiateCheckout, CheckoutMutationSetShippingAddress, CheckoutMutationAddPaymentInstruction, CheckoutMutationRemovePaymentInstruction, CheckoutMutationSetShippingInstruction } from "../schemas/mutations/checkout.mutation";
5
+ import type { CheckoutQueryById, CheckoutQueryForAvailablePaymentMethods, CheckoutQueryForAvailableShippingMethods } from "../schemas/queries";
6
+
7
+ export abstract class CheckoutProvider<
8
+ T extends Checkout = Checkout
9
+ > extends BaseProvider<T> {
10
+
11
+ /**
12
+ * This starts a new checkout session for the given cart. The checkout might duplicate the cart, or just reference it, depending on implementation, but changes to the cart,
13
+ * is not reflected in the checkout, and vice versa. The checkout is a snapshot of the cart at the time of initiation.
14
+ * The checkout will typically copy over addresses from the user profile, if available, or from the anonymous profile in the session.
15
+ *
16
+ * Usecase: User has filled out cart, and is ready to checkout. You call this to create a checkout object, that you can then use to set shipping method, payment method etc.
17
+ * @param cartId The cart you are trying to checkout
18
+ * @param billingAddress the billing/shipping address to start with. This affects available shipping methods, and may be required by some payment providers.
19
+ * @param reqCtx
20
+ */
21
+ public abstract initiateCheckoutForCart(payload: CheckoutMutationInitiateCheckout, reqCtx: RequestContext): Promise<T>;
22
+
23
+
24
+ /**
25
+ * Fetches an existing checkout by its identifier.
26
+ *
27
+ * Usecase: User has navigated to the checkout page, or reloaded on it , or has been redirected back from the payment provider.
28
+ * @param payload
29
+ * @param reqCtx
30
+ */
31
+ public abstract getById(payload: CheckoutQueryById, reqCtx: RequestContext): Promise<T | null>;
32
+
33
+
34
+
35
+ /**
36
+ * Updates the shipping address for the checkout and recalculates the shipping methods and totals.
37
+ *
38
+ * Usecase: User has chosen home delivery and you have allowed them to change the address on the checkout page.
39
+ *
40
+ * NOTE: Unsure this is really needed.
41
+ * @param shippingAddress The updated shipping address. Note: This may also be the billing address, if your store does not differentiate.
42
+ */
43
+ public abstract setShippingAddress(payload: CheckoutMutationSetShippingAddress, reqCtx: RequestContext): Promise<T>;
44
+
45
+ /**
46
+ * Returns all available shipping methods for the given checkout. This will typically depend on the shipping address, and possibly also the items in the checkout.
47
+ *
48
+ * Usecase: User has filled out shipping address, and you need to show available shipping methods.
49
+ *
50
+ * @param checkoutId The checkout you want to get shipping methods for.
51
+ * @param reqCtx
52
+ */
53
+ public abstract getAvailableShippingMethods(payload: CheckoutQueryForAvailableShippingMethods, reqCtx: RequestContext): Promise<ShippingMethod[]>;
54
+
55
+ /**
56
+ * Returns all available payment methods for the given checkout. This will typically depend mostly on the billing address and jurisdiction.
57
+ *
58
+ * Usecase: User has chosen shipping method, and you need to show available payment methods.
59
+ *
60
+ * @param checkoutId The checkout you want to get payment methods for.
61
+ * @param reqCtx
62
+ */
63
+ public abstract getAvailablePaymentMethods(payload: CheckoutQueryForAvailablePaymentMethods, reqCtx: RequestContext): Promise<PaymentMethod[]>;
64
+
65
+
66
+ /**
67
+ * Adds a payment instruction to the checkout. This will typically create a payment intent in the payment provider, and return whatever is needed to continue the payment process, e.g. a client secret for Stripe, or a redirect URL for PayPal.
68
+ *
69
+ * Usecase: User has chosen a payment method, and you need to start the payment process.
70
+ */
71
+ public abstract addPaymentInstruction(payload: CheckoutMutationAddPaymentInstruction, reqCtx: RequestContext): Promise<T>;
72
+
73
+ /**
74
+ * Removes a payment instruction from the checkout. This will typically void the payment intent in the payment provider, and remove the payment instruction from the checkout.
75
+ *
76
+ * Usecase: User has decided to change payment method, or has cancelled the payment process.
77
+ * @param paymentInstructionId
78
+ */
79
+ public abstract removePaymentInstruction(payload: CheckoutMutationRemovePaymentInstruction, reqCtx: RequestContext): Promise<T>;
80
+
81
+
82
+
83
+ /**
84
+ * Sets the shipping method and optional pickup point for the checkout. The pickup point can be a physical store, a locker, or similar.
85
+ * If it is unset, it means home delivery to the shipping address.
86
+ *
87
+ *
88
+ * Usecase: record all the users shipping choices, and any special instructions they may have added.
89
+ *
90
+ * @param shippingMethodId
91
+ * @param pickupPoint
92
+ */
93
+ public abstract setShippingInstruction(payload: CheckoutMutationSetShippingInstruction, reqCtx: RequestContext): Promise<T>;
94
+
95
+ /**
96
+ * Finalizes the checkout process. This typically involves creating an order from the checkout and processing payment.
97
+ *
98
+ * Usecase: User has completed all necessary steps in the checkout process and is ready to place the order.
99
+ *
100
+ * @param payload
101
+ * @param reqCtx
102
+ */
103
+ public abstract finalizeCheckout(payload: CheckoutMutationFinalizeCheckout, reqCtx: RequestContext): Promise<T>;
104
+ }
105
+
106
+
107
+
108
+ /**
109
+ *
110
+ *
111
+ * How would this be used?
112
+ * // navigated to /payment
113
+ *
114
+ * const cart = await cartProvider.getById({id: 'cart-123'}, reqCtx);
115
+ *
116
+ * let address = null;
117
+ * if (reqCtx.identity.isAuthenticated) {
118
+ * const profile = await profileProvider.getByUserId({userId: reqCtx.identity.userId}, reqCtx);
119
+ * address = profile?.addresses?.[0];
120
+ * }
121
+ * if (!address) {
122
+ * address = reqCtx.session.anonymousProfile?.addresses?.[0];
123
+ * }
124
+ *
125
+ * // ok we are ready for checkout...
126
+ * const checkout = await checkoutProvider.initiateCheckoutForCart(cart.identifier, address, reqCtx);
127
+ *
128
+ * const paymentMethods = await paymentProvider.getAvailablePaymentMethods(checkout, reqCtx);
129
+ * const shippingMethods = await shippingProvider.getAvailableShippingMethods(checkout, reqCtx);
130
+ *
131
+ *
132
+ * onShippingSelected = async (shippingMethodId, pickupPoint) => {
133
+ * const checkout = await checkoutProvider.setShippingMethod(checkout.identifier, shippingMethodId, pickupPoint);
134
+ * return checkout;
135
+ * }
136
+ *
137
+ * onPaymentSelected = async (paymentMethodId) => {
138
+ * const checkout = await checkoutProvider.addPaymentInstruction(checkout.identifier, paymentMethodId);
139
+ * return checkout;
140
+ * }
141
+ *
142
+ * if (checkout.paymentInstructions.length === 0) {
143
+ * // show payment method selection
144
+ * return <PaymentMethodSelection methods={paymentMethods} onSelect={onPaymentSelected} />
145
+ *
146
+ * } else {
147
+ * if (checkout.paymentInstructions[0].status !== 'Authorized') {
148
+ * const pi = checkout.paymentInstructions[0];
149
+ * if (pi.provider === 'stripe') {
150
+ * return new StripeForm(pi.protocolData.find(x => x.key === 'clientSecret').value, onPaymentAuthorized);
151
+ * } else if (pi.provider === 'adyen') {
152
+ * return new RedirectTo(pi.protocolData.find(x => x.key === 'punchoutUrl').value);
153
+ * }
154
+ * }
155
+ * })
156
+ */
@@ -1,12 +1,13 @@
1
1
  export * from './analytics.provider';
2
2
  export * from './base.provider';
3
- export * from './cart-payment.provider';
4
3
  export * from './cart.provider';
5
4
  export * from './category.provider';
5
+ export * from './checkout.provider';
6
6
  export * from './identity.provider';
7
7
  export * from './inventory.provider';
8
8
  export * from './price.provider';
9
9
  export * from './product.provider';
10
10
  export * from './profile.provider';
11
11
  export * from './search.provider';
12
- export * from './store.provider';
12
+ export * from './store.provider';
13
+ export * from './order.provider'
@@ -0,0 +1,31 @@
1
+ import { BaseProvider } from "./base.provider";
2
+ import type { RequestContext } from "../schemas/session.schema";
3
+ import type { Order } from "../schemas/models";
4
+ import type { OrderQueryById } from "../schemas/queries";
5
+
6
+ export abstract class OrderProvider<
7
+ T extends Order = Order
8
+ > extends BaseProvider<T> {
9
+
10
+ /**
11
+ * Get order by ID.
12
+ *
13
+ * Usecase: Fetch order after checkout, to check if we are fully paid and can continue to order confirmation page.
14
+ * @param payload
15
+ * @param session
16
+ */
17
+ public abstract getById(payload: OrderQueryById, reqCtx: RequestContext): Promise<T>;
18
+
19
+ protected createEmptyOrder(): T {
20
+ const order = this.newModel();
21
+ order.meta = { placeholder: true, cache: { hit: true, key: 'empty-order' } };
22
+ order.identifier = { key: '' };
23
+ return order;
24
+ }
25
+
26
+ protected override getResourceName(): string {
27
+ return 'order';
28
+ }
29
+ }
30
+
31
+
@@ -1,14 +1,14 @@
1
1
  import type { Product } from '../schemas/models/product.model';
2
2
  import { BaseProvider } from './base.provider';
3
3
  import type { RequestContext } from '../schemas/session.schema';
4
- import type { ProductQueryById, ProductQueryBySlug } from '../schemas/queries/product.query';
4
+ import type { ProductQueryById, ProductQueryBySKU, ProductQueryBySlug } from '../schemas/queries/product.query';
5
5
 
6
6
  export abstract class ProductProvider<
7
7
  T extends Product = Product
8
8
  > extends BaseProvider<T> {
9
9
  public abstract getById(payload: ProductQueryById, reqCtx: RequestContext): Promise<T>;
10
10
  public abstract getBySlug(payload: ProductQueryBySlug, reqCtx: RequestContext): Promise<T | null>;
11
-
11
+ public abstract getBySKU(payload: ProductQueryBySKU | ProductQueryBySKU[], reqCtx: RequestContext): Promise<T>;
12
12
 
13
13
  protected createEmptyProduct(id: string): T {
14
14
  const product = this.newModel();
@@ -6,7 +6,8 @@ export const CapabilitiesSchema = z.looseObject({
6
6
  analytics: z.boolean(),
7
7
  identity: z.boolean(),
8
8
  cart: z.boolean(),
9
- cartPayment: z.boolean(),
9
+ checkout: z.boolean(),
10
+ order: z.boolean(),
10
11
  inventory: z.boolean(),
11
12
  price: z.boolean(),
12
13
  category: z.boolean(),
@@ -4,22 +4,9 @@ import { BaseModelSchema } from './base.model';
4
4
  import { MonetaryAmountSchema } from './price.model';
5
5
  import { AddressSchema } from './profile.model';
6
6
  import { ShippingMethodSchema } from './shipping-method.model';
7
+ import { CostBreakDownSchema, ItemCostBreakdownSchema } from './cost.model';
7
8
 
8
- export const CostBreakDownSchema = z.looseObject({
9
- totalTax: MonetaryAmountSchema.default(() => MonetaryAmountSchema.parse({})).describe('The amount of tax paid on the cart. This may include VAT, GST, sales tax, etc.'),
10
- totalDiscount: MonetaryAmountSchema.default(() => MonetaryAmountSchema.parse({})).describe('The amount of discount applied to the cart.'),
11
- totalSurcharge: MonetaryAmountSchema.default(() => MonetaryAmountSchema.parse({})).describe('The amount of surcharge applied to the cart.'),
12
- totalShipping: MonetaryAmountSchema.default(() => MonetaryAmountSchema.parse({})).describe('The amount of shipping fees for the cart.'),
13
- totalProductPrice: MonetaryAmountSchema.default(() => MonetaryAmountSchema.parse({})).describe('The total price of products in the cart.'),
14
- grandTotal: MonetaryAmountSchema.default(() => MonetaryAmountSchema.parse({})).describe('The total price for the cart including all taxes, discounts, and shipping.'),
15
- });
16
9
 
17
- export const ItemCostBreakdownSchema = z.looseObject({
18
- unitPrice: MonetaryAmountSchema.default(() => MonetaryAmountSchema.parse({})).describe('The price per single unit of the item.'),
19
- unitDiscount: MonetaryAmountSchema.default(() => MonetaryAmountSchema.parse({})).describe('The discount applied per single unit of the item.'),
20
- totalPrice: MonetaryAmountSchema.default(() => MonetaryAmountSchema.parse({})).describe('The total price for all units of the item.'),
21
- totalDiscount: MonetaryAmountSchema.default(() => MonetaryAmountSchema.parse({})).describe('The total discount applied to all units of the item.'),
22
- });
23
10
 
24
11
 
25
12
  export const CartItemSchema = z.looseObject({
@@ -41,14 +28,8 @@ export const CartSchema = BaseModelSchema.extend({
41
28
  description: z.string().default(''),
42
29
 
43
30
 
44
- shippingAddress: AddressSchema.optional(),
45
- billingAddress: AddressSchema.optional(),
46
- shippingMethod: ShippingMethodSchema.optional(),
47
31
  });
48
32
 
49
33
 
50
-
51
- export type CostBreakDown = z.infer<typeof CostBreakDownSchema>;
52
- export type ItemCostBreakdown = z.infer<typeof ItemCostBreakdownSchema>;
53
34
  export type CartItem = z.infer<typeof CartItemSchema>;
54
35
  export type Cart = z.infer<typeof CartSchema>;
@@ -0,0 +1,68 @@
1
+
2
+
3
+ import { z } from 'zod';
4
+ import { BaseModelSchema, ImageSchema } from './base.model';
5
+ import { CartIdentifierSchema, CheckoutIdentifierSchema, CheckoutItemIdentifierSchema, FulfillmentCenterIdentifierSchema, OrderIdentifierSchema, ProductIdentifierSchema, SKUIdentifierSchema } from './identifiers.model';
6
+ import { CostBreakDownSchema, ItemCostBreakdownSchema } from './cost.model';
7
+ import { AddressSchema } from './profile.model';
8
+ import { ShippingInstructionSchema, ShippingMethodSchema } from './shipping-method.model';
9
+ import { PaymentInstructionSchema } from './payment.model';
10
+
11
+
12
+
13
+ export const CheckoutItemSchema = z.looseObject({
14
+ identifier: CheckoutItemIdentifierSchema.default(() => CheckoutItemIdentifierSchema.parse({})),
15
+ sku: SKUIdentifierSchema.default(() => SKUIdentifierSchema.parse({})),
16
+ quantity: z.number().default(0),
17
+ price: ItemCostBreakdownSchema.default(() => ItemCostBreakdownSchema.parse({})),
18
+ });
19
+
20
+
21
+ /**
22
+ * A checkout represents the data entity that is used to create an order.
23
+ * The checkout is "stable", meaning you cannot change items or quantities on it. Only shipping, billing, and payment details.
24
+ *
25
+ * This means, a cart is never checked out. Rather you provide the cart and other fixed info to the checkout, and from there you get
26
+ * payments and shipping methods.
27
+ */
28
+ export const CheckoutSchema = BaseModelSchema.extend({
29
+ identifier: CheckoutIdentifierSchema.default(() => CheckoutIdentifierSchema.parse({})),
30
+
31
+ /**
32
+ * Do we need this?
33
+ */
34
+ originalCartReference: CartIdentifierSchema.default(() => CartIdentifierSchema.parse({})),
35
+
36
+ /**
37
+ * If the checkout has been completed, this will point to the resulting order.
38
+ */
39
+ resultingOrder: OrderIdentifierSchema.optional(),
40
+
41
+ items: z.array(CheckoutItemSchema).default(() => []),
42
+ price: CostBreakDownSchema.default(() => CostBreakDownSchema.parse({})),
43
+
44
+ name: z.string().default(''),
45
+ description: z.string().default(''),
46
+
47
+
48
+ billingAddress: AddressSchema.optional(),
49
+
50
+ /**
51
+ * Shipping and billing details can be changed on the checkout, but not items or quantities.
52
+ */
53
+ shippingAddress: AddressSchema.optional(),
54
+ shippingInstruction: ShippingInstructionSchema.optional(),
55
+ paymentInstructions: z.array(PaymentInstructionSchema).default(() => []),
56
+
57
+ /**
58
+ * Indicates if the checkout has all the required information to be finalized into an order.
59
+ * This does not mean it will succeed, as there may be issues with payment or shipping, but all required information is present.
60
+ */
61
+ readyForFinalization: z.boolean().default(false).describe('Indicates if the checkout has all the required information to be finalized into an order. This does not mean it will succeed, as there may be issues with payment or shipping, but all required information is present.'),
62
+ });
63
+
64
+
65
+
66
+
67
+ export type CheckoutItem = z.infer<typeof CheckoutItemSchema>;
68
+ export type Checkout = z.infer<typeof CheckoutSchema>;
@@ -0,0 +1,21 @@
1
+ import z from "zod";
2
+ import { MonetaryAmountSchema } from "./price.model";
3
+
4
+ export const CostBreakDownSchema = z.looseObject({
5
+ totalTax: MonetaryAmountSchema.default(() => MonetaryAmountSchema.parse({})).describe('The amount of tax paid on the cart. This may include VAT, GST, sales tax, etc.'),
6
+ totalDiscount: MonetaryAmountSchema.default(() => MonetaryAmountSchema.parse({})).describe('The amount of discount applied to the cart.'),
7
+ totalSurcharge: MonetaryAmountSchema.default(() => MonetaryAmountSchema.parse({})).describe('The amount of surcharge applied to the cart.'),
8
+ totalShipping: MonetaryAmountSchema.default(() => MonetaryAmountSchema.parse({})).describe('The amount of shipping fees for the cart.'),
9
+ totalProductPrice: MonetaryAmountSchema.default(() => MonetaryAmountSchema.parse({})).describe('The total price of products in the cart.'),
10
+ grandTotal: MonetaryAmountSchema.default(() => MonetaryAmountSchema.parse({})).describe('The total price for the cart including all taxes, discounts, and shipping.'),
11
+ });
12
+
13
+ export const ItemCostBreakdownSchema = z.looseObject({
14
+ unitPrice: MonetaryAmountSchema.default(() => MonetaryAmountSchema.parse({})).describe('The price per single unit of the item.'),
15
+ unitDiscount: MonetaryAmountSchema.default(() => MonetaryAmountSchema.parse({})).describe('The discount applied per single unit of the item.'),
16
+ totalPrice: MonetaryAmountSchema.default(() => MonetaryAmountSchema.parse({})).describe('The total price for all units of the item.'),
17
+ totalDiscount: MonetaryAmountSchema.default(() => MonetaryAmountSchema.parse({})).describe('The total discount applied to all units of the item.'),
18
+ });
19
+
20
+ export type CostBreakDown = z.infer<typeof CostBreakDownSchema>;
21
+ export type ItemCostBreakdown = z.infer<typeof ItemCostBreakdownSchema>;
@@ -52,6 +52,15 @@ export const OrderItemIdentifierSchema = z.looseObject({
52
52
  key: z.string().default('').nonoptional(),
53
53
  });
54
54
 
55
+
56
+ export const CheckoutIdentifierSchema = z.looseObject({
57
+ key: z.string().default('').nonoptional()
58
+ });
59
+
60
+ export const CheckoutItemIdentifierSchema = z.looseObject({
61
+ key: z.string().default('').nonoptional()
62
+ });
63
+
55
64
  /**
56
65
  * The target store the user is interacting with. Can change over time, and is not necessarily the same as the default store.
57
66
  */
@@ -75,7 +84,7 @@ export const IdentityIdentifierSchema = z.looseObject({
75
84
  });
76
85
 
77
86
  export const ShippingMethodIdentifierSchema = z.looseObject({
78
- key: z.string().default('').nonoptional(),
87
+ key: z.string().default('').nonoptional(),
79
88
  });
80
89
 
81
90
  export const PaymentMethodIdentifierSchema = z.looseObject({
@@ -92,6 +101,10 @@ export const PaymentInstructionIdentifierSchema = z.looseObject({
92
101
  key: z.string().default('').nonoptional(),
93
102
  });
94
103
 
104
+ export const PickupPointIdentifierSchema = z.looseObject({
105
+ key: z.string().default('').nonoptional()
106
+ });
107
+
95
108
  export type ProductIdentifier = z.infer<typeof ProductIdentifierSchema>;
96
109
  export type SearchIdentifier = z.infer<typeof SearchIdentifierSchema>;
97
110
  export type FacetIdentifier = z.infer<typeof FacetIdentifierSchema>;
@@ -118,6 +131,10 @@ export type PaymentInstructionIdentifier = z.infer<
118
131
  >;
119
132
  export type OrderIdentifier = z.infer<typeof OrderIdentifierSchema>;
120
133
  export type OrderItemIdentifier = z.infer<typeof OrderItemIdentifierSchema>;
134
+
135
+ export type CheckoutIdentifier = z.infer<typeof CheckoutIdentifierSchema>;
136
+ export type CheckoutItemIdentifier = z.infer<typeof CheckoutItemIdentifierSchema>;
137
+ export type PickupPointIdentifier = z.infer<typeof PickupPointIdentifierSchema>;
121
138
  export type StoreIdentifier = z.infer<typeof StoreIdentifierSchema>;
122
139
 
123
140
  export type IdentifierType =
@@ -138,4 +155,8 @@ export type IdentifierType =
138
155
  | AddressIdentifier
139
156
  | PaymentInstructionIdentifier
140
157
  | OrderIdentifier
141
- | OrderItemIdentifier;
158
+ | OrderItemIdentifier
159
+ | CheckoutIdentifier
160
+ | CheckoutItemIdentifier
161
+ | StoreIdentifier
162
+ | PickupPointIdentifier;
@@ -3,12 +3,15 @@ import { BaseModelSchema } from './base.model';
3
3
  import { IdentityIdentifierSchema } from './identifiers.model';
4
4
 
5
5
  export const AnonymousIdentitySchema = BaseModelSchema.extend({
6
- type: z.literal('Anonymous')
6
+ type: z.literal('Anonymous').default('Anonymous'),
7
+ token: z.string().optional(),
8
+ refresh_token: z.string().optional(),
9
+ expiry: z.coerce.date().default(new Date())
7
10
  });
8
11
 
9
12
  export const GuestIdentitySchema = BaseModelSchema.extend({
10
13
  id: IdentityIdentifierSchema.default(() => IdentityIdentifierSchema.parse({})),
11
- type: z.literal('Guest'),
14
+ type: z.literal('Guest').default('Guest'),
12
15
  token: z.string().optional(),
13
16
  refresh_token: z.string().optional(),
14
17
  expiry: z.coerce.date().default(new Date())
@@ -16,7 +19,7 @@ export const GuestIdentitySchema = BaseModelSchema.extend({
16
19
 
17
20
  export const RegisteredIdentitySchema = BaseModelSchema.extend({
18
21
  id: IdentityIdentifierSchema.default(() => IdentityIdentifierSchema.parse({})),
19
- type: z.literal('Registered'),
22
+ type: z.literal('Registered').default('Registered'),
20
23
  logonId: z.string().default(''),
21
24
  token: z.string().optional(),
22
25
  refresh_token: z.string().optional(),
@@ -12,4 +12,8 @@ export * from './product.model';
12
12
  export * from './profile.model';
13
13
  export * from './search.model';
14
14
  export * from './shipping-method.model';
15
- export * from './store.model';
15
+ export * from './store.model';
16
+ export * from './order.model';
17
+ export * from './cost.model';
18
+ export * from './checkout.model';
19
+ export * from './payment.model';
@@ -0,0 +1,47 @@
1
+ import { z } from 'zod';
2
+ import { CartIdentifierSchema, CartItemIdentifierSchema, IdentityIdentifierSchema, PaymentInstructionIdentifierSchema, ProductIdentifierSchema, SKUIdentifierSchema } from '../models/identifiers.model';
3
+ import { BaseModelSchema } from './base.model';
4
+ import { AddressSchema } from './profile.model';
5
+ import { ShippingMethodSchema } from './shipping-method.model';
6
+
7
+ import { CostBreakDownSchema, ItemCostBreakdownSchema } from './cost.model';
8
+ import { PaymentInstructionSchema } from './payment.model';
9
+
10
+ export const OrderStatusSchema = z.enum(['AwaitingPayment', 'ReleasedToFulfillment', 'Shipped', 'Cancelled']).default('AwaitingPayment').describe('The current status of the order.');
11
+ export const OrderInventoryStatusSchema = z.enum(['NotAllocated', 'Allocated', 'Backordered', 'Preordered']).default('Allocated').describe('The inventory release status of the order.');
12
+
13
+
14
+ export const OrderItemSchema = z.looseObject({
15
+ identifier: CartItemIdentifierSchema.default(() => CartItemIdentifierSchema.parse({})),
16
+ sku: SKUIdentifierSchema.default(() => SKUIdentifierSchema.parse({})),
17
+ quantity: z.number().default(0),
18
+ price: ItemCostBreakdownSchema.default(() => ItemCostBreakdownSchema.parse({})),
19
+
20
+ inventoryStatus: OrderInventoryStatusSchema.default('Allocated').describe('The inventory release status of the order item.'),
21
+ });
22
+
23
+ export const OrderSchema = BaseModelSchema.extend({
24
+ identifier: CartIdentifierSchema.default(() => CartIdentifierSchema.parse({})),
25
+
26
+ userId: IdentityIdentifierSchema.default(() => IdentityIdentifierSchema.parse({})),
27
+
28
+ items: z.array(OrderItemSchema).default(() => []),
29
+ price: CostBreakDownSchema.default(() => CostBreakDownSchema.parse({})),
30
+ name: z.string().default(''),
31
+ description: z.string().default(''),
32
+
33
+ shippingAddress: AddressSchema.optional(),
34
+ billingAddress: AddressSchema.optional(),
35
+ shippingMethod: ShippingMethodSchema.optional(),
36
+
37
+ orderStatus: OrderStatusSchema.default('AwaitingPayment'),
38
+ inventoryStatus: OrderInventoryStatusSchema.default('Allocated'),
39
+
40
+ paymentInstructions: z.array(PaymentInstructionSchema).default(() => []),
41
+ cartReference: CartIdentifierSchema.optional().describe('Reference to the cart from which this order was created.'),
42
+ });
43
+
44
+
45
+
46
+ export type OrderItem = z.infer<typeof OrderItemSchema>;
47
+ export type Order = z.infer<typeof OrderSchema>;
@@ -1,8 +1,7 @@
1
1
  import { z } from 'zod';
2
2
  import { BaseModelSchema, ImageSchema } from './base.model';
3
- import { CartIdentifierSchema, InventoryIdentifierSchema, PaymentInstructionIdentifierSchema, PaymentMethodIdentifierSchema } from './identifiers.model';
3
+ import { CartIdentifierSchema, OrderIdentifierSchema, PaymentInstructionIdentifierSchema, PaymentMethodIdentifierSchema } from './identifiers.model';
4
4
  import { MonetaryAmountSchema } from './price.model';
5
- import { describe } from 'node:test';
6
5
 
7
6
  export const PaymentStatusSchema = z.enum(['pending', 'authorized', 'canceled', 'capture', 'partial_capture', 'refunded', 'partial_refund']);
8
7
 
@@ -27,15 +26,9 @@ export const PaymentInstructionSchema = BaseModelSchema.extend({
27
26
  status: PaymentStatusSchema.default('pending'),
28
27
  });
29
28
 
30
- export const CartPaymentInstructionSchema = PaymentInstructionSchema.extend({
31
- cart: CartIdentifierSchema.default(() => CartIdentifierSchema.parse({}))
32
- });
33
29
 
34
- export const OrderPaymentInstructionSchema = PaymentInstructionSchema.extend({
35
- order: z.string().default('') // OrderIdentifierSchema
36
- });
37
30
 
38
- export type CartPaymentInstruction = z.infer<typeof CartPaymentInstructionSchema>;
39
- export type OrderPaymentInstruction = z.infer<typeof OrderPaymentInstructionSchema>;
31
+
40
32
  export type PaymentInstruction = z.infer<typeof PaymentInstructionSchema>;
41
33
  export type PaymentStatus = z.infer<typeof PaymentStatusSchema>;
34
+ export type PaymentMethod = z.infer<typeof PaymentMethodSchema>;
@@ -1,9 +1,12 @@
1
1
  import { z } from 'zod';
2
- import { ProductIdentifierSchema } from './identifiers.model';
3
- import { BaseModelSchema } from './base.model';
2
+ import { ProductIdentifierSchema, SKUIdentifierSchema } from './identifiers.model';
3
+ import { BaseModelSchema, ImageSchema } from './base.model';
4
4
 
5
5
  export const SKUSchema = z.looseObject({
6
- identifier: ProductIdentifierSchema.default(() => ProductIdentifierSchema.parse({})),
6
+ identifier: SKUIdentifierSchema.default(() => SKUIdentifierSchema.parse({})),
7
+ /* name: z.string().default(''),
8
+ slug: z.string().default(''),
9
+ image: ImageSchema.default(() => ImageSchema.parse({})), */
7
10
  });
8
11
 
9
12
  export const ProductAttributeSchema = z.looseObject({
@@ -1,7 +1,25 @@
1
1
  import z from "zod";
2
2
  import { ShippingMethodIdentifierSchema } from "./identifiers.model";
3
3
  import { MonetaryAmountSchema } from "./price.model";
4
- import { ImageSchema } from "./base.model";
4
+ import { BaseModelSchema, ImageSchema } from "./base.model";
5
+ import { AddressSchema } from "./profile.model";
6
+
7
+
8
+
9
+
10
+ export const PickupPointSchema = z.looseObject({
11
+ identifier: z.object({
12
+ key: z.string().default('').nonoptional()
13
+ }).default(() => ({ key: '' })),
14
+ name: z.string().default(''),
15
+ description: z.string().default(''),
16
+ address: AddressSchema.default(() => AddressSchema.parse({})),
17
+ openingHours: z.string().default('').optional().describe('The opening hours of the pickup point, if applicable. This could be a string like "Mon-Fri 9am-5pm".'),
18
+ contactPhone: z.string().default('').optional().describe('The contact phone number for the pickup point, if applicable.'),
19
+ contactEmail: z.string().default('').optional().describe('The contact email for the pickup point, if applicable.'),
20
+ instructions: z.string().default('').optional().describe('Any special instructions for picking up from this point.'),
21
+ });
22
+
5
23
 
6
24
  export const ShippingMethodSchema = z.looseObject({
7
25
  identifier: ShippingMethodIdentifierSchema.default(() => ShippingMethodIdentifierSchema.parse({})),
@@ -10,5 +28,18 @@ export const ShippingMethodSchema = z.looseObject({
10
28
  logo: ImageSchema.optional(),
11
29
  price: MonetaryAmountSchema.default(() => MonetaryAmountSchema.parse({})),
12
30
  deliveryTime: z.string().default(''),
31
+ carrier: z.string().default('').optional(),
32
+ });
33
+
34
+
35
+ export const ShippingInstructionSchema = BaseModelSchema.extend({
36
+ shippingMethod: ShippingMethodIdentifierSchema.default(() => ShippingMethodIdentifierSchema.parse({})),
37
+ pickupPoint: z.string().default('').describe('An optional pickup point for the shipping method. This could be a physical store, a locker, or similar. If not set, it means home delivery to the shipping address.'),
38
+ instructions: z.string().default('').describe('Optional instructions for the shipping. This could be delivery instructions, or similar.'),
39
+ consentForUnattendedDelivery: z.boolean().default(false).describe('Indicates if the customer has given consent for unattended delivery, if applicable.'),
13
40
  });
14
41
 
42
+
43
+ export type ShippingMethod = z.infer<typeof ShippingMethodSchema>;
44
+ export type PickupPoint = z.infer<typeof PickupPointSchema>;
45
+ export type ShippingInstruction = z.infer<typeof ShippingInstructionSchema>;