@nextblock-cms/ecom 0.22.1 → 0.22.3

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 (88) hide show
  1. package/README.md +43 -43
  2. package/index.cjs +1 -1
  3. package/index.es.js +31 -31
  4. package/lib/components/Checkout.cjs +1 -1
  5. package/lib/components/Checkout.es.js +1 -0
  6. package/lib/components/SubscriptionSelector.cjs +1 -1
  7. package/lib/components/SubscriptionSelector.es.js +91 -92
  8. package/lib/coupon-server.cjs +1 -1
  9. package/lib/coupon-server.es.js +78 -61
  10. package/lib/coupons.cjs +1 -1
  11. package/lib/coupons.d.ts +9 -0
  12. package/lib/coupons.es.js +11 -2
  13. package/lib/currency-sync.cjs +1 -1
  14. package/lib/currency-sync.es.js +1 -1
  15. package/lib/freemius-coupons.cjs +1 -1
  16. package/lib/freemius-coupons.es.js +88 -92
  17. package/lib/freemius-license-claim.cjs +1 -1
  18. package/lib/freemius-license-claim.d.ts +13 -0
  19. package/lib/freemius-license-claim.es.js +44 -29
  20. package/lib/freemius-license.cjs +1 -1
  21. package/lib/freemius-license.es.js +19 -17
  22. package/lib/freemius-order-sync.cjs +1 -1
  23. package/lib/freemius-order-sync.d.ts +44 -0
  24. package/lib/freemius-order-sync.es.js +164 -77
  25. package/lib/freemius-pricing-server.cjs +1 -0
  26. package/lib/freemius-pricing-server.d.ts +65 -0
  27. package/lib/freemius-pricing-server.es.js +82 -0
  28. package/lib/freemius-pricing.cjs +1 -0
  29. package/lib/freemius-pricing.d.ts +53 -0
  30. package/lib/freemius-pricing.es.js +51 -0
  31. package/lib/invoice-server.cjs +1 -1
  32. package/lib/invoice-server.es.js +1 -0
  33. package/lib/pages/cms/coupons/CouponsPage.cjs +1 -1
  34. package/lib/pages/cms/coupons/CouponsPage.es.js +1 -0
  35. package/lib/pages/cms/coupons/EditCouponPage.cjs +1 -1
  36. package/lib/pages/cms/coupons/EditCouponPage.es.js +1 -0
  37. package/lib/pages/cms/coupons/actions.cjs +1 -1
  38. package/lib/pages/cms/coupons/actions.es.js +1 -0
  39. package/lib/pages/cms/orders/actions.cjs +1 -1
  40. package/lib/pages/cms/orders/actions.es.js +1 -0
  41. package/lib/pages/cms/orders/export-actions.cjs +1 -1
  42. package/lib/pages/cms/orders/export-actions.es.js +1 -0
  43. package/lib/pages/cms/orders/server-actions.cjs +1 -1
  44. package/lib/pages/cms/orders/server-actions.es.js +1 -0
  45. package/lib/pages/cms/products/ProductsPage.cjs +1 -1
  46. package/lib/pages/cms/products/ProductsPage.es.js +1 -0
  47. package/lib/pages/cms/products/[id]/edit/EditProductPage.cjs +1 -1
  48. package/lib/pages/cms/products/[id]/edit/EditProductPage.es.js +1 -0
  49. package/lib/pages/cms/products/actions.cjs +3 -3
  50. package/lib/pages/cms/products/actions.d.ts +11 -5
  51. package/lib/pages/cms/products/actions.es.js +45 -12
  52. package/lib/pages/cms/products/inventory/actions.cjs +1 -1
  53. package/lib/pages/cms/products/inventory/actions.es.js +1 -0
  54. package/lib/pages/cms/products/new/NewProductPage.cjs +1 -1
  55. package/lib/pages/cms/products/new/NewProductPage.es.js +1 -0
  56. package/lib/pages/cms/products/server-actions.cjs +1 -1
  57. package/lib/pages/cms/products/server-actions.es.js +1 -0
  58. package/lib/pages/cms/shipping/ShippingPage.cjs +1 -1
  59. package/lib/pages/cms/shipping/ShippingPage.es.js +1 -0
  60. package/lib/pages/cms/shipping/server-actions.cjs +1 -1
  61. package/lib/pages/cms/shipping/server-actions.es.js +1 -0
  62. package/lib/pages/cms/taxes/TaxesPage.cjs +1 -1
  63. package/lib/pages/cms/taxes/TaxesPage.es.js +1 -0
  64. package/lib/payment-config.cjs +1 -1
  65. package/lib/payment-config.es.js +1 -0
  66. package/lib/providers/freemius.cjs +1 -1
  67. package/lib/providers/freemius.es.js +200 -187
  68. package/lib/providers/stripe.cjs +1 -1
  69. package/lib/providers/stripe.es.js +151 -150
  70. package/lib/server-actions/coupon-actions.cjs +1 -1
  71. package/lib/server-actions/coupon-actions.es.js +1 -0
  72. package/lib/server-actions/customer-actions.d.ts +6 -1
  73. package/lib/server-actions/require-ecom-role.cjs +1 -1
  74. package/lib/server-actions/require-ecom-role.es.js +22 -10
  75. package/lib/server-actions/tax-actions.cjs +1 -1
  76. package/lib/server-actions/tax-actions.es.js +1 -0
  77. package/lib/shared-inventory.cjs +1 -1
  78. package/lib/shared-inventory.es.js +1 -1
  79. package/lib/stripe/checkout.cjs +1 -1
  80. package/lib/stripe/checkout.es.js +1 -0
  81. package/lib/stripe/order-sync.cjs +1 -1
  82. package/lib/stripe/order-sync.es.js +1 -0
  83. package/lib/stripe/webhooks.cjs +1 -1
  84. package/lib/stripe/webhooks.d.ts +10 -0
  85. package/lib/stripe/webhooks.es.js +23 -10
  86. package/package.json +4 -4
  87. package/server.cjs +1 -1
  88. package/server.es.js +31 -31
