@nextblock-cms/ecom 0.10.2 → 0.10.4

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 (34) hide show
  1. package/lib/components/CustomerProfileForm.cjs.js +1 -1
  2. package/lib/components/CustomerProfileForm.es.js +162 -159
  3. package/lib/freemius-coupons.cjs.js +1 -1
  4. package/lib/freemius-coupons.es.js +51 -49
  5. package/lib/pages/cms/payments/PaymentsClient.cjs.js +1 -1
  6. package/lib/pages/cms/payments/PaymentsClient.d.ts +4 -1
  7. package/lib/pages/cms/payments/PaymentsClient.es.js +255 -127
  8. package/lib/pages/cms/payments/PaymentsPage.cjs.js +1 -1
  9. package/lib/pages/cms/payments/PaymentsPage.es.js +20 -16
  10. package/lib/pages/cms/payments/actions.cjs.js +1 -1
  11. package/lib/pages/cms/payments/actions.d.ts +1 -0
  12. package/lib/pages/cms/payments/actions.es.js +41 -13
  13. package/lib/pages/cms/payments/queries.cjs.js +1 -1
  14. package/lib/pages/cms/payments/queries.es.js +13 -24
  15. package/lib/payment-config.cjs.js +1 -0
  16. package/lib/payment-config.d.ts +57 -0
  17. package/lib/payment-config.es.js +137 -0
  18. package/lib/providers/freemius.cjs.js +2 -2
  19. package/lib/providers/freemius.es.js +108 -107
  20. package/lib/providers/stripe.cjs.js +1 -1
  21. package/lib/providers/stripe.es.js +167 -167
  22. package/lib/stripe/checkout.cjs.js +1 -1
  23. package/lib/stripe/checkout.es.js +14 -14
  24. package/lib/stripe/client.cjs.js +1 -1
  25. package/lib/stripe/client.d.ts +1 -1
  26. package/lib/stripe/client.es.js +8 -5
  27. package/lib/stripe/order-sync.cjs.js +1 -1
  28. package/lib/stripe/order-sync.es.js +50 -50
  29. package/lib/stripe/webhooks.cjs.js +1 -1
  30. package/lib/stripe/webhooks.es.js +12 -10
  31. package/package.json +4 -4
  32. package/server.cjs.js +1 -1
  33. package/server.d.ts +1 -0
  34. package/server.es.js +188 -178
@@ -1,10 +1,11 @@
1
1
  import { createClient as H } from "@supabase/supabase-js";
2
2
  import Q from "crypto";
3
3
  import { Freemius as te } from "@freemius/sdk";
