@nextblock-cms/ecom 0.10.2 → 0.10.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.
- package/lib/components/CustomerProfileForm.cjs.js +1 -1
- package/lib/components/CustomerProfileForm.es.js +162 -159
- package/lib/freemius-coupons.cjs.js +1 -1
- package/lib/freemius-coupons.es.js +51 -49
- package/lib/pages/cms/payments/PaymentsClient.cjs.js +1 -1
- package/lib/pages/cms/payments/PaymentsClient.d.ts +4 -1
- package/lib/pages/cms/payments/PaymentsClient.es.js +255 -127
- package/lib/pages/cms/payments/PaymentsPage.cjs.js +1 -1
- package/lib/pages/cms/payments/PaymentsPage.es.js +20 -16
- package/lib/pages/cms/payments/actions.cjs.js +1 -1
- package/lib/pages/cms/payments/actions.d.ts +1 -0
- package/lib/pages/cms/payments/actions.es.js +41 -13
- package/lib/pages/cms/payments/queries.cjs.js +1 -1
- package/lib/pages/cms/payments/queries.es.js +13 -24
- package/lib/payment-config.cjs.js +1 -0
- package/lib/payment-config.d.ts +57 -0
- package/lib/payment-config.es.js +137 -0
- package/lib/providers/freemius.cjs.js +2 -2
- package/lib/providers/freemius.es.js +108 -107
- package/lib/providers/stripe.cjs.js +1 -1
- package/lib/providers/stripe.es.js +167 -167
- package/lib/stripe/checkout.cjs.js +1 -1
- package/lib/stripe/checkout.es.js +14 -14
- package/lib/stripe/client.cjs.js +1 -1
- package/lib/stripe/client.d.ts +1 -1
- package/lib/stripe/client.es.js +8 -5
- package/lib/stripe/order-sync.cjs.js +1 -1
- package/lib/stripe/order-sync.es.js +50 -50
- package/lib/stripe/webhooks.cjs.js +1 -1
- package/lib/stripe/webhooks.es.js +12 -10
- package/package.json +4 -4
- package/server.cjs.js +1 -1
- package/server.d.ts +1 -0
- package/server.es.js +188 -178
|
@@ -1 +1 @@
|
|
|
1
|
-
"use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const
|
|
1
|
+
"use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const I=require("@nextblock-cms/utils"),f=require("./providers/freemius.cjs.js"),h=require("./payment-config.cjs.js");function y(e){if(!e)return null;const o=new Date(e);return Number.isNaN(o.getTime())?e:o.toISOString().replace("T"," ").replace(/\.\d{3}Z$/,"")}function C(e){return e==="percent"?"percentage":"dollar"}function E(e){return f.resolveFreemiusCheckoutCredentials(e).apiKey||f.readFreemiusEnvValue("FREEMIUS_API_KEY")}async function l(e){await h.hydrateFreemiusEnvFromDb();const o=E(e.productId);if(!o)throw new Error(`Missing Freemius API bearer token for product ${e.productId}. Set FREEMIUS_API_KEY or FREEMIUS_CHECKOUT_PRODUCTS_JSON[${e.productId}].apiKey.`);const s=e.couponId?`/${e.couponId}`:"",t=await fetch(`https://api.freemius.com/v1/products/${e.productId}/coupons${s}.json`,{method:e.method,headers:{Authorization:`Bearer ${o}`,"Content-Type":"application/json",Accept:"application/json"},body:e.method==="DELETE"?void 0:JSON.stringify(e.body||{})}),n=await t.text(),r=n?JSON.parse(n):null;if(!t.ok)throw new Error(r?.message||r?.error?.message||`Freemius coupon request failed with ${t.status}`);return r}function g(e,o){return{code:e.code,discount:e.discount_type==="fixed"?I.minorUnitAmountToMajor(e.discount_amount,"USD"):e.discount_amount,discount_type:C(e.discount_type),plans:o.planIds.length>0?o.planIds.join(","):null,licenses:null,billing_cycles:null,start_date:y(e.starts_at),end_date:y(e.ends_at),redemptions_limit:e.redemption_limit??null,has_renewals_discount:!1,has_addons_discount:!1,is_one_per_user:!1,is_active:e.is_active,user_type:"all"}}async function F(e,o){if(o.provider_scope==="stripe")return[];const{data:s,error:t}=await e.from("coupon_products").select("product_id").eq("coupon_id",o.id);if(t)throw new Error(t.message);const n=(s||[]).map(c=>c.product_id);let r=e.from("products").select("id, freemius_product_id, freemius_plan_id").eq("payment_provider","freemius").not("freemius_product_id","is",null);n.length>0&&(r=r.in("id",n));const{data:u,error:i}=await r;if(i)throw new Error(i.message);const d=new Map;for(const c of u||[]){const a=String(c.freemius_product_id||"").trim();if(!a)continue;const p=d.get(a)??{freemiusProductId:a,productId:c.id,planIds:[]};n.length>0&&c.freemius_plan_id&&p.planIds.push(String(c.freemius_plan_id)),d.set(a,p)}return[...d.values()].map(c=>({...c,planIds:[...new Set(c.planIds)]}))}async function P(e,o){const{data:s}=await e.from("coupon_freemius_mappings").select("sync_status, sync_error").eq("coupon_id",o),t=s||[];if(t.length===0){await e.from("coupons").update({freemius_sync_status:"not_required",freemius_sync_error:null}).eq("id",o);return}const n=t.find(r=>r.sync_status==="failed");await e.from("coupons").update({freemius_sync_status:n?"failed":"synced",freemius_sync_error:n?.sync_error??null}).eq("id",o)}async function q(e){const{data:o,error:s}=await e.client.from("coupons").select("id, code, name, internal_note, provider_scope, discount_type, discount_amount, is_active, starts_at, ends_at, redemption_limit").eq("id",e.couponId).single();if(s||!o)return{success:!1,error:s?.message||"Coupon not found"};const t=o,n=await F(e.client,t);await e.client.from("coupons").update({freemius_sync_status:n.length>0?"pending":"not_required",freemius_sync_error:null}).eq("id",t.id);for(const r of n){const{data:u}=await e.client.from("coupon_freemius_mappings").select("id, freemius_coupon_id").eq("coupon_id",t.id).eq("freemius_product_id",r.freemiusProductId).maybeSingle(),i=g(t,r);try{const d=await l({productId:r.freemiusProductId,method:u?.freemius_coupon_id?"PUT":"POST",couponId:u?.freemius_coupon_id??null,body:i}),c=d?.coupon??d;await e.client.from("coupon_freemius_mappings").upsert({id:u?.id,coupon_id:t.id,product_id:r.productId,freemius_product_id:r.freemiusProductId,freemius_coupon_id:c?.id?String(c.id):u?.freemius_coupon_id??null,freemius_coupon_code:t.code,sync_status:"synced",sync_error:null,remote_payload:d,last_synced_at:new Date().toISOString()},{onConflict:"coupon_id,freemius_product_id"})}catch(d){await e.client.from("coupon_freemius_mappings").upsert({id:u?.id,coupon_id:t.id,product_id:r.productId,freemius_product_id:r.freemiusProductId,freemius_coupon_id:u?.freemius_coupon_id??null,freemius_coupon_code:t.code,sync_status:"failed",sync_error:d.message||"Freemius sync failed",last_synced_at:new Date().toISOString()},{onConflict:"coupon_id,freemius_product_id"})}}return await P(e.client,t.id),{success:!0,targetCount:n.length}}function v(e){const o=(e.sku||"").toUpperCase().replace(/[^A-Z0-9]/g,"");return o?`SALE${o}`.slice(0,32):`SALE${e.productId.replace(/[^A-Za-z0-9]/g,"").toUpperCase()}`.slice(0,32)}function T(e,o){if(typeof e!="number"||e<=0||typeof o!="number"||o<0||o>=e)return null;const s=Math.round((1-o/e)*100);return s<=0||s>100?null:s}async function b(e){const{data:o,error:s}=await e.client.from("products").select("id, sku, price, sale_price, sale_start_at, sale_end_at, payment_provider, freemius_product_id, freemius_plan_id").eq("id",e.productId).maybeSingle();if(s||!o)return{success:!1,error:s?.message||"Product not found"};const t=o,n=String(t.freemius_product_id||"").trim();if(t.payment_provider!=="freemius"||!n)return{success:!0,skipped:!0,reason:"not_a_freemius_product"};const r=T(t.price,t.sale_price),u=r!==null,{data:i}=await e.client.from("product_freemius_sale_coupons").select("id, freemius_coupon_id, freemius_coupon_code, discount_percent, is_active").eq("product_id",t.id).maybeSingle();if(!u&&!i?.freemius_coupon_id)return i?.id&&await e.client.from("product_freemius_sale_coupons").update({is_active:!1,updated_at:new Date().toISOString()}).eq("id",i.id),{success:!0,active:!1};const d=i?.freemius_coupon_code||v({sku:t.sku,productId:t.id}),c=t.freemius_plan_id?[String(t.freemius_plan_id)]:[],a=r??i?.discount_percent??1,p={id:t.id,code:d,name:`Scheduled sale ${t.sku||t.id}`,discount_type:"percent",discount_amount:a,is_active:u,starts_at:t.sale_start_at,ends_at:t.sale_end_at,redemption_limit:null},S={productId:t.id,planIds:c},w=g(p,S);try{const _=await l({productId:n,method:i?.freemius_coupon_id?"PUT":"POST",couponId:i?.freemius_coupon_id??null,body:w}),m=_?.coupon??_;return await e.client.from("product_freemius_sale_coupons").upsert({id:i?.id,product_id:t.id,freemius_product_id:n,freemius_plan_id:t.freemius_plan_id?String(t.freemius_plan_id):null,freemius_coupon_id:m?.id?String(m.id):i?.freemius_coupon_id??null,freemius_coupon_code:d,discount_percent:r,starts_at:t.sale_start_at,ends_at:t.sale_end_at,is_active:u,sync_status:"synced",sync_error:null,remote_payload:_,last_synced_at:new Date().toISOString()},{onConflict:"product_id"}),{success:!0,active:u,code:d}}catch(_){return await e.client.from("product_freemius_sale_coupons").upsert({id:i?.id,product_id:t.id,freemius_product_id:n,freemius_plan_id:t.freemius_plan_id?String(t.freemius_plan_id):null,freemius_coupon_id:i?.freemius_coupon_id??null,freemius_coupon_code:d,discount_percent:r,starts_at:t.sale_start_at,ends_at:t.sale_end_at,is_active:u,sync_status:"failed",sync_error:_.message||"Freemius sale coupon sync failed",last_synced_at:new Date().toISOString()},{onConflict:"product_id"}),{success:!1,error:_.message||"Freemius sale coupon sync failed"}}}async function D(e){const{data:o}=await e.client.from("coupon_freemius_mappings").select("id, freemius_product_id, freemius_coupon_id").eq("coupon_id",e.couponId).not("freemius_coupon_id","is",null);for(const s of o||[])try{await l({productId:s.freemius_product_id,couponId:s.freemius_coupon_id,method:"DELETE"}),await e.client.from("coupon_freemius_mappings").update({sync_status:"deleted",sync_error:null,updated_at:new Date().toISOString()}).eq("id",s.id)}catch(t){await e.client.from("coupon_freemius_mappings").update({sync_status:"failed",sync_error:t.message||"Freemius delete failed",updated_at:new Date().toISOString()}).eq("id",s.id)}}exports.deleteCouponFromFreemius=D;exports.syncCouponToFreemius=q;exports.syncProductSaleCouponToFreemius=b;
|
|
@@ -1,19 +1,21 @@
|
|
|
1
|
-
import { minorUnitAmountToMajor as
|
|
1
|
+
import { minorUnitAmountToMajor as I } from "@nextblock-cms/utils";
|
|
2
2
|
import { resolveFreemiusCheckoutCredentials as S, readFreemiusEnvValue as h } from "./providers/freemius.es.js";
|
|
3
|
+
import { hydrateFreemiusEnvFromDb as C } from "./payment-config.es.js";
|
|
3
4
|
function f(e) {
|
|
4
5
|
if (!e)
|
|
5
6
|
return null;
|
|
6
7
|
const o = new Date(e);
|
|
7
8
|
return Number.isNaN(o.getTime()) ? e : o.toISOString().replace("T", " ").replace(/\.\d{3}Z$/, "");
|
|
8
9
|
}
|
|
9
|
-
function
|
|
10
|
+
function E(e) {
|
|
10
11
|
return e === "percent" ? "percentage" : "dollar";
|
|
11
12
|
}
|
|
12
|
-
function
|
|
13
|
+
function P(e) {
|
|
13
14
|
return S(e).apiKey || h("FREEMIUS_API_KEY");
|
|
14
15
|
}
|
|
15
16
|
async function l(e) {
|
|
16
|
-
|
|
17
|
+
await C();
|
|
18
|
+
const o = P(e.productId);
|
|
17
19
|
if (!o)
|
|
18
20
|
throw new Error(
|
|
19
21
|
`Missing Freemius API bearer token for product ${e.productId}. Set FREEMIUS_API_KEY or FREEMIUS_CHECKOUT_PRODUCTS_JSON[${e.productId}].apiKey.`
|
|
@@ -29,7 +31,7 @@ async function l(e) {
|
|
|
29
31
|
},
|
|
30
32
|
body: e.method === "DELETE" ? void 0 : JSON.stringify(e.body || {})
|
|
31
33
|
}
|
|
32
|
-
),
|
|
34
|
+
), i = await t.text(), r = i ? JSON.parse(i) : null;
|
|
33
35
|
if (!t.ok)
|
|
34
36
|
throw new Error(
|
|
35
37
|
r?.message || r?.error?.message || `Freemius coupon request failed with ${t.status}`
|
|
@@ -39,8 +41,8 @@ async function l(e) {
|
|
|
39
41
|
function y(e, o) {
|
|
40
42
|
return {
|
|
41
43
|
code: e.code,
|
|
42
|
-
discount: e.discount_type === "fixed" ?
|
|
43
|
-
discount_type:
|
|
44
|
+
discount: e.discount_type === "fixed" ? I(e.discount_amount, "USD") : e.discount_amount,
|
|
45
|
+
discount_type: E(e.discount_type),
|
|
44
46
|
plans: o.planIds.length > 0 ? o.planIds.join(",") : null,
|
|
45
47
|
licenses: null,
|
|
46
48
|
billing_cycles: null,
|
|
@@ -54,18 +56,18 @@ function y(e, o) {
|
|
|
54
56
|
user_type: "all"
|
|
55
57
|
};
|
|
56
58
|
}
|
|
57
|
-
async function
|
|
59
|
+
async function q(e, o) {
|
|
58
60
|
if (o.provider_scope === "stripe")
|
|
59
61
|
return [];
|
|
60
62
|
const { data: s, error: t } = await e.from("coupon_products").select("product_id").eq("coupon_id", o.id);
|
|
61
63
|
if (t)
|
|
62
64
|
throw new Error(t.message);
|
|
63
|
-
const
|
|
65
|
+
const i = (s || []).map((c) => c.product_id);
|
|
64
66
|
let r = e.from("products").select("id, freemius_product_id, freemius_plan_id").eq("payment_provider", "freemius").not("freemius_product_id", "is", null);
|
|
65
|
-
|
|
66
|
-
const { data: u, error:
|
|
67
|
-
if (
|
|
68
|
-
throw new Error(
|
|
67
|
+
i.length > 0 && (r = r.in("id", i));
|
|
68
|
+
const { data: u, error: n } = await r;
|
|
69
|
+
if (n)
|
|
70
|
+
throw new Error(n.message);
|
|
69
71
|
const d = /* @__PURE__ */ new Map();
|
|
70
72
|
for (const c of u || []) {
|
|
71
73
|
const a = String(c.freemius_product_id || "").trim();
|
|
@@ -76,14 +78,14 @@ async function P(e, o) {
|
|
|
76
78
|
productId: c.id,
|
|
77
79
|
planIds: []
|
|
78
80
|
};
|
|
79
|
-
|
|
81
|
+
i.length > 0 && c.freemius_plan_id && p.planIds.push(String(c.freemius_plan_id)), d.set(a, p);
|
|
80
82
|
}
|
|
81
83
|
return [...d.values()].map((c) => ({
|
|
82
84
|
...c,
|
|
83
85
|
planIds: [...new Set(c.planIds)]
|
|
84
86
|
}));
|
|
85
87
|
}
|
|
86
|
-
async function
|
|
88
|
+
async function F(e, o) {
|
|
87
89
|
const { data: s } = await e.from("coupon_freemius_mappings").select("sync_status, sync_error").eq("coupon_id", o), t = s || [];
|
|
88
90
|
if (t.length === 0) {
|
|
89
91
|
await e.from("coupons").update({
|
|
@@ -92,13 +94,13 @@ async function q(e, o) {
|
|
|
92
94
|
}).eq("id", o);
|
|
93
95
|
return;
|
|
94
96
|
}
|
|
95
|
-
const
|
|
97
|
+
const i = t.find((r) => r.sync_status === "failed");
|
|
96
98
|
await e.from("coupons").update({
|
|
97
|
-
freemius_sync_status:
|
|
98
|
-
freemius_sync_error:
|
|
99
|
+
freemius_sync_status: i ? "failed" : "synced",
|
|
100
|
+
freemius_sync_error: i?.sync_error ?? null
|
|
99
101
|
}).eq("id", o);
|
|
100
102
|
}
|
|
101
|
-
async function
|
|
103
|
+
async function A(e) {
|
|
102
104
|
const { data: o, error: s } = await e.client.from("coupons").select(
|
|
103
105
|
"id, code, name, internal_note, provider_scope, discount_type, discount_amount, is_active, starts_at, ends_at, redemption_limit"
|
|
104
106
|
).eq("id", e.couponId).single();
|
|
@@ -107,19 +109,19 @@ async function O(e) {
|
|
|
107
109
|
success: !1,
|
|
108
110
|
error: s?.message || "Coupon not found"
|
|
109
111
|
};
|
|
110
|
-
const t = o,
|
|
112
|
+
const t = o, i = await q(e.client, t);
|
|
111
113
|
await e.client.from("coupons").update({
|
|
112
|
-
freemius_sync_status:
|
|
114
|
+
freemius_sync_status: i.length > 0 ? "pending" : "not_required",
|
|
113
115
|
freemius_sync_error: null
|
|
114
116
|
}).eq("id", t.id);
|
|
115
|
-
for (const r of
|
|
116
|
-
const { data: u } = await e.client.from("coupon_freemius_mappings").select("id, freemius_coupon_id").eq("coupon_id", t.id).eq("freemius_product_id", r.freemiusProductId).maybeSingle(),
|
|
117
|
+
for (const r of i) {
|
|
118
|
+
const { data: u } = await e.client.from("coupon_freemius_mappings").select("id, freemius_coupon_id").eq("coupon_id", t.id).eq("freemius_product_id", r.freemiusProductId).maybeSingle(), n = y(t, r);
|
|
117
119
|
try {
|
|
118
120
|
const d = await l({
|
|
119
121
|
productId: r.freemiusProductId,
|
|
120
122
|
method: u?.freemius_coupon_id ? "PUT" : "POST",
|
|
121
123
|
couponId: u?.freemius_coupon_id ?? null,
|
|
122
|
-
body:
|
|
124
|
+
body: n
|
|
123
125
|
}), c = d?.coupon ?? d;
|
|
124
126
|
await e.client.from("coupon_freemius_mappings").upsert(
|
|
125
127
|
{
|
|
@@ -153,34 +155,34 @@ async function O(e) {
|
|
|
153
155
|
);
|
|
154
156
|
}
|
|
155
157
|
}
|
|
156
|
-
return await
|
|
158
|
+
return await F(e.client, t.id), {
|
|
157
159
|
success: !0,
|
|
158
|
-
targetCount:
|
|
160
|
+
targetCount: i.length
|
|
159
161
|
};
|
|
160
162
|
}
|
|
161
163
|
function v(e) {
|
|
162
164
|
const o = (e.sku || "").toUpperCase().replace(/[^A-Z0-9]/g, "");
|
|
163
165
|
return o ? `SALE${o}`.slice(0, 32) : `SALE${e.productId.replace(/[^A-Za-z0-9]/g, "").toUpperCase()}`.slice(0, 32);
|
|
164
166
|
}
|
|
165
|
-
function
|
|
167
|
+
function D(e, o) {
|
|
166
168
|
if (typeof e != "number" || e <= 0 || typeof o != "number" || o < 0 || o >= e)
|
|
167
169
|
return null;
|
|
168
170
|
const s = Math.round((1 - o / e) * 100);
|
|
169
171
|
return s <= 0 || s > 100 ? null : s;
|
|
170
172
|
}
|
|
171
|
-
async function
|
|
173
|
+
async function U(e) {
|
|
172
174
|
const { data: o, error: s } = await e.client.from("products").select(
|
|
173
175
|
"id, sku, price, sale_price, sale_start_at, sale_end_at, payment_provider, freemius_product_id, freemius_plan_id"
|
|
174
176
|
).eq("id", e.productId).maybeSingle();
|
|
175
177
|
if (s || !o)
|
|
176
178
|
return { success: !1, error: s?.message || "Product not found" };
|
|
177
|
-
const t = o,
|
|
178
|
-
if (t.payment_provider !== "freemius" || !
|
|
179
|
+
const t = o, i = String(t.freemius_product_id || "").trim();
|
|
180
|
+
if (t.payment_provider !== "freemius" || !i)
|
|
179
181
|
return { success: !0, skipped: !0, reason: "not_a_freemius_product" };
|
|
180
|
-
const r =
|
|
181
|
-
if (!u && !
|
|
182
|
-
return
|
|
183
|
-
const d =
|
|
182
|
+
const r = D(t.price, t.sale_price), u = r !== null, { data: n } = await e.client.from("product_freemius_sale_coupons").select("id, freemius_coupon_id, freemius_coupon_code, discount_percent, is_active").eq("product_id", t.id).maybeSingle();
|
|
183
|
+
if (!u && !n?.freemius_coupon_id)
|
|
184
|
+
return n?.id && await e.client.from("product_freemius_sale_coupons").update({ is_active: !1, updated_at: (/* @__PURE__ */ new Date()).toISOString() }).eq("id", n.id), { success: !0, active: !1 };
|
|
185
|
+
const d = n?.freemius_coupon_code || v({ sku: t.sku, productId: t.id }), c = t.freemius_plan_id ? [String(t.freemius_plan_id)] : [], a = r ?? n?.discount_percent ?? 1, p = {
|
|
184
186
|
id: t.id,
|
|
185
187
|
code: d,
|
|
186
188
|
name: `Scheduled sale ${t.sku || t.id}`,
|
|
@@ -193,21 +195,21 @@ async function b(e) {
|
|
|
193
195
|
}, g = {
|
|
194
196
|
productId: t.id,
|
|
195
197
|
planIds: c
|
|
196
|
-
},
|
|
198
|
+
}, w = y(p, g);
|
|
197
199
|
try {
|
|
198
200
|
const _ = await l({
|
|
199
|
-
productId:
|
|
200
|
-
method:
|
|
201
|
-
couponId:
|
|
202
|
-
body:
|
|
201
|
+
productId: i,
|
|
202
|
+
method: n?.freemius_coupon_id ? "PUT" : "POST",
|
|
203
|
+
couponId: n?.freemius_coupon_id ?? null,
|
|
204
|
+
body: w
|
|
203
205
|
}), m = _?.coupon ?? _;
|
|
204
206
|
return await e.client.from("product_freemius_sale_coupons").upsert(
|
|
205
207
|
{
|
|
206
|
-
id:
|
|
208
|
+
id: n?.id,
|
|
207
209
|
product_id: t.id,
|
|
208
|
-
freemius_product_id:
|
|
210
|
+
freemius_product_id: i,
|
|
209
211
|
freemius_plan_id: t.freemius_plan_id ? String(t.freemius_plan_id) : null,
|
|
210
|
-
freemius_coupon_id: m?.id ? String(m.id) :
|
|
212
|
+
freemius_coupon_id: m?.id ? String(m.id) : n?.freemius_coupon_id ?? null,
|
|
211
213
|
freemius_coupon_code: d,
|
|
212
214
|
discount_percent: r,
|
|
213
215
|
starts_at: t.sale_start_at,
|
|
@@ -223,11 +225,11 @@ async function b(e) {
|
|
|
223
225
|
} catch (_) {
|
|
224
226
|
return await e.client.from("product_freemius_sale_coupons").upsert(
|
|
225
227
|
{
|
|
226
|
-
id:
|
|
228
|
+
id: n?.id,
|
|
227
229
|
product_id: t.id,
|
|
228
|
-
freemius_product_id:
|
|
230
|
+
freemius_product_id: i,
|
|
229
231
|
freemius_plan_id: t.freemius_plan_id ? String(t.freemius_plan_id) : null,
|
|
230
|
-
freemius_coupon_id:
|
|
232
|
+
freemius_coupon_id: n?.freemius_coupon_id ?? null,
|
|
231
233
|
freemius_coupon_code: d,
|
|
232
234
|
discount_percent: r,
|
|
233
235
|
starts_at: t.sale_start_at,
|
|
@@ -244,7 +246,7 @@ async function b(e) {
|
|
|
244
246
|
};
|
|
245
247
|
}
|
|
246
248
|
}
|
|
247
|
-
async function
|
|
249
|
+
async function $(e) {
|
|
248
250
|
const { data: o } = await e.client.from("coupon_freemius_mappings").select("id, freemius_product_id, freemius_coupon_id").eq("coupon_id", e.couponId).not("freemius_coupon_id", "is", null);
|
|
249
251
|
for (const s of o || [])
|
|
250
252
|
try {
|
|
@@ -266,7 +268,7 @@ async function A(e) {
|
|
|
266
268
|
}
|
|
267
269
|
}
|
|
268
270
|
export {
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
271
|
+
$ as deleteCouponFromFreemius,
|
|
272
|
+
A as syncCouponToFreemius,
|
|
273
|
+
U as syncProductSaleCouponToFreemius
|
|
272
274
|
};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
"use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const e=require("react/jsx-runtime"),
|
|
1
|
+
"use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const e=require("react/jsx-runtime"),f=require("react"),r=require("@nextblock-cms/ui"),u=require("lucide-react"),y=require("react-dom");function v({initialEnabledProviders:s,configStatus:t,credentials:i,saveAction:a,saveCredentialsAction:l}){const[d,m]=f.useState(s),c=t?.stripe?.hasKeys,o=t?.freemius?.hasKeys;return e.jsxs("div",{className:"space-y-6 max-w-3xl p-8",children:[e.jsxs("div",{children:[e.jsx("h1",{className:"text-3xl font-bold tracking-tight",children:"Payment Settings"}),e.jsx("p",{className:"text-sm text-muted-foreground",children:"Enter your provider API keys, then enable the providers your store needs. Physical products use Stripe and digital products use Freemius."})]}),e.jsx(g,{credentials:i,saveAction:l}),e.jsxs("form",{action:a,className:"space-y-6",children:[e.jsx("input",{type:"hidden",name:"stripe_enabled",value:d.stripe?"true":"false"}),e.jsx("input",{type:"hidden",name:"freemius_enabled",value:d.freemius?"true":"false"}),e.jsxs(r.Card,{children:[e.jsxs(r.CardHeader,{children:[e.jsx(r.CardTitle,{children:"Payment Providers"}),e.jsx(r.CardDescription,{children:"You can run both providers at the same time. Each product picks its provider from its product type."})]}),e.jsxs(r.CardContent,{className:"space-y-6",children:[e.jsx(x,{id:"stripe-enabled",label:"Stripe for Physical Products",description:"Use Stripe Checkout for physical merchandise and other shippable goods.",checked:d.stripe,disabled:!c,onCheckedChange:h=>m(p=>({...p,stripe:h})),ready:c,children:c?e.jsxs("div",{className:"mt-2 text-sm text-green-600 flex items-center gap-2",children:[e.jsx(u.CheckCircle2,{className:"w-4 h-4"}),e.jsx("span",{children:"Ready to process physical product checkout"})]}):e.jsx(j,{provider:"Stripe",missingKeys:t.stripe.missing,docsUrl:"https://dashboard.stripe.com/apikeys",docsLabel:"Stripe Dashboard -> Developers -> API Keys"})}),e.jsx(x,{id:"freemius-enabled",label:"Freemius for Digital Products",description:"Use Freemius for software licenses, SaaS plans, and other digital products.",checked:d.freemius,disabled:!o,onCheckedChange:h=>m(p=>({...p,freemius:h})),ready:o,children:o?e.jsxs("div",{className:"mt-2 text-sm text-green-600 flex items-center gap-2",children:[e.jsx(u.CheckCircle2,{className:"w-4 h-4"}),e.jsx("span",{children:"Ready to process digital product checkout"})]}):e.jsx(j,{provider:"Freemius",missingKeys:t.freemius.missing,docsUrl:"https://dashboard.freemius.com/",docsLabel:"Freemius Dashboard -> Developers -> Credentials"})}),e.jsx("div",{className:"flex justify-end pt-4",children:e.jsx(b,{})})]})]})]})]})}function b(){const{pending:s}=y.useFormStatus();return e.jsx(r.Button,{type:"submit",disabled:s,children:s?"Saving...":"Save Changes"})}function n({id:s,label:t,type:i="text",defaultValue:a,placeholder:l,hint:d}){return e.jsxs("div",{className:"space-y-1.5",children:[e.jsx(r.Label,{htmlFor:s,children:t}),e.jsx(r.Input,{id:s,name:s,type:i,defaultValue:a,placeholder:l,autoComplete:i==="password"?"new-password":"off"}),d&&e.jsx("p",{className:"text-xs text-muted-foreground",children:d})]})}function g({credentials:s,saveAction:t}){const i="•••••••• (stored — leave blank to keep)";return e.jsxs(r.Card,{children:[e.jsxs(r.CardHeader,{children:[e.jsx(r.CardTitle,{children:"Provider API Keys"}),e.jsxs(r.CardDescription,{children:["Keys are encrypted at rest and used DB-first (these override any ",e.jsx("code",{children:".env"})," ","values). Leave a secret blank to keep the stored value."]})]}),e.jsx(r.CardContent,{children:e.jsxs("form",{action:t,className:"space-y-6",children:[e.jsxs("div",{className:"space-y-4",children:[e.jsx("h3",{className:"text-sm font-semibold",children:"Stripe (physical products)"}),e.jsxs("div",{className:"grid gap-4 sm:grid-cols-2",children:[e.jsx(n,{id:"stripe_publishableKey",label:"Publishable key",defaultValue:s.stripe.publishableKey,placeholder:"pk_live_…"}),e.jsx(n,{id:"stripe_secretKey",label:"Secret key",type:"password",placeholder:s.stripe.hasSecretKey?i:"sk_live_…"}),e.jsx(n,{id:"stripe_webhookSecret",label:"Webhook signing secret",type:"password",placeholder:s.stripe.hasWebhookSecret?i:"whsec_…"})]})]}),e.jsxs("div",{className:"space-y-4",children:[e.jsx("h3",{className:"text-sm font-semibold",children:"Freemius (digital products)"}),e.jsxs("div",{className:"grid gap-4 sm:grid-cols-2",children:[e.jsx(n,{id:"freemius_developerId",label:"Developer ID",defaultValue:s.freemius.developerId}),e.jsx(n,{id:"freemius_productId",label:"Product ID",defaultValue:s.freemius.productId}),e.jsx(n,{id:"freemius_publicKey",label:"Public key",defaultValue:s.freemius.publicKey,placeholder:"pk_…"}),e.jsx(n,{id:"freemius_secretKey",label:"Secret key",type:"password",placeholder:s.freemius.hasSecretKey?i:"sk_…"}),e.jsx(n,{id:"freemius_apiKey",label:"API key",type:"password",placeholder:s.freemius.hasApiKey?i:"API key"})]})]}),s.envFallbackActive&&e.jsx("p",{className:"text-xs text-amber-700",children:"Stripe keys are currently read from environment variables. Saving here moves them into the database and takes precedence."}),e.jsx("div",{className:"flex justify-end",children:e.jsx(b,{})})]})})]})}function x({id:s,label:t,description:i,checked:a,disabled:l,ready:d,onCheckedChange:m,children:c}){return e.jsx("div",{className:"rounded-md border p-4",children:e.jsxs("div",{className:"flex items-start gap-3",children:[e.jsx(r.Checkbox,{id:s,checked:a,disabled:l,onCheckedChange:o=>m(!!o),className:"mt-1"}),e.jsxs("div",{className:"grid gap-1.5 leading-none w-full",children:[e.jsxs("div",{className:"flex items-center justify-between gap-3 flex-wrap",children:[e.jsx(r.Label,{htmlFor:s,className:"font-semibold text-base cursor-pointer",children:t}),e.jsx("span",{className:`text-xs font-medium ${a?"text-foreground":"text-muted-foreground"}`,children:a?"Enabled":"Disabled"})]}),e.jsx("p",{className:"text-sm text-muted-foreground",children:i}),!d&&e.jsx("p",{className:"text-xs text-amber-700",children:"This provider cannot be enabled until all required environment variables are present."}),c]})]})})}function j({provider:s,missingKeys:t,docsUrl:i,docsLabel:a}){return e.jsxs("div",{className:"mt-3 text-sm p-4 rounded-md border border-destructive/20 bg-destructive/5 text-foreground",children:[e.jsxs("div",{className:"flex items-center gap-2 font-semibold text-destructive mb-2",children:[e.jsx(u.AlertCircle,{className:"w-4 h-4"}),e.jsx("span",{children:"Configuration Required"})]}),e.jsxs("p",{className:"mb-2",children:["The ",s," integration still needs the following:"]}),e.jsx("ul",{className:"list-disc list-inside bg-white/50 dark:bg-black/20 p-2 rounded mb-3 text-xs",children:t.map(l=>e.jsx("li",{children:l},l))}),e.jsx("p",{className:"mb-2",children:e.jsx("strong",{children:"How to fix:"})}),e.jsxs("ol",{className:"list-decimal list-inside space-y-1 ml-1 mb-3",children:[e.jsxs("li",{children:["Get your API keys from"," ",e.jsx("a",{href:i,target:"_blank",rel:"noopener noreferrer",className:"underline font-medium hover:text-destructive/80",children:a}),"."]}),e.jsxs("li",{children:["Enter them in the ",e.jsx("strong",{children:"Provider API Keys"})," section above and save."]}),e.jsx("li",{children:"This provider can then be enabled."})]})]})}exports.PaymentsClient=v;
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { PaymentCredentialsView } from '../../../payment-config';
|
|
1
2
|
interface ConfigStatus {
|
|
2
3
|
stripe: {
|
|
3
4
|
hasKeys: boolean;
|
|
@@ -8,12 +9,14 @@ interface ConfigStatus {
|
|
|
8
9
|
missing: string[];
|
|
9
10
|
};
|
|
10
11
|
}
|
|
11
|
-
export declare function PaymentsClient({ initialEnabledProviders, configStatus, saveAction, }: {
|
|
12
|
+
export declare function PaymentsClient({ initialEnabledProviders, configStatus, credentials, saveAction, saveCredentialsAction, }: {
|
|
12
13
|
initialEnabledProviders: {
|
|
13
14
|
stripe: boolean;
|
|
14
15
|
freemius: boolean;
|
|
15
16
|
};
|
|
16
17
|
configStatus: ConfigStatus;
|
|
18
|
+
credentials: PaymentCredentialsView;
|
|
17
19
|
saveAction: (formData: FormData) => Promise<void>;
|
|
20
|
+
saveCredentialsAction: (formData: FormData) => Promise<void>;
|
|
18
21
|
}): import("react").JSX.Element;
|
|
19
22
|
export {};
|