@@ -1 +1 @@
1
- const e=require("../../../../_virtual/_rolldown/runtime.cjs"),t=require("../../../states.cjs"),n=require("../../../inventory-settings.cjs"),r=require("../payments/queries.cjs"),i=require("./actions.cjs"),a=require("./components/TaxRateForm.cjs");let o=require("next/link");o=e.__toESM(o,1);let s=require("lucide-react"),c=require("react/jsx-runtime"),l=require("@nextblock-cms/db/server"),u=require("@nextblock-cms/ui");function d(e){return`${e.toFixed(4).replace(/\.?0+$/,``)}%`}function f(e){return e.state_code?`${e.country_code} - ${t.resolveSubdivisionName(e.country_code,e.state_code)}`:`${e.country_code} - Country-wide`}async function p({searchParams:e}){let t=(0,l.createClient)(),p=(0,l.getServiceRoleSupabaseClient)(),[m,h,g]=await Promise.all([n.getEcommerceInventorySettings(t),r.getEnabledPaymentProviders(),p.from(`tax_rates`).select(`id, country_code, state_code, tax_name, tax_rate, created_at, updated_at`).order(`country_code`).order(`state_code`).order(`tax_name`)]),_=g.data||[],v=g.error,y=h.stripe;return(0,c.jsxs)(`div`,{className:`mx-auto w-full max-w-6xl space-y-6 px-6 py-8`,children:[e?.success?(0,c.jsx)(`div`,{className:`rounded-lg border border-emerald-200 bg-emerald-50 px-4 py-3 text-sm text-emerald-700`,children:e.success}):null,(0,c.jsxs)(`div`,{className:`flex items-center justify-between gap-4`,children:[(0,c.jsxs)(`div`,{className:`flex items-center gap-3`,children:[(0,c.jsx)(u.Button,{asChild:!0,variant:`outline`,size:`icon`,"aria-label":`Back to shipping`,children:(0,c.jsx)(o.default,{href:`/cms/shipping`,children:(0,c.jsx)(s.ArrowLeft,{className:`h-4 w-4`})})}),(0,c.jsxs)(`div`,{children:[(0,c.jsx)(`h1`,{className:`text-2xl font-bold`,children:`Tax Settings`}),(0,c.jsx)(`p`,{className:`text-sm text-muted-foreground`,children:`Configure Stripe tax behavior globally and maintain manual country or state/province tax rates for physical goods.`})]})]}),(0,c.jsxs)(`div`,{className:`flex items-center gap-2`,children:[(0,c.jsxs)(u.Badge,{variant:y?`default`:`outline`,className:`uppercase`,children:[`Stripe `,y?`Enabled`:`Disabled`]}),(0,c.jsx)(`div`,{className:`rounded-full border bg-muted/30 p-3 text-muted-foreground`,children:(0,c.jsx)(s.Settings2,{className:`h-5 w-5`})})]})]}),y?(0,c.jsxs)(c.Fragment,{children:[(0,c.jsxs)(u.Card,{children:[(0,c.jsxs)(u.CardHeader,{children:[(0,c.jsx)(u.CardTitle,{children:`Global Tax Controls`}),(0,c.jsx)(u.CardDescription,{children:`Manual mode uses the tax rates below. Automatic mode uses Stripe Tax during Stripe Checkout instead of a free third-party tax API.`})]}),(0,c.jsx)(u.CardContent,{children:(0,c.jsxs)(`form`,{action:i.updateTaxSettingsAction,className:`space-y-6`,children:[(0,c.jsxs)(`div`,{className:`rounded-lg border bg-muted/20 p-4`,children:[(0,c.jsx)(`input`,{type:`hidden`,name:`enableTaxes`,value:`false`}),(0,c.jsxs)(`label`,{htmlFor:`enable-taxes`,className:`flex cursor-pointer items-start gap-3`,children:[(0,c.jsx)(`input`,{id:`enable-taxes`,name:`enableTaxes`,type:`checkbox`,value:`true`,defaultChecked:m.enableTaxes,className:`mt-1 h-4 w-4 rounded border-slate-300 text-primary focus:ring-primary`}),(0,c.jsxs)(`span`,{className:`space-y-1`,children:[(0,c.jsx)(`span`,{className:`block font-medium`,children:`Enable taxes`}),(0,c.jsx)(`span`,{className:`block text-sm text-muted-foreground`,children:`When disabled, tax totals resolve to zero even if product or jurisdiction records exist.`})]})]})]}),(0,c.jsxs)(`div`,{className:`grid gap-4 md:grid-cols-[minmax(0,1fr)_auto] md:items-end`,children:[(0,c.jsxs)(`div`,{className:`space-y-2`,children:[(0,c.jsx)(`label`,{htmlFor:`tax-calculation-mode`,className:`text-sm font-medium text-foreground`,children:`Tax calculation mode`}),(0,c.jsxs)(`select`,{id:`tax-calculation-mode`,name:`taxCalculationMode`,defaultValue:m.taxCalculationMode,className:`flex h-10 w-full rounded-md border border-input bg-background px-3 py-2 text-sm`,children:[(0,c.jsx)(`option`,{value:`manual`,children:`Manual tax rates`}),(0,c.jsx)(`option`,{value:`automatic`,children:`Automatic via Stripe Tax`})]}),(0,c.jsx)(`p`,{className:`text-sm text-muted-foreground`,children:`Automatic mode depends on your Stripe Tax setup. Manual rates stay saved and can be used again if you switch back later.`})]}),(0,c.jsx)(`div`,{className:`flex justify-end`,children:(0,c.jsx)(u.Button,{type:`submit`,children:`Save Tax Settings`})})]})]})})]}),(0,c.jsxs)(u.Card,{children:[(0,c.jsx)(u.CardHeader,{children:(0,c.jsxs)(`div`,{className:`flex items-center justify-between gap-4`,children:[(0,c.jsxs)(`div`,{children:[(0,c.jsx)(u.CardTitle,{children:`Manual Tax Rates`}),(0,c.jsx)(u.CardDescription,{children:`Add combined taxes as separate rows. For example, create both GST and PST for the same province if they should stack.`})]}),(0,c.jsx)(u.Badge,{variant:m.taxCalculationMode===`manual`?`default`:`outline`,children:m.taxCalculationMode===`manual`?`Active Mode`:`Stored for Manual Mode`})]})}),(0,c.jsxs)(u.CardContent,{className:`space-y-6`,children:[v?(0,c.jsx)(`div`,{className:`rounded-lg border border-amber-200 bg-amber-50 px-4 py-3 text-sm text-amber-800`,children:`Tax rates couldn't be loaded yet. This usually means the new tax migration hasn't been applied to the current database.`}):null,v?null:(0,c.jsxs)(c.Fragment,{children:[(0,c.jsxs)(`div`,{className:`rounded-xl border bg-card p-4`,children:[(0,c.jsxs)(`div`,{className:`mb-4 flex items-center gap-2`,children:[(0,c.jsx)(s.ShieldCheck,{className:`h-4 w-4 text-primary`}),(0,c.jsx)(`h2`,{className:`font-semibold`,children:`Create a Tax Rate`})]}),(0,c.jsx)(a.TaxRateForm,{})]}),(0,c.jsx)(`div`,{className:`space-y-4`,children:_.length===0?(0,c.jsxs)(`div`,{className:`rounded-xl border border-dashed bg-muted/10 px-4 py-8 text-center`,children:[(0,c.jsx)(`p`,{className:`font-medium`,children:`No manual tax rates yet`}),(0,c.jsx)(`p`,{className:`mt-1 text-sm text-muted-foreground`,children:`Add country-wide or state/province-specific rows to start calculating manual taxes.`})]}):_.map(e=>(0,c.jsxs)(u.Card,{className:`border-muted`,children:[(0,c.jsx)(u.CardHeader,{className:`pb-4`,children:(0,c.jsxs)(`div`,{className:`flex items-start justify-between gap-4`,children:[(0,c.jsxs)(`div`,{className:`space-y-1`,children:[(0,c.jsx)(u.CardTitle,{className:`text-base`,children:e.tax_name}),(0,c.jsx)(u.CardDescription,{children:f(e)})]}),(0,c.jsxs)(`div`,{className:`flex items-center gap-2`,children:[(0,c.jsx)(u.Badge,{variant:`outline`,children:d(Number(e.tax_rate))}),(0,c.jsx)(`form`,{action:async()=>{"use server";await i.deleteTaxRateAction(e.id)},children:(0,c.jsx)(u.Button,{type:`submit`,variant:`ghost`,size:`icon`,"aria-label":`Delete tax rate`,children:(0,c.jsx)(s.Trash2,{className:`h-4 w-4`})})})]})]})}),(0,c.jsx)(u.CardContent,{children:(0,c.jsx)(a.TaxRateForm,{initialData:e,submitLabel:`Update tax rate`,compact:!0})})]},e.id))})]})]})]})]}):(0,c.jsxs)(u.Card,{className:`border-dashed`,children:[(0,c.jsxs)(u.CardHeader,{children:[(0,c.jsx)(u.CardTitle,{children:`Enable Stripe to configure physical-product taxes`}),(0,c.jsx)(u.CardDescription,{children:`Stripe tax settings apply whenever Stripe is enabled for physical products. Freemius still handles taxes on its own digital checkout flow.`})]}),(0,c.jsx)(u.CardContent,{children:(0,c.jsx)(u.Button,{asChild:!0,variant:`outline`,children:(0,c.jsx)(o.default,{href:`/cms/payments`,children:`Open Payment Settings`})})})]})]})}exports.TaxesPage=p;
1
+ const e=require("../../../../_virtual/_rolldown/runtime.cjs"),t=require("../../../states.cjs"),n=require("../../../inventory-settings.cjs"),r=require("../payments/queries.cjs"),i=require("./actions.cjs"),a=require("./components/TaxRateForm.cjs");let o=require("next/link");o=e.__toESM(o,1);let s=require("lucide-react"),c=require("react/jsx-runtime");require("server-only");let l=require("@nextblock-cms/db/server"),u=require("@nextblock-cms/ui");function d(e){return`${e.toFixed(4).replace(/\.?0+$/,``)}%`}function f(e){return e.state_code?`${e.country_code} - ${t.resolveSubdivisionName(e.country_code,e.state_code)}`:`${e.country_code} - Country-wide`}async function p({searchParams:e}){let t=(0,l.createClient)(),p=(0,l.getServiceRoleSupabaseClient)(),[m,h,g]=await Promise.all([n.getEcommerceInventorySettings(t),r.getEnabledPaymentProviders(),p.from(`tax_rates`).select(`id, country_code, state_code, tax_name, tax_rate, created_at, updated_at`).order(`country_code`).order(`state_code`).order(`tax_name`)]),_=g.data||[],v=g.error,y=h.stripe;return(0,c.jsxs)(`div`,{className:`mx-auto w-full max-w-6xl space-y-6 px-6 py-8`,children:[e?.success?(0,c.jsx)(`div`,{className:`rounded-lg border border-emerald-200 bg-emerald-50 px-4 py-3 text-sm text-emerald-700`,children:e.success}):null,(0,c.jsxs)(`div`,{className:`flex items-center justify-between gap-4`,children:[(0,c.jsxs)(`div`,{className:`flex items-center gap-3`,children:[(0,c.jsx)(u.Button,{asChild:!0,variant:`outline`,size:`icon`,"aria-label":`Back to shipping`,children:(0,c.jsx)(o.default,{href:`/cms/shipping`,children:(0,c.jsx)(s.ArrowLeft,{className:`h-4 w-4`})})}),(0,c.jsxs)(`div`,{children:[(0,c.jsx)(`h1`,{className:`text-2xl font-bold`,children:`Tax Settings`}),(0,c.jsx)(`p`,{className:`text-sm text-muted-foreground`,children:`Configure Stripe tax behavior globally and maintain manual country or state/province tax rates for physical goods.`})]})]}),(0,c.jsxs)(`div`,{className:`flex items-center gap-2`,children:[(0,c.jsxs)(u.Badge,{variant:y?`default`:`outline`,className:`uppercase`,children:[`Stripe `,y?`Enabled`:`Disabled`]}),(0,c.jsx)(`div`,{className:`rounded-full border bg-muted/30 p-3 text-muted-foreground`,children:(0,c.jsx)(s.Settings2,{className:`h-5 w-5`})})]})]}),y?(0,c.jsxs)(c.Fragment,{children:[(0,c.jsxs)(u.Card,{children:[(0,c.jsxs)(u.CardHeader,{children:[(0,c.jsx)(u.CardTitle,{children:`Global Tax Controls`}),(0,c.jsx)(u.CardDescription,{children:`Manual mode uses the tax rates below. Automatic mode uses Stripe Tax during Stripe Checkout instead of a free third-party tax API.`})]}),(0,c.jsx)(u.CardContent,{children:(0,c.jsxs)(`form`,{action:i.updateTaxSettingsAction,className:`space-y-6`,children:[(0,c.jsxs)(`div`,{className:`rounded-lg border bg-muted/20 p-4`,children:[(0,c.jsx)(`input`,{type:`hidden`,name:`enableTaxes`,value:`false`}),(0,c.jsxs)(`label`,{htmlFor:`enable-taxes`,className:`flex cursor-pointer items-start gap-3`,children:[(0,c.jsx)(`input`,{id:`enable-taxes`,name:`enableTaxes`,type:`checkbox`,value:`true`,defaultChecked:m.enableTaxes,className:`mt-1 h-4 w-4 rounded border-slate-300 text-primary focus:ring-primary`}),(0,c.jsxs)(`span`,{className:`space-y-1`,children:[(0,c.jsx)(`span`,{className:`block font-medium`,children:`Enable taxes`}),(0,c.jsx)(`span`,{className:`block text-sm text-muted-foreground`,children:`When disabled, tax totals resolve to zero even if product or jurisdiction records exist.`})]})]})]}),(0,c.jsxs)(`div`,{className:`grid gap-4 md:grid-cols-[minmax(0,1fr)_auto] md:items-end`,children:[(0,c.jsxs)(`div`,{className:`space-y-2`,children:[(0,c.jsx)(`label`,{htmlFor:`tax-calculation-mode`,className:`text-sm font-medium text-foreground`,children:`Tax calculation mode`}),(0,c.jsxs)(`select`,{id:`tax-calculation-mode`,name:`taxCalculationMode`,defaultValue:m.taxCalculationMode,className:`flex h-10 w-full rounded-md border border-input bg-background px-3 py-2 text-sm`,children:[(0,c.jsx)(`option`,{value:`manual`,children:`Manual tax rates`}),(0,c.jsx)(`option`,{value:`automatic`,children:`Automatic via Stripe Tax`})]}),(0,c.jsx)(`p`,{className:`text-sm text-muted-foreground`,children:`Automatic mode depends on your Stripe Tax setup. Manual rates stay saved and can be used again if you switch back later.`})]}),(0,c.jsx)(`div`,{className:`flex justify-end`,children:(0,c.jsx)(u.Button,{type:`submit`,children:`Save Tax Settings`})})]})]})})]}),(0,c.jsxs)(u.Card,{children:[(0,c.jsx)(u.CardHeader,{children:(0,c.jsxs)(`div`,{className:`flex items-center justify-between gap-4`,children:[(0,c.jsxs)(`div`,{children:[(0,c.jsx)(u.CardTitle,{children:`Manual Tax Rates`}),(0,c.jsx)(u.CardDescription,{children:`Add combined taxes as separate rows. For example, create both GST and PST for the same province if they should stack.`})]}),(0,c.jsx)(u.Badge,{variant:m.taxCalculationMode===`manual`?`default`:`outline`,children:m.taxCalculationMode===`manual`?`Active Mode`:`Stored for Manual Mode`})]})}),(0,c.jsxs)(u.CardContent,{className:`space-y-6`,children:[v?(0,c.jsx)(`div`,{className:`rounded-lg border border-amber-200 bg-amber-50 px-4 py-3 text-sm text-amber-800`,children:`Tax rates couldn't be loaded yet. This usually means the new tax migration hasn't been applied to the current database.`}):null,v?null:(0,c.jsxs)(c.Fragment,{children:[(0,c.jsxs)(`div`,{className:`rounded-xl border bg-card p-4`,children:[(0,c.jsxs)(`div`,{className:`mb-4 flex items-center gap-2`,children:[(0,c.jsx)(s.ShieldCheck,{className:`h-4 w-4 text-primary`}),(0,c.jsx)(`h2`,{className:`font-semibold`,children:`Create a Tax Rate`})]}),(0,c.jsx)(a.TaxRateForm,{})]}),(0,c.jsx)(`div`,{className:`space-y-4`,children:_.length===0?(0,c.jsxs)(`div`,{className:`rounded-xl border border-dashed bg-muted/10 px-4 py-8 text-center`,children:[(0,c.jsx)(`p`,{className:`font-medium`,children:`No manual tax rates yet`}),(0,c.jsx)(`p`,{className:`mt-1 text-sm text-muted-foreground`,children:`Add country-wide or state/province-specific rows to start calculating manual taxes.`})]}):_.map(e=>(0,c.jsxs)(u.Card,{className:`border-muted`,children:[(0,c.jsx)(u.CardHeader,{className:`pb-4`,children:(0,c.jsxs)(`div`,{className:`flex items-start justify-between gap-4`,children:[(0,c.jsxs)(`div`,{className:`space-y-1`,children:[(0,c.jsx)(u.CardTitle,{className:`text-base`,children:e.tax_name}),(0,c.jsx)(u.CardDescription,{children:f(e)})]}),(0,c.jsxs)(`div`,{className:`flex items-center gap-2`,children:[(0,c.jsx)(u.Badge,{variant:`outline`,children:d(Number(e.tax_rate))}),(0,c.jsx)(`form`,{action:async()=>{"use server";await i.deleteTaxRateAction(e.id)},children:(0,c.jsx)(u.Button,{type:`submit`,variant:`ghost`,size:`icon`,"aria-label":`Delete tax rate`,children:(0,c.jsx)(s.Trash2,{className:`h-4 w-4`})})})]})]})}),(0,c.jsx)(u.CardContent,{children:(0,c.jsx)(a.TaxRateForm,{initialData:e,submitLabel:`Update tax rate`,compact:!0})})]},e.id))})]})]})]})]}):(0,c.jsxs)(u.Card,{className:`border-dashed`,children:[(0,c.jsxs)(u.CardHeader,{children:[(0,c.jsx)(u.CardTitle,{children:`Enable Stripe to configure physical-product taxes`}),(0,c.jsx)(u.CardDescription,{children:`Stripe tax settings apply whenever Stripe is enabled for physical products. Freemius still handles taxes on its own digital checkout flow.`})]}),(0,c.jsx)(u.CardContent,{children:(0,c.jsx)(u.Button,{asChild:!0,variant:`outline`,children:(0,c.jsx)(o.default,{href:`/cms/payments`,children:`Open Payment Settings`})})})]})]})}exports.TaxesPage=p;
@@ -6,6 +6,7 @@ import { TaxRateForm as a } from "./components/TaxRateForm.es.js";
6
6
  import o from "next/link";
