@nextblock-cms/ecom 0.22.0 → 0.22.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (62) hide show
  1. package/index.cjs +1 -1
  2. package/index.es.js +31 -31
  3. package/lib/components/Checkout.cjs +1 -1
  4. package/lib/components/Checkout.es.js +2 -1
  5. package/lib/coupon-server.cjs +1 -1
  6. package/lib/coupon-server.d.ts +65 -1
  7. package/lib/coupon-server.es.js +151 -91
  8. package/lib/coupons.cjs +1 -1
  9. package/lib/coupons.d.ts +13 -0
  10. package/lib/coupons.es.js +5 -4
  11. package/lib/order-access-token.cjs +1 -0
  12. package/lib/order-access-token.d.ts +2 -0
  13. package/lib/order-access-token.es.js +18 -0
  14. package/lib/pages/cms/orders/actions.cjs +3 -3
  15. package/lib/pages/cms/orders/actions.es.js +48 -26
  16. package/lib/pages/cms/orders/export-actions.cjs +1 -1
  17. package/lib/pages/cms/orders/export-actions.d.ts +42 -1
  18. package/lib/pages/cms/orders/export-actions.es.js +18 -16
  19. package/lib/pages/cms/orders/server-actions.cjs +1 -1
  20. package/lib/pages/cms/orders/server-actions.es.js +25 -15
  21. package/lib/pages/cms/products/actions.cjs +4 -4
  22. package/lib/pages/cms/products/actions.es.js +44 -41
  23. package/lib/pages/cms/products/inventory/actions.cjs +2 -2
  24. package/lib/pages/cms/products/inventory/actions.es.js +23 -23
  25. package/lib/pages/cms/products/server-actions.cjs +1 -1
  26. package/lib/pages/cms/products/server-actions.es.js +109 -108
  27. package/lib/pages/cms/shipping/server-actions.cjs +1 -1
  28. package/lib/pages/cms/shipping/server-actions.es.js +27 -26
  29. package/lib/payment-config.cjs +1 -1
  30. package/lib/payment-config.d.ts +4 -2
  31. package/lib/payment-config.es.js +73 -72
  32. package/lib/product-actions.cjs +1 -1
  33. package/lib/product-actions.es.js +6 -6
  34. package/lib/providers/checkout-items.cjs +1 -0
  35. package/lib/providers/checkout-items.d.ts +30 -0
  36. package/lib/providers/checkout-items.es.js +43 -0
  37. package/lib/providers/freemius.cjs +1 -1
  38. package/lib/providers/freemius.d.ts +1 -1
  39. package/lib/providers/freemius.es.js +166 -144
  40. package/lib/providers/stripe.cjs +1 -1
  41. package/lib/providers/stripe.d.ts +1 -1
  42. package/lib/providers/stripe.es.js +191 -146
  43. package/lib/server-actions/coupon-actions.cjs +1 -1
  44. package/lib/server-actions/coupon-actions.d.ts +11 -12
  45. package/lib/server-actions/coupon-actions.es.js +19 -11
  46. package/lib/server-actions/require-ecom-role.cjs +1 -0
  47. package/lib/server-actions/require-ecom-role.d.ts +5825 -0
  48. package/lib/server-actions/require-ecom-role.es.js +24 -0
  49. package/lib/server-actions/shipping-actions.cjs +1 -1
  50. package/lib/server-actions/shipping-actions.es.js +4 -4
  51. package/lib/server-actions/tax-actions.cjs +1 -1
  52. package/lib/server-actions/tax-actions.es.js +22 -18
  53. package/lib/shipping/checkout-shipping-method.cjs +7 -0
  54. package/lib/shipping/checkout-shipping-method.d.ts +115 -0
  55. package/lib/shipping/checkout-shipping-method.es.js +167 -0
  56. package/lib/shipping/resolver.cjs +1 -7
  57. package/lib/shipping/resolver.d.ts +7 -12
  58. package/lib/shipping/resolver.es.js +13 -38
  59. package/package.json +4 -4
  60. package/server.cjs +1 -1
  61. package/server.d.ts +1 -0
  62. package/server.es.js +49 -48
@@ -1,19 +1,20 @@
1
1
  import { isDigitalItem as e } from "../types.es.js";
