@replohq/sdk 1.2.1 → 1.2.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/cart/cart-schema.d.ts +4 -0
- package/cart/cart-schema.js +6 -1
- package/cart/cart-schema.js.map +2 -2
- package/cart/cart-types.d.ts +12 -0
- package/cart/cart-types.js.map +1 -1
- package/cart/utils/cart-utils.d.ts +7 -6
- package/cart/utils/cart-utils.js +6 -3
- package/cart/utils/cart-utils.js.map +2 -2
- package/lib/buildMetadata.js +3 -3
- package/package.json +4 -4
package/cart/cart-schema.d.ts
CHANGED
|
@@ -70,5 +70,9 @@ export declare const cartSchema: z.ZodObject<{
|
|
|
70
70
|
code: z.ZodString;
|
|
71
71
|
applicable: z.ZodBoolean;
|
|
72
72
|
}, z.core.$strip>>>;
|
|
73
|
+
discountAllocations: z.ZodOptional<z.ZodArray<z.ZodObject<{
|
|
74
|
+
discountedAmount: z.ZodNumber;
|
|
75
|
+
title: z.ZodNullable<z.ZodString>;
|
|
76
|
+
}, z.core.$strip>>>;
|
|
73
77
|
}, z.core.$strip>;
|
|
74
78
|
export type Cart = z.infer<typeof cartSchema>;
|
package/cart/cart-schema.js
CHANGED
|
@@ -56,12 +56,17 @@ const cartDiscountCodeSchema = z.object({
|
|
|
56
56
|
code: z.string(),
|
|
57
57
|
applicable: z.boolean()
|
|
58
58
|
});
|
|
59
|
+
const cartDiscountAllocationSchema = z.object({
|
|
60
|
+
discountedAmount: amountSchema,
|
|
61
|
+
title: z.string().nullable()
|
|
62
|
+
});
|
|
59
63
|
const cartSchema = z.object({
|
|
60
64
|
id: z.string(),
|
|
61
65
|
lines: z.array(cartLineSchema),
|
|
62
66
|
cost: cartCostSchema,
|
|
63
67
|
checkoutUrl: z.string().optional(),
|
|
64
|
-
discountCodes: z.array(cartDiscountCodeSchema).optional()
|
|
68
|
+
discountCodes: z.array(cartDiscountCodeSchema).optional(),
|
|
69
|
+
discountAllocations: z.array(cartDiscountAllocationSchema).optional()
|
|
65
70
|
});
|
|
66
71
|
export {
|
|
67
72
|
cartSchema
|
package/cart/cart-schema.js.map
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../cart/cart-schema.ts"],
|
|
4
|
-
"sourcesContent": ["import { z } from \"zod\";\n\n// NOTE (Ryan, 2026-07-23, REPL-27611): Self-contained copy of the cart wire\n// schema that the SDK gateway validates on published pages, so nothing\n// shipped to a generated site imports from `schemas`. The backend keeps the\n// canonical copy in `schemas/cart.ts` (its cart services can't depend on\n// the SDK without a cycle); `cart-schema.spec.ts` keeps the two in lockstep.\n// This module is internal wire validation; public types live in `cart/cart-types`.\n\n// ---------------------------------------------------------------------------\n// Cart line attribute\n// ---------------------------------------------------------------------------\n\nconst cartLineAttributeSchema = z.object({\n key: z.string(),\n value: z.union([z.string(), z.number(), z.boolean()]),\n});\n\n// ---------------------------------------------------------------------------\n// Image (cart-scoped; lightweight compared to objectType image)\n// ---------------------------------------------------------------------------\n\nconst cartImageSchema = z.object({\n url: z.string(),\n altText: z.string().nullable(),\n});\n\n// ---------------------------------------------------------------------------\n// Selling plan types\n// ---------------------------------------------------------------------------\n\n// Integer minor units (Stripe convention): 1999 = $19.99 USD. Mirrors\n// amountSchema in schemas/money.ts, which shipped code cannot import.\nconst amountSchema = z.number().int();\nconst amountWithCurrencyCodeSchema = z.object({\n amount: amountSchema,\n currencyCode: z.string(),\n});\n\nconst sellingPlanPriceAdjustmentSchema = z.object({\n compareAtPrice: amountWithCurrencyCodeSchema,\n perDeliveryPrice: amountWithCurrencyCodeSchema,\n price: amountWithCurrencyCodeSchema,\n unitPrice: amountWithCurrencyCodeSchema.nullable(),\n});\n\nconst sellingPlanAllocationSchema = z.object({\n sellingPlan: z.object({\n id: z.string(),\n name: z.string(),\n description: z.string().nullable(),\n }),\n priceAdjustments: z.array(sellingPlanPriceAdjustmentSchema),\n checkoutChargeAmount: amountWithCurrencyCodeSchema,\n remainingBalanceChargeAmount: amountWithCurrencyCodeSchema,\n});\n\n// ---------------------------------------------------------------------------\n// Cart line merchandise\n// ---------------------------------------------------------------------------\n\nconst cartLineMerchandiseSchema = z.object({\n id: z.string(),\n product: z.object({\n id: z.string(),\n title: z.string(),\n }),\n title: z.string(),\n price: amountSchema,\n compareAtPrice: amountSchema.nullish(),\n image: cartImageSchema.nullable(),\n selectedOptions: z.array(z.object({ name: z.string(), value: z.string() })),\n});\n\n// ---------------------------------------------------------------------------\n// Cart line\n// ---------------------------------------------------------------------------\n\nconst cartLineSchema = z.object({\n id: z.string(),\n quantity: z.number(),\n merchandise: cartLineMerchandiseSchema,\n attributes: z.array(cartLineAttributeSchema),\n sellingPlanAllocation: sellingPlanAllocationSchema.nullish(),\n});\n\n// ---------------------------------------------------------------------------\n// Cart cost\n// ---------------------------------------------------------------------------\n\nconst cartCostSchema = z.object({\n subtotalAmount: amountSchema,\n totalAmount: amountSchema,\n currencyCode: z.string(),\n});\n\n// ---------------------------------------------------------------------------\n// Cart discount code\n// ---------------------------------------------------------------------------\n\nconst cartDiscountCodeSchema = z.object({\n code: z.string(),\n applicable: z.boolean(),\n});\n\n// ---------------------------------------------------------------------------\n// Cart (top level)\n// ---------------------------------------------------------------------------\n\nexport const cartSchema = z.object({\n id: z.string(),\n lines: z.array(cartLineSchema),\n cost: cartCostSchema,\n checkoutUrl: z.string().optional(),\n discountCodes: z.array(cartDiscountCodeSchema).optional(),\n});\n\nexport type Cart = z.infer<typeof cartSchema>;\n"],
|
|
5
|
-
"mappings": "AAAA,SAAS,SAAS;AAalB,MAAM,0BAA0B,EAAE,OAAO;AAAA,EACvC,KAAK,EAAE,OAAO;AAAA,EACd,OAAO,EAAE,MAAM,CAAC,EAAE,OAAO,GAAG,EAAE,OAAO,GAAG,EAAE,QAAQ,CAAC,CAAC;AACtD,CAAC;AAMD,MAAM,kBAAkB,EAAE,OAAO;AAAA,EAC/B,KAAK,EAAE,OAAO;AAAA,EACd,SAAS,EAAE,OAAO,EAAE,SAAS;AAC/B,CAAC;AAQD,MAAM,eAAe,EAAE,OAAO,EAAE,IAAI;AACpC,MAAM,+BAA+B,EAAE,OAAO;AAAA,EAC5C,QAAQ;AAAA,EACR,cAAc,EAAE,OAAO;AACzB,CAAC;AAED,MAAM,mCAAmC,EAAE,OAAO;AAAA,EAChD,gBAAgB;AAAA,EAChB,kBAAkB;AAAA,EAClB,OAAO;AAAA,EACP,WAAW,6BAA6B,SAAS;AACnD,CAAC;AAED,MAAM,8BAA8B,EAAE,OAAO;AAAA,EAC3C,aAAa,EAAE,OAAO;AAAA,IACpB,IAAI,EAAE,OAAO;AAAA,IACb,MAAM,EAAE,OAAO;AAAA,IACf,aAAa,EAAE,OAAO,EAAE,SAAS;AAAA,EACnC,CAAC;AAAA,EACD,kBAAkB,EAAE,MAAM,gCAAgC;AAAA,EAC1D,sBAAsB;AAAA,EACtB,8BAA8B;AAChC,CAAC;AAMD,MAAM,4BAA4B,EAAE,OAAO;AAAA,EACzC,IAAI,EAAE,OAAO;AAAA,EACb,SAAS,EAAE,OAAO;AAAA,IAChB,IAAI,EAAE,OAAO;AAAA,IACb,OAAO,EAAE,OAAO;AAAA,EAClB,CAAC;AAAA,EACD,OAAO,EAAE,OAAO;AAAA,EAChB,OAAO;AAAA,EACP,gBAAgB,aAAa,QAAQ;AAAA,EACrC,OAAO,gBAAgB,SAAS;AAAA,EAChC,iBAAiB,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,EAAE,OAAO,GAAG,OAAO,EAAE,OAAO,EAAE,CAAC,CAAC;AAC5E,CAAC;AAMD,MAAM,iBAAiB,EAAE,OAAO;AAAA,EAC9B,IAAI,EAAE,OAAO;AAAA,EACb,UAAU,EAAE,OAAO;AAAA,EACnB,aAAa;AAAA,EACb,YAAY,EAAE,MAAM,uBAAuB;AAAA,EAC3C,uBAAuB,4BAA4B,QAAQ;AAC7D,CAAC;AAMD,MAAM,iBAAiB,EAAE,OAAO;AAAA,EAC9B,gBAAgB;AAAA,EAChB,aAAa;AAAA,EACb,cAAc,EAAE,OAAO;AACzB,CAAC;AAMD,MAAM,yBAAyB,EAAE,OAAO;AAAA,EACtC,MAAM,EAAE,OAAO;AAAA,EACf,YAAY,EAAE,QAAQ;AACxB,CAAC;AAMM,MAAM,aAAa,EAAE,OAAO;AAAA,EACjC,IAAI,EAAE,OAAO;AAAA,EACb,OAAO,EAAE,MAAM,cAAc;AAAA,EAC7B,MAAM;AAAA,EACN,aAAa,EAAE,OAAO,EAAE,SAAS;AAAA,EACjC,eAAe,EAAE,MAAM,sBAAsB,EAAE,SAAS;
|
|
4
|
+
"sourcesContent": ["import { z } from \"zod\";\n\n// NOTE (Ryan, 2026-07-23, REPL-27611): Self-contained copy of the cart wire\n// schema that the SDK gateway validates on published pages, so nothing\n// shipped to a generated site imports from `schemas`. The backend keeps the\n// canonical copy in `schemas/cart.ts` (its cart services can't depend on\n// the SDK without a cycle); `cart-schema.spec.ts` keeps the two in lockstep.\n// This module is internal wire validation; public types live in `cart/cart-types`.\n\n// ---------------------------------------------------------------------------\n// Cart line attribute\n// ---------------------------------------------------------------------------\n\nconst cartLineAttributeSchema = z.object({\n key: z.string(),\n value: z.union([z.string(), z.number(), z.boolean()]),\n});\n\n// ---------------------------------------------------------------------------\n// Image (cart-scoped; lightweight compared to objectType image)\n// ---------------------------------------------------------------------------\n\nconst cartImageSchema = z.object({\n url: z.string(),\n altText: z.string().nullable(),\n});\n\n// ---------------------------------------------------------------------------\n// Selling plan types\n// ---------------------------------------------------------------------------\n\n// Integer minor units (Stripe convention): 1999 = $19.99 USD. Mirrors\n// amountSchema in schemas/money.ts, which shipped code cannot import.\nconst amountSchema = z.number().int();\nconst amountWithCurrencyCodeSchema = z.object({\n amount: amountSchema,\n currencyCode: z.string(),\n});\n\nconst sellingPlanPriceAdjustmentSchema = z.object({\n compareAtPrice: amountWithCurrencyCodeSchema,\n perDeliveryPrice: amountWithCurrencyCodeSchema,\n price: amountWithCurrencyCodeSchema,\n unitPrice: amountWithCurrencyCodeSchema.nullable(),\n});\n\nconst sellingPlanAllocationSchema = z.object({\n sellingPlan: z.object({\n id: z.string(),\n name: z.string(),\n description: z.string().nullable(),\n }),\n priceAdjustments: z.array(sellingPlanPriceAdjustmentSchema),\n checkoutChargeAmount: amountWithCurrencyCodeSchema,\n remainingBalanceChargeAmount: amountWithCurrencyCodeSchema,\n});\n\n// ---------------------------------------------------------------------------\n// Cart line merchandise\n// ---------------------------------------------------------------------------\n\nconst cartLineMerchandiseSchema = z.object({\n id: z.string(),\n product: z.object({\n id: z.string(),\n title: z.string(),\n }),\n title: z.string(),\n price: amountSchema,\n compareAtPrice: amountSchema.nullish(),\n image: cartImageSchema.nullable(),\n selectedOptions: z.array(z.object({ name: z.string(), value: z.string() })),\n});\n\n// ---------------------------------------------------------------------------\n// Cart line\n// ---------------------------------------------------------------------------\n\nconst cartLineSchema = z.object({\n id: z.string(),\n quantity: z.number(),\n merchandise: cartLineMerchandiseSchema,\n attributes: z.array(cartLineAttributeSchema),\n sellingPlanAllocation: sellingPlanAllocationSchema.nullish(),\n});\n\n// ---------------------------------------------------------------------------\n// Cart cost\n// ---------------------------------------------------------------------------\n\nconst cartCostSchema = z.object({\n subtotalAmount: amountSchema,\n totalAmount: amountSchema,\n currencyCode: z.string(),\n});\n\n// ---------------------------------------------------------------------------\n// Cart discount code\n// ---------------------------------------------------------------------------\n\nconst cartDiscountCodeSchema = z.object({\n code: z.string(),\n applicable: z.boolean(),\n});\n\n// ---------------------------------------------------------------------------\n// Cart discount allocation\n// ---------------------------------------------------------------------------\n\nconst cartDiscountAllocationSchema = z.object({\n discountedAmount: amountSchema,\n title: z.string().nullable(),\n});\n\n// ---------------------------------------------------------------------------\n// Cart (top level)\n// ---------------------------------------------------------------------------\n\nexport const cartSchema = z.object({\n id: z.string(),\n lines: z.array(cartLineSchema),\n cost: cartCostSchema,\n checkoutUrl: z.string().optional(),\n discountCodes: z.array(cartDiscountCodeSchema).optional(),\n discountAllocations: z.array(cartDiscountAllocationSchema).optional(),\n});\n\nexport type Cart = z.infer<typeof cartSchema>;\n"],
|
|
5
|
+
"mappings": "AAAA,SAAS,SAAS;AAalB,MAAM,0BAA0B,EAAE,OAAO;AAAA,EACvC,KAAK,EAAE,OAAO;AAAA,EACd,OAAO,EAAE,MAAM,CAAC,EAAE,OAAO,GAAG,EAAE,OAAO,GAAG,EAAE,QAAQ,CAAC,CAAC;AACtD,CAAC;AAMD,MAAM,kBAAkB,EAAE,OAAO;AAAA,EAC/B,KAAK,EAAE,OAAO;AAAA,EACd,SAAS,EAAE,OAAO,EAAE,SAAS;AAC/B,CAAC;AAQD,MAAM,eAAe,EAAE,OAAO,EAAE,IAAI;AACpC,MAAM,+BAA+B,EAAE,OAAO;AAAA,EAC5C,QAAQ;AAAA,EACR,cAAc,EAAE,OAAO;AACzB,CAAC;AAED,MAAM,mCAAmC,EAAE,OAAO;AAAA,EAChD,gBAAgB;AAAA,EAChB,kBAAkB;AAAA,EAClB,OAAO;AAAA,EACP,WAAW,6BAA6B,SAAS;AACnD,CAAC;AAED,MAAM,8BAA8B,EAAE,OAAO;AAAA,EAC3C,aAAa,EAAE,OAAO;AAAA,IACpB,IAAI,EAAE,OAAO;AAAA,IACb,MAAM,EAAE,OAAO;AAAA,IACf,aAAa,EAAE,OAAO,EAAE,SAAS;AAAA,EACnC,CAAC;AAAA,EACD,kBAAkB,EAAE,MAAM,gCAAgC;AAAA,EAC1D,sBAAsB;AAAA,EACtB,8BAA8B;AAChC,CAAC;AAMD,MAAM,4BAA4B,EAAE,OAAO;AAAA,EACzC,IAAI,EAAE,OAAO;AAAA,EACb,SAAS,EAAE,OAAO;AAAA,IAChB,IAAI,EAAE,OAAO;AAAA,IACb,OAAO,EAAE,OAAO;AAAA,EAClB,CAAC;AAAA,EACD,OAAO,EAAE,OAAO;AAAA,EAChB,OAAO;AAAA,EACP,gBAAgB,aAAa,QAAQ;AAAA,EACrC,OAAO,gBAAgB,SAAS;AAAA,EAChC,iBAAiB,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,EAAE,OAAO,GAAG,OAAO,EAAE,OAAO,EAAE,CAAC,CAAC;AAC5E,CAAC;AAMD,MAAM,iBAAiB,EAAE,OAAO;AAAA,EAC9B,IAAI,EAAE,OAAO;AAAA,EACb,UAAU,EAAE,OAAO;AAAA,EACnB,aAAa;AAAA,EACb,YAAY,EAAE,MAAM,uBAAuB;AAAA,EAC3C,uBAAuB,4BAA4B,QAAQ;AAC7D,CAAC;AAMD,MAAM,iBAAiB,EAAE,OAAO;AAAA,EAC9B,gBAAgB;AAAA,EAChB,aAAa;AAAA,EACb,cAAc,EAAE,OAAO;AACzB,CAAC;AAMD,MAAM,yBAAyB,EAAE,OAAO;AAAA,EACtC,MAAM,EAAE,OAAO;AAAA,EACf,YAAY,EAAE,QAAQ;AACxB,CAAC;AAMD,MAAM,+BAA+B,EAAE,OAAO;AAAA,EAC5C,kBAAkB;AAAA,EAClB,OAAO,EAAE,OAAO,EAAE,SAAS;AAC7B,CAAC;AAMM,MAAM,aAAa,EAAE,OAAO;AAAA,EACjC,IAAI,EAAE,OAAO;AAAA,EACb,OAAO,EAAE,MAAM,cAAc;AAAA,EAC7B,MAAM;AAAA,EACN,aAAa,EAAE,OAAO,EAAE,SAAS;AAAA,EACjC,eAAe,EAAE,MAAM,sBAAsB,EAAE,SAAS;AAAA,EACxD,qBAAqB,EAAE,MAAM,4BAA4B,EAAE,SAAS;AACtE,CAAC;",
|
|
6
6
|
"names": []
|
|
7
7
|
}
|
package/cart/cart-types.d.ts
CHANGED
|
@@ -100,12 +100,24 @@ export interface CartDiscountCode {
|
|
|
100
100
|
*/
|
|
101
101
|
applicable: boolean;
|
|
102
102
|
}
|
|
103
|
+
/**
|
|
104
|
+
* One discount Shopify applied to a cart line or to the whole cart. The amount
|
|
105
|
+
* is already subtracted from `cost.totalAmount` (and from `cost.subtotalAmount`
|
|
106
|
+
* for line-level discounts).
|
|
107
|
+
*/
|
|
108
|
+
export interface CartDiscountAllocation {
|
|
109
|
+
/** Integer minor units (Stripe convention) in the cart's currencyCode */
|
|
110
|
+
discountedAmount: number;
|
|
111
|
+
/** Automatic discount title or discount code; null when Shopify has neither */
|
|
112
|
+
title: string | null;
|
|
113
|
+
}
|
|
103
114
|
export interface Cart {
|
|
104
115
|
id: string;
|
|
105
116
|
lines: CartLine[];
|
|
106
117
|
cost: CartCost;
|
|
107
118
|
checkoutUrl?: string;
|
|
108
119
|
discountCodes?: CartDiscountCode[];
|
|
120
|
+
discountAllocations?: CartDiscountAllocation[];
|
|
109
121
|
}
|
|
110
122
|
export interface CartLinePayload {
|
|
111
123
|
id: string;
|
package/cart/cart-types.js.map
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../cart/cart-types.ts"],
|
|
4
|
-
"sourcesContent": ["/**\n * TypeScript types for cart data structures. Use these types when working with cart data, but don't import from this module directly in components - use the cart hooks instead.\n * @module\n */\n\nimport type { SellingPlanGroup } from \"../loaders/loader-schemas\";\n\nexport interface Image {\n url: string;\n altText: string | null;\n}\n\nexport interface CartLineMerchandise {\n id: string;\n product: {\n id: string;\n title: string;\n sellingPlanGroups?: SellingPlanGroup[];\n };\n title: string;\n /** Integer minor units (Stripe convention): 1999 = $19.99 USD */\n price: number;\n compareAtPrice?: number | null;\n image: Image | null;\n selectedOptions: {\n name: string;\n value: string;\n }[];\n}\n\nexport interface CartLineAttribute {\n key: string;\n value: string | number | boolean;\n}\n\n/** Replo attribution property added to cart/buy-now line items for order attribution in Shopify. */\nexport const REPLO_ATTRIBUTION_PROPERTY: CartLineAttribute = {\n key: \"_replo\",\n value: \"true\",\n};\n\nexport interface SellingPlanPriceAdjustment {\n compareAtPrice: {\n amount: number;\n currencyCode: string;\n };\n perDeliveryPrice: {\n amount: number;\n currencyCode: string;\n };\n price: {\n amount: number;\n currencyCode: string;\n };\n unitPrice: {\n amount: number;\n currencyCode: string;\n } | null;\n}\n\nexport interface SellingPlanAllocation {\n sellingPlan: {\n id: string;\n name: string;\n description: string | null;\n };\n priceAdjustments: SellingPlanPriceAdjustment[];\n checkoutChargeAmount: {\n amount: number;\n currencyCode: string;\n };\n remainingBalanceChargeAmount: {\n amount: number;\n currencyCode: string;\n };\n}\n\nexport interface CartLine {\n id: string;\n quantity: number;\n /**\n * Null when this is an optimistic line whose merchandise couldn't be\n * resolved from the query cache or passed explicitly. Consumers should\n * render a skeleton/loading state in that case; the line is replaced\n * with real merchandise once the server roundtrip lands.\n */\n merchandise: CartLineMerchandise | null;\n attributes: CartLineAttribute[];\n sellingPlanAllocation?: SellingPlanAllocation | null;\n}\n\nexport interface CartCost {\n /** Integer minor units (Stripe convention) in currencyCode */\n subtotalAmount: number;\n totalAmount: number;\n currencyCode: string;\n}\n\n/**\n * Represents a discount code applied to a cart.\n */\nexport interface CartDiscountCode {\n /** The discount code string */\n code: string;\n /**\n * Whether the discount code is applicable to the current cart.\n * A code may not be applicable due to:\n * - Cart contents not meeting product/collection eligibility\n * - Minimum purchase amount not met\n * - Code expired or usage limits reached\n * - Customer restrictions\n * - Conflicting discount rules\n */\n applicable: boolean;\n}\n\nexport interface Cart {\n id: string;\n lines: CartLine[];\n cost: CartCost;\n checkoutUrl?: string;\n discountCodes?: CartDiscountCode[];\n}\n\nexport interface CartLinePayload {\n id: string;\n quantity: number;\n merchandise?: CartLineMerchandise;\n properties?: CartLineAttribute[];\n sellingPlanId?: string | null;\n}\n\nexport interface AddToCartPayload {\n lines: CartLinePayload[];\n cartId: string;\n}\n\nexport interface UpdateCartLineItemPayload {\n line: CartLinePayload;\n cartId: string;\n}\n\nexport interface RemoveFromCartPayload {\n lineIds: string[];\n cartId: string;\n}\n\nexport interface UpdateCartDiscountCodesPayload {\n cartId: string;\n discountCodes: string[];\n}\n"],
|
|
4
|
+
"sourcesContent": ["/**\n * TypeScript types for cart data structures. Use these types when working with cart data, but don't import from this module directly in components - use the cart hooks instead.\n * @module\n */\n\nimport type { SellingPlanGroup } from \"../loaders/loader-schemas\";\n\nexport interface Image {\n url: string;\n altText: string | null;\n}\n\nexport interface CartLineMerchandise {\n id: string;\n product: {\n id: string;\n title: string;\n sellingPlanGroups?: SellingPlanGroup[];\n };\n title: string;\n /** Integer minor units (Stripe convention): 1999 = $19.99 USD */\n price: number;\n compareAtPrice?: number | null;\n image: Image | null;\n selectedOptions: {\n name: string;\n value: string;\n }[];\n}\n\nexport interface CartLineAttribute {\n key: string;\n value: string | number | boolean;\n}\n\n/** Replo attribution property added to cart/buy-now line items for order attribution in Shopify. */\nexport const REPLO_ATTRIBUTION_PROPERTY: CartLineAttribute = {\n key: \"_replo\",\n value: \"true\",\n};\n\nexport interface SellingPlanPriceAdjustment {\n compareAtPrice: {\n amount: number;\n currencyCode: string;\n };\n perDeliveryPrice: {\n amount: number;\n currencyCode: string;\n };\n price: {\n amount: number;\n currencyCode: string;\n };\n unitPrice: {\n amount: number;\n currencyCode: string;\n } | null;\n}\n\nexport interface SellingPlanAllocation {\n sellingPlan: {\n id: string;\n name: string;\n description: string | null;\n };\n priceAdjustments: SellingPlanPriceAdjustment[];\n checkoutChargeAmount: {\n amount: number;\n currencyCode: string;\n };\n remainingBalanceChargeAmount: {\n amount: number;\n currencyCode: string;\n };\n}\n\nexport interface CartLine {\n id: string;\n quantity: number;\n /**\n * Null when this is an optimistic line whose merchandise couldn't be\n * resolved from the query cache or passed explicitly. Consumers should\n * render a skeleton/loading state in that case; the line is replaced\n * with real merchandise once the server roundtrip lands.\n */\n merchandise: CartLineMerchandise | null;\n attributes: CartLineAttribute[];\n sellingPlanAllocation?: SellingPlanAllocation | null;\n}\n\nexport interface CartCost {\n /** Integer minor units (Stripe convention) in currencyCode */\n subtotalAmount: number;\n totalAmount: number;\n currencyCode: string;\n}\n\n/**\n * Represents a discount code applied to a cart.\n */\nexport interface CartDiscountCode {\n /** The discount code string */\n code: string;\n /**\n * Whether the discount code is applicable to the current cart.\n * A code may not be applicable due to:\n * - Cart contents not meeting product/collection eligibility\n * - Minimum purchase amount not met\n * - Code expired or usage limits reached\n * - Customer restrictions\n * - Conflicting discount rules\n */\n applicable: boolean;\n}\n\n/**\n * One discount Shopify applied to a cart line or to the whole cart. The amount\n * is already subtracted from `cost.totalAmount` (and from `cost.subtotalAmount`\n * for line-level discounts).\n */\nexport interface CartDiscountAllocation {\n /** Integer minor units (Stripe convention) in the cart's currencyCode */\n discountedAmount: number;\n /** Automatic discount title or discount code; null when Shopify has neither */\n title: string | null;\n}\n\nexport interface Cart {\n id: string;\n lines: CartLine[];\n cost: CartCost;\n checkoutUrl?: string;\n discountCodes?: CartDiscountCode[];\n discountAllocations?: CartDiscountAllocation[];\n}\n\nexport interface CartLinePayload {\n id: string;\n quantity: number;\n merchandise?: CartLineMerchandise;\n properties?: CartLineAttribute[];\n sellingPlanId?: string | null;\n}\n\nexport interface AddToCartPayload {\n lines: CartLinePayload[];\n cartId: string;\n}\n\nexport interface UpdateCartLineItemPayload {\n line: CartLinePayload;\n cartId: string;\n}\n\nexport interface RemoveFromCartPayload {\n lineIds: string[];\n cartId: string;\n}\n\nexport interface UpdateCartDiscountCodesPayload {\n cartId: string;\n discountCodes: string[];\n}\n"],
|
|
5
5
|
"mappings": "AAoCO,MAAM,6BAAgD;AAAA,EAC3D,KAAK;AAAA,EACL,OAAO;AACT;",
|
|
6
6
|
"names": []
|
|
7
7
|
}
|
|
@@ -13,20 +13,21 @@ export interface CartTotals {
|
|
|
13
13
|
export declare function calculateLineItemsSubtotal(lineItems: CartLine[]): number;
|
|
14
14
|
/**
|
|
15
15
|
* Recompute a cart's cost from its line items. Cookie carts are their own source
|
|
16
|
-
* of truth (no server roundtrip) and apply no
|
|
17
|
-
*
|
|
18
|
-
* every consumer that trusts it (cart total,
|
|
19
|
-
* a priced cart.
|
|
16
|
+
* of truth (no server roundtrip) and apply no discounts, so subtotal equals
|
|
17
|
+
* total and there are no discount allocations. Without this the cost stays at
|
|
18
|
+
* the 0 it was created with, and every consumer that trusts it (cart total,
|
|
19
|
+
* checkout analytics) reports $0 for a priced cart.
|
|
20
20
|
*/
|
|
21
21
|
export declare function recalculateCartCost(cart: Cart): Cart;
|
|
22
22
|
/**
|
|
23
23
|
* Calculate cart totals including subtotal, discounts, and final total.
|
|
24
24
|
* When cart cost data is provided (from Shopify), uses the actual totalAmount
|
|
25
|
-
*
|
|
25
|
+
* and sums the provider's discount allocations (automatic, code, and custom
|
|
26
|
+
* discounts, at both line and cart level) for the discount amount.
|
|
26
27
|
*
|
|
27
28
|
* @param options - Object containing lineItems and cart
|
|
28
29
|
* @param options.lineItems - Array of cart line items
|
|
29
|
-
* @param options.cart - Optional cart data from Shopify (includes discount
|
|
30
|
+
* @param options.cart - Optional cart data from Shopify (includes discount allocations)
|
|
30
31
|
*/
|
|
31
32
|
export declare function calculateCartTotals({ lineItems, cart, }: {
|
|
32
33
|
lineItems: CartLine[];
|
package/cart/utils/cart-utils.js
CHANGED
|
@@ -14,7 +14,8 @@ function recalculateCartCost(cart) {
|
|
|
14
14
|
...cart.cost,
|
|
15
15
|
subtotalAmount: subtotal,
|
|
16
16
|
totalAmount: subtotal
|
|
17
|
-
}
|
|
17
|
+
},
|
|
18
|
+
discountAllocations: []
|
|
18
19
|
};
|
|
19
20
|
}
|
|
20
21
|
function calculateCartTotals({
|
|
@@ -26,8 +27,10 @@ function calculateCartTotals({
|
|
|
26
27
|
return sum + getCartLinePricing(item).compareAtPrice * item.quantity;
|
|
27
28
|
}, 0);
|
|
28
29
|
const total = cart?.cost.totalAmount ?? lineItemSubtotal;
|
|
29
|
-
const
|
|
30
|
-
|
|
30
|
+
const discountAmount = (cart?.discountAllocations ?? []).reduce(
|
|
31
|
+
(sum, allocation) => sum + allocation.discountedAmount,
|
|
32
|
+
0
|
|
33
|
+
);
|
|
31
34
|
const totalSavings = compareAtSubtotal - total;
|
|
32
35
|
return {
|
|
33
36
|
subtotal: lineItemSubtotal,
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../../cart/utils/cart-utils.ts"],
|
|
4
|
-
"sourcesContent": ["import type { Cart, CartLine } from \"../cart-types\";\n\nimport { formatAmount } from \"schemas/money\";\n\nimport { getCartLinePricing } from \"./variant-to-cart-line\";\n\nexport interface CartTotals {\n subtotal: number;\n discountAmount: number;\n totalSavings: number;\n total: number;\n}\n\n/**\n * Sum the final (post selling-plan) price of every line item in the cart.\n * This is the authoritative subtotal for cookie-based carts, which have no\n * server-computed cost to rely on.\n */\nexport function calculateLineItemsSubtotal(lineItems: CartLine[]): number {\n return lineItems.reduce(\n (sum, item) => sum + getCartLinePricing(item).finalPrice * item.quantity,\n 0,\n );\n}\n\n/**\n * Recompute a cart's cost from its line items. Cookie carts are their own source\n * of truth (no server roundtrip) and apply no
|
|
5
|
-
"mappings": "AAEA,SAAS,oBAAoB;AAE7B,SAAS,0BAA0B;AAc5B,SAAS,2BAA2B,WAA+B;AACxE,SAAO,UAAU;AAAA,IACf,CAAC,KAAK,SAAS,MAAM,mBAAmB,IAAI,EAAE,aAAa,KAAK;AAAA,IAChE;AAAA,EACF;AACF;AASO,SAAS,oBAAoB,MAAkB;AACpD,QAAM,WAAW,2BAA2B,KAAK,KAAK;AACtD,SAAO;AAAA,IACL,GAAG;AAAA,IACH,MAAM;AAAA,MACJ,GAAG,KAAK;AAAA,MACR,gBAAgB;AAAA,MAChB,aAAa;AAAA,IACf;AAAA,
|
|
4
|
+
"sourcesContent": ["import type { Cart, CartLine } from \"../cart-types\";\n\nimport { formatAmount } from \"schemas/money\";\n\nimport { getCartLinePricing } from \"./variant-to-cart-line\";\n\nexport interface CartTotals {\n subtotal: number;\n discountAmount: number;\n totalSavings: number;\n total: number;\n}\n\n/**\n * Sum the final (post selling-plan) price of every line item in the cart.\n * This is the authoritative subtotal for cookie-based carts, which have no\n * server-computed cost to rely on.\n */\nexport function calculateLineItemsSubtotal(lineItems: CartLine[]): number {\n return lineItems.reduce(\n (sum, item) => sum + getCartLinePricing(item).finalPrice * item.quantity,\n 0,\n );\n}\n\n/**\n * Recompute a cart's cost from its line items. Cookie carts are their own source\n * of truth (no server roundtrip) and apply no discounts, so subtotal equals\n * total and there are no discount allocations. Without this the cost stays at\n * the 0 it was created with, and every consumer that trusts it (cart total,\n * checkout analytics) reports $0 for a priced cart.\n */\nexport function recalculateCartCost(cart: Cart): Cart {\n const subtotal = calculateLineItemsSubtotal(cart.lines);\n return {\n ...cart,\n cost: {\n ...cart.cost,\n subtotalAmount: subtotal,\n totalAmount: subtotal,\n },\n discountAllocations: [],\n };\n}\n\n/**\n * Calculate cart totals including subtotal, discounts, and final total.\n * When cart cost data is provided (from Shopify), uses the actual totalAmount\n * and sums the provider's discount allocations (automatic, code, and custom\n * discounts, at both line and cart level) for the discount amount.\n *\n * @param options - Object containing lineItems and cart\n * @param options.lineItems - Array of cart line items\n * @param options.cart - Optional cart data from Shopify (includes discount allocations)\n */\nexport function calculateCartTotals({\n lineItems,\n cart,\n}: {\n lineItems: CartLine[];\n cart: Cart | null;\n}): CartTotals {\n const lineItemSubtotal = calculateLineItemsSubtotal(lineItems);\n const compareAtSubtotal = lineItems.reduce((sum, item) => {\n return sum + getCartLinePricing(item).compareAtPrice * item.quantity;\n }, 0);\n\n // NOTE (Jasmine, 2026-07-22): Trust the provider's authoritative cost when\n // present. For Shopify this is the server-computed cart cost (including a\n // legitimate $0 when items aren't purchasable), which we must not\n // second-guess; cookie carts keep their cost truthful via\n // cookie-cart-persistence.ts.\n const total = cart?.cost.totalAmount ?? lineItemSubtotal;\n\n // Shopify folds line-level discounts into cost.subtotalAmount too, so the\n // cost gap can't be used; the allocations carry every applied discount.\n const discountAmount = (cart?.discountAllocations ?? []).reduce(\n (sum, allocation) => sum + allocation.discountedAmount,\n 0,\n );\n\n const totalSavings = compareAtSubtotal - total;\n\n return {\n subtotal: lineItemSubtotal,\n discountAmount,\n totalSavings,\n total,\n };\n}\n\n/**\n * @deprecated Back-compat shim kept for surface parity with canopy-sdk, so\n * sites migrating off `import { formatPrice } from\n * \"canopy-sdk/cart/utils/cart-utils\"` keep rendering with only the package\n * specifier renamed. It formats INTEGER MINOR UNITS \u2014 the units every cart\n * value uses (`calculateCartTotals`, `getCartLinePricing`, `CartCost`):\n * passing 1999 yields \"$19.99\", not \"$1,999.00\". New code should call\n * `formatAmount({ amount, currencyCode })` from `@replohq/sdk/money` directly.\n */\nexport function formatPrice(price: number, currency: string = \"USD\"): string {\n return formatAmount({ amount: price, currencyCode: currency });\n}\n\n/**\n * Validates and formats a Shopify selling plan ID to ensure it has the correct GID format.\n *\n * @param sellingPlanId - The selling plan ID to validate and format\n * @returns The formatted selling plan ID with GID prefix, or null if no ID provided\n */\nexport function formatSellingPlanId(\n sellingPlanId: string | null | undefined,\n): string | null {\n if (!sellingPlanId) {\n return null;\n }\n\n // Check if it already has the gid format\n if (sellingPlanId.startsWith(\"gid://shopify/SellingPlan/\")) {\n return sellingPlanId;\n }\n\n // If it doesn't have the gid format, prepend it\n return `gid://shopify/SellingPlan/${sellingPlanId}`;\n}\n"],
|
|
5
|
+
"mappings": "AAEA,SAAS,oBAAoB;AAE7B,SAAS,0BAA0B;AAc5B,SAAS,2BAA2B,WAA+B;AACxE,SAAO,UAAU;AAAA,IACf,CAAC,KAAK,SAAS,MAAM,mBAAmB,IAAI,EAAE,aAAa,KAAK;AAAA,IAChE;AAAA,EACF;AACF;AASO,SAAS,oBAAoB,MAAkB;AACpD,QAAM,WAAW,2BAA2B,KAAK,KAAK;AACtD,SAAO;AAAA,IACL,GAAG;AAAA,IACH,MAAM;AAAA,MACJ,GAAG,KAAK;AAAA,MACR,gBAAgB;AAAA,MAChB,aAAa;AAAA,IACf;AAAA,IACA,qBAAqB,CAAC;AAAA,EACxB;AACF;AAYO,SAAS,oBAAoB;AAAA,EAClC;AAAA,EACA;AACF,GAGe;AACb,QAAM,mBAAmB,2BAA2B,SAAS;AAC7D,QAAM,oBAAoB,UAAU,OAAO,CAAC,KAAK,SAAS;AACxD,WAAO,MAAM,mBAAmB,IAAI,EAAE,iBAAiB,KAAK;AAAA,EAC9D,GAAG,CAAC;AAOJ,QAAM,QAAQ,MAAM,KAAK,eAAe;AAIxC,QAAM,kBAAkB,MAAM,uBAAuB,CAAC,GAAG;AAAA,IACvD,CAAC,KAAK,eAAe,MAAM,WAAW;AAAA,IACtC;AAAA,EACF;AAEA,QAAM,eAAe,oBAAoB;AAEzC,SAAO;AAAA,IACL,UAAU;AAAA,IACV;AAAA,IACA;AAAA,IACA;AAAA,EACF;AACF;AAWO,SAAS,YAAY,OAAe,WAAmB,OAAe;AAC3E,SAAO,aAAa,EAAE,QAAQ,OAAO,cAAc,SAAS,CAAC;AAC/D;AAQO,SAAS,oBACd,eACe;AACf,MAAI,CAAC,eAAe;AAClB,WAAO;AAAA,EACT;AAGA,MAAI,cAAc,WAAW,4BAA4B,GAAG;AAC1D,WAAO;AAAA,EACT;AAGA,SAAO,6BAA6B,aAAa;AACnD;",
|
|
6
6
|
"names": []
|
|
7
7
|
}
|
package/lib/buildMetadata.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
export const BUILD_METADATA = {
|
|
2
2
|
"packageName": "@replohq/sdk",
|
|
3
|
-
"version": "1.2.
|
|
3
|
+
"version": "1.2.2",
|
|
4
4
|
"branch": "HEAD",
|
|
5
|
-
"commit": "
|
|
6
|
-
"builtAt": "2026-09-
|
|
5
|
+
"commit": "169d937b821d030ec7248cb90cc303bad98f79d4",
|
|
6
|
+
"builtAt": "2026-09-02T22:01:44.766Z"
|
|
7
7
|
};
|
package/package.json
CHANGED
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@replohq/sdk",
|
|
3
|
-
"version": "1.2.
|
|
3
|
+
"version": "1.2.2",
|
|
4
4
|
"reploBuild": {
|
|
5
5
|
"packageName": "@replohq/sdk",
|
|
6
|
-
"version": "1.2.
|
|
6
|
+
"version": "1.2.2",
|
|
7
7
|
"branch": "HEAD",
|
|
8
|
-
"commit": "
|
|
9
|
-
"builtAt": "2026-09-
|
|
8
|
+
"commit": "169d937b821d030ec7248cb90cc303bad98f79d4",
|
|
9
|
+
"builtAt": "2026-09-02T22:01:44.766Z"
|
|
10
10
|
},
|
|
11
11
|
"description": "Replo SDK — cart, analytics, and data loaders for agent-built Next.js sites.",
|
|
12
12
|
"license": "SEE LICENSE IN LICENSE",
|