7
7
  import { ArrowLeft as s, Settings2 as c, ShieldCheck as l, Trash2 as u } from "lucide-react";
8
8
  import { Fragment as d, jsx as f, jsxs as p } from "react/jsx-runtime";
9
+ import "server-only";
9
10
  import { createClient as m, getServiceRoleSupabaseClient as h } from "@nextblock-cms/db/server";
10
11
  import { Badge as g, Button as _, Card as v, CardContent as y, CardDescription as b, CardHeader as x, CardTitle as S } from "@nextblock-cms/ui";
11
12
  //#region src/lib/pages/cms/taxes/TaxesPage.tsx
@@ -1 +1 @@
1
- const e=require("./server-actions/require-ecom-role.cjs");let t=require("@nextblock-cms/db/server");var n=`payment_secret`,r=`payment_public`,i=6e4,a=null;function o(e){return e&&typeof e==`object`&&!Array.isArray(e)?e:{}}async function s(e=!1){let s=Date.now();if(!e&&a&&s-a.at<i)return{secret:a.secret,public:a.public};let c={},l={};try{let e=(0,t.getServiceRoleSupabaseClient)(),[{data:i},{data:a}]=await Promise.all([e.from(`site_settings`).select(`value`).eq(`key`,n).maybeSingle(),e.from(`site_settings`).select(`value`).eq(`key`,r).maybeSingle()]);c=o(i?.value),l=o(a?.value)}catch{}return a={at:s,secret:c,public:l},{secret:c,public:l}}function c(){a=null}function l(e,n){return(0,t.tryDecryptWithEnvKey)(e[n])}async function u(){let{secret:e}=await s();return(0,t.resolveConfigValue)(l(e,`stripeSecretKey`),`STRIPE_SECRET_KEY`)}async function d(){let{secret:e}=await s();return(0,t.resolveConfigValue)(l(e,`stripeWebhookSecret`),`STRIPE_WEBHOOK_SECRET`)}async function f(){let{public:e}=await s(),n=o(e.stripe).publishableKey;return(0,t.resolveConfigValue)(typeof n==`string`?n:null,`NEXT_PUBLIC_STRIPE_PUBLISHABLE_KEY`)}async function p(){try{let{secret:e,public:t}=await s(),n=o(t.freemius),r=(e,t)=>{t&&t.trim()&&(process.env[e]=t.trim())};r(`FREEMIUS_SECRET_KEY`,l(e,`freemiusSecretKey`)),r(`FREEMIUS_API_KEY`,l(e,`freemiusApiKey`)),r(`FREEMIUS_ECOMMERCE_SANDBOX_SECRET_KEY`,l(e,`freemiusSandboxSecretKey`)),r(`FREEMIUS_PUBLIC_KEY`,typeof n.publicKey==`string`?n.publicKey:null),r(`FREEMIUS_PRODUCT_ID`,typeof n.productId==`string`?n.productId:null),r(`FREEMIUS_DEVELOPER_ID`,typeof n.developerId==`string`?n.developerId:null)}catch(e){console.warn(`[payment-config] Could not hydrate Freemius credentials from the database:`,e)}}async function m(){let{secret:e,public:n}=await s(),r=o(n.freemius),i=o(n.stripe),a=[];(0,t.resolveConfigValue)(l(e,`stripeSecretKey`),`STRIPE_SECRET_KEY`)||a.push(`Secret key`),(0,t.resolveConfigValue)(typeof i.publishableKey==`string`?i.publishableKey:null,`NEXT_PUBLIC_STRIPE_PUBLISHABLE_KEY`)||a.push(`Publishable key`),(0,t.resolveConfigValue)(l(e,`stripeWebhookSecret`),`STRIPE_WEBHOOK_SECRET`)||a.push(`Webhook secret`);let c=[];return(0,t.resolveConfigValue)(typeof r.publicKey==`string`?r.publicKey:null,`FREEMIUS_PUBLIC_KEY`)||c.push(`Public key`),(0,t.resolveConfigValue)(l(e,`freemiusSecretKey`),`FREEMIUS_SECRET_KEY`)||c.push(`Secret key`),{stripe:{hasKeys:a.length===0,missing:a},freemius:{hasKeys:c.length===0,missing:c}}}async function h(){let i=await e.getEcomActorRole()===`ADMIN`?(0,t.getServiceRoleSupabaseClient)():(0,t.createClient)(),[{data:a},{data:s}]=await Promise.all([i.from(`site_settings`).select(`value`).eq(`key`,n).maybeSingle(),i.from(`site_settings`).select(`value`).eq(`key`,r).maybeSingle()]),c=o(a?.value),l=o(s?.value),u=o(l.stripe),d=o(l.freemius),f=e=>typeof e==`string`?e:``;return{stripe:{publishableKey:f(u.publishableKey),hasSecretKey:(0,t.getSecretEnvelopeStatus)(c.stripeSecretKey).hasStoredValue,hasWebhookSecret:(0,t.getSecretEnvelopeStatus)(c.stripeWebhookSecret).hasStoredValue},freemius:{developerId:f(d.developerId),publicKey:f(d.publicKey),productId:f(d.productId),hasSecretKey:(0,t.getSecretEnvelopeStatus)(c.freemiusSecretKey).hasStoredValue,hasApiKey:(0,t.getSecretEnvelopeStatus)(c.freemiusApiKey).hasStoredValue},envFallbackActive:!(c.stripeSecretKey||!process.env.STRIPE_SECRET_KEY)}}async function g(i){let a=await e.requireEcomAdmin(),s={stripe:{publishableKey:i.stripe.publishableKey.trim()},freemius:{developerId:i.freemius.developerId.trim(),publicKey:i.freemius.publicKey.trim(),productId:i.freemius.productId.trim(),sandboxEnabled:!1}},{error:l}=await a.from(`site_settings`).upsert({key:r,value:s});if(l)throw console.error(`Error saving payment_public settings:`,l.message),Error(`Failed to save payment settings.`);let u=[[`stripeSecretKey`,i.stripe.secretKey],[`stripeWebhookSecret`,i.stripe.webhookSecret],[`freemiusSecretKey`,i.freemius.secretKey],[`freemiusApiKey`,i.freemius.apiKey]];if(u.some(([,e])=>e&&e.trim())){if((0,t.isSandboxEnvironment)())throw Error(`The sandbox cannot store live payment credentials.`);let{data:e}=await a.from(`site_settings`).select(`value`).eq(`key`,n).maybeSingle(),r={...o(e?.value)};for(let[e,n]of u)n&&n.trim()&&(r[e]=(0,t.encryptWithEnvKey)(n.trim()));let{error:i}=await a.from(`site_settings`).upsert({key:n,value:r});if(i)throw console.error(`Error saving payment_secret settings:`,i.message),Error(`Failed to save payment credentials.`)}c()}exports.clearPaymentConfigCache=c,exports.getPaymentConfigStatus=m,exports.getPaymentCredentialsView=h,exports.hydrateFreemiusEnvFromDb=p,exports.resolveStripePublishableKey=f,exports.resolveStripeSecretKey=u,exports.resolveStripeWebhookSecret=d,exports.savePaymentCredentials=g;
1
+ const e=require("./server-actions/require-ecom-role.cjs");require("server-only");let t=require("@nextblock-cms/db/server");var n=`payment_secret`,r=`payment_public`,i=6e4,a=null;function o(e){return e&&typeof e==`object`&&!Array.isArray(e)?e:{}}async function s(e=!1){let s=Date.now();if(!e&&a&&s-a.at<i)return{secret:a.secret,public:a.public};let c={},l={};try{let e=(0,t.getServiceRoleSupabaseClient)(),[{data:i},{data:a}]=await Promise.all([e.from(`site_settings`).select(`value`).eq(`key`,n).maybeSingle(),e.from(`site_settings`).select(`value`).eq(`key`,r).maybeSingle()]);c=o(i?.value),l=o(a?.value)}catch{}return a={at:s,secret:c,public:l},{secret:c,public:l}}function c(){a=null}function l(e,n){return(0,t.tryDecryptWithEnvKey)(e[n])}async function u(){let{secret:e}=await s();return(0,t.resolveConfigValue)(l(e,`stripeSecretKey`),`STRIPE_SECRET_KEY`)}async function d(){let{secret:e}=await s();return(0,t.resolveConfigValue)(l(e,`stripeWebhookSecret`),`STRIPE_WEBHOOK_SECRET`)}async function f(){let{public:e}=await s(),n=o(e.stripe).publishableKey;return(0,t.resolveConfigValue)(typeof n==`string`?n:null,`NEXT_PUBLIC_STRIPE_PUBLISHABLE_KEY`)}async function p(){try{let{secret:e,public:t}=await s(),n=o(t.freemius),r=(e,t)=>{t&&t.trim()&&(process.env[e]=t.trim())};r(`FREEMIUS_SECRET_KEY`,l(e,`freemiusSecretKey`)),r(`FREEMIUS_API_KEY`,l(e,`freemiusApiKey`)),r(`FREEMIUS_ECOMMERCE_SANDBOX_SECRET_KEY`,l(e,`freemiusSandboxSecretKey`)),r(`FREEMIUS_PUBLIC_KEY`,typeof n.publicKey==`string`?n.publicKey:null),r(`FREEMIUS_PRODUCT_ID`,typeof n.productId==`string`?n.productId:null),r(`FREEMIUS_DEVELOPER_ID`,typeof n.developerId==`string`?n.developerId:null)}catch(e){console.warn(`[payment-config] Could not hydrate Freemius credentials from the database:`,e)}}async function m(){let{secret:e,public:n}=await s(),r=o(n.freemius),i=o(n.stripe),a=[];(0,t.resolveConfigValue)(l(e,`stripeSecretKey`),`STRIPE_SECRET_KEY`)||a.push(`Secret key`),(0,t.resolveConfigValue)(typeof i.publishableKey==`string`?i.publishableKey:null,`NEXT_PUBLIC_STRIPE_PUBLISHABLE_KEY`)||a.push(`Publishable key`),(0,t.resolveConfigValue)(l(e,`stripeWebhookSecret`),`STRIPE_WEBHOOK_SECRET`)||a.push(`Webhook secret`);let c=[];return(0,t.resolveConfigValue)(typeof r.publicKey==`string`?r.publicKey:null,`FREEMIUS_PUBLIC_KEY`)||c.push(`Public key`),(0,t.resolveConfigValue)(l(e,`freemiusSecretKey`),`FREEMIUS_SECRET_KEY`)||c.push(`Secret key`),{stripe:{hasKeys:a.length===0,missing:a},freemius:{hasKeys:c.length===0,missing:c}}}async function h(){let i=await e.getEcomActorRole()===`ADMIN`?(0,t.getServiceRoleSupabaseClient)():(0,t.createClient)(),[{data:a},{data:s}]=await Promise.all([i.from(`site_settings`).select(`value`).eq(`key`,n).maybeSingle(),i.from(`site_settings`).select(`value`).eq(`key`,r).maybeSingle()]),c=o(a?.value),l=o(s?.value),u=o(l.stripe),d=o(l.freemius),f=e=>typeof e==`string`?e:``;return{stripe:{publishableKey:f(u.publishableKey),hasSecretKey:(0,t.getSecretEnvelopeStatus)(c.stripeSecretKey).hasStoredValue,hasWebhookSecret:(0,t.getSecretEnvelopeStatus)(c.stripeWebhookSecret).hasStoredValue},freemius:{developerId:f(d.developerId),publicKey:f(d.publicKey),productId:f(d.productId),hasSecretKey:(0,t.getSecretEnvelopeStatus)(c.freemiusSecretKey).hasStoredValue,hasApiKey:(0,t.getSecretEnvelopeStatus)(c.freemiusApiKey).hasStoredValue},envFallbackActive:!(c.stripeSecretKey||!process.env.STRIPE_SECRET_KEY)}}async function g(i){let a=await e.requireEcomAdmin(),s={stripe:{publishableKey:i.stripe.publishableKey.trim()},freemius:{developerId:i.freemius.developerId.trim(),publicKey:i.freemius.publicKey.trim(),productId:i.freemius.productId.trim(),sandboxEnabled:!1}},{error:l}=await a.from(`site_settings`).upsert({key:r,value:s});if(l)throw console.error(`Error saving payment_public settings:`,l.message),Error(`Failed to save payment settings.`);let u=[[`stripeSecretKey`,i.stripe.secretKey],[`stripeWebhookSecret`,i.stripe.webhookSecret],[`freemiusSecretKey`,i.freemius.secretKey],[`freemiusApiKey`,i.freemius.apiKey]];if(u.some(([,e])=>e&&e.trim())){if((0,t.isSandboxEnvironment)())throw Error(`The sandbox cannot store live payment credentials.`);let{data:e}=await a.from(`site_settings`).select(`value`).eq(`key`,n).maybeSingle(),r={...o(e?.value)};for(let[e,n]of u)n&&n.trim()&&(r[e]=(0,t.encryptWithEnvKey)(n.trim()));let{error:i}=await a.from(`site_settings`).upsert({key:n,value:r});if(i)throw console.error(`Error saving payment_secret settings:`,i.message),Error(`Failed to save payment credentials.`)}c()}exports.clearPaymentConfigCache=c,exports.getPaymentConfigStatus=m,exports.getPaymentCredentialsView=h,exports.hydrateFreemiusEnvFromDb=p,exports.resolveStripePublishableKey=f,exports.resolveStripeSecretKey=u,exports.resolveStripeWebhookSecret=d,exports.savePaymentCredentials=g;
@@ -1,4 +1,5 @@
1
1
  import { getEcomActorRole as e, requireEcomAdmin as t } from "./server-actions/require-ecom-role.es.js";
