@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
@@ -3,17 +3,19 @@ import { getCouponQuote as r, recordCouponRedemption as i } from "../coupon-serv
3
3
  import { normalizeOrderCustomerDetails as a } from "../customer.es.js";
4
4
  import { fillMissingUserProfileCheckoutDetails as o, upsertDefaultUserAddresses as s } from "../customer-addresses.es.js";
5
5
  import { hydrateFreemiusEnvFromDb as c } from "../payment-config.es.js";
6
- import { createClient as l } from "@supabase/supabase-js";
7
- import u from "crypto";
8
- import { Freemius as d } from "@freemius/sdk";
6
+ import { mintOrderAccessToken as l } from "../order-access-token.es.js";
7
+ import { normalizeCheckoutItems as u } from "./checkout-items.es.js";
8
+ import { createClient as d } from "@supabase/supabase-js";
9
+ import f from "crypto";
10
+ import { Freemius as p } from "@freemius/sdk";
9
11
  //#region src/lib/providers/freemius.ts
10
- function f(e) {
12
+ function m(e) {
11
13
  let t = process.env[e];
12
14
  if (!t) return null;
13
15
  let n = t.trim();
14
16
  return n.startsWith("\"") && n.endsWith("\"") || n.startsWith("'") && n.endsWith("'") ? n.slice(1, -1).trim() : n;
15
17
  }
16
- function p(e) {
18
+ function h(e) {
17
19
  let t = e?.trim();
18
20
  if (!t) return {
19
21
  firstName: null,
@@ -25,39 +27,39 @@ function p(e) {
25
27
  lastName: r.length > 0 ? r.join(" ") : null
26
28
  };
27
29
  }
28
- function m(e) {
30
+ function g(e) {
29
31
  if (e == null || e === "") return 0;
30
32
  let t = Number(e);
31
33
  return !Number.isFinite(t) || t <= 0 ? 0 : Math.round(t);
32
34
  }
33
- function h(e) {
35
+ function _(e) {
34
36
  return e === !0 || e === 1 || e === "1" || e === "true";
35
37
  }
36
- function g(e, t) {
38
+ function v(e, t) {
37
39
  let n = e?.[t];
38
40
  return Array.isArray(n) ? n : n && typeof n == "object" ? [n] : [];
39
41
  }
40
- function _(e, t) {
42
+ function y(e, t) {
41
43
  for (let n of t) {
42
- let t = g(e, n);
44
+ let t = v(e, n);
43
45
  if (t.length > 0) return t;
44
46
  }
45
47
  return Array.isArray(e) ? e : [];
46
48
  }
47
- function v(e) {
49
+ function b(e) {
48
50
  if (e == null || e === "") return null;
49
51
  let t = Number(e);
50
52
  return Number.isFinite(t) ? t : null;
51
53
  }
52
- function y(e) {
54
+ function x(e) {
53
55
  return e === null ? 0 : e > 5e3 ? (console.warn(`[Freemius Sync] Suspiciously high price detected: ${e}. Assuming it is already in cents.`), Math.round(e)) : Math.round(e * 100);
54
56
  }
55
- function b(e) {
57
+ function S(e) {
56
58
  let t = Number(e);
57
59
  return !Number.isFinite(t) || t < 1 ? 1 : Math.round(t);
58
60
  }
59
- function x() {
60
- let e = f("FREEMIUS_CHECKOUT_PRODUCTS_JSON");
61
+ function C() {
62
+ let e = m("FREEMIUS_CHECKOUT_PRODUCTS_JSON");
61
63
  if (!e) return null;
62
64
  try {
63
65
  let t = JSON.parse(e);
@@ -66,8 +68,8 @@ function x() {
66
68
  return console.error("[Freemius Checkout] Failed to parse FREEMIUS_CHECKOUT_PRODUCTS_JSON:", e), null;
67
69
  }
68
70
  }
69
- function S(e) {
70
- let t = x(), n = String(e), r = t?.[n], i = f("FREEMIUS_PRODUCT_ID"), a = f("FREEMIUS_ECOMMERCE_SANDBOX_PUBLIC_KEY"), o = f("FREEMIUS_ECOMMERCE_SANDBOX_SECRET_KEY");
71
+ function w(e) {
72
+ let t = C(), n = String(e), r = t?.[n], i = m("FREEMIUS_PRODUCT_ID"), a = m("FREEMIUS_ECOMMERCE_SANDBOX_PUBLIC_KEY"), o = m("FREEMIUS_ECOMMERCE_SANDBOX_SECRET_KEY");
71
73
  return r?.publicKey ? {
72
74
  publicKey: r.publicKey,
73
75
  secretKey: r.secretKey ?? null,
@@ -76,85 +78,99 @@ function S(e) {
76
78
  } : process.env.FREEMIUS_SANDBOX_ENABLED === "true" && i && i === n && a ? {
77
79
  publicKey: a,
78
80
  secretKey: o,
79
- apiKey: f("FREEMIUS_API_KEY"),
81
+ apiKey: m("FREEMIUS_API_KEY"),
80
82
  source: "single-product-sandbox-env"
81
- } : i && i === n && f("FREEMIUS_PUBLIC_KEY") ? {
82
- publicKey: f("FREEMIUS_PUBLIC_KEY"),
83
- secretKey: f("FREEMIUS_SECRET_KEY"),
84
- apiKey: f("FREEMIUS_API_KEY"),
83
+ } : i && i === n && m("FREEMIUS_PUBLIC_KEY") ? {
84
+ publicKey: m("FREEMIUS_PUBLIC_KEY"),
85
+ secretKey: m("FREEMIUS_SECRET_KEY"),
86
+ apiKey: m("FREEMIUS_API_KEY"),
85
87
  source: "single-product-env"
86
88
  } : {
87
- publicKey: f("FREEMIUS_PUBLIC_KEY"),
88
- secretKey: f("FREEMIUS_SECRET_KEY"),
89
- apiKey: f("FREEMIUS_API_KEY"),
89
+ publicKey: m("FREEMIUS_PUBLIC_KEY"),
90
+ secretKey: m("FREEMIUS_SECRET_KEY"),
91
+ apiKey: m("FREEMIUS_API_KEY"),
90
92
  source: "legacy-env"
91
93
  };
92
94
  }
93
- async function C(e) {
95
+ async function T(e) {
94
96
  if (!e.apiKey) throw Error("Missing Freemius API key for SDK sandbox generation.");
95
- return new d({
97
+ return new p({
96
98
  productId: Number(e.productId),
97
99
  apiKey: e.apiKey,
98
100
  secretKey: e.secretKey,
99
101
  publicKey: e.publicKey
100
102
  }).checkout.getSandboxParams();
101
103
  }
102
- var w = class {
104
+ var E = class {
103
105
  getProviderName() {
104
106
  return "Freemius";
105
107
  }
106
- async createCheckoutSession({ items: d, customerEmail: h, customerPhone: g, userId: _, billingAddress: v, shippingAddress: y, currencyCode: b, couponCode: x, couponContextItems: w }) {
107
- let T = process.env.NEXT_PUBLIC_SUPABASE_URL || process.env.SUPABASE_URL, E = process.env.SUPABASE_SERVICE_ROLE_KEY || process.env.SUPABASE_SECRET_KEY;
108
- if (!T || !E) return {
108
+ async createCheckoutSession({ items: p, customerEmail: _, customerPhone: v, userId: y, billingAddress: b, shippingAddress: x, currencyCode: S, couponCode: C, couponContextItems: E }) {
109
+ let D = process.env.NEXT_PUBLIC_SUPABASE_URL || process.env.SUPABASE_URL, O = process.env.SUPABASE_SERVICE_ROLE_KEY || process.env.SUPABASE_SECRET_KEY;
110
+ if (!D || !O) return {
109
111
  error: "Missing Supabase credentials for checkout (Service Key required).",
110
112
  url: null
111
113
  };
112
- let D = l(T, E);
113
- if (!d || d.length === 0) return {
114
+ let k = d(D, O);
115
+ if (!p || p.length === 0) return {
114
116
  error: "Cart is empty",
115
117
  url: null
116
118
  };
117
- if (d.length !== 1) return {
119
+ if (p.length !== 1) return {
118
120
  error: "Freemius items must be checked out one at a time.",
119
121
  url: null
120
122
  };
121
- let { data: O, error: k } = await D.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 }), A = O ?? [];
122
- if (k || A.length === 0) return {
123
+ let A = u(p);
124
+ if (!A.ok) return {
125
+ url: null,
126
+ ...A.error
127
+ };
128
+ let ee = A.items;
129
+ if (E && E.length > 0) {
130
+ let e = u(E);
131
+ if (!e.ok) return {
132
+ url: null,
133
+ ...e.error
134
+ };
135
+ ee = e.items;
136
+ }
137
+ let { data: te, error: ne } = await k.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 }), j = te ?? [];
138
+ if (ne || j.length === 0) return {
123
139
  error: "Failed to resolve store currencies",
124
140
  url: null
125
141
  };
126
- let ee = e(A), j = A.find((e) => e.code === (b || "").toUpperCase()) ?? ee, M = d[0], { data: N, error: te } = await D.from("products").select("id, title, price, prices, sale_price, sale_prices, sale_start_at, sale_end_at, scheduled_price, scheduled_prices, scheduled_price_at, freemius_plan_id, freemius_product_id, trial_period_days, trial_requires_payment_method").eq("id", M.product_id).single();
127
- if (te || !N) return {
142
+ let re = e(j), M = j.find((e) => e.code === (S || "").toUpperCase()) ?? re, N = A.items[0], { data: P, error: ie } = await k.from("products").select("id, title, price, prices, sale_price, sale_prices, sale_start_at, sale_end_at, scheduled_price, scheduled_prices, scheduled_price_at, freemius_plan_id, freemius_product_id, trial_period_days, trial_requires_payment_method").eq("id", N.product_id).single();
143
+ if (ie || !P) return {
128
144
  error: "Product not found",
129
145
  url: null
130
146
  };
131
- let P = N.freemius_plan_id, F = N.freemius_product_id;
132
- if (!P || !F) return {
147
+ let F = P.freemius_plan_id, I = P.freemius_product_id;
148
+ if (!F || !I) return {
133
149
  error: "Product is not configured for Freemius checkout (missing Plan ID or Product ID)",
134
150
  url: null
135
151
  };
136
- let I = n({
137
- prices: N.prices || {},
138
- salePrices: N.sale_prices || {},
139
- fallbackPrice: N.price,
140
- fallbackSalePrice: N.sale_price,
141
- saleStartAt: N.sale_start_at,
142
- saleEndAt: N.sale_end_at,
143
- scheduledPrice: N.scheduled_price,
144
- scheduledPrices: N.scheduled_prices || {},
145
- scheduledPriceAt: N.scheduled_price_at,
146
- currencyCode: j.code,
147
- currencies: A
148
- }), L = I.sale_price ?? I.price, ne = t({
149
- saleStartAt: N.sale_start_at,
150
- saleEndAt: N.sale_end_at
151
- }), R = L * M.quantity, z = null, B = 0;
152
- if (x) {
152
+ let L = n({
153
+ prices: P.prices || {},
154
+ salePrices: P.sale_prices || {},
155
+ fallbackPrice: P.price,
156
+ fallbackSalePrice: P.sale_price,
157
+ saleStartAt: P.sale_start_at,
158
+ saleEndAt: P.sale_end_at,
159
+ scheduledPrice: P.scheduled_price,
160
+ scheduledPrices: P.scheduled_prices || {},
161
+ scheduledPriceAt: P.scheduled_price_at,
162
+ currencyCode: M.code,
163
+ currencies: j
164
+ }), ae = L.sale_price ?? L.price, oe = t({
165
+ saleStartAt: P.sale_start_at,
166
+ saleEndAt: P.sale_end_at
167
+ }), R = ae * N.quantity, z = null, B = 0;
168
+ if (C) {
153
169
  let e = await r({
154
- client: D,
155
- code: x,
156
- items: w && w.length > 0 ? w : d,
157
- currencyCode: j.code
170
+ client: k,
171
+ code: C,
172
+ items: ee,
173
+ currencyCode: M.code
158
174
  });
159
175
  if (!e.success) return {
160
176
  error: e.error,
@@ -162,13 +178,13 @@ var w = class {
162
178
  errorStatus: 400,
163
179
  url: null
164
180
  };
165
- z = e.quote, B = Math.min(R, z.lineDiscounts.filter((e) => e.product_id === N.id).reduce((e, t) => e + t.discount, 0));
181
+ z = e.quote, B = Math.min(R, z.lineDiscounts.filter((e) => e.product_id === P.id).reduce((e, t) => e + t.discount, 0));
166
182
  }
167
- let V = m(N.trial_period_days), H = V > 0 ? M.trial_preference ? M.trial_preference : N.trial_requires_payment_method ? "paid" : "free" : null, U = "pending", W = p(v?.recipient_name ?? null), { data: G, error: K } = await D.from("orders").insert({
183
+ let V = g(P.trial_period_days), H = V > 0 ? N.trial_preference ? N.trial_preference : P.trial_requires_payment_method ? "paid" : "free" : null, U = "pending", W = h(b?.recipient_name ?? null), { data: G, error: K } = await k.from("orders").insert({
168
184
  status: U,
169
185
  total: Math.max(0, R - B),
170
- currency: j.code,
171
- exchange_rate_at_purchase: j.exchange_rate,
186
+ currency: M.code,
187
+ exchange_rate_at_purchase: M.exchange_rate,
172
188
  subtotal: R,
173
189
  discount_total: B,
174
190
  coupon_id: z?.couponId ?? null,
@@ -183,57 +199,62 @@ var w = class {
183
199
  final_amount_owned_by: "freemius"
184
200
  } : null,
185
201
  provider: "freemius",
186
- freemius_product_id: String(F),
187
- freemius_plan_id: String(P),
188
- user_id: _ || null,
202
+ freemius_product_id: String(I),
203
+ freemius_plan_id: String(F),
204
+ user_id: y || null,
189
205
  customer_details: a({
190
- email: h,
191
- phone: g,
192
- name: v?.recipient_name,
193
- billing: v,
194
- shipping: y
206
+ email: _,
207
+ phone: v,
208
+ name: b?.recipient_name,
209
+ billing: b,
210
+ shipping: x
195
211
  })
196
212
  }).select("id").single();
197
213
  if (K || !G) return console.error("Failed to create pending order:", K), {
198
214
  error: "Failed to initiate order",
199
215
  url: null
200
216
  };
201
- let { error: q } = await D.from("order_items").insert([{
217
+ let { error: q } = await k.from("order_items").insert([{
202
218
  order_id: G.id,
203
- product_id: N.id,
204
- quantity: M.quantity,
205
- price_at_purchase: L
219
+ product_id: P.id,
220
+ quantity: N.quantity,
221
+ price_at_purchase: ae
206
222
  }]);
207
- if (q && console.error("Failed to insert order items:", q), _) try {
223
+ if (q && console.error("Failed to insert order items:", q), y) try {
208
224
  await s({
209
- userId: _,
210
- billingAddress: v,
211
- shippingAddress: y,
212
- client: D
225
+ userId: y,
226
+ billingAddress: b,
227
+ shippingAddress: x,
228
+ client: k
213
229
  }), await o({
214
- userId: _,
215
- fullName: v?.recipient_name ?? y?.recipient_name ?? null,
216
- phone: g,
217
- client: D
230
+ userId: y,
231
+ fullName: b?.recipient_name ?? x?.recipient_name ?? null,
232
+ phone: v,
233
+ client: k
218
234
  });
219
235
  } catch (e) {
220
236
  console.error("Failed to sync checkout profile defaults before checkout:", e);
221
237
  }
222
- z && await i({
223
- client: D,
238
+ if (z && !(await i({
239
+ client: k,
224
240
  quote: z,
225
241
  orderId: G.id,
226
242
  provider: "freemius",
227
243
  discountTotal: B,
228
- userId: _,
229
- customerEmail: h,
244
+ userId: y,
245
+ customerEmail: _,
230
246
  metadata: {
231
- currency: j.code,
247
+ currency: M.code,
232
248
  subtotal: R,
233
249
  final_amount_owned_by: "freemius"
234
250
  }
235
- }), await c();
236
- let J = process.env.FREEMIUS_SANDBOX_ENABLED === "true", Y = S(F), X = Y.publicKey, Z = Y.secretKey, re = Y.apiKey;
251
+ })).success) return await k.from("orders").update({ status: "failed" }).eq("id", G.id), {
252
+ url: null,
253
+ error: "Coupon is no longer available.",
254
+ errorKey: "ecommerce.coupon_invalid"
255
+ };
256
+ await c();
257
+ let J = process.env.FREEMIUS_SANDBOX_ENABLED === "true", Y = w(I), X = Y.publicKey, Z = Y.secretKey, se = Y.apiKey;
237
258
  if (!X || J && !Z) return console.error("Freemius checkout blocked: missing credentials (PUBLIC_KEY or SECRET_KEY) in CMS → Payments or environment."), {
238
259
  error: "This store is not able to take payments right now. Please contact the seller to complete your purchase.",
239
260
  errorKey: "ecommerce.checkout_payments_unavailable",
@@ -241,38 +262,38 @@ var w = class {
241
262
  url: null
242
263
  };
243
264
  if (J && Y.source === "legacy-env") {
244
- let e = f("FREEMIUS_PRODUCT_ID"), t = !!f("FREEMIUS_ECOMMERCE_SANDBOX_PUBLIC_KEY"), n = !!f("FREEMIUS_ECOMMERCE_SANDBOX_SECRET_KEY");
245
- console.warn(`[Freemius Checkout] Sandbox is enabled for product ${F}, but no product-scoped checkout credentials were selected. Falling back to legacy FREEMIUS_PUBLIC_KEY/FREEMIUS_SECRET_KEY may open live checkout instead of sandbox.`, {
265
+ let e = m("FREEMIUS_PRODUCT_ID"), t = !!m("FREEMIUS_ECOMMERCE_SANDBOX_PUBLIC_KEY"), n = !!m("FREEMIUS_ECOMMERCE_SANDBOX_SECRET_KEY");
266
+ console.warn(`[Freemius Checkout] Sandbox is enabled for product ${I}, but no product-scoped checkout credentials were selected. Falling back to legacy FREEMIUS_PUBLIC_KEY/FREEMIUS_SECRET_KEY may open live checkout instead of sandbox.`, {
246
267
  configuredProductId: e,
247
- productIdsMatch: e === String(F),
268
+ productIdsMatch: e === String(I),
248
269
  hasSandboxOverridePublicKey: t,
249
270
  hasSandboxOverrideSecretKey: n,
250
- hasCheckoutProductsJson: !!f("FREEMIUS_CHECKOUT_PRODUCTS_JSON")
271
+ hasCheckoutProductsJson: !!m("FREEMIUS_CHECKOUT_PRODUCTS_JSON")
251
272
  });
252
273
  }
253
274
  let Q = !1;
254
275
  if (J && Z && X) try {
255
- Q = await C({
256
- productId: F,
276
+ Q = await T({
277
+ productId: I,
257
278
  publicKey: X,
258
279
  secretKey: Z,
259
- apiKey: re
280
+ apiKey: se
260
281
  });
261
282
  } catch (e) {
262
283
  console.warn("Freemius Checkout - SDK sandbox generation failed. Falling back to manual token generation.", e, {
263
284
  credentialSource: Y.source,
264
- hasApiKey: !!re
285
+ hasApiKey: !!se
265
286
  });
266
- let t = Math.floor(Date.now() / 1e3).toString(), n = `${t}${F}${Z}${X}checkout`;
287
+ let t = Math.floor(Date.now() / 1e3).toString(), n = `${t}${I}${Z}${X}checkout`;
267
288
  Q = {
268
289
  ctx: t,
269
- token: u.createHash("md5").update(n).digest("hex")
290
+ token: f.createHash("md5").update(n).digest("hex")
270
291
  };
271
292
  }
272
- let $ = new URL(`https://checkout.freemius.com/app/${F}/plan/${P}/`);
273
- if (J && Z && X ? ($.searchParams.append("sandbox", Q.token), $.searchParams.append("s_ctx_ts", Q.ctx)) : J && $.searchParams.append("sandbox", "true"), h && $.searchParams.append("user_email", h), W.firstName && $.searchParams.append("user_firstname", W.firstName), W.lastName && $.searchParams.append("user_lastname", W.lastName), $.searchParams.append("currency", j.code.toLowerCase()), M.billing_cycle && $.searchParams.append("billing_cycle", M.billing_cycle), H && $.searchParams.append("trial", H), z) $.searchParams.append("coupon", z.code);
274
- else if (ne) {
275
- let { data: e } = await D.from("product_freemius_sale_coupons").select("freemius_coupon_code, is_active, starts_at, ends_at, sync_status").eq("product_id", N.id).maybeSingle();
293
+ let $ = new URL(`https://checkout.freemius.com/app/${I}/plan/${F}/`);
294
+ if (J && Z && X ? ($.searchParams.append("sandbox", Q.token), $.searchParams.append("s_ctx_ts", Q.ctx)) : J && $.searchParams.append("sandbox", "true"), _ && $.searchParams.append("user_email", _), W.firstName && $.searchParams.append("user_firstname", W.firstName), W.lastName && $.searchParams.append("user_lastname", W.lastName), $.searchParams.append("currency", M.code.toLowerCase()), N.billing_cycle && $.searchParams.append("billing_cycle", N.billing_cycle), H && $.searchParams.append("trial", H), z) $.searchParams.append("coupon", z.code);
295
+ else if (oe) {
296
+ let { data: e } = await k.from("product_freemius_sale_coupons").select("freemius_coupon_code, is_active, starts_at, ends_at, sync_status").eq("product_id", P.id).maybeSingle();
276
297
  e?.is_active && e.sync_status === "synced" && e.freemius_coupon_code && t({
277
298
  saleStartAt: e.starts_at,
278
299
  saleEndAt: e.ends_at
@@ -282,27 +303,28 @@ var w = class {
282
303
  url: $.toString(),
283
304
  customProps: {
284
305
  provider: "freemius",
285
- plugin_id: F,
286
- plan_id: P,
306
+ plugin_id: I,
307
+ plan_id: F,
287
308
  public_key: X,
288
- user_email: h,
309
+ user_email: _,
289
310
  user_firstname: W.firstName,
290
311
  user_lastname: W.lastName,
291
312
  credential_source: Y.source,
292
313
  sandbox: Q,
293
- billing_cycle: M.billing_cycle,
314
+ billing_cycle: N.billing_cycle,
294
315
  trial: H,
295
316
  trial_period_days: V,
296
- trial_requires_payment_method: N.trial_requires_payment_method,
317
+ trial_requires_payment_method: P.trial_requires_payment_method,
297
318
  initial_order_status: U,
298
319
  coupon: z?.code ?? null,
299
- order_id: G.id
320
+ order_id: G.id,
321
+ success_token: l(G.id)
300
322
  }
301
323
  };
302
324
  }
303
325
  };
304
- async function T(e, t, n, r) {
305
- let i = (/* @__PURE__ */ new Date()).toUTCString().replace("GMT", "+0000"), a = `GET\n\n\n${i}\n${e}`, o = u.createHmac("sha256", r).update(a).digest("hex"), s = `FS ${t}:${n}:${Buffer.from(o).toString("base64").replace(/\+/g, "-").replace(/\//g, "_").replace(/=/g, "")}`, c = await fetch(`https://api.freemius.com${e}`, { headers: {
326
+ async function D(e, t, n, r) {
327
+ let i = (/* @__PURE__ */ new Date()).toUTCString().replace("GMT", "+0000"), a = `GET\n\n\n${i}\n${e}`, o = f.createHmac("sha256", r).update(a).digest("hex"), s = `FS ${t}:${n}:${Buffer.from(o).toString("base64").replace(/\+/g, "-").replace(/\//g, "_").replace(/=/g, "")}`, c = await fetch(`https://api.freemius.com${e}`, { headers: {
306
328
  Authorization: s,
307
329
  Date: i,
308
330
  Accept: "application/json"
@@ -313,16 +335,16 @@ async function T(e, t, n, r) {
313
335
  }
314
336
  return c.json();
315
337
  }
316
- async function E() {
317
- let e = f("FREEMIUS_DEVELOPER_ID"), t = f("FREEMIUS_PUBLIC_KEY"), n = f("FREEMIUS_SECRET_KEY"), r = process.env.NEXT_PUBLIC_SUPABASE_URL || process.env.SUPABASE_URL, i = process.env.SUPABASE_SERVICE_ROLE_KEY || process.env.SUPABASE_SECRET_KEY;
338
+ async function O() {
339
+ let e = m("FREEMIUS_DEVELOPER_ID"), t = m("FREEMIUS_PUBLIC_KEY"), n = m("FREEMIUS_SECRET_KEY"), r = process.env.NEXT_PUBLIC_SUPABASE_URL || process.env.SUPABASE_URL, i = process.env.SUPABASE_SERVICE_ROLE_KEY || process.env.SUPABASE_SECRET_KEY;
318
340
  if (!e || !t || !n || !r || !i) throw Error("Missing necessary environment variables for Freemius Sync.");
319
- let a = l(r, i, { auth: {
341
+ let a = d(r, i, { auth: {
320
342
  autoRefreshToken: !1,
321
343
  persistSession: !1
322
- } }), o = (r) => T(r, e, t, n);
344
+ } }), o = (r) => D(r, e, t, n);
323
345
  try {
324
346
  console.log(`[Freemius Sync] Fetching all plugins for developer ${e}...`);
325
- let t = _(await o(`/v1/developers/${e}/plugins.json`), ["plugins", "plugin"]);
347
+ let t = y(await o(`/v1/developers/${e}/plugins.json`), ["plugins", "plugin"]);
326
348
  console.log(`[Freemius Sync] Found ${t.length} plugins. Syncing plans...`);
327
349
  let n = 0, { data: r } = await a.from("languages").select("id").eq("code", "en").single(), i = r?.id;
328
350
  if (!i) throw Error("English language not found in database. Cannot sync products.");
@@ -332,7 +354,7 @@ async function E() {
332
354
  console.warn("[Freemius Sync] Skipping plugin without an id:", r);
333
355
  continue;
334
356
  }
335
- let s = await O(a, e, t, r.title || r.name || `Freemius Product ${t}`, o, i);
357
+ let s = await A(a, e, t, r.title || r.name || `Freemius Product ${t}`, o, i);
336
358
  n += s;
337
359
  }
338
360
  return {
@@ -343,22 +365,22 @@ async function E() {
343
365
  throw console.error("[Freemius Sync] Global Error:", e), e;
344
366
  }
345
367
  }
346
- async function D(e) {
347
- let t = f("FREEMIUS_DEVELOPER_ID"), n = f("FREEMIUS_PUBLIC_KEY"), r = f("FREEMIUS_SECRET_KEY"), i = process.env.NEXT_PUBLIC_SUPABASE_URL || process.env.SUPABASE_URL, a = process.env.SUPABASE_SERVICE_ROLE_KEY || process.env.SUPABASE_SECRET_KEY;
368
+ async function k(e) {
369
+ let t = m("FREEMIUS_DEVELOPER_ID"), n = m("FREEMIUS_PUBLIC_KEY"), r = m("FREEMIUS_SECRET_KEY"), i = process.env.NEXT_PUBLIC_SUPABASE_URL || process.env.SUPABASE_URL, a = process.env.SUPABASE_SERVICE_ROLE_KEY || process.env.SUPABASE_SECRET_KEY;
348
370
  if (!t || !n || !r || !i || !a) throw Error("Missing environment variables for Freemius Sync.");
349
- let o = l(i, a), s = (e) => T(e, t, n, r), { data: c } = await o.from("languages").select("id").eq("code", "en").single(), u = c?.id;
350
- if (!u) throw Error("English language not found in database. Cannot sync products.");
351
- let d = await s(`/v1/developers/${t}/plugins/${e}.json`), p = d.plugin ?? d;
371
+ let o = d(i, a), s = (e) => D(e, t, n, r), { data: c } = await o.from("languages").select("id").eq("code", "en").single(), l = c?.id;
372
+ if (!l) throw Error("English language not found in database. Cannot sync products.");
373
+ let u = await s(`/v1/developers/${t}/plugins/${e}.json`), f = u.plugin ?? u;
352
374
  return {
353
375
  success: !0,
354
- count: await O(o, t, e, p.title || p.name || `Freemius Product ${e}`, s, u)
376
+ count: await A(o, t, e, f.title || f.name || `Freemius Product ${e}`, s, l)
355
377
  };
356
378
  }
357
- async function O(e, t, n, r, i, a) {
379
+ async function A(e, t, n, r, i, a) {
358
380
  console.log(`[Freemius Sync] Fetching plans for plugin: ${r} (${n})...`);
359
381
  let o = 0;
360
382
  try {
361
- let s = _(await i(`/v1/developers/${t}/plugins/${n}/plans.json`), ["plans", "plan"]);
383
+ let s = y(await i(`/v1/developers/${t}/plugins/${n}/plans.json`), ["plans", "plan"]);
362
384
  console.log(`[Freemius Sync] Received ${s.length} plans for plugin ${n}.`);
363
385
  for (let c of s) {
364
386
  let s = c.id?.toString();
@@ -378,25 +400,25 @@ async function O(e, t, n, r, i, a) {
378
400
  } catch (e) {
379
401
  console.warn(`[Freemius Sync] Could not fetch trial details for plan ${s}:`, e instanceof Error ? e.message : e);
380
402
  }
381
- let f = m(d.trial_period), p = f > 0 && h(d.is_require_subscription), g = 0, x = [];
403
+ let f = g(d.trial_period), p = f > 0 && _(d.is_require_subscription), m = 0, h = [];
382
404
  try {
383
- if (x = _(await i(`/v1/developers/${t}/plugins/${n}/plans/${s}/pricing.json`), [
405
+ if (h = y(await i(`/v1/developers/${t}/plugins/${n}/plans/${s}/pricing.json`), [
384
406
  "pricing",
385
407
  "prices",
386
408
  "pricings"
387
- ]), x.length > 0) {
388
- let e = x[0];
389
- g = y(v(e.annual_price) ?? v(e.monthly_price) ?? v(e.lifetime_price));
409
+ ]), h.length > 0) {
410
+ let e = h[0];
411
+ m = x(b(e.annual_price) ?? b(e.monthly_price) ?? b(e.lifetime_price));
390
412
  }
391
- console.log(`[Freemius Sync] Plan: ${u} -> Resolved Price (cents): ${g}`);
413
+ console.log(`[Freemius Sync] Plan: ${u} -> Resolved Price (cents): ${m}`);
392
414
  } catch (e) {
393
415
  console.warn(`[Freemius Sync] Could not fetch pricing for plan ${s}:`, e instanceof Error ? e.message : e);
394
416
  }
395
- let S = `${r}-${u}`.toLowerCase().replace(/[^\w\s-]/g, "").replace(/[\s_]+/g, "-").replace(/^-+|-+$/g, ""), C = {
417
+ let v = `${r}-${u}`.toLowerCase().replace(/[^\w\s-]/g, "").replace(/[\s_]+/g, "-").replace(/^-+|-+$/g, ""), C = {
396
418
  title: `${r} - ${u}`,
397
- slug: S,
419
+ slug: v,
398
420
  short_description: c.description || "",
399
- price: g,
421
+ price: m,
400
422
  product_type: "digital",
401
423
  payment_provider: "freemius",
402
424
  freemius_plan_id: s,
@@ -430,13 +452,13 @@ async function O(e, t, n, r, i, a) {
430
452
  }).select("id").single();
431
453
  n && console.warn(`[Freemius Sync] Could not insert local plan for ${C.sku}:`, n.message || n), t && (k = t.id);
432
454
  }
433
- if (k && x.length > 0) for (let t of x) {
434
- let n = b(t.licenses ?? t.license_quota ?? t.quota), { data: r, error: i } = await e.from("freemius_pricing").select("id").eq("plan_id", k).eq("license_quota", n).maybeSingle();
455
+ if (k && h.length > 0) for (let t of h) {
456
+ let n = S(t.licenses ?? t.license_quota ?? t.quota), { data: r, error: i } = await e.from("freemius_pricing").select("id").eq("plan_id", k).eq("license_quota", n).maybeSingle();
435
457
  i && console.warn(`[Freemius Sync] Could not check pricing for plan ${k}, quota ${n}:`, i.message || i);
436
458
  let a = {
437
- api_monthly_price: v(t.monthly_price),
438
- api_annual_price: v(t.annual_price),
439
- api_lifetime_price: v(t.lifetime_price),
459
+ api_monthly_price: b(t.monthly_price),
460
+ api_annual_price: b(t.annual_price),
461
+ api_lifetime_price: b(t.lifetime_price),
440
462
  updated_at: (/* @__PURE__ */ new Date()).toISOString()
441
463
  };
442
464
  if (r) {
@@ -459,4 +481,4 @@ async function O(e, t, n, r, i, a) {
459
481
  return o;
460
482
  }
461
483
  //#endregion
462
- export { w as FreemiusProvider, x as parseFreemiusCheckoutCredentialsMap, f as readFreemiusEnvValue, S as resolveFreemiusCheckoutCredentials, E as syncFreemiusProductsToSupabase, D as syncSingleFreemiusProduct };
484
+ export { E as FreemiusProvider, C as parseFreemiusCheckoutCredentialsMap, m as readFreemiusEnvValue, w as resolveFreemiusCheckoutCredentials, O as syncFreemiusProductsToSupabase, k as syncSingleFreemiusProduct };
@@ -1 +1 @@
1
- const e=require("../types.cjs"),t=require("../currency.cjs"),n=require("../coupons.cjs"),r=require("../coupon-server.cjs"),i=require("../countries.cjs"),a=require("../variation-utils.cjs"),o=require("../inventory-settings.cjs"),s=require("../tax-calculation.cjs"),c=require("../customer.cjs"),l=require("../customer-addresses.cjs"),u=require("../order-tax-details.cjs"),d=require("../stripe/client.cjs");let ee=require("@supabase/supabase-js");var te=i.countries.map(e=>e.code),f=new Set(`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(`.`));function p(e){if(e)return{line1:e.line1||void 0,line2:e.line2||void 0,city:e.city||void 0,state:e.state||void 0,postal_code:e.postal_code||void 0,country:e.country_code||void 0}}function ne(e){let t=e?.trim().replace(`_`,`-`);if(!t)return;let n=[t,t.toLowerCase(),t.split(`-`)[0].toLowerCase()];for(let e of n)if(f.has(e))return e}function re(e,t){return a.resolveTranslatedText(e.name,e.name_translations||null,t)}async function ie(e){if(!e.email)return null;let t=await d.getStripeClient(),n=p(e.shippingAddress),r=e.shippingAddress?.recipient_name||e.billingAddress?.recipient_name||void 0,i={email:e.email,name:e.billingAddress?.recipient_name||e.shippingAddress?.recipient_name||void 0,phone:e.phone||void 0,address:p(e.billingAddress),metadata:e.userId?{userId:e.userId}:void 0,...n&&r?{shipping:{name:r,phone:e.phone||void 0,address:n}}:{}};try{let n=(await t.customers.list({email:e.email,limit:1})).data[0];return n?(await t.customers.update(n.id,i),n.id):(await t.customers.create(i)).id}catch(e){return console.error(`Failed to upsert Stripe customer for checkout prefill:`,e),null}}var m=class{getProviderName(){return`Stripe`}async createCheckoutSession({items:i,customerEmail:a,customerPhone:f,userId:p,billingAddress:m,shippingAddress:h,shippingMethodId:g,currencyCode:ae,locale:_,couponCode:v,couponContextItems:y}){let oe=await d.getStripeClient(),b=process.env.NEXT_PUBLIC_SUPABASE_URL||process.env.SUPABASE_URL,x=process.env.SUPABASE_SERVICE_ROLE_KEY||process.env.SUPABASE_SECRET_KEY;if(!b||!x)return console.error(`Missing Supabase credentials for checkout (Service Key required).`),{error:`Internal Server Error`,url:null};let S=(0,ee.createClient)(b,x),C=process.env.NEXT_PUBLIC_URL||`http://localhost:4200`,se=i.some(t=>!e.isDigitalItem(t));if(!i.length)return{error:`Cart is empty`,url:null};let{data:ce,error:le}=await S.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}),w=ce??[];if(le||w.length===0)return console.error(`Error fetching currencies for checkout:`,le),{error:`Failed to resolve store currencies`,url:null};let T=t.getDefaultCurrency(w),E=w.find(e=>e.code===(ae||``).toUpperCase())??T,D=E.code.toLowerCase(),O=await o.getEcommerceInventorySettings(S),ue=i.map(e=>e.product_id),k=i.map(e=>e.variant_id).filter(e=>!!e),{data:A,error:j}=await S.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`,ue);if(j||!A)return console.error(`Error fetching products for validation:`,j),{error:`Failed to validate product prices`,url:null};let{data:de,error:M}=k.length?await S.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`,k):{data:[],error:null};if(M)return console.error(`Error fetching variants for validation:`,M),{error:`Failed to validate product variants`,url:null};let N=new Map(A.map(e=>[e.id,e])),P=new Map((de||[]).map(e=>[e.id,e])),F=new Set,I=new Map;for(let e of i){let t=N.get(e.product_id);if(!t)continue;let n=(e.variant_id?P.get(e.variant_id):null)?.sku||t.sku;n&&(F.add(n),I.set(n,(I.get(n)??0)+e.quantity))}let{data:fe,error:L}=F.size?await S.from(`inventory_items`).select(`sku, quantity`).in(`sku`,[...F]):{data:[],error:null};if(L)return console.error(`Error fetching SKU inventory for validation:`,L),{error:`Failed to validate SKU inventory`,url:null};let R=new Map((fe||[]).map(e=>[e.sku,Math.max(0,e.quantity??0)])),z=[],B=[],pe=[],V=0,H=0,U=null;if(v){let e=await r.getCouponQuote({client:S,code:v,items:y&&y.length>0?y:i,currencyCode:E.code});if(!e.success)return{error:e.error,errorKey:e.errorKey,errorStatus:400,url:null};U=e.quote}let me=r.getQuoteLineDiscountMap(U),he=e=>{let t=e.unitAmount*e.quantity,n=Math.max(0,t-e.lineDiscount);if(n<=0)return;let r=Math.floor(n/e.quantity),i=n-r*e.quantity,a=(t,n)=>{n<=0||t<=0||z.push({price_data:{currency:e.currency,product_data:{name:e.name,tax_code:s.getStripeTaxCodeForProduct(e.isTaxable),metadata:{productId:e.productId,variantId:e.variantId||``}},tax_behavior:`exclusive`,unit_amount:t},quantity:n})};a(r,e.quantity-i),a(r+1,i)};for(let e of i){let r=N.get(e.product_id);if(!r)return console.warn(`Product ${e.product_id} not found in DB.`),{url:null,...o.createInventoryUnavailableError(e.title)};let i=t.resolveEffectivePriceForCurrency({prices:t.normalizePriceMap(r.prices),salePrices:r.sale_prices||{},fallbackPrice:r.price,fallbackSalePrice:r.sale_price,saleStartAt:r.sale_start_at,saleEndAt:r.sale_end_at,scheduledPrice:r.scheduled_price,scheduledPrices:t.normalizePriceMap(r.scheduled_prices),scheduledPriceAt:r.scheduled_price_at,currencyCode:E.code,currencies:w}),a=i.sale_price??i.price,s=r.title,c=null;if(e.variant_id){let n=P.get(e.variant_id);if(!n||n.product_id!==e.product_id)return{url:null,...o.createInventoryUnavailableError(e.title)};let i=I.get(n.sku)??e.quantity,l=R.has(n.sku)?R.get(n.sku)??0:Math.max(0,n.stock_quantity??0);if(O.trackQuantities&&i>l)return{url:null,...o.createInventoryInsufficientError(e.title,l)};let u=t.resolveEffectivePriceForCurrency({prices:t.normalizePriceMap(n.prices),salePrices:n.sale_prices||{},fallbackPrice:n.price,fallbackSalePrice:n.sale_price,saleStartAt:n.sale_start_at,saleEndAt:n.sale_end_at,scheduledPrice:n.scheduled_price,scheduledPrices:t.normalizePriceMap(n.scheduled_prices),scheduledPriceAt:n.scheduled_price_at,currencyCode:E.code,currencies:w});a=u.sale_price??u.price,c=n.id,s=e.variant_label?`${r.title} - ${e.variant_label}`:`${r.title} - ${n.sku}`}else{let t=I.get(r.sku)??e.quantity,n=R.has(r.sku)?R.get(r.sku)??0:Math.max(0,r.stock??0);if(O.trackQuantities&&t>n)return{url:null,...o.createInventoryInsufficientError(e.title,n)}}let l=r.is_taxable??!0;if(a<0)return{error:`A product variation produced an invalid price.`,url:null};let u=Math.min(a*e.quantity,me.get(n.getCartLineCouponKey(e))??0);he({name:s,currency:D,productId:r.id,variantId:c,isTaxable:l,unitAmount:a,quantity:e.quantity,lineDiscount:u}),V+=a*e.quantity,H+=u,pe.push({product_id:r.id,quantity:e.quantity,price_at_purchase:a,variant_id:c}),B.push({product_id:r.id,quantity:e.quantity,unit_amount:a,discount_amount:u,is_taxable:l})}if(z.length===0&&H>=V)return{error:`This coupon would reduce the Stripe order to zero. Use a smaller discount for Stripe checkout.`,errorKey:`ecommerce.coupon_zero_total_not_supported`,errorStatus:400,url:null};if(z.length===0)return{error:`No valid items in cart`,url:null};let W=0,G=null;if(g){let{data:e,error:n}=await S.from(`shipping_zone_methods`).select(`id, name, name_translations, cost_amount, cost_currency`).eq(`id`,g).single();if(n)return console.error(`Failed to load shipping method:`,n),{error:`Failed to load shipping method`,url:null};W=t.convertMinorUnitAmount({amount:e.cost_amount??0,fromCurrencyCode:e.cost_currency||T.code,toCurrencyCode:E.code,currencies:w}),G=re(e,_)}let K=se?h??m:m,q;try{q=await s.calculateCheckoutTaxes(S,{items:B,destination:{country_code:K?.country_code,state:K?.state}})}catch(e){return console.error(`Failed to calculate checkout taxes:`,e),{error:`Failed to calculate taxes`,url:null}}W>0&&G&&z.push({price_data:{currency:D,product_data:{name:G,tax_code:q.enabled&&q.mode===`automatic`?s.STRIPE_TAX_CODE_SHIPPING:s.STRIPE_TAX_CODE_NONTAXABLE},tax_behavior:`exclusive`,unit_amount:W},quantity:1});let J=q.enabled&&q.mode===`manual`&&!q.isPendingExternalCalculation?q.amount:0;J>0&&z.push({price_data:{currency:D,product_data:{name:`Tax`,tax_code:s.STRIPE_TAX_CODE_NONTAXABLE},tax_behavior:`exclusive`,unit_amount:J},quantity:1});let ge=c.normalizeOrderCustomerDetails({email:a,phone:f,name:m?.recipient_name,billing:m,shipping:h}),Y=E.code,_e=u.buildOrderTaxDetailsFromCalculation({calculation:q,subtotal:V,shippingTotal:W,total:Math.max(0,V-H)+W+J,currency:Y}),ve=Math.max(0,V-H)+W+J,{data:X,error:Z}=await S.from(`orders`).insert({status:`pending`,total:ve,currency:Y,exchange_rate_at_purchase:E.exchange_rate,subtotal:V,shipping_total:W,tax_total:J,tax_details:_e,coupon_id:U?.couponId??null,coupon_code:U?.code??null,discount_total:H,discount_details:U?{code:U.code,discount_type:U.discountType,discount_amount:U.discountAmount,provider:`stripe`,provider_discounts:U.providerDiscounts,line_discounts:U.lineDiscounts}:null,provider:`stripe`,user_id:p,customer_details:ge}).select(`id`).single();if(Z||!X)return console.error(`Failed to create pending order:`,Z),{error:`Failed to initiate order`,url:null};let Q=X.id,{error:ye}=await S.from(`order_items`).insert(pe.map(e=>({order_id:Q,product_id:e.product_id,variant_id:e.variant_id??null,quantity:e.quantity,price_at_purchase:e.price_at_purchase})));if(ye)return console.error(`Failed to insert order items:`,ye),await S.from(`orders`).update({status:`failed`}).eq(`id`,Q),{error:`Failed to record order items`,url:null};if(p)try{await l.upsertDefaultUserAddresses({userId:p,billingAddress:m,shippingAddress:h,client:S}),await l.fillMissingUserProfileCheckoutDetails({userId:p,fullName:m?.recipient_name??h?.recipient_name??null,phone:f,client:S})}catch(e){console.error(`Failed to sync checkout profile defaults before checkout:`,e)}U&&await r.recordCouponRedemption({client:S,quote:U,orderId:Q,provider:`stripe`,discountTotal:H,userId:p,customerEmail:a,metadata:{currency:E.code,subtotal:V,shipping_total:W,tax_total:J}});let $=await ie({email:a,phone:f,userId:p,billingAddress:m,shippingAddress:h});try{let e=await oe.checkout.sessions.create({mode:`payment`,success_url:`${C}/checkout/success?session_id={CHECKOUT_SESSION_ID}`,cancel_url:`${C}/checkout`,locale:ne(_),line_items:z,automatic_tax:q.enabled&&q.mode===`automatic`?{enabled:!0}:void 0,billing_address_collection:`auto`,customer:$||void 0,customer_email:$?void 0:a||void 0,customer_creation:$?void 0:`if_required`,customer_update:$?{name:`auto`,address:`auto`,shipping:`auto`}:void 0,shipping_address_collection:se?{allowed_countries:te}:void 0,metadata:{orderId:Q,taxMode:q.mode,currencyCode:E.code,couponCode:U?.code||``}}),{error:t}=await S.from(`orders`).update({stripe_session_id:e.id}).eq(`id`,Q);return t&&console.error(`Failed to save Stripe session ID on order:`,t),{url:e.url}}catch(e){return console.error(`Stripe session creation failed:`,e),await S.from(`orders`).update({status:`failed`}).eq(`id`,Q),e?.name===`StripeNotConfiguredError`||e?.type===`StripeAuthenticationError`?{error:`This store is not able to take payments right now. Please contact the seller to complete your purchase.`,errorKey:`ecommerce.checkout_payments_unavailable`,errorStatus:503,url:null}:{error:`Something went wrong while preparing your checkout. Please try again.`,errorKey:`ecommerce.checkout_internal_server_error`,url:null}}}};exports.StripeProvider=m;
1
+ const e=require("../types.cjs"),t=require("../currency.cjs"),n=require("../coupons.cjs"),r=require("../coupon-server.cjs"),i=require("../countries.cjs"),a=require("../shipping/checkout-shipping-method.cjs"),o=require("../inventory-settings.cjs"),s=require("../tax-calculation.cjs"),c=require("../customer.cjs"),l=require("../customer-addresses.cjs"),u=require("./checkout-items.cjs"),ee=require("../order-tax-details.cjs"),d=require("../stripe/client.cjs");let te=require("@supabase/supabase-js");var ne=i.countries.map(e=>e.code),f=new Set(`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(`.`));function p(e){if(e)return{line1:e.line1||void 0,line2:e.line2||void 0,city:e.city||void 0,state:e.state||void 0,postal_code:e.postal_code||void 0,country:e.country_code||void 0}}function re(e){let t=e?.trim().replace(`_`,`-`);if(!t)return;let n=[t,t.toLowerCase(),t.split(`-`)[0].toLowerCase()];for(let e of n)if(f.has(e))return e}async function ie(e){if(!e.email)return null;let t=await d.getStripeClient(),n=p(e.shippingAddress),r=e.shippingAddress?.recipient_name||e.billingAddress?.recipient_name||void 0,i={email:e.email,name:e.billingAddress?.recipient_name||e.shippingAddress?.recipient_name||void 0,phone:e.phone||void 0,address:p(e.billingAddress),metadata:e.userId?{userId:e.userId}:void 0,...n&&r?{shipping:{name:r,phone:e.phone||void 0,address:n}}:{}};try{let n=(await t.customers.list({email:e.email,limit:1})).data[0];return n?(await t.customers.update(n.id,i),n.id):(await t.customers.create(i)).id}catch(e){return console.error(`Failed to upsert Stripe customer for checkout prefill:`,e),null}}var m=class{getProviderName(){return`Stripe`}async createCheckoutSession({items:i,customerEmail:f,customerPhone:p,userId:m,billingAddress:h,shippingAddress:g,shippingMethodId:_,currencyCode:ae,locale:v,couponCode:y,couponContextItems:b}){let oe=await d.getStripeClient(),x=process.env.NEXT_PUBLIC_SUPABASE_URL||process.env.SUPABASE_URL,S=process.env.SUPABASE_SERVICE_ROLE_KEY||process.env.SUPABASE_SECRET_KEY;if(!x||!S)return console.error(`Missing Supabase credentials for checkout (Service Key required).`),{error:`Internal Server Error`,url:null};let C=(0,te.createClient)(x,S),se=process.env.NEXT_PUBLIC_URL||`http://localhost:4200`;if(!i?.length)return{error:`Cart is empty`,url:null};let w=u.normalizeCheckoutItems(i);if(!w.ok)return{url:null,...w.error};let T=w.items,ce=T;if(b&&b.length>0){let e=u.normalizeCheckoutItems(b);if(!e.ok)return{url:null,...e.error};ce=e.items}let E=T.some(t=>!e.isDigitalItem(t)),{data:le,error:ue}=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=le??[];if(ue||D.length===0)return console.error(`Error fetching currencies for checkout:`,ue),{error:`Failed to resolve store currencies`,url:null};let de=t.getDefaultCurrency(D),O=D.find(e=>e.code===(ae||``).toUpperCase())??de,k=O.code.toLowerCase(),A=await o.getEcommerceInventorySettings(C),fe=T.map(e=>e.product_id),j=T.map(e=>e.variant_id).filter(e=>!!e),{data:M,error:N}=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`,fe);if(N||!M)return console.error(`Error fetching products for validation:`,N),{error:`Failed to validate product prices`,url:null};let{data:pe,error:P}=j.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`,j):{data:[],error:null};if(P)return console.error(`Error fetching variants for validation:`,P),{error:`Failed to validate product variants`,url:null};let F=new Map(M.map(e=>[e.id,e])),I=new Map((pe||[]).map(e=>[e.id,e])),L=new Set,R=new Map;for(let e of T){let t=F.get(e.product_id);if(!t)continue;let n=(e.variant_id?I.get(e.variant_id):null)?.sku||t.sku;n&&(L.add(n),R.set(n,(R.get(n)??0)+e.quantity))}let{data:me,error:z}=L.size?await C.from(`inventory_items`).select(`sku, quantity`).in(`sku`,[...L]):{data:[],error:null};if(z)return console.error(`Error fetching SKU inventory for validation:`,z),{error:`Failed to validate SKU inventory`,url:null};let B=new Map((me||[]).map(e=>[e.sku,Math.max(0,e.quantity??0)])),V=[],H=[],U=[],W=0,G=0,K=null;if(y){let e=await r.getCouponQuote({client:C,code:y,items:ce,currencyCode:O.code});if(!e.success)return{error:e.error,errorKey:e.errorKey,errorStatus:400,url:null};K=e.quote}let he=r.getQuoteLineDiscountMap(K),ge=e=>{let t=e.unitAmount*e.quantity,n=Math.max(0,t-e.lineDiscount);if(n<=0)return;let r=Math.floor(n/e.quantity),i=n-r*e.quantity,a=(t,n)=>{n<=0||t<=0||V.push({price_data:{currency:e.currency,product_data:{name:e.name,tax_code:s.getStripeTaxCodeForProduct(e.isTaxable),metadata:{productId:e.productId,variantId:e.variantId||``}},tax_behavior:`exclusive`,unit_amount:t},quantity:n})};a(r,e.quantity-i),a(r+1,i)};for(let e of T){let r=F.get(e.product_id);if(!r)return console.warn(`Product ${e.product_id} not found in DB.`),{url:null,...o.createInventoryUnavailableError(e.title)};let i=t.resolveEffectivePriceForCurrency({prices:t.normalizePriceMap(r.prices),salePrices:r.sale_prices||{},fallbackPrice:r.price,fallbackSalePrice:r.sale_price,saleStartAt:r.sale_start_at,saleEndAt:r.sale_end_at,scheduledPrice:r.scheduled_price,scheduledPrices:t.normalizePriceMap(r.scheduled_prices),scheduledPriceAt:r.scheduled_price_at,currencyCode:O.code,currencies:D}),a=i.sale_price??i.price,s=r.title,c=null;if(e.variant_id){let n=I.get(e.variant_id);if(!n||n.product_id!==e.product_id)return{url:null,...o.createInventoryUnavailableError(e.title)};let i=R.get(n.sku)??e.quantity,l=B.has(n.sku)?B.get(n.sku)??0:Math.max(0,n.stock_quantity??0);if(A.trackQuantities&&i>l)return{url:null,...o.createInventoryInsufficientError(e.title,l)};let u=t.resolveEffectivePriceForCurrency({prices:t.normalizePriceMap(n.prices),salePrices:n.sale_prices||{},fallbackPrice:n.price,fallbackSalePrice:n.sale_price,saleStartAt:n.sale_start_at,saleEndAt:n.sale_end_at,scheduledPrice:n.scheduled_price,scheduledPrices:t.normalizePriceMap(n.scheduled_prices),scheduledPriceAt:n.scheduled_price_at,currencyCode:O.code,currencies:D});a=u.sale_price??u.price,c=n.id,s=e.variant_label?`${r.title} - ${e.variant_label}`:`${r.title} - ${n.sku}`}else{let t=R.get(r.sku)??e.quantity,n=B.has(r.sku)?B.get(r.sku)??0:Math.max(0,r.stock??0);if(A.trackQuantities&&t>n)return{url:null,...o.createInventoryInsufficientError(e.title,n)}}let l=r.is_taxable??!0;if(a<0)return{error:`A product variation produced an invalid price.`,url:null};let u=Math.min(a*e.quantity,he.get(n.getCartLineCouponKey(e))??0);ge({name:s,currency:k,productId:r.id,variantId:c,isTaxable:l,unitAmount:a,quantity:e.quantity,lineDiscount:u}),W+=a*e.quantity,G+=u,U.push({product_id:r.id,quantity:e.quantity,price_at_purchase:a,variant_id:c}),H.push({product_id:r.id,quantity:e.quantity,unit_amount:a,discount_amount:u,is_taxable:l})}if(V.length===0&&G>=W)return{error:`This coupon would reduce the Stripe order to zero. Use a smaller discount for Stripe checkout.`,errorKey:`ecommerce.coupon_zero_total_not_supported`,errorStatus:400,url:null};if(V.length===0)return{error:`No valid items in cart`,url:null};let q=0,J=null;if(E){let e=a.normalizeShippingDestination({country:g?.country_code,state:g?.state,postal_code:g?.postal_code});if(!e)return{url:null,...a.createShippingAddressRequiredError()};let t={destination:e,cartTotal:Math.max(0,W-G),currencies:D,currencyCode:O.code};if(_){let e=await a.resolveCheckoutShippingMethod(C,{...t,methodId:_,languageCode:v});if(!e.ok)return e.reason===`load_failed`?(console.error(`Failed to load shipping method:`,e.error),{error:`Failed to load shipping method`,url:null}):(console.warn(`Checkout rejected shipping method ${_}: ${e.reason}`),{url:null,...a.createInvalidShippingMethodError()});q=e.method.amount,J=e.method.name}else{let e=await a.listEligibleShippingMethods(C,t);if(!e.ok)return console.error(`Failed to load shipping methods:`,e.error),{error:`Failed to load shipping method`,url:null};if(e.methods.length>0)return{url:null,...a.createShippingMethodRequiredError()}}}let _e=E?g??h:h,Y;try{Y=await s.calculateCheckoutTaxes(C,{items:H,destination:{country_code:_e?.country_code,state:_e?.state}})}catch(e){return console.error(`Failed to calculate checkout taxes:`,e),{error:`Failed to calculate taxes`,url:null}}q>0&&J&&V.push({price_data:{currency:k,product_data:{name:J,tax_code:Y.enabled&&Y.mode===`automatic`?s.STRIPE_TAX_CODE_SHIPPING:s.STRIPE_TAX_CODE_NONTAXABLE},tax_behavior:`exclusive`,unit_amount:q},quantity:1});let X=Y.enabled&&Y.mode===`manual`&&!Y.isPendingExternalCalculation?Y.amount:0;X>0&&V.push({price_data:{currency:k,product_data:{name:`Tax`,tax_code:s.STRIPE_TAX_CODE_NONTAXABLE},tax_behavior:`exclusive`,unit_amount:X},quantity:1});let ve=c.normalizeOrderCustomerDetails({email:f,phone:p,name:h?.recipient_name,billing:h,shipping:g}),Z=O.code,ye=ee.buildOrderTaxDetailsFromCalculation({calculation:Y,subtotal:W,shippingTotal:q,total:Math.max(0,W-G)+q+X,currency:Z}),be=Math.max(0,W-G)+q+X,{data:xe,error:Se}=await C.from(`orders`).insert({status:`pending`,total:be,currency:Z,exchange_rate_at_purchase:O.exchange_rate,subtotal:W,shipping_total:q,tax_total:X,tax_details:ye,coupon_id:K?.couponId??null,coupon_code:K?.code??null,discount_total:G,discount_details:K?{code:K.code,discount_type:K.discountType,discount_amount:K.discountAmount,provider:`stripe`,provider_discounts:K.providerDiscounts,line_discounts:K.lineDiscounts}:null,provider:`stripe`,user_id:m,customer_details:ve}).select(`id`).single();if(Se||!xe)return console.error(`Failed to create pending order:`,Se),{error:`Failed to initiate order`,url:null};let Q=xe.id,{error:Ce}=await C.from(`order_items`).insert(U.map(e=>({order_id:Q,product_id:e.product_id,variant_id:e.variant_id??null,quantity:e.quantity,price_at_purchase:e.price_at_purchase})));if(Ce)return console.error(`Failed to insert order items:`,Ce),await C.from(`orders`).update({status:`failed`}).eq(`id`,Q),{error:`Failed to record order items`,url:null};if(m)try{await l.upsertDefaultUserAddresses({userId:m,billingAddress:h,shippingAddress:g,client:C}),await l.fillMissingUserProfileCheckoutDetails({userId:m,fullName:h?.recipient_name??g?.recipient_name??null,phone:p,client:C})}catch(e){console.error(`Failed to sync checkout profile defaults before checkout:`,e)}if(K&&!(await r.recordCouponRedemption({client:C,quote:K,orderId:Q,provider:`stripe`,discountTotal:G,userId:m,customerEmail:f,metadata:{currency:O.code,subtotal:W,shipping_total:q,tax_total:X}})).success)return await C.from(`orders`).update({status:`failed`}).eq(`id`,Q),{url:null,error:`Coupon is no longer available.`,errorKey:`ecommerce.coupon_invalid`};let $=await ie({email:f,phone:p,userId:m,billingAddress:h,shippingAddress:g});try{let e=await oe.checkout.sessions.create({mode:`payment`,success_url:`${se}/checkout/success?session_id={CHECKOUT_SESSION_ID}`,cancel_url:`${se}/checkout`,locale:re(v),line_items:V,automatic_tax:Y.enabled&&Y.mode===`automatic`?{enabled:!0}:void 0,billing_address_collection:`auto`,customer:$||void 0,customer_email:$?void 0:f||void 0,customer_creation:$?void 0:`if_required`,customer_update:$?{name:`auto`,address:`auto`,shipping:`auto`}:void 0,shipping_address_collection:E?{allowed_countries:ne}:void 0,metadata:{orderId:Q,taxMode:Y.mode,currencyCode:O.code,couponCode:K?.code||``}}),{error:t}=await C.from(`orders`).update({stripe_session_id:e.id}).eq(`id`,Q);return t&&console.error(`Failed to save Stripe session ID on order:`,t),{url:e.url}}catch(e){return console.error(`Stripe session creation failed:`,e),await C.from(`orders`).update({status:`failed`}).eq(`id`,Q),e?.name===`StripeNotConfiguredError`||e?.type===`StripeAuthenticationError`?{error:`This store is not able to take payments right now. Please contact the seller to complete your purchase.`,errorKey:`ecommerce.checkout_payments_unavailable`,errorStatus:503,url:null}:{error:`Something went wrong while preparing your checkout. Please try again.`,errorKey:`ecommerce.checkout_internal_server_error`,url:null}}}};exports.StripeProvider=m;
@@ -2,7 +2,7 @@ import { CheckoutSessionInput } from '../customer';
2
2
  import { PaymentProvider } from '../types';
3
3
  export declare class StripeProvider implements PaymentProvider {
4
4
  getProviderName(): string;
5
- createCheckoutSession({ items: cartItems, customerEmail, customerPhone, userId, billingAddress, shippingAddress, shippingMethodId, currencyCode, locale, couponCode, couponContextItems, }: CheckoutSessionInput): Promise<{
5
+ createCheckoutSession({ items: submittedCartItems, customerEmail, customerPhone, userId, billingAddress, shippingAddress, shippingMethodId, currencyCode, locale, couponCode, couponContextItems: submittedCouponContextItems, }: CheckoutSessionInput): Promise<{
6
6
  url: string | null;
7
7
  error?: string;
8
8
  errorKey?: string;