@nextblock-cms/ecom 0.8.1 → 0.8.6

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 (71) hide show
  1. package/AddToCartButton-DsSEH9yp.cjs +1 -0
  2. package/AddToCartButton-ffE0DhHu.js +59 -0
  3. package/CouponForm-BI_5SBHQ.js +152 -0
  4. package/CouponForm-D_uu2bLP.cjs +1 -0
  5. package/CurrencyProvider-Cg-Q6ucj.cjs +1 -0
  6. package/CurrencyProvider-OzlRN96V.js +120 -0
  7. package/CurrencyProvider.cjs.js +1 -0
  8. package/CurrencyProvider.es.js +10 -0
  9. package/ProductDetailsLayout-BxJH_BxR.cjs +1 -0
  10. package/ProductDetailsLayout-Dg8dRTYp.js +530 -0
  11. package/ProductGrid-BdL7iglO.cjs +1 -0
  12. package/ProductGrid-D3AWM8sr.js +130 -0
  13. package/actions-AHmBrS5e.cjs +48 -0
  14. package/actions-j5fuSZX-.js +820 -0
  15. package/cart-store.cjs.js +1 -0
  16. package/cart-store.es.js +116 -0
  17. package/components/Cart.cjs.js +1 -0
  18. package/components/Cart.es.js +259 -0
  19. package/components/CartDrawer.cjs.js +1 -0
  20. package/components/CartDrawer.es.js +118 -0
  21. package/components/CartIcon.cjs.js +1 -0
  22. package/components/CartIcon.es.js +33 -0
  23. package/components/Checkout.cjs.js +1 -0
  24. package/components/Checkout.es.js +1020 -0
  25. package/components/CurrencySwitcher.cjs.js +1 -0
  26. package/components/CurrencySwitcher.es.js +17 -0
  27. package/components/FeaturedProduct.cjs.js +1 -0
  28. package/components/FeaturedProduct.es.js +71 -0
  29. package/components/ProductDetailsLayout.cjs.js +1 -0
  30. package/components/ProductDetailsLayout.es.js +19 -0
  31. package/components/ProductGrid.cjs.js +1 -0
  32. package/components/ProductGrid.es.js +6 -0
  33. package/components/SimpleTiptapRenderer.cjs.js +1 -0
  34. package/components/SimpleTiptapRenderer.es.js +187 -0
  35. package/coupon-server-C9ySm3I5.cjs +1 -0
  36. package/coupon-server-DUKVtyYs.js +248 -0
  37. package/currency-constants.cjs.js +1 -0
  38. package/currency-constants.es.js +4 -0
  39. package/currency.cjs.js +1 -0
  40. package/currency.es.js +312 -0
  41. package/customer-C-UPvrYN.cjs +1 -0
  42. package/customer-C3xccjUg.js +57 -0
  43. package/index.cjs.js +1 -1
  44. package/index.es.js +414 -3105
  45. package/invoice-ui-CAnJPu6n.cjs +29 -0
  46. package/invoice-ui-DtpbTJE1.js +2886 -0
  47. package/package.json +10 -5
  48. package/product-actions-CONBF8i6.cjs +251 -0
  49. package/product-actions-DjlIWCMH.js +691 -0
  50. package/resolver-Fz_FKsfX.cjs +7 -0
  51. package/resolver-cfrCaHpE.js +128 -0
  52. package/server-actions/product-actions.cjs.js +1 -0
  53. package/server-actions/product-actions.es.js +15 -0
  54. package/server.cjs.js +27 -27
  55. package/server.es.js +478 -463
  56. package/shipping-actions-BnHjlo2q.js +25 -0
  57. package/shipping-actions-D6zt20gg.cjs +1 -0
  58. package/states-CWYRxV4B.cjs +1 -0
  59. package/states-DlHJezQ1.js +200 -0
  60. package/tax-calculation-Dab89aHd.js +181 -0
  61. package/tax-calculation-MkDKOEkL.cjs +1 -0
  62. package/trials-DvZaOtNy.cjs +1 -0
  63. package/trials-RDcRAZKx.js +29 -0
  64. package/types.cjs.js +1 -0
  65. package/types.es.js +33 -0
  66. package/use-cart.cjs.js +1 -0
  67. package/use-cart.es.js +43 -0
  68. package/variation-utils.cjs.js +1 -0
  69. package/variation-utils.es.js +246 -0
  70. package/invoice-ui-BJZfedDd.cjs +0 -332
  71. package/invoice-ui-GJ1ADAjn.js +0 -5759