2
+ import "server-only";
2
3
  import { createClient as n, encryptWithEnvKey as r, getSecretEnvelopeStatus as i, getServiceRoleSupabaseClient as a, isSandboxEnvironment as o, resolveConfigValue as s, tryDecryptWithEnvKey as c } from "@nextblock-cms/db/server";
3
4
  //#region src/lib/payment-config.ts
4
5
  var l = "payment_secret", u = "payment_public", d = 6e4, f = null;
@@ -1 +1 @@
1
- const e=require("../../_virtual/_rolldown/runtime.cjs"),t=require("../currency.cjs"),n=require("../coupon-server.cjs"),r=require("../customer.cjs"),i=require("../customer-addresses.cjs"),a=require("../payment-config.cjs"),o=require("../order-access-token.cjs"),s=require("./checkout-items.cjs");let c=require("@supabase/supabase-js"),l=require("crypto");l=e.__toESM(l,1);let u=require("@freemius/sdk");function d(e){let t=process.env[e];if(!t)return null;let n=t.trim();return n.startsWith(`"`)&&n.endsWith(`"`)||n.startsWith(`'`)&&n.endsWith(`'`)?n.slice(1,-1).trim():n}function f(e){let t=e?.trim();if(!t)return{firstName:null,lastName:null};let[n,...r]=t.split(/\s+/);return{firstName:n||null,lastName:r.length>0?r.join(` `):null}}function p(e){if(e==null||e===``)return 0;let t=Number(e);return!Number.isFinite(t)||t<=0?0:Math.round(t)}function m(e){return e===!0||e===1||e===`1`||e===`true`}function h(e,t){let n=e?.[t];return Array.isArray(n)?n:n&&typeof n==`object`?[n]:[]}function g(e,t){for(let n of t){let t=h(e,n);if(t.length>0)return t}return Array.isArray(e)?e:[]}function _(e){if(e==null||e===``)return null;let t=Number(e);return Number.isFinite(t)?t:null}function ee(e){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)}function v(e){let t=Number(e);return!Number.isFinite(t)||t<1?1:Math.round(t)}function y(){let e=d(`FREEMIUS_CHECKOUT_PRODUCTS_JSON`);if(!e)return null;try{let t=JSON.parse(e);return t&&typeof t==`object`?t:null}catch(e){return console.error(`[Freemius Checkout] Failed to parse FREEMIUS_CHECKOUT_PRODUCTS_JSON:`,e),null}}function b(e){let t=y(),n=String(e),r=t?.[n],i=d(`FREEMIUS_PRODUCT_ID`),a=d(`FREEMIUS_ECOMMERCE_SANDBOX_PUBLIC_KEY`),o=d(`FREEMIUS_ECOMMERCE_SANDBOX_SECRET_KEY`);return r?.publicKey?{publicKey:r.publicKey,secretKey:r.secretKey??null,apiKey:r.apiKey??null,source:`product-map`}:process.env.FREEMIUS_SANDBOX_ENABLED===`true`&&i&&i===n&&a?{publicKey:a,secretKey:o,apiKey:d(`FREEMIUS_API_KEY`),source:`single-product-sandbox-env`}:i&&i===n&&d(`FREEMIUS_PUBLIC_KEY`)?{publicKey:d(`FREEMIUS_PUBLIC_KEY`),secretKey:d(`FREEMIUS_SECRET_KEY`),apiKey:d(`FREEMIUS_API_KEY`),source:`single-product-env`}:{publicKey:d(`FREEMIUS_PUBLIC_KEY`),secretKey:d(`FREEMIUS_SECRET_KEY`),apiKey:d(`FREEMIUS_API_KEY`),source:`legacy-env`}}async function x(e){if(!e.apiKey)throw Error(`Missing Freemius API key for SDK sandbox generation.`);return new u.Freemius({productId:Number(e.productId),apiKey:e.apiKey,secretKey:e.secretKey,publicKey:e.publicKey}).checkout.getSandboxParams()}var S=class{getProviderName(){return`Freemius`}async createCheckoutSession({items:e,customerEmail:u,customerPhone:m,userId:h,billingAddress:g,shippingAddress:_,currencyCode:ee,couponCode:v,couponContextItems:y}){let S=process.env.NEXT_PUBLIC_SUPABASE_URL||process.env.SUPABASE_URL,C=process.env.SUPABASE_SERVICE_ROLE_KEY||process.env.SUPABASE_SECRET_KEY;if(!S||!C)return{error:`Missing Supabase credentials for checkout (Service Key required).`,url:null};let w=(0,c.createClient)(S,C);if(!e||e.length===0)return{error:`Cart is empty`,url:null};if(e.length!==1)return{error:`Freemius items must be checked out one at a time.`,url:null};let T=s.normalizeCheckoutItems(e);if(!T.ok)return{url:null,...T.error};let E=T.items;if(y&&y.length>0){let e=s.normalizeCheckoutItems(y);if(!e.ok)return{url:null,...e.error};E=e.items}let{data:D,error:O}=await w.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}),k=D??[];if(O||k.length===0)return{error:`Failed to resolve store currencies`,url:null};let te=t.getDefaultCurrency(k),A=k.find(e=>e.code===(ee||``).toUpperCase())??te,j=T.items[0],{data:M,error:ne}=await w.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`,j.product_id).single();if(ne||!M)return{error:`Product not found`,url:null};let N=M.freemius_plan_id,P=M.freemius_product_id;if(!N||!P)return{error:`Product is not configured for Freemius checkout (missing Plan ID or Product ID)`,url:null};let F=t.resolveEffectivePriceForCurrency({prices:M.prices||{},salePrices:M.sale_prices||{},fallbackPrice:M.price,fallbackSalePrice:M.sale_price,saleStartAt:M.sale_start_at,saleEndAt:M.sale_end_at,scheduledPrice:M.scheduled_price,scheduledPrices:M.scheduled_prices||{},scheduledPriceAt:M.scheduled_price_at,currencyCode:A.code,currencies:k}),I=F.sale_price??F.price,re=t.isSaleWindowActive({saleStartAt:M.sale_start_at,saleEndAt:M.sale_end_at}),L=I*j.quantity,R=null,z=0;if(v){let e=await n.getCouponQuote({client:w,code:v,items:E,currencyCode:A.code});if(!e.success)return{error:e.error,errorKey:e.errorKey,errorStatus:400,url:null};R=e.quote,z=Math.min(L,R.lineDiscounts.filter(e=>e.product_id===M.id).reduce((e,t)=>e+t.discount,0))}let B=p(M.trial_period_days),V=B>0?j.trial_preference?j.trial_preference:M.trial_requires_payment_method?`paid`:`free`:null,H=`pending`,U=f(g?.recipient_name??null),{data:W,error:G}=await w.from(`orders`).insert({status:H,total:Math.max(0,L-z),currency:A.code,exchange_rate_at_purchase:A.exchange_rate,subtotal:L,discount_total:z,coupon_id:R?.couponId??null,coupon_code:R?.code??null,discount_details:R?{code:R.code,discount_type:R.discountType,discount_amount:R.discountAmount,provider:`freemius`,provider_discounts:R.providerDiscounts,line_discounts:R.lineDiscounts,final_amount_owned_by:`freemius`}:null,provider:`freemius`,freemius_product_id:String(P),freemius_plan_id:String(N),user_id:h||null,customer_details:r.normalizeOrderCustomerDetails({email:u,phone:m,name:g?.recipient_name,billing:g,shipping:_})}).select(`id`).single();if(G||!W)return console.error(`Failed to create pending order:`,G),{error:`Failed to initiate order`,url:null};let{error:K}=await w.from(`order_items`).insert([{order_id:W.id,product_id:M.id,quantity:j.quantity,price_at_purchase:I}]);if(K&&console.error(`Failed to insert order items:`,K),h)try{await i.upsertDefaultUserAddresses({userId:h,billingAddress:g,shippingAddress:_,client:w}),await i.fillMissingUserProfileCheckoutDetails({userId:h,fullName:g?.recipient_name??_?.recipient_name??null,phone:m,client:w})}catch(e){console.error(`Failed to sync checkout profile defaults before checkout:`,e)}if(R&&!(await n.recordCouponRedemption({client:w,quote:R,orderId:W.id,provider:`freemius`,discountTotal:z,userId:h,customerEmail:u,metadata:{currency:A.code,subtotal:L,final_amount_owned_by:`freemius`}})).success)return await w.from(`orders`).update({status:`failed`}).eq(`id`,W.id),{url:null,error:`Coupon is no longer available.`,errorKey:`ecommerce.coupon_invalid`};await a.hydrateFreemiusEnvFromDb();let q=process.env.FREEMIUS_SANDBOX_ENABLED===`true`,J=b(P),Y=J.publicKey,X=J.secretKey,Z=J.apiKey;if(!Y||q&&!X)return console.error(`Freemius checkout blocked: missing credentials (PUBLIC_KEY or SECRET_KEY) in CMS → Payments or environment.`),{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};if(q&&J.source===`legacy-env`){let e=d(`FREEMIUS_PRODUCT_ID`),t=!!d(`FREEMIUS_ECOMMERCE_SANDBOX_PUBLIC_KEY`),n=!!d(`FREEMIUS_ECOMMERCE_SANDBOX_SECRET_KEY`);console.warn(`[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.`,{configuredProductId:e,productIdsMatch:e===String(P),hasSandboxOverridePublicKey:t,hasSandboxOverrideSecretKey:n,hasCheckoutProductsJson:!!d(`FREEMIUS_CHECKOUT_PRODUCTS_JSON`)})}let Q=!1;if(q&&X&&Y)try{Q=await x({productId:P,publicKey:Y,secretKey:X,apiKey:Z})}catch(e){console.warn(`Freemius Checkout - SDK sandbox generation failed. Falling back to manual token generation.`,e,{credentialSource:J.source,hasApiKey:!!Z});let t=Math.floor(Date.now()/1e3).toString(),n=`${t}${P}${X}${Y}checkout`;Q={ctx:t,token:l.default.createHash(`md5`).update(n).digest(`hex`)}}let $=new URL(`https://checkout.freemius.com/app/${P}/plan/${N}/`);if(q&&X&&Y?($.searchParams.append(`sandbox`,Q.token),$.searchParams.append(`s_ctx_ts`,Q.ctx)):q&&$.searchParams.append(`sandbox`,`true`),u&&$.searchParams.append(`user_email`,u),U.firstName&&$.searchParams.append(`user_firstname`,U.firstName),U.lastName&&$.searchParams.append(`user_lastname`,U.lastName),$.searchParams.append(`currency`,A.code.toLowerCase()),j.billing_cycle&&$.searchParams.append(`billing_cycle`,j.billing_cycle),V&&$.searchParams.append(`trial`,V),R)$.searchParams.append(`coupon`,R.code);else if(re){let{data:e}=await w.from(`product_freemius_sale_coupons`).select(`freemius_coupon_code, is_active, starts_at, ends_at, sync_status`).eq(`product_id`,M.id).maybeSingle();e?.is_active&&e.sync_status===`synced`&&e.freemius_coupon_code&&t.isSaleWindowActive({saleStartAt:e.starts_at,saleEndAt:e.ends_at})&&$.searchParams.append(`coupon`,e.freemius_coupon_code)}return{url:$.toString(),customProps:{provider:`freemius`,plugin_id:P,plan_id:N,public_key:Y,user_email:u,user_firstname:U.firstName,user_lastname:U.lastName,credential_source:J.source,sandbox:Q,billing_cycle:j.billing_cycle,trial:V,trial_period_days:B,trial_requires_payment_method:M.trial_requires_payment_method,initial_order_status:H,coupon:R?.code??null,order_id:W.id,success_token:o.mintOrderAccessToken(W.id)}}}};async function C(e,t,n,r){let i=new Date().toUTCString().replace(`GMT`,`+0000`),a=`GET\n\n\n${i}\n${e}`,o=l.default.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:{Authorization:s,Date:i,Accept:`application/json`}});if(!c.ok){let t=await c.text();throw console.error(`[Freemius API] [ERROR] ${e} returned ${c.status}: ${t}`),Error(`Freemius API failed on ${e}: ${c.status} - ${t}`)}return c.json()}async function w(){let e=d(`FREEMIUS_DEVELOPER_ID`),t=d(`FREEMIUS_PUBLIC_KEY`),n=d(`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;if(!e||!t||!n||!r||!i)throw Error(`Missing necessary environment variables for Freemius Sync.`);let a=(0,c.createClient)(r,i,{auth:{autoRefreshToken:!1,persistSession:!1}}),o=r=>C(r,e,t,n);try{console.log(`[Freemius Sync] Fetching all plugins for developer ${e}...`);let t=g(await o(`/v1/developers/${e}/plugins.json`),[`plugins`,`plugin`]);console.log(`[Freemius Sync] Found ${t.length} plugins. Syncing plans...`);let n=0,{data:r}=await a.from(`languages`).select(`id`).eq(`code`,`en`).single(),i=r?.id;if(!i)throw Error(`English language not found in database. Cannot sync products.`);for(let r of t){let t=r.id?.toString();if(!t){console.warn(`[Freemius Sync] Skipping plugin without an id:`,r);continue}let s=await E(a,e,t,r.title||r.name||`Freemius Product ${t}`,o,i);n+=s}return{success:!0,count:n}}catch(e){throw console.error(`[Freemius Sync] Global Error:`,e),e}}async function T(e){let t=d(`FREEMIUS_DEVELOPER_ID`),n=d(`FREEMIUS_PUBLIC_KEY`),r=d(`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;if(!t||!n||!r||!i||!a)throw Error(`Missing environment variables for Freemius Sync.`);let o=(0,c.createClient)(i,a),s=e=>C(e,t,n,r),{data:l}=await o.from(`languages`).select(`id`).eq(`code`,`en`).single(),u=l?.id;if(!u)throw Error(`English language not found in database. Cannot sync products.`);let f=await s(`/v1/developers/${t}/plugins/${e}.json`),p=f.plugin??f;return{success:!0,count:await E(o,t,e,p.title||p.name||`Freemius Product ${e}`,s,u)}}async function E(e,t,n,r,i,a){console.log(`[Freemius Sync] Fetching plans for plugin: ${r} (${n})...`);let o=0;try{let s=g(await i(`/v1/developers/${t}/plugins/${n}/plans.json`),[`plans`,`plan`]);console.log(`[Freemius Sync] Received ${s.length} plans for plugin ${n}.`);for(let c of s){let s=c.id?.toString();if(!s){console.warn(`[Freemius Sync] Skipping plan without an id:`,c);continue}let l=c.name||c.title||s,u=c.title||l;console.log(`[Freemius Sync] Processing plan: ${u} (${s})...`);let d=c;if(d.trial_period===void 0||d.is_require_subscription===void 0)try{let e=await i(`/v1/developers/${t}/plugins/${n}/plans/${s}.json`),r=e.plan??e;d={...d,...r}}catch(e){console.warn(`[Freemius Sync] Could not fetch trial details for plan ${s}:`,e instanceof Error?e.message:e)}let f=p(d.trial_period),h=f>0&&m(d.is_require_subscription),y=0,b=[];try{if(b=g(await i(`/v1/developers/${t}/plugins/${n}/plans/${s}/pricing.json`),[`pricing`,`prices`,`pricings`]),b.length>0){let e=b[0];y=ee(_(e.annual_price)??_(e.monthly_price)??_(e.lifetime_price))}console.log(`[Freemius Sync] Plan: ${u} -> Resolved Price (cents): ${y}`)}catch(e){console.warn(`[Freemius Sync] Could not fetch pricing for plan ${s}:`,e instanceof Error?e.message:e)}let x=`${r}-${u}`.toLowerCase().replace(/[^\w\s-]/g,``).replace(/[\s_]+/g,`-`).replace(/^-+|-+$/g,``),S={title:`${r} - ${u}`,slug:x,short_description:c.description||``,price:y,product_type:`digital`,payment_provider:`freemius`,freemius_plan_id:s,freemius_product_id:n,trial_period_days:f,trial_requires_payment_method:h,status:`active`,stock:999,sku:`FM-${n}-${s}`,language_id:a},{data:C,error:w}=await e.from(`products`).upsert(S,{onConflict:`language_id, sku`}).select();if(w||!C||C.length===0){console.error(`[Freemius Sync] Error upserting product ${S.sku}:`,w);continue}let T=C[0].id,{data:E,error:D}=await e.from(`freemius_plans`).select(`id`).eq(`product_id`,T).eq(`name`,l).maybeSingle();D&&console.warn(`[Freemius Sync] Could not check existing local plan for ${S.sku}:`,D.message||D);let O=``;if(E){O=E.id;let{error:t}=await e.from(`freemius_plans`).update({title:u,updated_at:new Date().toISOString()}).eq(`id`,O);t&&console.warn(`[Freemius Sync] Could not update local plan ${O}:`,t.message||t)}else{let{data:t,error:n}=await e.from(`freemius_plans`).insert({product_id:T,name:l,title:u}).select(`id`).single();n&&console.warn(`[Freemius Sync] Could not insert local plan for ${S.sku}:`,n.message||n),t&&(O=t.id)}if(O&&b.length>0)for(let t of b){let n=v(t.licenses??t.license_quota??t.quota),{data:r,error:i}=await e.from(`freemius_pricing`).select(`id`).eq(`plan_id`,O).eq(`license_quota`,n).maybeSingle();i&&console.warn(`[Freemius Sync] Could not check pricing for plan ${O}, quota ${n}:`,i.message||i);let a={api_monthly_price:_(t.monthly_price),api_annual_price:_(t.annual_price),api_lifetime_price:_(t.lifetime_price),updated_at:new Date().toISOString()};if(r){let{error:t}=await e.from(`freemius_pricing`).update(a).eq(`id`,r.id);t&&console.warn(`[Freemius Sync] Could not update pricing ${r.id}:`,t.message||t)}else{let{error:t}=await e.from(`freemius_pricing`).insert({plan_id:O,license_quota:n,...a});t&&console.warn(`[Freemius Sync] Could not insert pricing for plan ${O}, quota ${n}:`,t.message||t)}}console.log(`[Freemius Sync] Successfully fully synced product ${S.sku}.`),o++}}catch(e){console.error(`[Freemius Sync] Failed sync for plugin ${n}:`,e.message)}return o}exports.FreemiusProvider=S,exports.parseFreemiusCheckoutCredentialsMap=y,exports.readFreemiusEnvValue=d,exports.resolveFreemiusCheckoutCredentials=b,exports.syncFreemiusProductsToSupabase=w,exports.syncSingleFreemiusProduct=T;
1
+ const e=require("../../_virtual/_rolldown/runtime.cjs"),t=require("../currency.cjs"),n=require("../coupons.cjs"),r=require("../freemius-pricing-server.cjs"),i=require("../coupon-server.cjs"),a=require("../customer.cjs"),o=require("../customer-addresses.cjs"),s=require("../payment-config.cjs"),c=require("../order-access-token.cjs"),l=require("./checkout-items.cjs");require("server-only");let u=require("@supabase/supabase-js"),d=require("crypto");d=e.__toESM(d,1);let f=require("@freemius/sdk");function p(e){let t=process.env[e];if(!t)return null;let n=t.trim();return n.startsWith(`"`)&&n.endsWith(`"`)||n.startsWith(`'`)&&n.endsWith(`'`)?n.slice(1,-1).trim():n}function m(e){let t=e?.trim();if(!t)return{firstName:null,lastName:null};let[n,...r]=t.split(/\s+/);return{firstName:n||null,lastName:r.length>0?r.join(` `):null}}function h(e){if(e==null||e===``)return 0;let t=Number(e);return!Number.isFinite(t)||t<=0?0:Math.round(t)}function g(e){return e===!0||e===1||e===`1`||e===`true`}function _(e,t){let n=e?.[t];return Array.isArray(n)?n:n&&typeof n==`object`?[n]:[]}function v(e,t){for(let n of t){let t=_(e,n);if(t.length>0)return t}return Array.isArray(e)?e:[]}function y(e){if(e==null||e===``)return null;let t=Number(e);return Number.isFinite(t)?t:null}function b(e){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)}function x(e){let t=Number(e);return!Number.isFinite(t)||t<1?1:Math.round(t)}function S(){let e=p(`FREEMIUS_CHECKOUT_PRODUCTS_JSON`);if(!e)return null;try{let t=JSON.parse(e);return t&&typeof t==`object`?t:null}catch(e){return console.error(`[Freemius Checkout] Failed to parse FREEMIUS_CHECKOUT_PRODUCTS_JSON:`,e),null}}function C(e){let t=S(),n=String(e),r=t?.[n],i=p(`FREEMIUS_PRODUCT_ID`),a=p(`FREEMIUS_ECOMMERCE_SANDBOX_PUBLIC_KEY`),o=p(`FREEMIUS_ECOMMERCE_SANDBOX_SECRET_KEY`);return r?.publicKey?{publicKey:r.publicKey,secretKey:r.secretKey??null,apiKey:r.apiKey??null,source:`product-map`}:process.env.FREEMIUS_SANDBOX_ENABLED===`true`&&i&&i===n&&a?{publicKey:a,secretKey:o,apiKey:p(`FREEMIUS_API_KEY`),source:`single-product-sandbox-env`}:i&&i===n&&p(`FREEMIUS_PUBLIC_KEY`)?{publicKey:p(`FREEMIUS_PUBLIC_KEY`),secretKey:p(`FREEMIUS_SECRET_KEY`),apiKey:p(`FREEMIUS_API_KEY`),source:`single-product-env`}:{publicKey:p(`FREEMIUS_PUBLIC_KEY`),secretKey:p(`FREEMIUS_SECRET_KEY`),apiKey:p(`FREEMIUS_API_KEY`),source:`legacy-env`}}async function w(e){if(!e.apiKey)throw Error(`Missing Freemius API key for SDK sandbox generation.`);return new f.Freemius({productId:Number(e.productId),apiKey:e.apiKey,secretKey:e.secretKey,publicKey:e.publicKey}).checkout.getSandboxParams()}var T=class{getProviderName(){return`Freemius`}async createCheckoutSession({items:e,customerEmail:f,customerPhone:g,userId:_,billingAddress:v,shippingAddress:y,currencyCode:b,couponCode:x,couponContextItems:S}){let T=process.env.NEXT_PUBLIC_SUPABASE_URL||process.env.SUPABASE_URL,E=process.env.SUPABASE_SERVICE_ROLE_KEY||process.env.SUPABASE_SECRET_KEY;if(!T||!E)return{error:`Missing Supabase credentials for checkout (Service Key required).`,url:null};let D=(0,u.createClient)(T,E);if(!e||e.length===0)return{error:`Cart is empty`,url:null};if(e.length!==1)return{error:`Freemius items must be checked out one at a time.`,url:null};let O=l.normalizeCheckoutItems(e);if(!O.ok)return{url:null,...O.error};let k=O.items;if(S&&S.length>0){let e=l.normalizeCheckoutItems(S);if(!e.ok)return{url:null,...e.error};k=n.reconcileCouponContextItems(O.items,e.items)}let{data:ee,error:te}=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=ee??[];if(te||A.length===0)return{error:`Failed to resolve store currencies`,url:null};let ne=t.getDefaultCurrency(A),j=A.find(e=>e.code===(b||``).toUpperCase())??ne,M=O.items[0],{data:N,error:re}=await D.from(`products`).select(`${r.FREEMIUS_PRICED_PRODUCT_COLUMNS}, title, freemius_plan_id, freemius_product_id, trial_period_days, trial_requires_payment_method`).eq(`id`,M.product_id).single();if(re||!N)return{error:`Product not found`,url:null};let P=N.freemius_plan_id,F=N.freemius_product_id;if(!P||!F)return{error:`Product is not configured for Freemius checkout (missing Plan ID or Product ID)`,url:null};let I;try{I=await r.resolveFreemiusUnitAmount({client:D,product:N,billingCycle:M.billing_cycle,currencyCode:j.code,currencies:A})}catch(e){return console.error(`Failed to resolve Freemius pricing:`,e),{error:`Failed to resolve product pricing`,url:null}}if(!I.ok)return{url:null,...l.createInvalidCheckoutItemsError()};let L=I.unitAmount,R=I.billingCycle,ie=t.isSaleWindowActive({saleStartAt:N.sale_start_at,saleEndAt:N.sale_end_at}),z=L*M.quantity,B=null,V=0;if(x){let e=await i.getCouponQuote({client:D,code:x,items:k.map(e=>e.product_id===N.id?{...e,billing_cycle:R??void 0}:e),currencyCode:j.code});if(!e.success)return{error:e.error,errorKey:e.errorKey,errorStatus:400,url:null};B=e.quote,V=Math.min(z,B.lineDiscounts.filter(e=>e.product_id===N.id).reduce((e,t)=>e+t.discount,0))}let H=h(N.trial_period_days),U=H>0?M.trial_preference?M.trial_preference:N.trial_requires_payment_method?`paid`:`free`:null,W=`pending`,G=m(v?.recipient_name??null),{data:K,error:q}=await D.from(`orders`).insert({status:W,total:Math.max(0,z-V),currency:j.code,exchange_rate_at_purchase:j.exchange_rate,subtotal:z,discount_total:V,coupon_id:B?.couponId??null,coupon_code:B?.code??null,discount_details:B?{code:B.code,discount_type:B.discountType,discount_amount:B.discountAmount,provider:`freemius`,provider_discounts:B.providerDiscounts,line_discounts:B.lineDiscounts,final_amount_owned_by:`freemius`}:null,provider:`freemius`,freemius_product_id:String(F),freemius_plan_id:String(P),user_id:_||null,customer_details:a.normalizeOrderCustomerDetails({email:f,phone:g,name:v?.recipient_name,billing:v,shipping:y})}).select(`id`).single();if(q||!K)return console.error(`Failed to create pending order:`,q),{error:`Failed to initiate order`,url:null};let{error:ae}=await D.from(`order_items`).insert([{order_id:K.id,product_id:N.id,quantity:M.quantity,price_at_purchase:L}]);if(ae&&console.error(`Failed to insert order items:`,ae),_)try{await o.upsertDefaultUserAddresses({userId:_,billingAddress:v,shippingAddress:y,client:D}),await o.fillMissingUserProfileCheckoutDetails({userId:_,fullName:v?.recipient_name??y?.recipient_name??null,phone:g,client:D})}catch(e){console.error(`Failed to sync checkout profile defaults before checkout:`,e)}if(B&&!(await i.recordCouponRedemption({client:D,quote:B,orderId:K.id,provider:`freemius`,discountTotal:V,userId:_,customerEmail:f,metadata:{currency:j.code,subtotal:z,final_amount_owned_by:`freemius`}})).success)return await D.from(`orders`).update({status:`failed`}).eq(`id`,K.id),{url:null,error:`Coupon is no longer available.`,errorKey:`ecommerce.coupon_invalid`};await s.hydrateFreemiusEnvFromDb();let J=process.env.FREEMIUS_SANDBOX_ENABLED===`true`,Y=C(F),X=Y.publicKey,Z=Y.secretKey,oe=Y.apiKey;if(!X||J&&!Z)return console.error(`Freemius checkout blocked: missing credentials (PUBLIC_KEY or SECRET_KEY) in CMS → Payments or environment.`),{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};if(J&&Y.source===`legacy-env`){let e=p(`FREEMIUS_PRODUCT_ID`),t=!!p(`FREEMIUS_ECOMMERCE_SANDBOX_PUBLIC_KEY`),n=!!p(`FREEMIUS_ECOMMERCE_SANDBOX_SECRET_KEY`);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.`,{configuredProductId:e,productIdsMatch:e===String(F),hasSandboxOverridePublicKey:t,hasSandboxOverrideSecretKey:n,hasCheckoutProductsJson:!!p(`FREEMIUS_CHECKOUT_PRODUCTS_JSON`)})}let Q=!1;if(J&&Z&&X)try{Q=await w({productId:F,publicKey:X,secretKey:Z,apiKey:oe})}catch(e){console.warn(`Freemius Checkout - SDK sandbox generation failed. Falling back to manual token generation.`,e,{credentialSource:Y.source,hasApiKey:!!oe});let t=Math.floor(Date.now()/1e3).toString(),n=`${t}${F}${Z}${X}checkout`;Q={ctx:t,token:d.default.createHash(`md5`).update(n).digest(`hex`)}}let $=new URL(`https://checkout.freemius.com/app/${F}/plan/${P}/`);if(J&&Z&&X?($.searchParams.append(`sandbox`,Q.token),$.searchParams.append(`s_ctx_ts`,Q.ctx)):J&&$.searchParams.append(`sandbox`,`true`),f&&$.searchParams.append(`user_email`,f),G.firstName&&$.searchParams.append(`user_firstname`,G.firstName),G.lastName&&$.searchParams.append(`user_lastname`,G.lastName),$.searchParams.append(`currency`,j.code.toLowerCase()),R&&$.searchParams.append(`billing_cycle`,R),U&&$.searchParams.append(`trial`,U),B)$.searchParams.append(`coupon`,B.code);else if(ie){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();e?.is_active&&e.sync_status===`synced`&&e.freemius_coupon_code&&t.isSaleWindowActive({saleStartAt:e.starts_at,saleEndAt:e.ends_at})&&$.searchParams.append(`coupon`,e.freemius_coupon_code)}return{url:$.toString(),customProps:{provider:`freemius`,plugin_id:F,plan_id:P,public_key:X,user_email:f,user_firstname:G.firstName,user_lastname:G.lastName,credential_source:Y.source,sandbox:Q,billing_cycle:R,trial:U,trial_period_days:H,trial_requires_payment_method:N.trial_requires_payment_method,initial_order_status:W,coupon:B?.code??null,order_id:K.id,success_token:c.mintOrderAccessToken(K.id)}}}};async function E(e,t,n,r){let i=new Date().toUTCString().replace(`GMT`,`+0000`),a=`GET\n\n\n${i}\n${e}`,o=d.default.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:{Authorization:s,Date:i,Accept:`application/json`}});if(!c.ok){let t=await c.text();throw console.error(`[Freemius API] [ERROR] ${e} returned ${c.status}: ${t}`),Error(`Freemius API failed on ${e}: ${c.status} - ${t}`)}return c.json()}async function D(){let e=p(`FREEMIUS_DEVELOPER_ID`),t=p(`FREEMIUS_PUBLIC_KEY`),n=p(`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;if(!e||!t||!n||!r||!i)throw Error(`Missing necessary environment variables for Freemius Sync.`);let a=(0,u.createClient)(r,i,{auth:{autoRefreshToken:!1,persistSession:!1}}),o=r=>E(r,e,t,n);try{console.log(`[Freemius Sync] Fetching all plugins for developer ${e}...`);let t=v(await o(`/v1/developers/${e}/plugins.json`),[`plugins`,`plugin`]);console.log(`[Freemius Sync] Found ${t.length} plugins. Syncing plans...`);let n=0,{data:r}=await a.from(`languages`).select(`id`).eq(`code`,`en`).single(),i=r?.id;if(!i)throw Error(`English language not found in database. Cannot sync products.`);for(let r of t){let t=r.id?.toString();if(!t){console.warn(`[Freemius Sync] Skipping plugin without an id:`,r);continue}let s=await k(a,e,t,r.title||r.name||`Freemius Product ${t}`,o,i);n+=s}return{success:!0,count:n}}catch(e){throw console.error(`[Freemius Sync] Global Error:`,e),e}}async function O(e){let t=p(`FREEMIUS_DEVELOPER_ID`),n=p(`FREEMIUS_PUBLIC_KEY`),r=p(`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;if(!t||!n||!r||!i||!a)throw Error(`Missing environment variables for Freemius Sync.`);let o=(0,u.createClient)(i,a),s=e=>E(e,t,n,r),{data:c}=await o.from(`languages`).select(`id`).eq(`code`,`en`).single(),l=c?.id;if(!l)throw Error(`English language not found in database. Cannot sync products.`);let d=await s(`/v1/developers/${t}/plugins/${e}.json`),f=d.plugin??d;return{success:!0,count:await k(o,t,e,f.title||f.name||`Freemius Product ${e}`,s,l)}}async function k(e,t,n,r,i,a){console.log(`[Freemius Sync] Fetching plans for plugin: ${r} (${n})...`);let o=0;try{let s=v(await i(`/v1/developers/${t}/plugins/${n}/plans.json`),[`plans`,`plan`]);console.log(`[Freemius Sync] Received ${s.length} plans for plugin ${n}.`);for(let c of s){let s=c.id?.toString();if(!s){console.warn(`[Freemius Sync] Skipping plan without an id:`,c);continue}let l=c.name||c.title||s,u=c.title||l;console.log(`[Freemius Sync] Processing plan: ${u} (${s})...`);let d=c;if(d.trial_period===void 0||d.is_require_subscription===void 0)try{let e=await i(`/v1/developers/${t}/plugins/${n}/plans/${s}.json`),r=e.plan??e;d={...d,...r}}catch(e){console.warn(`[Freemius Sync] Could not fetch trial details for plan ${s}:`,e instanceof Error?e.message:e)}let f=h(d.trial_period),p=f>0&&g(d.is_require_subscription),m=0,_=[];try{if(_=v(await i(`/v1/developers/${t}/plugins/${n}/plans/${s}/pricing.json`),[`pricing`,`prices`,`pricings`]),_.length>0){let e=_[0];m=b(y(e.annual_price)??y(e.monthly_price)??y(e.lifetime_price))}console.log(`[Freemius Sync] Plan: ${u} -> Resolved Price (cents): ${m}`)}catch(e){console.warn(`[Freemius Sync] Could not fetch pricing for plan ${s}:`,e instanceof Error?e.message:e)}let S=`${r}-${u}`.toLowerCase().replace(/[^\w\s-]/g,``).replace(/[\s_]+/g,`-`).replace(/^-+|-+$/g,``),C={title:`${r} - ${u}`,slug:S,short_description:c.description||``,price:m,product_type:`digital`,payment_provider:`freemius`,freemius_plan_id:s,freemius_product_id:n,trial_period_days:f,trial_requires_payment_method:p,status:`active`,stock:999,sku:`FM-${n}-${s}`,language_id:a},{data:w,error:T}=await e.from(`products`).upsert(C,{onConflict:`language_id, sku`}).select();if(T||!w||w.length===0){console.error(`[Freemius Sync] Error upserting product ${C.sku}:`,T);continue}let E=w[0].id,{data:D,error:O}=await e.from(`freemius_plans`).select(`id`).eq(`product_id`,E).eq(`name`,l).maybeSingle();O&&console.warn(`[Freemius Sync] Could not check existing local plan for ${C.sku}:`,O.message||O);let k=``;if(D){k=D.id;let{error:t}=await e.from(`freemius_plans`).update({title:u,updated_at:new Date().toISOString()}).eq(`id`,k);t&&console.warn(`[Freemius Sync] Could not update local plan ${k}:`,t.message||t)}else{let{data:t,error:n}=await e.from(`freemius_plans`).insert({product_id:E,name:l,title:u}).select(`id`).single();n&&console.warn(`[Freemius Sync] Could not insert local plan for ${C.sku}:`,n.message||n),t&&(k=t.id)}if(k&&_.length>0)for(let t of _){let n=x(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();i&&console.warn(`[Freemius Sync] Could not check pricing for plan ${k}, quota ${n}:`,i.message||i);let a={api_monthly_price:y(t.monthly_price),api_annual_price:y(t.annual_price),api_lifetime_price:y(t.lifetime_price),updated_at:new Date().toISOString()};if(r){let{error:t}=await e.from(`freemius_pricing`).update(a).eq(`id`,r.id);t&&console.warn(`[Freemius Sync] Could not update pricing ${r.id}:`,t.message||t)}else{let{error:t}=await e.from(`freemius_pricing`).insert({plan_id:k,license_quota:n,...a});t&&console.warn(`[Freemius Sync] Could not insert pricing for plan ${k}, quota ${n}:`,t.message||t)}}console.log(`[Freemius Sync] Successfully fully synced product ${C.sku}.`),o++}}catch(e){console.error(`[Freemius Sync] Failed sync for plugin ${n}:`,e.message)}return o}exports.FreemiusProvider=T,exports.parseFreemiusCheckoutCredentialsMap=S,exports.readFreemiusEnvValue=p,exports.resolveFreemiusCheckoutCredentials=C,exports.syncFreemiusProductsToSupabase=D,exports.syncSingleFreemiusProduct=O;