2
- import { convertMinorUnitAmount as t, getDefaultCurrency as n, normalizePriceMap as r, resolveEffectivePriceForCurrency as i } from "../currency.es.js";
3
- import { getCartLineCouponKey as a } from "../coupons.es.js";
4
- import { getCouponQuote as o, getQuoteLineDiscountMap as s, recordCouponRedemption as c } from "../coupon-server.es.js";
5
- import { countries as l } from "../countries.es.js";
6
- import { resolveTranslatedText as u } from "../variation-utils.es.js";
7
- import { createInventoryInsufficientError as d, createInventoryUnavailableError as f, getEcommerceInventorySettings as ee } from "../inventory-settings.es.js";
8
- import { STRIPE_TAX_CODE_NONTAXABLE as p, STRIPE_TAX_CODE_SHIPPING as te, calculateCheckoutTaxes as ne, getStripeTaxCodeForProduct as re } from "../tax-calculation.es.js";
9
- import { normalizeOrderCustomerDetails as ie } from "../customer.es.js";
10
- import { fillMissingUserProfileCheckoutDetails as ae, upsertDefaultUserAddresses as oe } from "../customer-addresses.es.js";
11
- import { buildOrderTaxDetailsFromCalculation as se } from "../order-tax-details.es.js";
12
- import { getStripeClient as m } from "../stripe/client.es.js";
13
- import { createClient as ce } from "@supabase/supabase-js";
2
+ import { getDefaultCurrency as t, normalizePriceMap as n, resolveEffectivePriceForCurrency as r } from "../currency.es.js";
3
+ import { getCartLineCouponKey as i } from "../coupons.es.js";
4
+ import { getCouponQuote as a, getQuoteLineDiscountMap as o, recordCouponRedemption as s } from "../coupon-server.es.js";
5
+ import { countries as c } from "../countries.es.js";
6
+ import { createInvalidShippingMethodError as l, createShippingAddressRequiredError as u, createShippingMethodRequiredError as ee, listEligibleShippingMethods as te, normalizeShippingDestination as ne, resolveCheckoutShippingMethod as re } from "../shipping/checkout-shipping-method.es.js";
7
+ import { createInventoryInsufficientError as ie, createInventoryUnavailableError as ae, getEcommerceInventorySettings as oe } from "../inventory-settings.es.js";
8
+ import { STRIPE_TAX_CODE_NONTAXABLE as d, STRIPE_TAX_CODE_SHIPPING as se, calculateCheckoutTaxes as ce, getStripeTaxCodeForProduct as le } from "../tax-calculation.es.js";
9
+ import { normalizeOrderCustomerDetails as ue } from "../customer.es.js";
10
+ import { fillMissingUserProfileCheckoutDetails as de, upsertDefaultUserAddresses as fe } from "../customer-addresses.es.js";
11
+ import { normalizeCheckoutItems as f } from "./checkout-items.es.js";
12
+ import { buildOrderTaxDetailsFromCalculation as pe } from "../order-tax-details.es.js";
13
+ import { getStripeClient as p } from "../stripe/client.es.js";
14
+ import { createClient as me } from "@supabase/supabase-js";
14
15
  //#region src/lib/providers/stripe.ts