4
- import { normalizeOrderCustomerDetails as ne } from "../customer.es.js";
5
- import { getCouponQuote as ie, recordCouponRedemption as se } from "../coupon-server.es.js";
6
- import { upsertDefaultUserAddresses as oe, fillMissingUserProfileCheckoutDetails as ce } from "../customer-addresses.es.js";
7
- import { getDefaultCurrency as ae, resolveEffectivePriceForCurrency as le, isSaleWindowActive as z } from "../currency.es.js";
4
+ import { hydrateFreemiusEnvFromDb as ne } from "../payment-config.es.js";
5
+ import { normalizeOrderCustomerDetails as ie } from "../customer.es.js";
6
+ import { getCouponQuote as se, recordCouponRedemption as oe } from "../coupon-server.es.js";
7
+ import { upsertDefaultUserAddresses as ae, fillMissingUserProfileCheckoutDetails as ce } from "../customer-addresses.es.js";
8
+ import { getDefaultCurrency as ue, resolveEffectivePriceForCurrency as le, isSaleWindowActive as z } from "../currency.es.js";
8
9
  function o(e) {
9
10
  const r = process.env[e];
10
11
  if (!r)
@@ -12,7 +13,7 @@ function o(e) {
12
13
  const t = r.trim();
13
14
  return t.startsWith('"') && t.endsWith('"') || t.startsWith("'") && t.endsWith("'") ? t.slice(1, -1).trim() : t;
14
15
  }
15
- function ue(e) {
16
+ function de(e) {
16
17
  const r = e?.trim();
17
18
  if (!r)
18
19
  return {
@@ -31,16 +32,16 @@ function G(e) {
31
32
  const r = Number(e);
32
33
  return !Number.isFinite(r) || r <= 0 ? 0 : Math.round(r);
33
34
  }
34
- function de(e) {
35
+ function pe(e) {
35
36
  return e === !0 || e === 1 || e === "1" || e === "true";
36
37
  }
37
- function pe(e, r) {
38
+ function _e(e, r) {
38
39
  const t = e?.[r];
39
40
  return Array.isArray(t) ? t : t && typeof t == "object" ? [t] : [];
40
41
  }
41
42
  function X(e, r) {
42
43
  for (const t of r) {
43
- const i = pe(e, t);
44
+ const i = _e(e, t);
44
45
  if (i.length > 0)
45
46
  return i;
46
47
  }
@@ -52,16 +53,16 @@ function D(e) {
52
53
  const r = Number(e);
53
54
  return Number.isFinite(r) ? r : null;
54
55
  }
55
- function _e(e) {
56
+ function me(e) {
56
57
  return e === null ? 0 : e > 5e3 ? (console.warn(
57
58
  `[Freemius Sync] Suspiciously high price detected: ${e}. Assuming it is already in cents.`
58
59
  ), Math.round(e)) : Math.round(e * 100);
59
60
  }
60
- function me(e) {
61
+ function fe(e) {
61
62
  const r = Number(e);
62
63
  return !Number.isFinite(r) || r < 1 ? 1 : Math.round(r);
63
64
  }
64
- function fe() {
65
+ function Ee() {
65
66
  const e = o("FREEMIUS_CHECKOUT_PRODUCTS_JSON");
66
67
  if (!e)
67
68
  return null;
@@ -75,8 +76,8 @@ function fe() {
75
76
  ), null;
76
77
  }
77
78
  }
78
- function Ee(e) {
79
- const r = fe(), t = String(e), i = r?.[t], c = o("FREEMIUS_PRODUCT_ID"), d = o(
79
+ function ge(e) {
80
+ const r = Ee(), t = String(e), i = r?.[t], a = o("FREEMIUS_PRODUCT_ID"), d = o(
80
81
  "FREEMIUS_ECOMMERCE_SANDBOX_PUBLIC_KEY"
81
82
  ), f = o(
82
83
  "FREEMIUS_ECOMMERCE_SANDBOX_SECRET_KEY"
@@ -86,12 +87,12 @@ function Ee(e) {
86
87
  secretKey: i.secretKey ?? null,
87
88
  apiKey: i.apiKey ?? null,
88
89
  source: "product-map"
89
- } : process.env.FREEMIUS_SANDBOX_ENABLED === "true" && c && c === t && d ? {
90
+ } : process.env.FREEMIUS_SANDBOX_ENABLED === "true" && a && a === t && d ? {
90
91
  publicKey: d,
91
92
  secretKey: f,
92
93
  apiKey: o("FREEMIUS_API_KEY"),
93
94
  source: "single-product-sandbox-env"
94
- } : c && c === t && o("FREEMIUS_PUBLIC_KEY") ? {
95
+ } : a && a === t && o("FREEMIUS_PUBLIC_KEY") ? {
95
96
  publicKey: o("FREEMIUS_PUBLIC_KEY"),
96
97
  secretKey: o("FREEMIUS_SECRET_KEY"),
97
98
  apiKey: o("FREEMIUS_API_KEY"),
@@ -103,7 +104,7 @@ function Ee(e) {
103
104
  source: "legacy-env"
104
105
  };
105
106
  }
106
- async function ge(e) {
107
+ async function Se(e) {
107
108
  if (!e.apiKey)
108
109
  throw new Error("Missing Freemius API key for SDK sandbox generation.");
109
110
  return new te({
@@ -113,7 +114,7 @@ async function ge(e) {
113
114
  publicKey: e.publicKey
114
115
  }).checkout.getSandboxParams();
115
116
  }
116
- class Ue {
117
+ class we {
117
118
  getProviderName() {
118
119
  return "Freemius";
119
120
  }
@@ -121,17 +122,17 @@ class Ue {
121
122
  items: r,
122
123
  customerEmail: t,
123
124
  customerPhone: i,
124
- userId: c,
125
+ userId: a,
125
126
  billingAddress: d,
126
127
  shippingAddress: f,
127
128
  currencyCode: m,
128
129
  couponCode: K,
129
130
  couponContextItems: E
130
131
  }) {
131
- const a = process.env.NEXT_PUBLIC_SUPABASE_URL || process.env.SUPABASE_URL, l = process.env.SUPABASE_SERVICE_ROLE_KEY || process.env.SUPABASE_SECRET_KEY;
132
- if (!a || !l)
132
+ const c = process.env.NEXT_PUBLIC_SUPABASE_URL || process.env.SUPABASE_URL, u = process.env.SUPABASE_SERVICE_ROLE_KEY || process.env.SUPABASE_SECRET_KEY;
133
+ if (!c || !u)
133
134
  return { error: "Missing Supabase credentials for checkout (Service Key required).", url: null };
134
- const p = H(a, l);
135
+ const p = H(c, u);
135
136
  if (!r || r.length === 0)
136
137
  return { error: "Cart is empty", url: null };
137
138
  if (r.length !== 1)
@@ -141,11 +142,11 @@ class Ue {
141
142
  ).eq("is_active", !0).order("code", { ascending: !0 }), v = g ?? [];
142
143
  if (U || v.length === 0)
143
144
  return { error: "Failed to resolve store currencies", url: null };
144
- const j = ae(v), b = v.find((u) => u.code === (m || "").toUpperCase()) ?? j, S = r[0], { data: s, error: I } = await p.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", S.product_id).single();
145
+ const j = ue(v), b = v.find((l) => l.code === (m || "").toUpperCase()) ?? j, S = r[0], { data: s, error: I } = await p.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", S.product_id).single();
145
146
  if (I || !s)
146
147
  return { error: "Product not found", url: null };
147
- const w = s.freemius_plan_id, P = s.freemius_product_id;
148
- if (!w || !P)
148
+ const R = s.freemius_plan_id, P = s.freemius_product_id;
149
+ if (!R || !P)
149
150
  return { error: "Product is not configured for Freemius checkout (missing Plan ID or Product ID)", url: null };
150
151
  const k = le({
151
152
  prices: s.prices || {},
@@ -165,25 +166,25 @@ class Ue {
165
166
  }), y = N * S.quantity;
166
167
  let n = null, _ = 0;
167
168
  if (K) {
168
- const u = await ie({
169
+ const l = await se({
169
170
  client: p,
170
171
  code: K,
171
172
  items: E && E.length > 0 ? E : r,
172
173
  currencyCode: b.code
173
174
  });
174
- if (!u.success)
175
+ if (!l.success)
175
176
  return {
176
- error: u.error,
177
- errorKey: u.errorKey,
177
+ error: l.error,
178
+ errorKey: l.errorKey,
178
179
  errorStatus: 400,
179
180
  url: null
180
181
  };
181
- n = u.quote, _ = Math.min(
182
+ n = l.quote, _ = Math.min(
182
183
  y,
183
184
  n.lineDiscounts.filter(($) => $.product_id === s.id).reduce(($, T) => $ + T.discount, 0)
184
185
  );
185
186
  }
186
- const F = G(s.trial_period_days), R = F > 0 ? S.trial_preference ? S.trial_preference : s.trial_requires_payment_method ? "paid" : "free" : null, B = "pending", h = ue(
187
+ const F = G(s.trial_period_days), w = F > 0 ? S.trial_preference ? S.trial_preference : s.trial_requires_payment_method ? "paid" : "free" : null, B = "pending", h = de(
187
188
  d?.recipient_name ?? null
188
189
  ), { data: Y, error: V } = await p.from("orders").insert({
189
190
  status: B,
@@ -205,9 +206,9 @@ class Ue {
205
206
  } : null,
206
207
  provider: "freemius",
207
208
  freemius_product_id: String(P),
208
- freemius_plan_id: String(w),
209
- user_id: c || null,
210
- customer_details: ne({
209
+ freemius_plan_id: String(R),
210
+ user_id: a || null,
211
+ customer_details: ie({
211
212
  email: t,
212
213
  phone: i,
213
214
  name: d?.recipient_name,
@@ -223,49 +224,49 @@ class Ue {
223
224
  quantity: S.quantity,
224
225
  price_at_purchase: N
225
226
  }]);
226
- if (J && console.error("Failed to insert order items:", J), c)
227
+ if (J && console.error("Failed to insert order items:", J), a)
227
228
  try {
228
- await oe({
229
- userId: c,
229
+ await ae({
230
+ userId: a,
230
231
  billingAddress: d,
231
232
  shippingAddress: f,
232
233
  client: p
233
234
  }), await ce({
234
- userId: c,
235
+ userId: a,
235
236
  fullName: d?.recipient_name ?? f?.recipient_name ?? null,
236
237
  phone: i,
237
238
  client: p
238
239
  });
239
- } catch (u) {
240
+ } catch (l) {
240
241
  console.error(
241
242
  "Failed to sync checkout profile defaults before checkout:",
242
- u
243
+ l
243
244
  );
244
245
  }
245
- n && await se({
246
+ n && await oe({
246
247
  client: p,
247
248
  quote: n,
248
249
  orderId: Y.id,
249
250
  provider: "freemius",
250
251
  discountTotal: _,
251
- userId: c,
252
+ userId: a,
252
253
  customerEmail: t,
253
254
  metadata: {
254
255
  currency: b.code,
255
256
  subtotal: y,
256
257
  final_amount_owned_by: "freemius"
257
258
  }
258
- });
259
- const O = process.env.FREEMIUS_SANDBOX_ENABLED === "true", M = Ee(P), A = M.publicKey, L = M.secretKey, W = M.apiKey;
259
+ }), await ne();
260
+ const O = process.env.FREEMIUS_SANDBOX_ENABLED === "true", M = ge(P), A = M.publicKey, L = M.secretKey, W = M.apiKey;
260
261
  if (!A || O && !L)
261
262
  return { error: "Missing FREEMIUS credentials (PUBLIC_KEY or SECRET_KEY) in environment variables.", url: null };
262
263
  if (O && M.source === "legacy-env") {
263
- const u = o("FREEMIUS_PRODUCT_ID"), $ = !!o("FREEMIUS_ECOMMERCE_SANDBOX_PUBLIC_KEY"), T = !!o("FREEMIUS_ECOMMERCE_SANDBOX_SECRET_KEY");
264
+ const l = o("FREEMIUS_PRODUCT_ID"), $ = !!o("FREEMIUS_ECOMMERCE_SANDBOX_PUBLIC_KEY"), T = !!o("FREEMIUS_ECOMMERCE_SANDBOX_SECRET_KEY");
264
265
  console.warn(
265
266
  `[Freemius Checkout] Sandbox is enabled for product ${P}, 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.`,
266
267
  {
267
- configuredProductId: u,
268
- productIdsMatch: u === String(P),
268
+ configuredProductId: l,
269
+ productIdsMatch: l === String(P),
269
270
  hasSandboxOverridePublicKey: $,
270
271
  hasSandboxOverrideSecretKey: T,
271
272
  hasCheckoutProductsJson: !!o("FREEMIUS_CHECKOUT_PRODUCTS_JSON")
@@ -275,16 +276,16 @@ class Ue {
275
276
  let q = !1;
276
277
  if (O && L && A)
277
278
  try {
278
- q = await ge({
279
+ q = await Se({
279
280
  productId: P,
280
281
  publicKey: A,
281
282
  secretKey: L,
282
283
  apiKey: W
283
284
  });
284
- } catch (u) {
285
+ } catch (l) {
285
286
  console.warn(
286
287
  "Freemius Checkout - SDK sandbox generation failed. Falling back to manual token generation.",
287
- u,
288
+ l,
288
289
  {
289
290
  credentialSource: M.source,
290
291
  hasApiKey: !!W
@@ -296,22 +297,22 @@ class Ue {
296
297
  token: re
297
298
  };
298
299
  }
299
- const C = new URL(`https://checkout.freemius.com/app/${P}/plan/${w}/`);
300
- if (O && L && A ? (C.searchParams.append("sandbox", q.token), C.searchParams.append("s_ctx_ts", q.ctx)) : O && C.searchParams.append("sandbox", "true"), t && C.searchParams.append("user_email", t), h.firstName && C.searchParams.append("user_firstname", h.firstName), h.lastName && C.searchParams.append("user_lastname", h.lastName), C.searchParams.append("currency", b.code.toLowerCase()), S.billing_cycle && C.searchParams.append("billing_cycle", S.billing_cycle), R && C.searchParams.append("trial", R), n)
300
+ const C = new URL(`https://checkout.freemius.com/app/${P}/plan/${R}/`);
301
+ if (O && L && A ? (C.searchParams.append("sandbox", q.token), C.searchParams.append("s_ctx_ts", q.ctx)) : O && C.searchParams.append("sandbox", "true"), t && C.searchParams.append("user_email", t), h.firstName && C.searchParams.append("user_firstname", h.firstName), h.lastName && C.searchParams.append("user_lastname", h.lastName), C.searchParams.append("currency", b.code.toLowerCase()), S.billing_cycle && C.searchParams.append("billing_cycle", S.billing_cycle), w && C.searchParams.append("trial", w), n)
301
302
  C.searchParams.append("coupon", n.code);
302
303
  else if (x) {
303
- const { data: u } = await p.from("product_freemius_sale_coupons").select("freemius_coupon_code, is_active, starts_at, ends_at, sync_status").eq("product_id", s.id).maybeSingle();
304
- u?.is_active && u.sync_status === "synced" && u.freemius_coupon_code && z({
305
- saleStartAt: u.starts_at,
306
- saleEndAt: u.ends_at
307
- }) && C.searchParams.append("coupon", u.freemius_coupon_code);
304
+ const { data: l } = await p.from("product_freemius_sale_coupons").select("freemius_coupon_code, is_active, starts_at, ends_at, sync_status").eq("product_id", s.id).maybeSingle();
305
+ l?.is_active && l.sync_status === "synced" && l.freemius_coupon_code && z({
306
+ saleStartAt: l.starts_at,
307
+ saleEndAt: l.ends_at
308
+ }) && C.searchParams.append("coupon", l.freemius_coupon_code);
308
309
  }
309
310
  return {
310
311
  url: C.toString(),
311
312
  customProps: {
312
313
  provider: "freemius",
313
314
  plugin_id: P,
314
- plan_id: w,
315
+ plan_id: R,
315
316
  public_key: A,
316
317
  user_email: t,
317
318
  user_firstname: h.firstName,
@@ -319,7 +320,7 @@ class Ue {
319
320
  credential_source: M.source,
320
321
  sandbox: q,
321
322
  billing_cycle: S.billing_cycle,
322
- trial: R,
323
+ trial: w,
323
324
  trial_period_days: F,
324
325
  trial_requires_payment_method: s.trial_requires_payment_method,
325
326
  initial_order_status: B,
@@ -334,24 +335,24 @@ async function Z(e, r, t, i) {
334
335
 
335
336
 
336
337
  ${d}
337
- ${e}`, m = Q.createHmac("sha256", i).update(f).digest("hex"), K = Buffer.from(m).toString("base64").replace(/\+/g, "-").replace(/\//g, "_").replace(/=/g, ""), E = `FS ${r}:${t}:${K}`, a = await fetch(`https://api.freemius.com${e}`, {
338
+ ${e}`, m = Q.createHmac("sha256", i).update(f).digest("hex"), K = Buffer.from(m).toString("base64").replace(/\+/g, "-").replace(/\//g, "_").replace(/=/g, ""), E = `FS ${r}:${t}:${K}`, c = await fetch(`https://api.freemius.com${e}`, {
338
339
  headers: {
339
340
  Authorization: E,
340
341
  Date: d,
341
342
  Accept: "application/json"
342
343
  }
343
344
  });
344
- if (!a.ok) {
345
- const l = await a.text();
346
- throw console.error(`[Freemius API] [ERROR] ${e} returned ${a.status}: ${l}`), new Error(`Freemius API failed on ${e}: ${a.status} - ${l}`);
345
+ if (!c.ok) {
346
+ const u = await c.text();
347
+ throw console.error(`[Freemius API] [ERROR] ${e} returned ${c.status}: ${u}`), new Error(`Freemius API failed on ${e}: ${c.status} - ${u}`);
347
348
  }
348
- return a.json();
349
+ return c.json();
349
350
  }
350
- async function be() {
351
- const e = o("FREEMIUS_DEVELOPER_ID"), r = o("FREEMIUS_PUBLIC_KEY"), t = o("FREEMIUS_SECRET_KEY"), i = process.env.NEXT_PUBLIC_SUPABASE_URL || process.env.SUPABASE_URL, c = process.env.SUPABASE_SERVICE_ROLE_KEY || process.env.SUPABASE_SECRET_KEY;
352
- if (!e || !r || !t || !i || !c)
351
+ async function Re() {
352
+ const e = o("FREEMIUS_DEVELOPER_ID"), r = o("FREEMIUS_PUBLIC_KEY"), t = o("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;
353
+ if (!e || !r || !t || !i || !a)
353
354
  throw new Error("Missing necessary environment variables for Freemius Sync.");
354
- const d = H(i, c, {
355
+ const d = H(i, a, {
355
356
  auth: { autoRefreshToken: !1, persistSession: !1 }
356
357
  }), f = (m) => Z(m, e, r, t);
357
358
  try {
@@ -359,8 +360,8 @@ async function be() {
359
360
  const m = await f(`/v1/developers/${e}/plugins.json`), K = X(m, ["plugins", "plugin"]);
360
361
  console.log(`[Freemius Sync] Found ${K.length} plugins. Syncing plans...`);
361
362
  let E = 0;
362
- const { data: a } = await d.from("languages").select("id").eq("code", "en").single(), l = a?.id;
363
- if (!l)
363
+ const { data: c } = await d.from("languages").select("id").eq("code", "en").single(), u = c?.id;
364
+ if (!u)
364
365
  throw new Error("English language not found in database. Cannot sync products.");
365
366
  for (const p of K) {
366
367
  const g = p.id?.toString();
@@ -374,7 +375,7 @@ async function be() {
374
375
  g,
375
376
  p.title || p.name || `Freemius Product ${g}`,
376
377
  f,
377
- l
378
+ u
378
379
  );
379
380
  E += U;
380
381
  }
@@ -383,88 +384,88 @@ async function be() {
383
384
  throw console.error("[Freemius Sync] Global Error:", m), m;
384
385
  }
385
386
  }
386
- async function Re(e) {
387
- const r = o("FREEMIUS_DEVELOPER_ID"), t = o("FREEMIUS_PUBLIC_KEY"), i = o("FREEMIUS_SECRET_KEY"), c = process.env.NEXT_PUBLIC_SUPABASE_URL || process.env.SUPABASE_URL, d = process.env.SUPABASE_SERVICE_ROLE_KEY || process.env.SUPABASE_SECRET_KEY;
388
- if (!r || !t || !i || !c || !d)
387
+ async function $e(e) {
388
+ const r = o("FREEMIUS_DEVELOPER_ID"), t = o("FREEMIUS_PUBLIC_KEY"), i = o("FREEMIUS_SECRET_KEY"), a = process.env.NEXT_PUBLIC_SUPABASE_URL || process.env.SUPABASE_URL, d = process.env.SUPABASE_SERVICE_ROLE_KEY || process.env.SUPABASE_SECRET_KEY;
389
+ if (!r || !t || !i || !a || !d)
389
390
  throw new Error("Missing environment variables for Freemius Sync.");
390
- const f = H(c, d), m = (g) => Z(g, r, t, i), { data: K } = await f.from("languages").select("id").eq("code", "en").single(), E = K?.id;
391
+ const f = H(a, d), m = (g) => Z(g, r, t, i), { data: K } = await f.from("languages").select("id").eq("code", "en").single(), E = K?.id;
391
392
  if (!E)
392
393
  throw new Error("English language not found in database. Cannot sync products.");
393
- const a = await m(`/v1/developers/${r}/plugins/${e}.json`), l = a.plugin ?? a;
394
+ const c = await m(`/v1/developers/${r}/plugins/${e}.json`), u = c.plugin ?? c;
394
395
  return { success: !0, count: await ee(
395
396
  f,
396
397
  r,
397
398
  e,
398
- l.title || l.name || `Freemius Product ${e}`,
399
+ u.title || u.name || `Freemius Product ${e}`,
399
400
  m,
400
401
  E
401
402
  ) };
402
403
  }
403
- async function ee(e, r, t, i, c, d) {
404
+ async function ee(e, r, t, i, a, d) {
404
405
  console.log(`[Freemius Sync] Fetching plans for plugin: ${i} (${t})...`);
405
406
  let f = 0;
406
407
  try {
407
- const m = `/v1/developers/${r}/plugins/${t}/plans.json`, K = await c(m), E = X(K, ["plans", "plan"]);
408
+ const m = `/v1/developers/${r}/plugins/${t}/plans.json`, K = await a(m), E = X(K, ["plans", "plan"]);
408
409
  console.log(`[Freemius Sync] Received ${E.length} plans for plugin ${t}.`);
409
- for (const a of E) {
410
- const l = a.id?.toString();
411
- if (!l) {
412
- console.warn("[Freemius Sync] Skipping plan without an id:", a);
410
+ for (const c of E) {
411
+ const u = c.id?.toString();
412
+ if (!u) {
413
+ console.warn("[Freemius Sync] Skipping plan without an id:", c);
413
414
  continue;
414
415
  }
415
- const p = a.name || a.title || l, g = a.title || p;
416
- console.log(`[Freemius Sync] Processing plan: ${g} (${l})...`);
417
- let U = a;
416
+ const p = c.name || c.title || u, g = c.title || p;
417
+ console.log(`[Freemius Sync] Processing plan: ${g} (${u})...`);
418
+ let U = c;
418
419
  if (U.trial_period === void 0 || U.is_require_subscription === void 0)
419
420
  try {
420
- const n = `/v1/developers/${r}/plugins/${t}/plans/${l}.json`, _ = await c(n), F = _.plan ?? _;
421
+ const n = `/v1/developers/${r}/plugins/${t}/plans/${u}.json`, _ = await a(n), F = _.plan ?? _;
421
422
  U = {
422
423
  ...U,
423
424
  ...F
424
425
  };
425
426
  } catch (n) {
426
427
  console.warn(
427
- `[Freemius Sync] Could not fetch trial details for plan ${l}:`,
428
+ `[Freemius Sync] Could not fetch trial details for plan ${u}:`,
428
429
  n instanceof Error ? n.message : n
429
430
  );
430
431
  }
431
- const v = G(U.trial_period), j = v > 0 && de(U.is_require_subscription);
432
+ const v = G(U.trial_period), j = v > 0 && pe(U.is_require_subscription);
432
433
  let b = 0, S = [];
433
434
  try {
434
- const n = `/v1/developers/${r}/plugins/${t}/plans/${l}/pricing.json`, _ = await c(n);
435
+ const n = `/v1/developers/${r}/plugins/${t}/plans/${u}/pricing.json`, _ = await a(n);
435
436
  if (S = X(_, [
436
437
  "pricing",
437
438
  "prices",
438
439
  "pricings"
439
440
  ]), S.length > 0) {
440
- const F = S[0], R = D(F.annual_price) ?? D(F.monthly_price) ?? D(F.lifetime_price);
441
- b = _e(R);
441
+ const F = S[0], w = D(F.annual_price) ?? D(F.monthly_price) ?? D(F.lifetime_price);
442
+ b = me(w);
442
443
  }
443
444
  console.log(`[Freemius Sync] Plan: ${g} -> Resolved Price (cents): ${b}`);
444
445
  } catch (n) {
445
- console.warn(`[Freemius Sync] Could not fetch pricing for plan ${l}:`, n instanceof Error ? n.message : n);
446
+ console.warn(`[Freemius Sync] Could not fetch pricing for plan ${u}:`, n instanceof Error ? n.message : n);
446
447
  }
447
448
  const s = `${i}-${g}`.toLowerCase().replace(/[^\w\s-]/g, "").replace(/[\s_]+/g, "-").replace(/^-+|-+$/g, ""), I = {
448
449
  title: `${i} - ${g}`,
449
450
  slug: s,
450
- short_description: a.description || "",
451
+ short_description: c.description || "",
451
452
  price: b,
452
453
  product_type: "digital",
453
454
  payment_provider: "freemius",
454
- freemius_plan_id: l,
455
+ freemius_plan_id: u,
455
456
  freemius_product_id: t,
456
457
  trial_period_days: v,
457
458
  trial_requires_payment_method: j,
458
459
  status: "active",
459
460
  stock: 999,
460
- sku: `FM-${t}-${l}`,
461
+ sku: `FM-${t}-${u}`,
461
462
  language_id: d
462
- }, { data: w, error: P } = await e.from("products").upsert(I, { onConflict: "language_id, sku" }).select();
463
- if (P || !w || w.length === 0) {
463
+ }, { data: R, error: P } = await e.from("products").upsert(I, { onConflict: "language_id, sku" }).select();
464
+ if (P || !R || R.length === 0) {
464
465
  console.error(`[Freemius Sync] Error upserting product ${I.sku}:`, P);
465
466
  continue;
466
467
  }
467
- const k = w[0].id, { data: N, error: x } = await e.from("freemius_plans").select("id").eq("product_id", k).eq("name", p).maybeSingle();
468
+ const k = R[0].id, { data: N, error: x } = await e.from("freemius_plans").select("id").eq("product_id", k).eq("name", p).maybeSingle();
468
469
  x && console.warn(
469
470
  `[Freemius Sync] Could not check existing local plan for ${I.sku}:`,
470
471
  x.message || x
@@ -490,12 +491,12 @@ async function ee(e, r, t, i, c, d) {
490
491
  }
491
492
  if (y && S.length > 0)
492
493
  for (const n of S) {
493
- const _ = me(
494
+ const _ = fe(
494
495
  n.licenses ?? n.license_quota ?? n.quota
495
- ), { data: F, error: R } = await e.from("freemius_pricing").select("id").eq("plan_id", y).eq("license_quota", _).maybeSingle();
496
- R && console.warn(
496
+ ), { data: F, error: w } = await e.from("freemius_pricing").select("id").eq("plan_id", y).eq("license_quota", _).maybeSingle();
497
+ w && console.warn(
497
498
  `[Freemius Sync] Could not check pricing for plan ${y}, quota ${_}:`,
498
- R.message || R
499
+ w.message || w
499
500
  );
500
501
  const B = {
501
502
  api_monthly_price: D(n.monthly_price),
@@ -529,10 +530,10 @@ async function ee(e, r, t, i, c, d) {
529
530
  return f;
530
531
  }
531
532
  export {
532
- Ue as FreemiusProvider,
533
- fe as parseFreemiusCheckoutCredentialsMap,
533
+ we as FreemiusProvider,
534
+ Ee as parseFreemiusCheckoutCredentialsMap,
534
535
  o as readFreemiusEnvValue,
535
- Ee as resolveFreemiusCheckoutCredentials,
536
- be as syncFreemiusProductsToSupabase,
537
- Re as syncSingleFreemiusProduct
536
+ ge as resolveFreemiusCheckoutCredentials,
537
+ Re as syncFreemiusProductsToSupabase,
538
+ $e as syncSingleFreemiusProduct
538
539
  };
@@ -1 +1 @@
1
- "use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const U=require("../stripe/client.cjs.js"),xe=require("@supabase/supabase-js"),ke=require("../countries.cjs.js"),Pe=require("../customer.cjs.js"),O=require("../coupon-server.cjs.js"),be=require("../coupons.cjs.js"),_e=require("../customer-addresses.cjs.js"),T=require("../inventory-settings.cjs.js"),w=require("../tax-calculation.cjs.js"),h=require("../currency.cjs.js"),Te=require("../order-tax-details.cjs.js"),we=require("../types.cjs.js"),Ae=require("../variation-utils.cjs.js"),Ie=ke.countries.map(r=>r.code),De=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"]);function pe(r){if(r)return{line1:r.line1||void 0,line2:r.line2||void 0,city:r.city||void 0,state:r.state||void 0,postal_code:r.postal_code||void 0,country:r.country_code||void 0}}function Me(r){const i=r?.trim().replace("_","-");if(!i)return;const l=[i,i.toLowerCase(),i.split("-")[0].toLowerCase()];for(const d of l)if(De.has(d))return d}function Ue(r,i){return Ae.resolveTranslatedText(r.name,r.name_translations||null,i)}async function Le(r){if(!r.email)return null;const i=pe(r.shippingAddress),l=r.shippingAddress?.recipient_name||r.billingAddress?.recipient_name||void 0,d={email:r.email,name:r.billingAddress?.recipient_name||r.shippingAddress?.recipient_name||void 0,phone:r.phone||void 0,address:pe(r.billingAddress),metadata:r.userId?{userId:r.userId}:void 0,...i&&l?{shipping:{name:l,phone:r.phone||void 0,address:i}}:{}};try{const s=(await U.stripe.customers.list({email:r.email,limit:1})).data[0];return s?(await U.stripe.customers.update(s.id,d),s.id):(await U.stripe.customers.create(d)).id}catch(_){return console.error("Failed to upsert Stripe customer for checkout prefill:",_),null}}class Fe{getProviderName(){return"Stripe"}async createCheckoutSession({items:i,customerEmail:l,customerPhone:d,userId:_,billingAddress:s,shippingAddress:y,shippingMethodId:B,currencyCode:me,locale:z,couponCode:K,couponContextItems:L}){const Q=process.env.NEXT_PUBLIC_SUPABASE_URL||process.env.SUPABASE_URL,$=process.env.SUPABASE_SERVICE_ROLE_KEY||process.env.SUPABASE_SECRET_KEY;if(!Q||!$)return console.error("Missing Supabase credentials for checkout (Service Key required)."),{error:"Internal Server Error",url:null};const a=xe.createClient(Q,$),X=process.env.NEXT_PUBLIC_URL||"http://localhost:4200",H=i.some(e=>!we.isDigitalItem(e));if(!i.length)return{error:"Cart is empty",url:null};const{data:he,error:j}=await a.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}),g=he??[];if(j||g.length===0)return console.error("Error fetching currencies for checkout:",j),{error:"Failed to resolve store currencies",url:null};const G=h.getDefaultCurrency(g),p=g.find(e=>e.code===(me||"").toUpperCase())??G,F=p.code.toLowerCase(),V=await T.getEcommerceInventorySettings(a),ve=i.map(e=>e.product_id),W=i.map(e=>e.variant_id).filter(e=>!!e),{data:Y,error:J}=await a.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);if(J||!Y)return console.error("Error fetching products for validation:",J),{error:"Failed to validate product prices",url:null};const{data:fe,error:Z}=W.length?await a.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",W):{data:[],error:null};if(Z)return console.error("Error fetching variants for validation:",Z),{error:"Failed to validate product variants",url:null};const ee=new Map(Y.map(e=>[e.id,e])),te=new Map((fe||[]).map(e=>[e.id,e])),R=new Set,A=new Map;for(const e of i){const t=ee.get(e.product_id);if(!t)continue;const n=(e.variant_id?te.get(e.variant_id):null)?.sku||t.sku;n&&(R.add(n),A.set(n,(A.get(n)??0)+e.quantity))}const{data:ye,error:re}=R.size?await a.from("inventory_items").select("sku, quantity").in("sku",[...R]):{data:[],error:null};if(re)return console.error("Error fetching SKU inventory for validation:",re),{error:"Failed to validate SKU inventory",url:null};const I=new Map((ye||[]).map(e=>[e.sku,Math.max(0,e.quantity??0)])),S=[],oe=[],ie=[];let v=0,C=0,c=null;if(K){const e=await O.getCouponQuote({client:a,code:K,items:L&&L.length>0?L:i,currencyCode:p.code});if(!e.success)return{error:e.error,errorKey:e.errorKey,errorStatus:400,url:null};c=e.quote}const ge=O.getQuoteLineDiscountMap(c),Se=e=>{const t=e.unitAmount*e.quantity,f=Math.max(0,t-e.lineDiscount);if(f<=0)return;const n=Math.floor(f/e.quantity),P=f-n*e.quantity,x=(b,k)=>{k<=0||b<=0||S.push({price_data:{currency:e.currency,product_data:{name:e.name,tax_code:w.getStripeTaxCodeForProduct(e.isTaxable),metadata:{productId:e.productId,variantId:e.variantId||""}},tax_behavior:"exclusive",unit_amount:b},quantity:k})};x(n,e.quantity-P),x(n+1,P)};for(const e of i){const t=ee.get(e.product_id);if(!t)return console.warn(`Product ${e.product_id} not found in DB.`),{url:null,...T.createInventoryUnavailableError(e.title)};const f=h.resolveEffectivePriceForCurrency({prices:h.normalizePriceMap(t.prices),salePrices:t.sale_prices||{},fallbackPrice:t.price,fallbackSalePrice:t.sale_price,saleStartAt:t.sale_start_at,saleEndAt:t.sale_end_at,scheduledPrice:t.scheduled_price,scheduledPrices:h.normalizePriceMap(t.scheduled_prices),scheduledPriceAt:t.scheduled_price_at,currencyCode:p.code,currencies:g});let n=f.sale_price??f.price,P=t.title,x=null;if(e.variant_id){const o=te.get(e.variant_id);if(!o||o.product_id!==e.product_id)return{url:null,...T.createInventoryUnavailableError(e.title)};const M=A.get(o.sku)??e.quantity,le=I.has(o.sku)?I.get(o.sku)??0:Math.max(0,o.stock_quantity??0);if(V.trackQuantities&&M>le)return{url:null,...T.createInventoryInsufficientError(e.title,le)};const de=h.resolveEffectivePriceForCurrency({prices:h.normalizePriceMap(o.prices),salePrices:o.sale_prices||{},fallbackPrice:o.price,fallbackSalePrice:o.sale_price,saleStartAt:o.sale_start_at,saleEndAt:o.sale_end_at,scheduledPrice:o.scheduled_price,scheduledPrices:h.normalizePriceMap(o.scheduled_prices),scheduledPriceAt:o.scheduled_price_at,currencyCode:p.code,currencies:g});n=de.sale_price??de.price,x=o.id,P=e.variant_label?`${t.title} - ${e.variant_label}`:`${t.title} - ${o.sku}`}else{const o=A.get(t.sku)??e.quantity,M=I.has(t.sku)?I.get(t.sku)??0:Math.max(0,t.stock??0);if(V.trackQuantities&&o>M)return{url:null,...T.createInventoryInsufficientError(e.title,M)}}const b=t.is_taxable??!0;if(n<0)return{error:"A product variation produced an invalid price.",url:null};const k=Math.min(n*e.quantity,ge.get(be.getCartLineCouponKey(e))??0);Se({name:P,currency:F,productId:t.id,variantId:x,isTaxable:b,unitAmount:n,quantity:e.quantity,lineDiscount:k}),v+=n*e.quantity,C+=k,ie.push({product_id:t.id,quantity:e.quantity,price_at_purchase:n,variant_id:x}),oe.push({product_id:t.id,quantity:e.quantity,unit_amount:n,discount_amount:k,is_taxable:b})}if(S.length===0&&C>=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(S.length===0)return{error:"No valid items in cart",url:null};let m=0,N=null;if(B){const{data:e,error:t}=await a.from("shipping_zone_methods").select("id, name, name_translations, cost_amount, cost_currency").eq("id",B).single();if(t)return console.error("Failed to load shipping method:",t),{error:"Failed to load shipping method",url:null};m=h.convertMinorUnitAmount({amount:e.cost_amount??0,fromCurrencyCode:e.cost_currency||G.code,toCurrencyCode:p.code,currencies:g}),N=Ue(e,z)}const ae=H?y??s:s;let u;try{u=await w.calculateCheckoutTaxes(a,{items:oe,destination:{country_code:ae?.country_code,state:ae?.state}})}catch(e){return console.error("Failed to calculate checkout taxes:",e),{error:"Failed to calculate taxes",url:null}}m>0&&N&&S.push({price_data:{currency:F,product_data:{name:N,tax_code:u.enabled&&u.mode==="automatic"?w.STRIPE_TAX_CODE_SHIPPING:w.STRIPE_TAX_CODE_NONTAXABLE},tax_behavior:"exclusive",unit_amount:m},quantity:1});const E=u.enabled&&u.mode==="manual"&&!u.isPendingExternalCalculation?u.amount:0;E>0&&S.push({price_data:{currency:F,product_data:{name:"Tax",tax_code:w.STRIPE_TAX_CODE_NONTAXABLE},tax_behavior:"exclusive",unit_amount:E},quantity:1});const Ce=Pe.normalizeOrderCustomerDetails({email:l,phone:d,name:s?.recipient_name,billing:s,shipping:y}),ne=p.code,Ee=Te.buildOrderTaxDetailsFromCalculation({calculation:u,subtotal:v,shippingTotal:m,total:Math.max(0,v-C)+m+E,currency:ne}),qe=Math.max(0,v-C)+m+E,{data:ce,error:se}=await a.from("orders").insert({status:"pending",total:qe,currency:ne,exchange_rate_at_purchase:p.exchange_rate,subtotal:v,shipping_total:m,tax_total:E,tax_details:Ee,coupon_id:c?.couponId??null,coupon_code:c?.code??null,discount_total:C,discount_details:c?{code:c.code,discount_type:c.discountType,discount_amount:c.discountAmount,provider:"stripe",provider_discounts:c.providerDiscounts,line_discounts:c.lineDiscounts}:null,provider:"stripe",user_id:_,customer_details:Ce}).select("id").single();if(se||!ce)return console.error("Failed to create pending order:",se),{error:"Failed to initiate order",url:null};const q=ce.id,{error:ue}=await a.from("order_items").insert(ie.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(ue)return console.error("Failed to insert order items:",ue),await a.from("orders").update({status:"failed"}).eq("id",q),{error:"Failed to record order items",url:null};if(_)try{await _e.upsertDefaultUserAddresses({userId:_,billingAddress:s,shippingAddress:y,client:a}),await _e.fillMissingUserProfileCheckoutDetails({userId:_,fullName:s?.recipient_name??y?.recipient_name??null,phone:d,client:a})}catch(e){console.error("Failed to sync checkout profile defaults before checkout:",e)}c&&await O.recordCouponRedemption({client:a,quote:c,orderId:q,provider:"stripe",discountTotal:C,userId:_,customerEmail:l,metadata:{currency:p.code,subtotal:v,shipping_total:m,tax_total:E}});const D=await Le({email:l,phone:d,userId:_,billingAddress:s,shippingAddress:y});try{const e=await U.stripe.checkout.sessions.create({mode:"payment",success_url:`${X}/checkout/success?session_id={CHECKOUT_SESSION_ID}`,cancel_url:`${X}/checkout`,locale:Me(z),line_items:S,automatic_tax:u.enabled&&u.mode==="automatic"?{enabled:!0}:void 0,billing_address_collection:"auto",customer:D||void 0,customer_email:D?void 0:l||void 0,customer_creation:D?void 0:"if_required",customer_update:D?{name:"auto",address:"auto",shipping:"auto"}:void 0,shipping_address_collection:H?{allowed_countries:Ie}:void 0,metadata:{orderId:q,taxMode:u.mode,currencyCode:p.code,couponCode:c?.code||""}}),{error:t}=await a.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 a.from("orders").update({status:"failed"}).eq("id",q),{error:e.message,url:null}}}}exports.StripeProvider=Fe;
1
+ "use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const pe=require("../stripe/client.cjs.js"),ke=require("@supabase/supabase-js"),Pe=require("../countries.cjs.js"),be=require("../customer.cjs.js"),O=require("../coupon-server.cjs.js"),Te=require("../coupons.cjs.js"),de=require("../customer-addresses.cjs.js"),T=require("../inventory-settings.cjs.js"),w=require("../tax-calculation.cjs.js"),v=require("../currency.cjs.js"),we=require("../order-tax-details.cjs.js"),Ae=require("../types.cjs.js"),Ie=require("../variation-utils.cjs.js"),De=Pe.countries.map(r=>r.code),Me=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"]);function _e(r){if(r)return{line1:r.line1||void 0,line2:r.line2||void 0,city:r.city||void 0,state:r.state||void 0,postal_code:r.postal_code||void 0,country:r.country_code||void 0}}function Ue(r){const i=r?.trim().replace("_","-");if(!i)return;const l=[i,i.toLowerCase(),i.split("-")[0].toLowerCase()];for(const d of l)if(Me.has(d))return d}function Le(r,i){return Ie.resolveTranslatedText(r.name,r.name_translations||null,i)}async function Fe(r){if(!r.email)return null;const i=await pe.getStripeClient(),l=_e(r.shippingAddress),d=r.shippingAddress?.recipient_name||r.billingAddress?.recipient_name||void 0,_={email:r.email,name:r.billingAddress?.recipient_name||r.shippingAddress?.recipient_name||void 0,phone:r.phone||void 0,address:_e(r.billingAddress),metadata:r.userId?{userId:r.userId}:void 0,...l&&d?{shipping:{name:d,phone:r.phone||void 0,address:l}}:{}};try{const p=(await i.customers.list({email:r.email,limit:1})).data[0];return p?(await i.customers.update(p.id,_),p.id):(await i.customers.create(_)).id}catch(u){return console.error("Failed to upsert Stripe customer for checkout prefill:",u),null}}class Re{getProviderName(){return"Stripe"}async createCheckoutSession({items:i,customerEmail:l,customerPhone:d,userId:_,billingAddress:u,shippingAddress:p,shippingMethodId:U,currencyCode:me,locale:B,couponCode:z,couponContextItems:L}){const he=await pe.getStripeClient(),K=process.env.NEXT_PUBLIC_SUPABASE_URL||process.env.SUPABASE_URL,Q=process.env.SUPABASE_SERVICE_ROLE_KEY||process.env.SUPABASE_SECRET_KEY;if(!K||!Q)return console.error("Missing Supabase credentials for checkout (Service Key required)."),{error:"Internal Server Error",url:null};const a=ke.createClient(K,Q),$=process.env.NEXT_PUBLIC_URL||"http://localhost:4200",X=i.some(e=>!Ae.isDigitalItem(e));if(!i.length)return{error:"Cart is empty",url:null};const{data:ve,error:H}=await a.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}),g=ve??[];if(H||g.length===0)return console.error("Error fetching currencies for checkout:",H),{error:"Failed to resolve store currencies",url:null};const j=v.getDefaultCurrency(g),m=g.find(e=>e.code===(me||"").toUpperCase())??j,F=m.code.toLowerCase(),G=await T.getEcommerceInventorySettings(a),fe=i.map(e=>e.product_id),V=i.map(e=>e.variant_id).filter(e=>!!e),{data:W,error:Y}=await a.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(Y||!W)return console.error("Error fetching products for validation:",Y),{error:"Failed to validate product prices",url:null};const{data:ye,error:J}=V.length?await a.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",V):{data:[],error:null};if(J)return console.error("Error fetching variants for validation:",J),{error:"Failed to validate product variants",url:null};const Z=new Map(W.map(e=>[e.id,e])),ee=new Map((ye||[]).map(e=>[e.id,e])),R=new Set,A=new Map;for(const e of i){const t=Z.get(e.product_id);if(!t)continue;const n=(e.variant_id?ee.get(e.variant_id):null)?.sku||t.sku;n&&(R.add(n),A.set(n,(A.get(n)??0)+e.quantity))}const{data:ge,error:te}=R.size?await a.from("inventory_items").select("sku, quantity").in("sku",[...R]):{data:[],error:null};if(te)return console.error("Error fetching SKU inventory for validation:",te),{error:"Failed to validate SKU inventory",url:null};const I=new Map((ge||[]).map(e=>[e.sku,Math.max(0,e.quantity??0)])),S=[],re=[],oe=[];let f=0,C=0,c=null;if(z){const e=await O.getCouponQuote({client:a,code:z,items:L&&L.length>0?L:i,currencyCode:m.code});if(!e.success)return{error:e.error,errorKey:e.errorKey,errorStatus:400,url:null};c=e.quote}const Se=O.getQuoteLineDiscountMap(c),Ce=e=>{const t=e.unitAmount*e.quantity,y=Math.max(0,t-e.lineDiscount);if(y<=0)return;const n=Math.floor(y/e.quantity),P=y-n*e.quantity,x=(b,k)=>{k<=0||b<=0||S.push({price_data:{currency:e.currency,product_data:{name:e.name,tax_code:w.getStripeTaxCodeForProduct(e.isTaxable),metadata:{productId:e.productId,variantId:e.variantId||""}},tax_behavior:"exclusive",unit_amount:b},quantity:k})};x(n,e.quantity-P),x(n+1,P)};for(const e of i){const t=Z.get(e.product_id);if(!t)return console.warn(`Product ${e.product_id} not found in DB.`),{url:null,...T.createInventoryUnavailableError(e.title)};const y=v.resolveEffectivePriceForCurrency({prices:v.normalizePriceMap(t.prices),salePrices:t.sale_prices||{},fallbackPrice:t.price,fallbackSalePrice:t.sale_price,saleStartAt:t.sale_start_at,saleEndAt:t.sale_end_at,scheduledPrice:t.scheduled_price,scheduledPrices:v.normalizePriceMap(t.scheduled_prices),scheduledPriceAt:t.scheduled_price_at,currencyCode:m.code,currencies:g});let n=y.sale_price??y.price,P=t.title,x=null;if(e.variant_id){const o=ee.get(e.variant_id);if(!o||o.product_id!==e.product_id)return{url:null,...T.createInventoryUnavailableError(e.title)};const M=A.get(o.sku)??e.quantity,ue=I.has(o.sku)?I.get(o.sku)??0:Math.max(0,o.stock_quantity??0);if(G.trackQuantities&&M>ue)return{url:null,...T.createInventoryInsufficientError(e.title,ue)};const le=v.resolveEffectivePriceForCurrency({prices:v.normalizePriceMap(o.prices),salePrices:o.sale_prices||{},fallbackPrice:o.price,fallbackSalePrice:o.sale_price,saleStartAt:o.sale_start_at,saleEndAt:o.sale_end_at,scheduledPrice:o.scheduled_price,scheduledPrices:v.normalizePriceMap(o.scheduled_prices),scheduledPriceAt:o.scheduled_price_at,currencyCode:m.code,currencies:g});n=le.sale_price??le.price,x=o.id,P=e.variant_label?`${t.title} - ${e.variant_label}`:`${t.title} - ${o.sku}`}else{const o=A.get(t.sku)??e.quantity,M=I.has(t.sku)?I.get(t.sku)??0:Math.max(0,t.stock??0);if(G.trackQuantities&&o>M)return{url:null,...T.createInventoryInsufficientError(e.title,M)}}const b=t.is_taxable??!0;if(n<0)return{error:"A product variation produced an invalid price.",url:null};const k=Math.min(n*e.quantity,Se.get(Te.getCartLineCouponKey(e))??0);Ce({name:P,currency:F,productId:t.id,variantId:x,isTaxable:b,unitAmount:n,quantity:e.quantity,lineDiscount:k}),f+=n*e.quantity,C+=k,oe.push({product_id:t.id,quantity:e.quantity,price_at_purchase:n,variant_id:x}),re.push({product_id:t.id,quantity:e.quantity,unit_amount:n,discount_amount:k,is_taxable:b})}if(S.length===0&&C>=f)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(S.length===0)return{error:"No valid items in cart",url:null};let h=0,N=null;if(U){const{data:e,error:t}=await a.from("shipping_zone_methods").select("id, name, name_translations, cost_amount, cost_currency").eq("id",U).single();if(t)return console.error("Failed to load shipping method:",t),{error:"Failed to load shipping method",url:null};h=v.convertMinorUnitAmount({amount:e.cost_amount??0,fromCurrencyCode:e.cost_currency||j.code,toCurrencyCode:m.code,currencies:g}),N=Le(e,B)}const ie=X?p??u:u;let s;try{s=await w.calculateCheckoutTaxes(a,{items:re,destination:{country_code:ie?.country_code,state:ie?.state}})}catch(e){return console.error("Failed to calculate checkout taxes:",e),{error:"Failed to calculate taxes",url:null}}h>0&&N&&S.push({price_data:{currency:F,product_data:{name:N,tax_code:s.enabled&&s.mode==="automatic"?w.STRIPE_TAX_CODE_SHIPPING:w.STRIPE_TAX_CODE_NONTAXABLE},tax_behavior:"exclusive",unit_amount:h},quantity:1});const E=s.enabled&&s.mode==="manual"&&!s.isPendingExternalCalculation?s.amount:0;E>0&&S.push({price_data:{currency:F,product_data:{name:"Tax",tax_code:w.STRIPE_TAX_CODE_NONTAXABLE},tax_behavior:"exclusive",unit_amount:E},quantity:1});const Ee=be.normalizeOrderCustomerDetails({email:l,phone:d,name:u?.recipient_name,billing:u,shipping:p}),ae=m.code,qe=we.buildOrderTaxDetailsFromCalculation({calculation:s,subtotal:f,shippingTotal:h,total:Math.max(0,f-C)+h+E,currency:ae}),xe=Math.max(0,f-C)+h+E,{data:ne,error:ce}=await a.from("orders").insert({status:"pending",total:xe,currency:ae,exchange_rate_at_purchase:m.exchange_rate,subtotal:f,shipping_total:h,tax_total:E,tax_details:qe,coupon_id:c?.couponId??null,coupon_code:c?.code??null,discount_total:C,discount_details:c?{code:c.code,discount_type:c.discountType,discount_amount:c.discountAmount,provider:"stripe",provider_discounts:c.providerDiscounts,line_discounts:c.lineDiscounts}:null,provider:"stripe",user_id:_,customer_details:Ee}).select("id").single();if(ce||!ne)return console.error("Failed to create pending order:",ce),{error:"Failed to initiate order",url:null};const q=ne.id,{error:se}=await a.from("order_items").insert(oe.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(se)return console.error("Failed to insert order items:",se),await a.from("orders").update({status:"failed"}).eq("id",q),{error:"Failed to record order items",url:null};if(_)try{await de.upsertDefaultUserAddresses({userId:_,billingAddress:u,shippingAddress:p,client:a}),await de.fillMissingUserProfileCheckoutDetails({userId:_,fullName:u?.recipient_name??p?.recipient_name??null,phone:d,client:a})}catch(e){console.error("Failed to sync checkout profile defaults before checkout:",e)}c&&await O.recordCouponRedemption({client:a,quote:c,orderId:q,provider:"stripe",discountTotal:C,userId:_,customerEmail:l,metadata:{currency:m.code,subtotal:f,shipping_total:h,tax_total:E}});const D=await Fe({email:l,phone:d,userId:_,billingAddress:u,shippingAddress:p});try{const e=await he.checkout.sessions.create({mode:"payment",success_url:`${$}/checkout/success?session_id={CHECKOUT_SESSION_ID}`,cancel_url:`${$}/checkout`,locale:Ue(B),line_items:S,automatic_tax:s.enabled&&s.mode==="automatic"?{enabled:!0}:void 0,billing_address_collection:"auto",customer:D||void 0,customer_email:D?void 0:l||void 0,customer_creation:D?void 0:"if_required",customer_update:D?{name:"auto",address:"auto",shipping:"auto"}:void 0,shipping_address_collection:X?{allowed_countries:De}:void 0,metadata:{orderId:q,taxMode:s.mode,currencyCode:m.code,couponCode:c?.code||""}}),{error:t}=await a.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 a.from("orders").update({status:"failed"}).eq("id",q),{error:e.message,url:null}}}}exports.StripeProvider=Re;