@@ -0,0 +1,820 @@
1
+ import { createClient as P, getServiceRoleSupabaseClient as ue } from "@nextblock-cms/db/server";
2
+ import { b as le, h as de, c as pe } from "./product-actions-DjlIWCMH.js";
3
+ import { createClient as G } from "@supabase/supabase-js";
4
+ import ne from "crypto";
5
+ import { Freemius as _e } from "@freemius/sdk";
6
+ import { n as se, b as me } from "./customer-C3xccjUg.js";
7
+ import { a as fe, r as ge } from "./coupon-server-DUKVtyYs.js";
8
+ import { getDefaultCurrency as ye, resolveEffectivePriceForCurrency as Ee, isSaleWindowActive as Z } from "./currency.es.js";
9
+ import { revalidatePath as X } from "next/cache";
10
+ function q(e) {
11
+ const r = e?.trim();
12
+ return r || null;
13
+ }
14
+ function ee(e) {
15
+ return e ? se({
16
+ company_name: e.company_name,
17
+ recipient_name: e.recipient_name,
18
+ line1: e.line1,
19
+ line2: e.line2,
20
+ city: e.city,
21
+ state: e.state,
22
+ postal_code: e.postal_code,
23
+ country_code: e.country_code
24
+ }) : null;
25
+ }
26
+ function re(e, r) {
27
+ return e?.find(
28
+ (t) => t.address_type === r && t.is_default
29
+ ) ?? e?.find((t) => t.address_type === r) ?? null;
30
+ }
31
+ async function te(e, r, t, n) {
32
+ const s = se(n), { data: o, error: l } = await e.from("user_addresses").select("*").eq("user_id", r).eq("address_type", t).order("is_default", { ascending: !1 }).order("updated_at", { ascending: !1 });
33
+ if (l)
34
+ throw new Error(l.message);
35
+ const c = o?.[0] ?? null, u = (o ?? []).slice(1).map((a) => a.id);
36
+ if (!s) {
37
+ if (o?.length) {
38
+ const a = o.map((m) => m.id), { error: d } = await e.from("user_addresses").delete().in("id", a);
39
+ if (d)
40
+ throw new Error(d.message);
41
+ }
42
+ return;
43
+ }
44
+ const y = {
45
+ user_id: r,
46
+ address_type: t,
47
+ is_default: !0,
48
+ company_name: s.company_name ?? null,
49
+ recipient_name: s.recipient_name ?? null,
50
+ line1: s.line1 ?? null,
51
+ line2: s.line2 ?? null,
52
+ city: s.city ?? null,
53
+ state: s.state ?? null,
54
+ postal_code: s.postal_code ?? null,
55
+ country_code: s.country_code ?? null,
56
+ updated_at: (/* @__PURE__ */ new Date()).toISOString()
57
+ };
58
+ if (c) {
59
+ const { error: a } = await e.from("user_addresses").update(y).eq("id", c.id);
60
+ if (a)
61
+ throw new Error(a.message);
62
+ } else {
63
+ const { error: a } = await e.from("user_addresses").insert(y);
64
+ if (a)
65
+ throw new Error(a.message);
66
+ }
67
+ if (u.length) {
68
+ const { error: a } = await e.from("user_addresses").delete().in("id", u);
69
+ if (a)
70
+ throw new Error(a.message);
71
+ }
72
+ }
73
+ async function Be(e, r) {
74
+ const t = r ?? P(), { data: n, error: s } = await t.from("user_addresses").select("*").eq("user_id", e).in("address_type", ["billing", "shipping"]).order("is_default", { ascending: !1 }).order("updated_at", { ascending: !1 });
75
+ if (s)
76
+ throw new Error(s.message);
77
+ const o = ee(re(n ?? [], "billing")), l = ee(
78
+ re(n ?? [], "shipping")
79
+ );
80
+ return {
81
+ billingAddress: o,
82
+ shippingAddress: l
83
+ };
84
+ }
85
+ async function he(e) {
86
+ const r = e.client ?? P();
87
+ await te(
88
+ r,
89
+ e.userId,
90
+ "billing",
91
+ e.billingAddress ?? null
92
+ ), await te(
93
+ r,
94
+ e.userId,
95
+ "shipping",
96
+ e.shippingAddress ?? null
97
+ );
98
+ }
99
+ async function Se(e) {
100
+ const r = e.client ?? P(), t = q(e.fullName), n = q(e.phone);
101
+ if (!t && !n)
102
+ return;
103
+ const { data: s, error: o } = await r.from("profiles").select("full_name, phone").eq("id", e.userId).maybeSingle();
104
+ if (o)
105
+ throw new Error(o.message);
106
+ if (!s)
107
+ return;
108
+ const l = q(s.full_name) || t, c = q(s.phone) || n;
109
+ if (q(s.full_name) === l && q(s.phone) === c)
110
+ return;
111
+ const { error: u } = await r.from("profiles").update({
112
+ full_name: l,
113
+ phone: c,
114
+ updated_at: (/* @__PURE__ */ new Date()).toISOString()
115
+ }).eq("id", e.userId);
116
+ if (u)
117
+ throw new Error(u.message);
118
+ }
119
+ function _(e) {
120
+ const r = process.env[e];
121
+ if (!r)
122
+ return null;
123
+ const t = r.trim();
124
+ return t.startsWith('"') && t.endsWith('"') || t.startsWith("'") && t.endsWith("'") ? t.slice(1, -1).trim() : t;
125
+ }
126
+ function we(e) {
127
+ const r = e?.trim();
128
+ if (!r)
129
+ return {
130
+ firstName: null,
131
+ lastName: null
132
+ };
133
+ const [t, ...n] = r.split(/\s+/);
134
+ return {
135
+ firstName: t || null,
136
+ lastName: n.length > 0 ? n.join(" ") : null
137
+ };
138
+ }
139
+ function ie(e) {
140
+ if (e == null || e === "")
141
+ return 0;
142
+ const r = Number(e);
143
+ return !Number.isFinite(r) || r <= 0 ? 0 : Math.round(r);
144
+ }
145
+ function Pe(e) {
146
+ return e === !0 || e === 1 || e === "1" || e === "true";
147
+ }
148
+ function Fe(e, r) {
149
+ const t = e?.[r];
150
+ return Array.isArray(t) ? t : t && typeof t == "object" ? [t] : [];
151
+ }
152
+ function V(e, r) {
153
+ for (const t of r) {
154
+ const n = Fe(e, t);
155
+ if (n.length > 0)
156
+ return n;
157
+ }
158
+ return Array.isArray(e) ? e : [];
159
+ }
160
+ function k(e) {
161
+ if (e == null || e === "")
162
+ return null;
163
+ const r = Number(e);
164
+ return Number.isFinite(r) ? r : null;
165
+ }
166
+ function be(e) {
167
+ return e === null ? 0 : e > 5e3 ? (console.warn(
168
+ `[Freemius Sync] Suspiciously high price detected: ${e}. Assuming it is already in cents.`
169
+ ), Math.round(e)) : Math.round(e * 100);
170
+ }
171
+ function Ce(e) {
172
+ const r = Number(e);
173
+ return !Number.isFinite(r) || r < 1 ? 1 : Math.round(r);
174
+ }
175
+ function ve() {
176
+ const e = _("FREEMIUS_CHECKOUT_PRODUCTS_JSON");
177
+ if (!e)
178
+ return null;
179
+ try {
180
+ const r = JSON.parse(e);
181
+ return r && typeof r == "object" ? r : null;
182
+ } catch (r) {
183
+ return console.error(
184
+ "[Freemius Checkout] Failed to parse FREEMIUS_CHECKOUT_PRODUCTS_JSON:",
185
+ r
186
+ ), null;
187
+ }
188
+ }
189
+ function Ke(e) {
190
+ const r = ve(), t = String(e), n = r?.[t], s = _("FREEMIUS_PRODUCT_ID"), o = _(
191
+ "FREEMIUS_ECOMMERCE_SANDBOX_PUBLIC_KEY"
192
+ ), l = _(
193
+ "FREEMIUS_ECOMMERCE_SANDBOX_SECRET_KEY"
194
+ );
195
+ return n?.publicKey ? {
196
+ publicKey: n.publicKey,
197
+ secretKey: n.secretKey ?? null,
198
+ apiKey: n.apiKey ?? null,
199
+ source: "product-map"
200
+ } : process.env.FREEMIUS_SANDBOX_ENABLED === "true" && s && s === t && o ? {
201
+ publicKey: o,
202
+ secretKey: l,
203
+ apiKey: _("FREEMIUS_API_KEY"),
204
+ source: "single-product-sandbox-env"
205
+ } : s && s === t && _("FREEMIUS_PUBLIC_KEY") ? {
206
+ publicKey: _("FREEMIUS_PUBLIC_KEY"),
207
+ secretKey: _("FREEMIUS_SECRET_KEY"),
208
+ apiKey: _("FREEMIUS_API_KEY"),
209
+ source: "single-product-env"
210
+ } : {
211
+ publicKey: _("FREEMIUS_PUBLIC_KEY"),
212
+ secretKey: _("FREEMIUS_SECRET_KEY"),
213
+ apiKey: _("FREEMIUS_API_KEY"),
214
+ source: "legacy-env"
215
+ };
216
+ }
217
+ async function Re(e) {
218
+ if (!e.apiKey)
219
+ throw new Error("Missing Freemius API key for SDK sandbox generation.");
220
+ return new _e({
221
+ productId: Number(e.productId),
222
+ apiKey: e.apiKey,
223
+ secretKey: e.secretKey,
224
+ publicKey: e.publicKey
225
+ }).checkout.getSandboxParams();
226
+ }
227
+ class Le {
228
+ getProviderName() {
229
+ return "Freemius";
230
+ }
231
+ async createCheckoutSession({
232
+ items: r,
233
+ customerEmail: t,
234
+ customerPhone: n,
235
+ userId: s,
236
+ billingAddress: o,
237
+ shippingAddress: l,
238
+ currencyCode: c,
239
+ couponCode: u,
240
+ couponContextItems: y
241
+ }) {
242
+ const a = process.env.NEXT_PUBLIC_SUPABASE_URL, d = process.env.SUPABASE_SERVICE_ROLE_KEY;
243
+ if (!a || !d)
244
+ return { error: "Missing Supabase credentials for checkout (Service Key required).", url: null };
245
+ const m = G(a, d);
246
+ if (!r || r.length === 0)
247
+ return { error: "Cart is empty", url: null };
248
+ if (r.length !== 1)
249
+ return { error: "Freemius items must be checked out one at a time.", url: null };
250
+ const { data: E, error: v } = await m.from("currencies").select(
251
+ "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"
252
+ ).eq("is_active", !0).order("code", { ascending: !0 }), I = E ?? [];
253
+ if (v || I.length === 0)
254
+ return { error: "Failed to resolve store currencies", url: null };
255
+ const H = ye(I), K = I.find((f) => f.code === (c || "").toUpperCase()) ?? H, h = r[0], { data: p, error: A } = await m.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", h.product_id).single();
256
+ if (A || !p)
257
+ return { error: "Product not found", url: null };
258
+ const U = p.freemius_plan_id, F = p.freemius_product_id;
259
+ if (!U || !F)
260
+ return { error: "Product is not configured for Freemius checkout (missing Plan ID or Product ID)", url: null };
261
+ const N = Ee({
262
+ prices: p.prices || {},
263
+ salePrices: p.sale_prices || {},
264
+ fallbackPrice: p.price,
265
+ fallbackSalePrice: p.sale_price,
266
+ saleStartAt: p.sale_start_at,
267
+ saleEndAt: p.sale_end_at,
268
+ scheduledPrice: p.scheduled_price,
269
+ scheduledPrices: p.scheduled_prices || {},
270
+ scheduledPriceAt: p.scheduled_price_at,
271
+ currencyCode: K.code,
272
+ currencies: I
273
+ }), x = N.sale_price ?? N.price, O = Z({
274
+ saleStartAt: p.sale_start_at,
275
+ saleEndAt: p.sale_end_at
276
+ }), S = x * h.quantity;
277
+ let i = null, g = 0;
278
+ if (u) {
279
+ const f = await fe({
280
+ client: m,
281
+ code: u,
282
+ items: y && y.length > 0 ? y : r,
283
+ currencyCode: K.code
284
+ });
285
+ if (!f.success)
286
+ return {
287
+ error: f.error,
288
+ errorKey: f.errorKey,
289
+ errorStatus: 400,
290
+ url: null
291
+ };
292
+ i = f.quote, g = Math.min(
293
+ S,
294
+ i.lineDiscounts.filter(($) => $.product_id === p.id).reduce(($, j) => $ + j.discount, 0)
295
+ );
296
+ }
297
+ const b = ie(p.trial_period_days), R = b > 0 ? h.trial_preference ? h.trial_preference : p.trial_requires_payment_method ? "paid" : "free" : null, B = "pending", w = we(
298
+ o?.recipient_name ?? null
299
+ ), { data: z, error: W } = await m.from("orders").insert({
300
+ status: B,
301
+ total: Math.max(0, S - g),
302
+ currency: K.code,
303
+ exchange_rate_at_purchase: K.exchange_rate,
304
+ subtotal: S,
305
+ discount_total: g,
306
+ coupon_id: i?.couponId ?? null,
307
+ coupon_code: i?.code ?? null,
308
+ discount_details: i ? {
309
+ code: i.code,
310
+ discount_type: i.discountType,
311
+ discount_amount: i.discountAmount,
312
+ provider: "freemius",
313
+ provider_discounts: i.providerDiscounts,
314
+ line_discounts: i.lineDiscounts,
315
+ final_amount_owned_by: "freemius"
316
+ } : null,
317
+ provider: "freemius",
318
+ freemius_product_id: String(F),
319
+ freemius_plan_id: String(U),
320
+ user_id: s || null,
321
+ customer_details: me({
322
+ email: t,
323
+ phone: n,
324
+ name: o?.recipient_name,
325
+ billing: o,
326
+ shipping: l
327
+ })
328
+ }).select("id").single();
329
+ if (W || !z)
330
+ return console.error("Failed to create pending order:", W), { error: "Failed to initiate order", url: null };
331
+ const { error: J } = await m.from("order_items").insert([{
332
+ order_id: z.id,
333
+ product_id: p.id,
334
+ quantity: h.quantity,
335
+ price_at_purchase: x
336
+ }]);
337
+ if (J && console.error("Failed to insert order items:", J), s)
338
+ try {
339
+ await he({
340
+ userId: s,
341
+ billingAddress: o,
342
+ shippingAddress: l,
343
+ client: m
344
+ }), await Se({
345
+ userId: s,
346
+ fullName: o?.recipient_name ?? l?.recipient_name ?? null,
347
+ phone: n,
348
+ client: m
349
+ });
350
+ } catch (f) {
351
+ console.error(
352
+ "Failed to sync checkout profile defaults before checkout:",
353
+ f
354
+ );
355
+ }
356
+ i && await ge({
357
+ client: m,
358
+ quote: i,
359
+ orderId: z.id,
360
+ provider: "freemius",
361
+ discountTotal: g,
362
+ userId: s,
363
+ customerEmail: t,
364
+ metadata: {
365
+ currency: K.code,
366
+ subtotal: S,
367
+ final_amount_owned_by: "freemius"
368
+ }
369
+ });
370
+ const L = process.env.FREEMIUS_SANDBOX_ENABLED === "true", M = Ke(F), D = M.publicKey, T = M.secretKey, Q = M.apiKey;
371
+ if (!D || L && !T)
372
+ return { error: "Missing FREEMIUS credentials (PUBLIC_KEY or SECRET_KEY) in environment variables.", url: null };
373
+ if (L && M.source === "legacy-env") {
374
+ const f = _("FREEMIUS_PRODUCT_ID"), $ = !!_("FREEMIUS_ECOMMERCE_SANDBOX_PUBLIC_KEY"), j = !!_("FREEMIUS_ECOMMERCE_SANDBOX_SECRET_KEY");
375
+ console.warn(
376
+ `[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.`,
377
+ {
378
+ configuredProductId: f,
379
+ productIdsMatch: f === String(F),
380
+ hasSandboxOverridePublicKey: $,
381
+ hasSandboxOverrideSecretKey: j,
382
+ hasCheckoutProductsJson: !!_("FREEMIUS_CHECKOUT_PRODUCTS_JSON")
383
+ }
384
+ );
385
+ }
386
+ let Y = !1;
387
+ if (L && T && D)
388
+ try {
389
+ Y = await Re({
390
+ productId: F,
391
+ publicKey: D,
392
+ secretKey: T,
393
+ apiKey: Q
394
+ });
395
+ } catch (f) {
396
+ console.warn(
397
+ "Freemius Checkout - SDK sandbox generation failed. Falling back to manual token generation.",
398
+ f,
399
+ {
400
+ credentialSource: M.source,
401
+ hasApiKey: !!Q
402
+ }
403
+ );
404
+ const $ = Math.floor(Date.now() / 1e3).toString(), j = `${$}${F}${T}${D}checkout`, ce = ne.createHash("md5").update(j).digest("hex");
405
+ Y = {
406
+ ctx: $,
407
+ token: ce
408
+ };
409
+ }
410
+ const C = new URL(`https://checkout.freemius.com/app/${F}/plan/${U}/`);
411
+ if (L && T && D ? (C.searchParams.append("sandbox", Y.token), C.searchParams.append("s_ctx_ts", Y.ctx)) : L && C.searchParams.append("sandbox", "true"), t && C.searchParams.append("user_email", t), w.firstName && C.searchParams.append("user_firstname", w.firstName), w.lastName && C.searchParams.append("user_lastname", w.lastName), C.searchParams.append("currency", K.code.toLowerCase()), h.billing_cycle && C.searchParams.append("billing_cycle", h.billing_cycle), R && C.searchParams.append("trial", R), i)
412
+ C.searchParams.append("coupon", i.code);
413
+ else if (O) {
414
+ const { data: f } = await m.from("product_freemius_sale_coupons").select("freemius_coupon_code, is_active, starts_at, ends_at, sync_status").eq("product_id", p.id).maybeSingle();
415
+ f?.is_active && f.sync_status === "synced" && f.freemius_coupon_code && Z({
416
+ saleStartAt: f.starts_at,
417
+ saleEndAt: f.ends_at
418
+ }) && C.searchParams.append("coupon", f.freemius_coupon_code);
419
+ }
420
+ return {
421
+ url: C.toString(),
422
+ customProps: {
423
+ provider: "freemius",
424
+ plugin_id: F,
425
+ plan_id: U,
426
+ public_key: D,
427
+ user_email: t,
428
+ user_firstname: w.firstName,
429
+ user_lastname: w.lastName,
430
+ credential_source: M.source,
431
+ sandbox: Y,
432
+ billing_cycle: h.billing_cycle,
433
+ trial: R,
434
+ trial_period_days: b,
435
+ trial_requires_payment_method: p.trial_requires_payment_method,
436
+ initial_order_status: B,
437
+ coupon: i?.code ?? null,
438
+ order_id: z.id
439
+ }
440
+ };
441
+ }
442
+ }
443
+ async function oe(e, r, t, n) {
444
+ const o = (/* @__PURE__ */ new Date()).toUTCString().replace("GMT", "+0000"), l = `GET
445
+
446
+
447
+ ${o}
448
+ ${e}`, c = ne.createHmac("sha256", n).update(l).digest("hex"), u = Buffer.from(c).toString("base64").replace(/\+/g, "-").replace(/\//g, "_").replace(/=/g, ""), y = `FS ${r}:${t}:${u}`, a = await fetch(`https://api.freemius.com${e}`, {
449
+ headers: {
450
+ Authorization: y,
451
+ Date: o,
452
+ Accept: "application/json"
453
+ }
454
+ });
455
+ if (!a.ok) {
456
+ const d = await a.text();
457
+ throw console.error(`[Freemius API] [ERROR] ${e} returned ${a.status}: ${d}`), new Error(`Freemius API failed on ${e}: ${a.status} - ${d}`);
458
+ }
459
+ return a.json();
460
+ }
461
+ async function Ue() {
462
+ const e = _("FREEMIUS_DEVELOPER_ID"), r = _("FREEMIUS_PUBLIC_KEY"), t = _("FREEMIUS_SECRET_KEY"), n = process.env.NEXT_PUBLIC_SUPABASE_URL, s = process.env.SUPABASE_SERVICE_ROLE_KEY;
463
+ if (!e || !r || !t || !n || !s)
464
+ throw new Error("Missing necessary environment variables for Freemius Sync.");
465
+ const o = G(n, s, {
466
+ auth: { autoRefreshToken: !1, persistSession: !1 }
467
+ }), l = (c) => oe(c, e, r, t);
468
+ try {
469
+ console.log(`[Freemius Sync] Fetching all plugins for developer ${e}...`);
470
+ const c = await l(`/v1/developers/${e}/plugins.json`), u = V(c, ["plugins", "plugin"]);
471
+ console.log(`[Freemius Sync] Found ${u.length} plugins. Syncing plans...`);
472
+ let y = 0;
473
+ const { data: a } = await o.from("languages").select("id").eq("code", "en").single(), d = a?.id;
474
+ if (!d)
475
+ throw new Error("English language not found in database. Cannot sync products.");
476
+ for (const m of u) {
477
+ const E = m.id?.toString();
478
+ if (!E) {
479
+ console.warn("[Freemius Sync] Skipping plugin without an id:", m);
480
+ continue;
481
+ }
482
+ const v = await ae(
483
+ o,
484
+ e,
485
+ E,
486
+ m.title || m.name || `Freemius Product ${E}`,
487
+ l,
488
+ d
489
+ );
490
+ y += v;
491
+ }
492
+ return { success: !0, count: y };
493
+ } catch (c) {
494
+ throw console.error("[Freemius Sync] Global Error:", c), c;
495
+ }
496
+ }
497
+ async function $e(e) {
498
+ const r = _("FREEMIUS_DEVELOPER_ID"), t = _("FREEMIUS_PUBLIC_KEY"), n = _("FREEMIUS_SECRET_KEY"), s = process.env.NEXT_PUBLIC_SUPABASE_URL, o = process.env.SUPABASE_SERVICE_ROLE_KEY;
499
+ if (!r || !t || !n || !s || !o)
500
+ throw new Error("Missing environment variables for Freemius Sync.");
501
+ const l = G(s, o), c = (E) => oe(E, r, t, n), { data: u } = await l.from("languages").select("id").eq("code", "en").single(), y = u?.id;
502
+ if (!y)
503
+ throw new Error("English language not found in database. Cannot sync products.");
504
+ const a = await c(`/v1/developers/${r}/plugins/${e}.json`), d = a.plugin ?? a;
505
+ return { success: !0, count: await ae(
506
+ l,
507
+ r,
508
+ e,
509
+ d.title || d.name || `Freemius Product ${e}`,
510
+ c,
511
+ y
512
+ ) };
513
+ }
514
+ async function ae(e, r, t, n, s, o) {
515
+ console.log(`[Freemius Sync] Fetching plans for plugin: ${n} (${t})...`);
516
+ let l = 0;
517
+ try {
518
+ const c = `/v1/developers/${r}/plugins/${t}/plans.json`, u = await s(c), y = V(u, ["plans", "plan"]);
519
+ console.log(`[Freemius Sync] Received ${y.length} plans for plugin ${t}.`);
520
+ for (const a of y) {
521
+ const d = a.id?.toString();
522
+ if (!d) {
523
+ console.warn("[Freemius Sync] Skipping plan without an id:", a);
524
+ continue;
525
+ }
526
+ const m = a.name || a.title || d, E = a.title || m;
527
+ console.log(`[Freemius Sync] Processing plan: ${E} (${d})...`);
528
+ let v = a;
529
+ if (v.trial_period === void 0 || v.is_require_subscription === void 0)
530
+ try {
531
+ const i = `/v1/developers/${r}/plugins/${t}/plans/${d}.json`, g = await s(i), b = g.plan ?? g;
532
+ v = {
533
+ ...v,
534
+ ...b
535
+ };
536
+ } catch (i) {
537
+ console.warn(
538
+ `[Freemius Sync] Could not fetch trial details for plan ${d}:`,
539
+ i instanceof Error ? i.message : i
540
+ );
541
+ }
542
+ const I = ie(v.trial_period), H = I > 0 && Pe(v.is_require_subscription);
543
+ let K = 0, h = [];
544
+ try {
545
+ const i = `/v1/developers/${r}/plugins/${t}/plans/${d}/pricing.json`, g = await s(i);
546
+ if (h = V(g, [
547
+ "pricing",
548
+ "prices",
549
+ "pricings"
550
+ ]), h.length > 0) {
551
+ const b = h[0], R = k(b.annual_price) ?? k(b.monthly_price) ?? k(b.lifetime_price);
552
+ K = be(R);
553
+ }
554
+ console.log(`[Freemius Sync] Plan: ${E} -> Resolved Price (cents): ${K}`);
555
+ } catch (i) {
556
+ console.warn(`[Freemius Sync] Could not fetch pricing for plan ${d}:`, i instanceof Error ? i.message : i);
557
+ }
558
+ const p = `${n}-${E}`.toLowerCase().replace(/[^\w\s-]/g, "").replace(/[\s_]+/g, "-").replace(/^-+|-+$/g, ""), A = {
559
+ title: `${n} - ${E}`,
560
+ slug: p,
561
+ short_description: a.description || "",
562
+ price: K,
563
+ product_type: "digital",
564
+ payment_provider: "freemius",
565
+ freemius_plan_id: d,
566
+ freemius_product_id: t,
567
+ trial_period_days: I,
568
+ trial_requires_payment_method: H,
569
+ status: "active",
570
+ stock: 999,
571
+ sku: `FM-${t}-${d}`,
572
+ language_id: o
573
+ }, { data: U, error: F } = await e.from("products").upsert(A, { onConflict: "language_id, sku" }).select();
574
+ if (F || !U || U.length === 0) {
575
+ console.error(`[Freemius Sync] Error upserting product ${A.sku}:`, F);
576
+ continue;
577
+ }
578
+ const N = U[0].id, { data: x, error: O } = await e.from("freemius_plans").select("id").eq("product_id", N).eq("name", m).maybeSingle();
579
+ O && console.warn(
580
+ `[Freemius Sync] Could not check existing local plan for ${A.sku}:`,
581
+ O.message || O
582
+ );
583
+ let S = "";
584
+ if (x) {
585
+ S = x.id;
586
+ const { error: i } = await e.from("freemius_plans").update({ title: E, updated_at: (/* @__PURE__ */ new Date()).toISOString() }).eq("id", S);
587
+ i && console.warn(
588
+ `[Freemius Sync] Could not update local plan ${S}:`,
589
+ i.message || i
590
+ );
591
+ } else {
592
+ const { data: i, error: g } = await e.from("freemius_plans").insert({
593
+ product_id: N,
594
+ name: m,
595
+ title: E
596
+ }).select("id").single();
597
+ g && console.warn(
598
+ `[Freemius Sync] Could not insert local plan for ${A.sku}:`,
599
+ g.message || g
600
+ ), i && (S = i.id);
601
+ }
602
+ if (S && h.length > 0)
603
+ for (const i of h) {
604
+ const g = Ce(
605
+ i.licenses ?? i.license_quota ?? i.quota
606
+ ), { data: b, error: R } = await e.from("freemius_pricing").select("id").eq("plan_id", S).eq("license_quota", g).maybeSingle();
607
+ R && console.warn(
608
+ `[Freemius Sync] Could not check pricing for plan ${S}, quota ${g}:`,
609
+ R.message || R
610
+ );
611
+ const B = {
612
+ api_monthly_price: k(i.monthly_price),
613
+ api_annual_price: k(i.annual_price),
614
+ api_lifetime_price: k(i.lifetime_price),
615
+ updated_at: (/* @__PURE__ */ new Date()).toISOString()
616
+ };
617
+ if (b) {
618
+ const { error: w } = await e.from("freemius_pricing").update(B).eq("id", b.id);
619
+ w && console.warn(
620
+ `[Freemius Sync] Could not update pricing ${b.id}:`,
621
+ w.message || w
622
+ );
623
+ } else {
624
+ const { error: w } = await e.from("freemius_pricing").insert({
625
+ plan_id: S,
626
+ license_quota: g,
627
+ ...B
628
+ });
629
+ w && console.warn(
630
+ `[Freemius Sync] Could not insert pricing for plan ${S}, quota ${g}:`,
631
+ w.message || w
632
+ );
633
+ }
634
+ }
635
+ console.log(`[Freemius Sync] Successfully fully synced product ${A.sku}.`), l++;
636
+ }
637
+ } catch (c) {
638
+ console.error(`[Freemius Sync] Failed sync for plugin ${t}:`, c.message);
639
+ }
640
+ return l;
641
+ }
642
+ async function Te(e) {
643
+ const r = P(), { data: t, count: n, error: s } = await await de(r, e);
644
+ if (s) throw new Error(s.message);
645
+ return { data: t, count: n };
646
+ }
647
+ async function Ye(e) {
648
+ const r = P(), { data: t, error: n } = await le(r, e);
649
+ if (n) throw new Error(n.message);
650
+ return t;
651
+ }
652
+ async function je() {
653
+ try {
654
+ const e = await Ue();
655
+ return X("/cms/products", "page"), { success: !0, data: e };
656
+ } catch (e) {
657
+ return { error: e.message || "Failed to sync with Freemius" };
658
+ }
659
+ }
660
+ async function Xe(e) {
661
+ try {
662
+ const r = await $e(e);
663
+ return X("/cms/products", "page"), { success: !0, data: r };
664
+ } catch (r) {
665
+ return { error: r.message || "Failed to sync product with Freemius" };
666
+ }
667
+ }
668
+ async function ze(e, r) {
669
+ try {
670
+ const t = P();
671
+ return await pe(t, e, r), X("/cms/products"), X(`/cms/products/${e}/edit`), { success: !0 };
672
+ } catch (t) {
673
+ return { success: !1, error: t.message || "Failed to copy product content" };
674
+ }
675
+ }
676
+ async function He(e) {
677
+ const r = P(), { data: t, error: n } = await r.from("products").select("id, title, language_id, slug").eq("translation_group_id", e);
678
+ if (n) throw new Error(n.message);
679
+ return t;
680
+ }
681
+ async function Ve() {
682
+ const e = ue(), { data: r, error: t } = await e.from("product_attributes").select(`
683
+ id,
684
+ name,
685
+ name_translations,
686
+ slug,
687
+ product_attribute_terms (
688
+ id,
689
+ attribute_id,
690
+ value,
691
+ slug,
692
+ sort_order,
693
+ value_translations
694
+ )
695
+ `);
696
+ if (t)
697
+ throw new Error(t.message);
698
+ return (r || []).map((n) => ({
699
+ ...n,
700
+ product_attribute_terms: (n.product_attribute_terms || []).sort(
701
+ (s, o) => (s.sort_order ?? Number.MAX_SAFE_INTEGER) - (o.sort_order ?? Number.MAX_SAFE_INTEGER) || s.value.localeCompare(o.value)
702
+ )
703
+ })).sort((n, s) => n.name.localeCompare(s.name));
704
+ }
705
+ async function Ge(e) {
706
+ const r = P(), { data: t, error: n } = await r.from("freemius_plans").select(`
707
+ id,
708
+ name,
709
+ title,
710
+ freemius_pricing (
711
+ id,
712
+ license_quota,
713
+ api_monthly_price,
714
+ api_annual_price,
715
+ api_lifetime_price,
716
+ override_monthly_price,
717
+ override_annual_price,
718
+ override_lifetime_price,
719
+ is_active
720
+ )
721
+ `).eq("product_id", e);
722
+ if (n) throw new Error(n.message);
723
+ return t;
724
+ }
725
+ async function We(e, r) {
726
+ const t = P(), { error: n } = await t.from("freemius_pricing").update({
727
+ ...r,
728
+ updated_at: (/* @__PURE__ */ new Date()).toISOString()
729
+ }).eq("id", e);
730
+ return n ? { success: !1, error: n.message } : (X("/cms/products"), { success: !0 });
731
+ }
732
+ async function Je(e) {
733
+ const r = P(), { data: t } = await r.from("products").select("translation_group_id").eq("id", e).maybeSingle();
734
+ let n = [e];
735
+ if (t?.translation_group_id) {
736
+ const { data: c } = await r.from("products").select("id").eq("translation_group_id", t.translation_group_id);
737
+ c && c.length > 0 && (n = c.map((u) => u.id));
738
+ }
739
+ const { data: s, error: o } = await r.from("freemius_plans").select(`
740
+ id,
741
+ name,
742
+ title,
743
+ freemius_pricing (
744
+ id,
745
+ license_quota,
746
+ api_monthly_price,
747
+ api_annual_price,
748
+ api_lifetime_price,
749
+ override_monthly_price,
750
+ override_annual_price,
751
+ override_lifetime_price,
752
+ is_active
753
+ )
754
+ `).in("product_id", n);
755
+ if (o) throw new Error(o.message);
756
+ return (s || []).map((c) => ({
757
+ id: c.id,
758
+ name: c.name,
759
+ title: c.title,
760
+ pricing: (c.freemius_pricing || []).filter((u) => u.is_active !== !1).map((u) => ({
761
+ id: u.id,
762
+ license_quota: u.license_quota,
763
+ monthly_price: u.override_monthly_price ?? u.api_monthly_price,
764
+ annual_price: u.override_annual_price ?? u.api_annual_price,
765
+ lifetime_price: u.override_lifetime_price ?? u.api_lifetime_price,
766
+ is_active: u.is_active
767
+ }))
768
+ }));
769
+ }
770
+ async function Qe() {
771
+ const e = P(), { data: r, error: t } = await e.from("categories").select("id, name, slug, description, created_at, name_translations, description_translations, product_categories(count)").order("name", { ascending: !0 });
772
+ if (t) throw new Error(t.message);
773
+ return (r || []).map((n) => {
774
+ const s = n.product_categories?.[0]?.count ?? n.product_categories?.count ?? 0;
775
+ return {
776
+ id: n.id,
777
+ name: n.name,
778
+ slug: n.slug,
779
+ description: n.description ?? "",
780
+ created_at: n.created_at,
781
+ productCount: Number(s),
782
+ name_translations: n.name_translations || {},
783
+ description_translations: n.description_translations || {}
784
+ };
785
+ });
786
+ }
787
+ async function Ze(e) {
788
+ const r = P(), { data: t, error: n } = await r.from("categories").select("id, name, slug, description, created_at").eq("slug", e).maybeSingle();
789
+ if (n) throw new Error(n.message);
790
+ return t;
791
+ }
792
+ async function er(e) {
793
+ const r = P(), { data: t, error: n } = await r.from("product_categories").select("category:categories(id, name, slug, description, name_translations, description_translations, created_at)").eq("product_id", e);
794
+ if (n) throw new Error(n.message);
795
+ return (t || []).map((s) => s.category).filter(Boolean);
796
+ }
797
+ export {
798
+ Le as F,
799
+ Ke as a,
800
+ Te as b,
801
+ Ve as c,
802
+ We as d,
803
+ Ye as e,
804
+ Se as f,
805
+ Je as g,
806
+ Ge as h,
807
+ He as i,
808
+ ze as j,
809
+ Qe as k,
810
+ Ze as l,
811
+ Be as m,
812
+ er as n,
813
+ $e as o,
814
+ ve as p,
815
+ Xe as q,
816
+ _ as r,
817
+ Ue as s,
818
+ je as t,
819
+ he as u
820
+ };