15
- var le = l.map((e) => e.code), h = /* @__PURE__ */ new Set(/* @__PURE__ */ "bg.cs.da.de.el.en.en-GB.es.es-419.et.fi.fil.fr.hr.hu.id.it.ja.ko.lt.lv.ms.mt.nb.nl.pl.pt.pt-BR.ro.ru.sk.sl.sv.th.tr.vi.zh.zh-HK.zh-TW".split("."));
16
- function g(e) {
16
+ var he = c.map((e) => e.code), m = /* @__PURE__ */ new Set(/* @__PURE__ */ "bg.cs.da.de.el.en.en-GB.es.es-419.et.fi.fil.fr.hr.hu.id.it.ja.ko.lt.lv.ms.mt.nb.nl.pl.pt.pt-BR.ro.ru.sk.sl.sv.th.tr.vi.zh.zh-HK.zh-TW".split("."));
17
+ function h(e) {
17
18
  if (e) return {
18
19
  line1: e.line1 || void 0,
19
20
  line2: e.line2 || void 0,
@@ -23,7 +24,7 @@ function g(e) {
23
24
  country: e.country_code || void 0
24
25
  };
25
26
  }
26
- function ue(e) {
27
+ function ge(e) {
27
28
  let t = e?.trim().replace("_", "-");
28
29
  if (!t) return;
29
30
  let n = [
@@ -31,18 +32,15 @@ function ue(e) {
31
32
  t.toLowerCase(),
32
33
  t.split("-")[0].toLowerCase()
33
34
  ];
34
- for (let e of n) if (h.has(e)) return e;
35
+ for (let e of n) if (m.has(e)) return e;
35
36
  }
36
- function de(e, t) {
37
- return u(e.name, e.name_translations || null, t);
38
- }
39
- async function fe(e) {
37
+ async function _e(e) {
40
38
  if (!e.email) return null;
41
- let t = await m(), n = g(e.shippingAddress), r = e.shippingAddress?.recipient_name || e.billingAddress?.recipient_name || void 0, i = {
39
+ let t = await p(), n = h(e.shippingAddress), r = e.shippingAddress?.recipient_name || e.billingAddress?.recipient_name || void 0, i = {
42
40
  email: e.email,
43
41
  name: e.billingAddress?.recipient_name || e.shippingAddress?.recipient_name || void 0,
44
42
  phone: e.phone || void 0,
45
- address: g(e.billingAddress),
43
+ address: h(e.billingAddress),
46
44
  metadata: e.userId ? { userId: e.userId } : void 0,
47
45
  ...n && r ? { shipping: {
48
46
  name: r,
@@ -60,61 +58,75 @@ async function fe(e) {
60
58
  return console.error("Failed to upsert Stripe customer for checkout prefill:", e), null;
61
59
  }
62
60
  }
63
- var _ = class {
61
+ var g = class {
64
62
  getProviderName() {
65
63
  return "Stripe";
66
64
  }
67
- async createCheckoutSession({ items: l, customerEmail: u, customerPhone: h, userId: g, billingAddress: _, shippingAddress: v, shippingMethodId: pe, currencyCode: me, locale: he, couponCode: y, couponContextItems: b }) {
68
- let ge = await m(), x = process.env.NEXT_PUBLIC_SUPABASE_URL || process.env.SUPABASE_URL, S = process.env.SUPABASE_SERVICE_ROLE_KEY || process.env.SUPABASE_SECRET_KEY;
69
- if (!x || !S) return console.error("Missing Supabase credentials for checkout (Service Key required)."), {
65
+ async createCheckoutSession({ items: c, customerEmail: m, customerPhone: h, userId: g, billingAddress: _, shippingAddress: v, shippingMethodId: y, currencyCode: ve, locale: b, couponCode: x, couponContextItems: S }) {
66
+ let ye = await p(), C = process.env.NEXT_PUBLIC_SUPABASE_URL || process.env.SUPABASE_URL, w = process.env.SUPABASE_SERVICE_ROLE_KEY || process.env.SUPABASE_SECRET_KEY;
67
+ if (!C || !w) return console.error("Missing Supabase credentials for checkout (Service Key required)."), {
70
68
  error: "Internal Server Error",
71
69
  url: null
72
70
  };
73
- let C = ce(x, S), w = process.env.NEXT_PUBLIC_URL || "http://localhost:4200", T = l.some((t) => !e(t));
74
- if (!l.length) return {
71
+ let T = me(C, w), E = process.env.NEXT_PUBLIC_URL || "http://localhost:4200";
72
+ if (!c?.length) return {
75
73
  error: "Cart is empty",
76
74
  url: null
77
75
  };
78
- let { data: _e, error: E } = await C.from("currencies").select("code, symbol, exchange_rate, is_default, is_active, auto_sync_product_prices, auto_update_exchange_rate, exchange_rate_source, exchange_rate_updated_at, rounding_mode, rounding_increment, rounding_charm_amount").eq("is_active", !0).order("code", { ascending: !0 }), D = _e ?? [];
79
- if (E || D.length === 0) return console.error("Error fetching currencies for checkout:", E), {
76
+ let D = f(c);
77
+ if (!D.ok) return {
78
+ url: null,
79
+ ...D.error
80
+ };
81
+ let O = D.items, k = O;
82
+ if (S && S.length > 0) {
83
+ let e = f(S);
84
+ if (!e.ok) return {
85
+ url: null,
86
+ ...e.error
87
+ };
88
+ k = e.items;
89
+ }
90
+ let A = O.some((t) => !e(t)), { data: be, error: j } = await T.from("currencies").select("code, symbol, exchange_rate, is_default, is_active, auto_sync_product_prices, auto_update_exchange_rate, exchange_rate_source, exchange_rate_updated_at, rounding_mode, rounding_increment, rounding_charm_amount").eq("is_active", !0).order("code", { ascending: !0 }), M = be ?? [];
91
+ if (j || M.length === 0) return console.error("Error fetching currencies for checkout:", j), {
80
92
  error: "Failed to resolve store currencies",
81
93
  url: null
82
94
  };
83
- let O = n(D), k = D.find((e) => e.code === (me || "").toUpperCase()) ?? O, A = k.code.toLowerCase(), j = await ee(C), ve = l.map((e) => e.product_id), M = l.map((e) => e.variant_id).filter((e) => !!e), { data: N, error: P } = await C.from("products").select("id, title, sku, price, prices, sale_price, sale_prices, sale_start_at, sale_end_at, scheduled_price, scheduled_prices, scheduled_price_at, stock, is_taxable").in("id", ve);
84
- if (P || !N) return console.error("Error fetching products for validation:", P), {
95
+ let xe = t(M), N = M.find((e) => e.code === (ve || "").toUpperCase()) ?? xe, P = N.code.toLowerCase(), F = await oe(T), Se = O.map((e) => e.product_id), I = O.map((e) => e.variant_id).filter((e) => !!e), { data: L, error: R } = await T.from("products").select("id, title, sku, price, prices, sale_price, sale_prices, sale_start_at, sale_end_at, scheduled_price, scheduled_prices, scheduled_price_at, stock, is_taxable").in("id", Se);
96
+ if (R || !L) return console.error("Error fetching products for validation:", R), {
85
97
  error: "Failed to validate product prices",
86
98
  url: null
87
99
  };
88
- let { data: ye, error: F } = M.length ? await C.from("product_variants").select("id, product_id, sku, price, prices, sale_price, sale_prices, sale_start_at, sale_end_at, scheduled_price, scheduled_prices, scheduled_price_at, stock_quantity").in("id", M) : {
100
+ let { data: Ce, error: we } = I.length ? await T.from("product_variants").select("id, product_id, sku, price, prices, sale_price, sale_prices, sale_start_at, sale_end_at, scheduled_price, scheduled_prices, scheduled_price_at, stock_quantity").in("id", I) : {
89
101
  data: [],
90
102
  error: null
91
103
  };
92
- if (F) return console.error("Error fetching variants for validation:", F), {
104
+ if (we) return console.error("Error fetching variants for validation:", we), {
93
105
  error: "Failed to validate product variants",
94
106
  url: null
95
107
  };
96
- let I = new Map(N.map((e) => [e.id, e])), L = new Map((ye || []).map((e) => [e.id, e])), R = /* @__PURE__ */ new Set(), z = /* @__PURE__ */ new Map();
97
- for (let e of l) {
98
- let t = I.get(e.product_id);
108
+ let z = new Map(L.map((e) => [e.id, e])), B = new Map((Ce || []).map((e) => [e.id, e])), V = /* @__PURE__ */ new Set(), H = /* @__PURE__ */ new Map();
109
+ for (let e of O) {
110
+ let t = z.get(e.product_id);
99
111
  if (!t) continue;
100
- let n = (e.variant_id ? L.get(e.variant_id) : null)?.sku || t.sku;
101
- n && (R.add(n), z.set(n, (z.get(n) ?? 0) + e.quantity));
112
+ let n = (e.variant_id ? B.get(e.variant_id) : null)?.sku || t.sku;
113
+ n && (V.add(n), H.set(n, (H.get(n) ?? 0) + e.quantity));
102
114
  }
103
- let { data: be, error: B } = R.size ? await C.from("inventory_items").select("sku, quantity").in("sku", [...R]) : {
115
+ let { data: Te, error: Ee } = V.size ? await T.from("inventory_items").select("sku, quantity").in("sku", [...V]) : {
104
116
  data: [],
105
117
  error: null
106
118
  };
107
- if (B) return console.error("Error fetching SKU inventory for validation:", B), {
119
+ if (Ee) return console.error("Error fetching SKU inventory for validation:", Ee), {
108
120
  error: "Failed to validate SKU inventory",
109
121
  url: null
110
122
  };
111
- let V = new Map((be || []).map((e) => [e.sku, Math.max(0, e.quantity ?? 0)])), H = [], U = [], W = [], G = 0, K = 0, q = null;
112
- if (y) {
113
- let e = await o({
114
- client: C,
115
- code: y,
116
- items: b && b.length > 0 ? b : l,
117
- currencyCode: k.code
123
+ let U = new Map((Te || []).map((e) => [e.sku, Math.max(0, e.quantity ?? 0)])), W = [], De = [], Oe = [], G = 0, K = 0, q = null;
124
+ if (x) {
125
+ let e = await a({
126
+ client: T,
127
+ code: x,
128
+ items: k,
129
+ currencyCode: N.code
118
130
  });
119
131
  if (!e.success) return {
120
132
  error: e.error,
@@ -124,16 +136,16 @@ var _ = class {
124
136
  };
125
137
  q = e.quote;
126
138
  }
127
- let xe = s(q), Se = (e) => {
139
+ let ke = o(q), Ae = (e) => {
128
140
  let t = e.unitAmount * e.quantity, n = Math.max(0, t - e.lineDiscount);
129
141
  if (n <= 0) return;
130
142
  let r = Math.floor(n / e.quantity), i = n - r * e.quantity, a = (t, n) => {
131
- n <= 0 || t <= 0 || H.push({
143
+ n <= 0 || t <= 0 || W.push({
132
144
  price_data: {
133
145
  currency: e.currency,
134
146
  product_data: {
135
147
  name: e.name,
136
- tax_code: re(e.isTaxable),
148
+ tax_code: le(e.isTaxable),
137
149
  metadata: {
138
150
  productId: e.productId,
139
151
  variantId: e.variantId || ""
@@ -147,55 +159,55 @@ var _ = class {
147
159
  };
148
160
  a(r, e.quantity - i), a(r + 1, i);
149
161
  };
150
- for (let e of l) {
151
- let t = I.get(e.product_id);
162
+ for (let e of O) {
163
+ let t = z.get(e.product_id);
152
164
  if (!t) return console.warn(`Product ${e.product_id} not found in DB.`), {
153
165
  url: null,
154
- ...f(e.title)
166
+ ...ae(e.title)
155
167
  };
156
- let n = i({
157
- prices: r(t.prices),
168
+ let a = r({
169
+ prices: n(t.prices),
158
170
  salePrices: t.sale_prices || {},
159
171
  fallbackPrice: t.price,
160
172
  fallbackSalePrice: t.sale_price,
161
173
  saleStartAt: t.sale_start_at,
162
174
  saleEndAt: t.sale_end_at,
163
175
  scheduledPrice: t.scheduled_price,
164
- scheduledPrices: r(t.scheduled_prices),
176
+ scheduledPrices: n(t.scheduled_prices),
165
177
  scheduledPriceAt: t.scheduled_price_at,
166
- currencyCode: k.code,
167
- currencies: D
168
- }), o = n.sale_price ?? n.price, s = t.title, c = null;
178
+ currencyCode: N.code,
179
+ currencies: M
180
+ }), o = a.sale_price ?? a.price, s = t.title, c = null;
169
181
  if (e.variant_id) {
170
- let n = L.get(e.variant_id);
171
- if (!n || n.product_id !== e.product_id) return {
182
+ let i = B.get(e.variant_id);
183
+ if (!i || i.product_id !== e.product_id) return {
172
184
  url: null,
173
- ...f(e.title)
185
+ ...ae(e.title)
174
186
  };
175
- let a = z.get(n.sku) ?? e.quantity, l = V.has(n.sku) ? V.get(n.sku) ?? 0 : Math.max(0, n.stock_quantity ?? 0);
176
- if (j.trackQuantities && a > l) return {
187
+ let a = H.get(i.sku) ?? e.quantity, l = U.has(i.sku) ? U.get(i.sku) ?? 0 : Math.max(0, i.stock_quantity ?? 0);
188
+ if (F.trackQuantities && a > l) return {
177
189
  url: null,
178
- ...d(e.title, l)
190
+ ...ie(e.title, l)
179
191
  };
180
- let u = i({
181
- prices: r(n.prices),
182
- salePrices: n.sale_prices || {},
183
- fallbackPrice: n.price,
184
- fallbackSalePrice: n.sale_price,
185
- saleStartAt: n.sale_start_at,
186
- saleEndAt: n.sale_end_at,
187
- scheduledPrice: n.scheduled_price,
188
- scheduledPrices: r(n.scheduled_prices),
189
- scheduledPriceAt: n.scheduled_price_at,
190
- currencyCode: k.code,
191
- currencies: D
192
+ let u = r({
193
+ prices: n(i.prices),
194
+ salePrices: i.sale_prices || {},
195
+ fallbackPrice: i.price,
196
+ fallbackSalePrice: i.sale_price,
197
+ saleStartAt: i.sale_start_at,
198
+ saleEndAt: i.sale_end_at,
199
+ scheduledPrice: i.scheduled_price,
200
+ scheduledPrices: n(i.scheduled_prices),
201
+ scheduledPriceAt: i.scheduled_price_at,
202
+ currencyCode: N.code,
203
+ currencies: M
192
204
  });
193
- o = u.sale_price ?? u.price, c = n.id, s = e.variant_label ? `${t.title} - ${e.variant_label}` : `${t.title} - ${n.sku}`;
205
+ o = u.sale_price ?? u.price, c = i.id, s = e.variant_label ? `${t.title} - ${e.variant_label}` : `${t.title} - ${i.sku}`;
194
206
  } else {
195
- let n = z.get(t.sku) ?? e.quantity, r = V.has(t.sku) ? V.get(t.sku) ?? 0 : Math.max(0, t.stock ?? 0);
196
- if (j.trackQuantities && n > r) return {
207
+ let n = H.get(t.sku) ?? e.quantity, r = U.has(t.sku) ? U.get(t.sku) ?? 0 : Math.max(0, t.stock ?? 0);
208
+ if (F.trackQuantities && n > r) return {
197
209
  url: null,
198
- ...d(e.title, r)
210
+ ...ie(e.title, r)
199
211
  };
200
212
  }
201
213
  let l = t.is_taxable ?? !0;
@@ -203,22 +215,22 @@ var _ = class {
203
215
  error: "A product variation produced an invalid price.",
204
216
  url: null
205
217
  };
206
- let u = Math.min(o * e.quantity, xe.get(a(e)) ?? 0);
207
- Se({
218
+ let u = Math.min(o * e.quantity, ke.get(i(e)) ?? 0);
219
+ Ae({
208
220
  name: s,
209
- currency: A,
221
+ currency: P,
210
222
  productId: t.id,
211
223
  variantId: c,
212
224
  isTaxable: l,
213
225
  unitAmount: o,
214
226
  quantity: e.quantity,
215
227
  lineDiscount: u
216
- }), G += o * e.quantity, K += u, W.push({
228
+ }), G += o * e.quantity, K += u, Oe.push({
217
229
  product_id: t.id,
218
230
  quantity: e.quantity,
219
231
  price_at_purchase: o,
220
232
  variant_id: c
221
- }), U.push({
233
+ }), De.push({
222
234
  product_id: t.id,
223
235
  quantity: e.quantity,
224
236
  unit_amount: o,
@@ -226,37 +238,66 @@ var _ = class {
226
238
  is_taxable: l
227
239
  });
228
240
  }
229
- if (H.length === 0 && K >= G) return {
241
+ if (W.length === 0 && K >= G) return {
230
242
  error: "This coupon would reduce the Stripe order to zero. Use a smaller discount for Stripe checkout.",
231
243
  errorKey: "ecommerce.coupon_zero_total_not_supported",
232
244
  errorStatus: 400,
233
245
  url: null
234
246
  };
235
- if (H.length === 0) return {
247
+ if (W.length === 0) return {
236
248
  error: "No valid items in cart",
237
249
  url: null
238
250
  };
239
251
  let J = 0, Y = null;
240
- if (pe) {
241
- let { data: e, error: n } = await C.from("shipping_zone_methods").select("id, name, name_translations, cost_amount, cost_currency").eq("id", pe).single();
242
- if (n) return console.error("Failed to load shipping method:", n), {
243
- error: "Failed to load shipping method",
244
- url: null
252
+ if (A) {
253
+ let e = ne({
254
+ country: v?.country_code,
255
+ state: v?.state,
256
+ postal_code: v?.postal_code
257
+ });
258
+ if (!e) return {
259
+ url: null,
260
+ ...u()
245
261
  };
246
- J = t({
247
- amount: e.cost_amount ?? 0,
248
- fromCurrencyCode: e.cost_currency || O.code,
249
- toCurrencyCode: k.code,
250
- currencies: D
251
- }), Y = de(e, he);
262
+ let t = {
263
+ destination: e,
264
+ cartTotal: Math.max(0, G - K),
265
+ currencies: M,
266
+ currencyCode: N.code
267
+ };
268
+ if (y) {
269
+ let e = await re(T, {
270
+ ...t,
271
+ methodId: y,
272
+ languageCode: b
273
+ });
274
+ if (!e.ok) return e.reason === "load_failed" ? (console.error("Failed to load shipping method:", e.error), {
275
+ error: "Failed to load shipping method",
276
+ url: null
277
+ }) : (console.warn(`Checkout rejected shipping method ${y}: ${e.reason}`), {
278
+ url: null,
279
+ ...l()
280
+ });
281
+ J = e.method.amount, Y = e.method.name;
282
+ } else {
283
+ let e = await te(T, t);
284
+ if (!e.ok) return console.error("Failed to load shipping methods:", e.error), {
285
+ error: "Failed to load shipping method",
286
+ url: null
287
+ };
288
+ if (e.methods.length > 0) return {
289
+ url: null,
290
+ ...ee()
291
+ };
292
+ }
252
293
  }
253
- let Ce = T ? v ?? _ : _, X;
294
+ let je = A ? v ?? _ : _, X;
254
295
  try {
255
- X = await ne(C, {
256
- items: U,
296
+ X = await ce(T, {
297
+ items: De,
257
298
  destination: {
258
- country_code: Ce?.country_code,
259
- state: Ce?.state
299
+ country_code: je?.country_code,
300
+ state: je?.state
260
301
  }
261
302
  });
262
303
  } catch (e) {
@@ -265,12 +306,12 @@ var _ = class {
265
306
  url: null
266
307
  };
267
308
  }
268
- J > 0 && Y && H.push({
309
+ J > 0 && Y && W.push({
269
310
  price_data: {
270
- currency: A,
311
+ currency: P,
271
312
  product_data: {
272
313
  name: Y,
273
- tax_code: X.enabled && X.mode === "automatic" ? te : p
314
+ tax_code: X.enabled && X.mode === "automatic" ? se : d
274
315
  },
275
316
  tax_behavior: "exclusive",
276
317
  unit_amount: J
@@ -278,39 +319,39 @@ var _ = class {
278
319
  quantity: 1
279
320
  });
280
321
  let Z = X.enabled && X.mode === "manual" && !X.isPendingExternalCalculation ? X.amount : 0;
281
- Z > 0 && H.push({
322
+ Z > 0 && W.push({
282
323
  price_data: {
283
- currency: A,
324
+ currency: P,
284
325
  product_data: {
285
326
  name: "Tax",
286
- tax_code: p
327
+ tax_code: d
287
328
  },
288
329
  tax_behavior: "exclusive",
289
330
  unit_amount: Z
290
331
  },
291
332
  quantity: 1
292
333
  });
293
- let we = ie({
294
- email: u,
334
+ let Me = ue({
335
+ email: m,
295
336
  phone: h,
296
337
  name: _?.recipient_name,
297
338
  billing: _,
298
339
  shipping: v
299
- }), Te = k.code, Ee = se({
340
+ }), Ne = N.code, Pe = pe({
300
341
  calculation: X,
301
342
  subtotal: G,
302
343
  shippingTotal: J,
303
344
  total: Math.max(0, G - K) + J + Z,
304
- currency: Te
305
- }), De = Math.max(0, G - K) + J + Z, { data: Oe, error: ke } = await C.from("orders").insert({
345
+ currency: Ne
346
+ }), Fe = Math.max(0, G - K) + J + Z, { data: Ie, error: Le } = await T.from("orders").insert({
306
347
  status: "pending",
307
- total: De,
308
- currency: Te,
309
- exchange_rate_at_purchase: k.exchange_rate,
348
+ total: Fe,
349
+ currency: Ne,
350
+ exchange_rate_at_purchase: N.exchange_rate,
310
351
  subtotal: G,
311
352
  shipping_total: J,
312
353
  tax_total: Z,
313
- tax_details: Ee,
354
+ tax_details: Pe,
314
355
  coupon_id: q?.couponId ?? null,
315
356
  coupon_code: q?.code ?? null,
316
357
  discount_total: K,
@@ -324,88 +365,92 @@ var _ = class {
324
365
  } : null,
325
366
  provider: "stripe",
326
367
  user_id: g,
327
- customer_details: we
368
+ customer_details: Me
328
369
  }).select("id").single();
329
- if (ke || !Oe) return console.error("Failed to create pending order:", ke), {
370
+ if (Le || !Ie) return console.error("Failed to create pending order:", Le), {
330
371
  error: "Failed to initiate order",
331
372
  url: null
332
373
  };
333
- let Q = Oe.id, { error: Ae } = await C.from("order_items").insert(W.map((e) => ({
374
+ let Q = Ie.id, { error: Re } = await T.from("order_items").insert(Oe.map((e) => ({
334
375
  order_id: Q,
335
376
  product_id: e.product_id,
336
377
  variant_id: e.variant_id ?? null,
337
378
  quantity: e.quantity,
338
379
  price_at_purchase: e.price_at_purchase
339
380
  })));
340
- if (Ae) return console.error("Failed to insert order items:", Ae), await C.from("orders").update({ status: "failed" }).eq("id", Q), {
381
+ if (Re) return console.error("Failed to insert order items:", Re), await T.from("orders").update({ status: "failed" }).eq("id", Q), {
341
382
  error: "Failed to record order items",
342
383
  url: null
343
384
  };
344
385
  if (g) try {
345
- await oe({
386
+ await fe({
346
387
  userId: g,
347
388
  billingAddress: _,
348
389
  shippingAddress: v,
349
- client: C
350
- }), await ae({
390
+ client: T
391
+ }), await de({
351
392
  userId: g,
352
393
  fullName: _?.recipient_name ?? v?.recipient_name ?? null,
353
394
  phone: h,
354
- client: C
395
+ client: T
355
396
  });
356
397
  } catch (e) {
357
398
  console.error("Failed to sync checkout profile defaults before checkout:", e);
358
399
  }
359
- q && await c({
360
- client: C,
400
+ if (q && !(await s({
401
+ client: T,
361
402
  quote: q,
362
403
  orderId: Q,
363
404
  provider: "stripe",
364
405
  discountTotal: K,
365
406
  userId: g,
366
- customerEmail: u,
407
+ customerEmail: m,
367
408
  metadata: {
368
- currency: k.code,
409
+ currency: N.code,
369
410
  subtotal: G,
370
411
  shipping_total: J,
371
412
  tax_total: Z
372
413
  }
373
- });
374
- let $ = await fe({
375
- email: u,
414
+ })).success) return await T.from("orders").update({ status: "failed" }).eq("id", Q), {
415
+ url: null,
416
+ error: "Coupon is no longer available.",
417
+ errorKey: "ecommerce.coupon_invalid"
418
+ };
419
+ let $ = await _e({
420
+ email: m,
376
421
  phone: h,
377
422
  userId: g,
378
423
  billingAddress: _,
379
424
  shippingAddress: v
380
425
  });
381
426
  try {
382
- let e = await ge.checkout.sessions.create({
427
+ let e = await ye.checkout.sessions.create({
383
428
  mode: "payment",
384
- success_url: `${w}/checkout/success?session_id={CHECKOUT_SESSION_ID}`,
385
- cancel_url: `${w}/checkout`,
386
- locale: ue(he),
387
- line_items: H,
429
+ success_url: `${E}/checkout/success?session_id={CHECKOUT_SESSION_ID}`,
430
+ cancel_url: `${E}/checkout`,
431
+ locale: ge(b),
432
+ line_items: W,
388
433
  automatic_tax: X.enabled && X.mode === "automatic" ? { enabled: !0 } : void 0,
389
434
  billing_address_collection: "auto",
390
435
  customer: $ || void 0,
391
- customer_email: $ ? void 0 : u || void 0,
436
+ customer_email: $ ? void 0 : m || void 0,
392
437
  customer_creation: $ ? void 0 : "if_required",
393
438
  customer_update: $ ? {
394
439
  name: "auto",
395
440
  address: "auto",
396
441
  shipping: "auto"
397
442
  } : void 0,
398
- shipping_address_collection: T ? { allowed_countries: le } : void 0,
443
+ shipping_address_collection: A ? { allowed_countries: he } : void 0,
399
444
  metadata: {
400
445
  orderId: Q,
401
446
  taxMode: X.mode,
402
- currencyCode: k.code,
447
+ currencyCode: N.code,
403
448
  couponCode: q?.code || ""
404
449
  }
405
- }), { error: t } = await C.from("orders").update({ stripe_session_id: e.id }).eq("id", Q);
450
+ }), { error: t } = await T.from("orders").update({ stripe_session_id: e.id }).eq("id", Q);
406
451
  return t && console.error("Failed to save Stripe session ID on order:", t), { url: e.url };
407
452
  } catch (e) {
408
- return console.error("Stripe session creation failed:", e), await C.from("orders").update({ status: "failed" }).eq("id", Q), e?.name === "StripeNotConfiguredError" || e?.type === "StripeAuthenticationError" ? {
453
+ return console.error("Stripe session creation failed:", e), await T.from("orders").update({ status: "failed" }).eq("id", Q), e?.name === "StripeNotConfiguredError" || e?.type === "StripeAuthenticationError" ? {
409
454
  error: "This store is not able to take payments right now. Please contact the seller to complete your purchase.",
410
455
  errorKey: "ecommerce.checkout_payments_unavailable",
411
456
  errorStatus: 503,
@@ -419,4 +464,4 @@ var _ = class {
419
464
  }
420
465
  };
421
466
  //#endregion
422
- export { _ as StripeProvider };
467
+ export { g as StripeProvider };
@@ -1 +1 @@
1
- "use server";const e=require("../coupon-server.cjs");let t=require("@nextblock-cms/db/server");async function n(n){try{let r=(0,t.getServiceRoleSupabaseClient)();return await e.getCouponQuote({client:r,code:n.code,items:Array.isArray(n.items)?n.items:[],currencyCode:n.currencyCode})}catch(e){return console.error(`Failed to validate coupon:`,e),{success:!1,error:e.message||`Failed to validate coupon.`,errorKey:`ecommerce.coupon_validation_failed`}}}exports.getCouponQuoteAction=n;
1
+ "use server";const e=require("../coupons.cjs"),t=require("../coupon-server.cjs");let n=require("next/headers"),r=require("@nextblock-cms/db/server");async function i(i){try{let a=await(0,n.headers)();if(!t.consumeCouponValidationToken(t.resolveCouponValidationThrottleKey(a)))return{success:!1,error:e.COUPON_THROTTLED_ERROR_MESSAGE,errorKey:e.COUPON_THROTTLED_ERROR_KEY};let o=(0,r.getServiceRoleSupabaseClient)();return await t.getCouponQuote({client:o,code:i.code,items:Array.isArray(i.items)?i.items:[],currencyCode:i.currencyCode})}catch(e){return console.error(`Failed to validate coupon:`,e),{success:!1,error:`We couldn't validate this coupon. Try again.`,errorKey:`ecommerce.coupon_validation_failed`}}}exports.getCouponQuoteAction=i;
@@ -1,17 +1,16 @@
1
1
  import { CartItem } from '../types';
2
+ /**
3
+ * Public coupon validation for the cart and checkout forms.
4
+ *
5
+ * Reachable by anyone (a server action is a POST endpoint dispatched by id, no session
6
+ * needed) and it reads with the service-role client, so it is the only way a visitor can ask
7
+ * "does this code exist?". Two things keep that from being an enumeration oracle:
8
+ * `getCouponQuote` answers every unusable code with the same message, and this action spends a
9
+ * per-client token before it touches the database. The bucket is in-memory and best-effort
10
+ * (see coupon-server.ts); the uniform reply is what makes a slow probe also an unreliable one.
11
+ */
2
12
  export declare function getCouponQuoteAction(input: {
3
13
  code?: string | null;
4
14
  items: CartItem[];
5
15
  currencyCode?: string | null;
6
- }): Promise<{
7
- success: true;
8
- quote: import('../coupons').CouponQuote;
9
- } | {
10
- success: false;
11
- error: string;
12
- errorKey?: string;
13
- } | {
14
- success: false;
15
- error: any;
16
- errorKey: string;
17
- }>;
16
+ }): Promise<import('../coupons').CouponQuoteResult>;
@@ -1,23 +1,31 @@
1
1
  "use server";
2
- import { getCouponQuote as e } from "../coupon-server.es.js";
3
- import { getServiceRoleSupabaseClient as t } from "@nextblock-cms/db/server";
2
+ import { COUPON_THROTTLED_ERROR_KEY as e, COUPON_THROTTLED_ERROR_MESSAGE as t } from "../coupons.es.js";
3
+ import { consumeCouponValidationToken as n, getCouponQuote as r, resolveCouponValidationThrottleKey as i } from "../coupon-server.es.js";
4
+ import { headers as a } from "next/headers";
5
+ import { getServiceRoleSupabaseClient as o } from "@nextblock-cms/db/server";
4
6
  //#region src/lib/server-actions/coupon-actions.ts
5
- async function n(n) {
7
+ async function s(s) {
6
8
  try {
7
- let r = t();
8
- return await e({
9
- client: r,
10
- code: n.code,
11
- items: Array.isArray(n.items) ? n.items : [],
12
- currencyCode: n.currencyCode
9
+ let c = await a();
10
+ if (!n(i(c))) return {
11
+ success: !1,
12
+ error: t,
13
+ errorKey: e
14
+ };
15
+ let l = o();
16
+ return await r({
17
+ client: l,
18
+ code: s.code,
19
+ items: Array.isArray(s.items) ? s.items : [],
20
+ currencyCode: s.currencyCode
13
21
  });
14
22
  } catch (e) {
15
23
  return console.error("Failed to validate coupon:", e), {
16
24
  success: !1,
17
- error: e.message || "Failed to validate coupon.",
25
+ error: "We couldn't validate this coupon. Try again.",
18
26
  errorKey: "ecommerce.coupon_validation_failed"
19
27
  };
20
28
  }
21
29
  }
22
30
  //#endregion
23
- export { n as getCouponQuoteAction };
31
+ export { s as getCouponQuoteAction };