@pybara/pybara-js 0.1.0 → 0.3.0
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/README.md +23 -11
- package/checkout.schema.json +143 -0
- package/dist/admin/core/PybaraAdminClient.d.ts +5 -0
- package/dist/admin/core/PybaraAdminClient.d.ts.map +1 -1
- package/dist/admin/index.d.ts +7 -2
- package/dist/admin/index.d.ts.map +1 -1
- package/dist/admin/index.js +1 -1
- package/dist/{admin-D2vUTEg1.js → admin-B1pVP25-.js} +29 -7
- package/dist/checkout.d.ts +16 -10
- package/dist/checkout.d.ts.map +1 -1
- package/dist/gate.d.ts +13 -7
- package/dist/gate.d.ts.map +1 -1
- package/dist/index.d.ts +7 -5
- package/dist/index.d.ts.map +1 -1
- package/dist/modal/config.d.ts +19 -0
- package/dist/modal/config.d.ts.map +1 -0
- package/dist/modal/index.d.ts +16 -0
- package/dist/modal/index.d.ts.map +1 -0
- package/dist/modal/index.js +1 -0
- package/dist/modal/lock-page-scroll.d.ts +9 -0
- package/dist/modal/lock-page-scroll.d.ts.map +1 -0
- package/dist/modal/modal.d.ts +160 -0
- package/dist/modal/modal.d.ts.map +1 -0
- package/dist/modal-BCDMoDW9.js +192 -0
- package/dist/pybara-js.iife.js +3 -3
- package/dist/pybara-js.js +177 -325
- package/dist/types.d.ts +16 -7
- package/dist/types.d.ts.map +1 -1
- package/package.json +22 -5
- package/dist/constants.d.ts +0 -13
- package/dist/constants.d.ts.map +0 -1
package/dist/pybara-js.js
CHANGED
|
@@ -1,401 +1,253 @@
|
|
|
1
1
|
/* Pybara.js - pybara.com */
|
|
2
|
-
import { n as e, r as t, t as n } from "./admin-
|
|
3
|
-
|
|
4
|
-
var
|
|
5
|
-
Z_INDEX: 999999,
|
|
6
|
-
BACKGROUND: "rgba(0, 0, 0, 0.7)"
|
|
7
|
-
}, i = {
|
|
8
|
-
OVERLAY_FADE_IN_MS: 200,
|
|
9
|
-
PANEL_OPEN_MS: 300,
|
|
10
|
-
PANEL_CLOSE_MS: 200,
|
|
11
|
-
OVERLAY_FADE_OUT_DELAY_MS: 50,
|
|
12
|
-
OVERLAY_FADE_OUT_MS: 150
|
|
13
|
-
}, a = 0, o = 0, s = 0;
|
|
14
|
-
function c(e) {
|
|
15
|
-
e.preventDefault();
|
|
16
|
-
}
|
|
17
|
-
function l(e) {
|
|
18
|
-
e.preventDefault();
|
|
19
|
-
}
|
|
20
|
-
function u(e) {
|
|
21
|
-
e.target instanceof HTMLInputElement || e.target instanceof HTMLTextAreaElement || [
|
|
22
|
-
"ArrowUp",
|
|
23
|
-
"ArrowDown",
|
|
24
|
-
"PageUp",
|
|
25
|
-
"PageDown",
|
|
26
|
-
"Home",
|
|
27
|
-
"End",
|
|
28
|
-
" "
|
|
29
|
-
].includes(e.key) && e.preventDefault();
|
|
30
|
-
}
|
|
31
|
-
function d() {
|
|
32
|
-
window.scrollTo(o, s);
|
|
33
|
-
}
|
|
34
|
-
function f() {
|
|
35
|
-
a === 0 && (o = window.scrollX, s = window.scrollY, window.addEventListener("wheel", c, { passive: !1 }), window.addEventListener("touchmove", l, { passive: !1 }), window.addEventListener("keydown", u), window.addEventListener("scroll", d)), a += 1;
|
|
36
|
-
}
|
|
37
|
-
function p() {
|
|
38
|
-
a !== 0 && (--a, a === 0 && (window.removeEventListener("wheel", c), window.removeEventListener("touchmove", l), window.removeEventListener("keydown", u), window.removeEventListener("scroll", d)));
|
|
39
|
-
}
|
|
40
|
-
//#endregion
|
|
41
|
-
//#region node_modules/@pybara/pybara-ux/dist/modal.js
|
|
42
|
-
function m() {
|
|
43
|
-
return window.matchMedia("(prefers-reduced-motion: reduce)").matches;
|
|
44
|
-
}
|
|
45
|
-
var h = [
|
|
46
|
-
"DESTINATION_REFUSED",
|
|
47
|
-
"INVALID_BENEFICIARY",
|
|
48
|
-
"NO_WALLET_AVAILABLE",
|
|
49
|
-
"SITE_MISMATCH"
|
|
50
|
-
];
|
|
51
|
-
function g(e) {
|
|
52
|
-
return h.includes(e) ? e : "UNKNOWN";
|
|
53
|
-
}
|
|
54
|
-
var _ = class extends Error {
|
|
55
|
-
constructor(e, t) {
|
|
56
|
-
super(t), this.name = "EmbeddedError", this.code = e, Object.setPrototypeOf(this, new.target.prototype);
|
|
57
|
-
}
|
|
58
|
-
};
|
|
59
|
-
function v(e) {
|
|
60
|
-
return typeof e == "object" && !!e && typeof e.type == "string" && e.type.startsWith("pybara_embedded_");
|
|
61
|
-
}
|
|
62
|
-
var y = class {
|
|
63
|
-
constructor(e) {
|
|
64
|
-
this.overlay = null, this.iframe = null, this.spinner = null, this.handleMessage = null, this.handleEscapeKey = null, this.closable = !0, this.iframeLoaded = !1, this.pendingPaymentData = null, this.config = e, this.walletOrigin = new URL(e.walletUrl).origin, this.createIframe();
|
|
65
|
-
}
|
|
66
|
-
createIframe() {
|
|
67
|
-
let e = document.createElement("div");
|
|
68
|
-
e.className = "pybara-checkout-overlay", e.style.cssText = `
|
|
69
|
-
position: fixed;
|
|
70
|
-
top: 0;
|
|
71
|
-
left: 0;
|
|
72
|
-
right: 0;
|
|
73
|
-
bottom: 0;
|
|
74
|
-
background: ${r.BACKGROUND};
|
|
75
|
-
z-index: ${r.Z_INDEX};
|
|
76
|
-
display: none;
|
|
77
|
-
align-items: center;
|
|
78
|
-
justify-content: center;
|
|
79
|
-
overscroll-behavior: none;
|
|
80
|
-
user-select: none;
|
|
81
|
-
`;
|
|
82
|
-
let t = document.createElement("iframe");
|
|
83
|
-
t.src = `${this.config.walletUrl}/pay?mode=embedded`, t.title = "Pybara Wallet", t.style.cssText = "\n width: 100%;\n max-width: 500px;\n height: 0;\n max-height: 90vh;\n border: none;\n border-radius: 20px;\n box-shadow: 0 20px 60px rgba(0, 0, 0, 0.5);\n overscroll-behavior: none;\n ";
|
|
84
|
-
let n = document.createElement("div");
|
|
85
|
-
n.setAttribute("aria-hidden", "true"), n.style.cssText = "\n position: absolute;\n inset: 0;\n display: flex;\n align-items: center;\n justify-content: center;\n pointer-events: none;\n ", n.innerHTML = "\n <svg viewBox=\"0 0 50 50\" width=\"50\" height=\"50\">\n <circle cx=\"25\" cy=\"25\" r=\"20\" fill=\"none\" stroke=\"white\" stroke-width=\"3\" stroke-linecap=\"round\" stroke-dasharray=\"80\" stroke-dashoffset=\"20\"/>\n </svg>\n ", n.querySelector("svg")?.animate([{ transform: "rotate(0deg)" }, { transform: "rotate(360deg)" }], {
|
|
86
|
-
duration: 1e3,
|
|
87
|
-
iterations: Infinity
|
|
88
|
-
}), t.addEventListener("load", () => {
|
|
89
|
-
this.iframeLoaded = !0, this.pendingPaymentData &&= (this.sendInitMessage(this.pendingPaymentData), null);
|
|
90
|
-
}, { once: !0 }), this.handleMessage = (e) => {
|
|
91
|
-
if (e.origin === this.walletOrigin && e.source === t.contentWindow && v(e.data)) switch (e.data.type) {
|
|
92
|
-
case "pybara_embedded_result":
|
|
93
|
-
this.config.onSuccess?.({
|
|
94
|
-
blockIndex: e.data.blockIndex,
|
|
95
|
-
reference: e.data.reference,
|
|
96
|
-
payerPrincipal: e.data.payerPrincipal,
|
|
97
|
-
token: e.data.token
|
|
98
|
-
});
|
|
99
|
-
break;
|
|
100
|
-
case "pybara_embedded_error":
|
|
101
|
-
this.close(), this.config.onError?.(new _(g(e.data.code), e.data.message));
|
|
102
|
-
break;
|
|
103
|
-
case "pybara_embedded_closed":
|
|
104
|
-
this.close(), this.config.onClose?.();
|
|
105
|
-
break;
|
|
106
|
-
case "pybara_embedded_resize":
|
|
107
|
-
t.style.height !== `${e.data.height}px` && (t.style.height = `${e.data.height}px`), this.spinner && (this.spinner.remove(), this.spinner = null, m() || t.animate([{
|
|
108
|
-
transform: "translateY(20px)",
|
|
109
|
-
opacity: 0
|
|
110
|
-
}, {
|
|
111
|
-
transform: "none",
|
|
112
|
-
opacity: 1
|
|
113
|
-
}], {
|
|
114
|
-
duration: i.PANEL_OPEN_MS,
|
|
115
|
-
easing: "ease"
|
|
116
|
-
}));
|
|
117
|
-
break;
|
|
118
|
-
case "pybara_embedded_closable": this.closable = e.data.closable;
|
|
119
|
-
}
|
|
120
|
-
}, window.addEventListener("message", this.handleMessage), this.handleEscapeKey = (e) => {
|
|
121
|
-
e.key === "Escape" && this.closable && (this.close(), this.config.onClose?.());
|
|
122
|
-
}, document.addEventListener("keydown", this.handleEscapeKey), e.appendChild(n), e.appendChild(t), document.body.appendChild(e), this.overlay = e, this.iframe = t, this.spinner = n;
|
|
123
|
-
}
|
|
124
|
-
sendInitMessage(e) {
|
|
125
|
-
let t = {
|
|
126
|
-
type: "pybara_embedded_init",
|
|
127
|
-
beneficiary: e.modalData.beneficiary,
|
|
128
|
-
salt: e.modalData.salt,
|
|
129
|
-
amountUSD: e.modalData.amountUSD,
|
|
130
|
-
reference: e.modalData.reference,
|
|
131
|
-
context: this.config.context,
|
|
132
|
-
...e.recurring ? { recurring: e.recurring } : {},
|
|
133
|
-
...e.sdkFields ? { sdkFields: e.sdkFields } : {},
|
|
134
|
-
...this.config.thankYouMessage ? { thankYouMessage: this.config.thankYouMessage } : {}
|
|
135
|
-
};
|
|
136
|
-
this.iframe?.contentWindow?.postMessage(t, this.walletOrigin);
|
|
137
|
-
}
|
|
138
|
-
open() {
|
|
139
|
-
this.overlay && this.overlay.style.display !== "flex" && (f(), this.overlay.style.display = "flex", m() || this.overlay.animate([{ opacity: 0 }, { opacity: 1 }], {
|
|
140
|
-
duration: i.OVERLAY_FADE_IN_MS,
|
|
141
|
-
easing: "ease"
|
|
142
|
-
}));
|
|
143
|
-
}
|
|
144
|
-
show(e) {
|
|
145
|
-
this.open(), this.iframeLoaded ? this.sendInitMessage(e) : this.pendingPaymentData = e;
|
|
146
|
-
}
|
|
147
|
-
renderTerminalState(e) {
|
|
148
|
-
this.close(), f();
|
|
149
|
-
let t = document.createElement("div");
|
|
150
|
-
t.className = "pybara-checkout-overlay", t.style.cssText = `
|
|
151
|
-
position: fixed;
|
|
152
|
-
top: 0;
|
|
153
|
-
left: 0;
|
|
154
|
-
right: 0;
|
|
155
|
-
bottom: 0;
|
|
156
|
-
background: ${r.BACKGROUND};
|
|
157
|
-
z-index: ${r.Z_INDEX};
|
|
158
|
-
display: flex;
|
|
159
|
-
align-items: center;
|
|
160
|
-
justify-content: center;
|
|
161
|
-
user-select: none;
|
|
162
|
-
`;
|
|
163
|
-
let n = document.createElement("div");
|
|
164
|
-
n.style.cssText = "\n background: #fff;\n border-radius: 12px;\n color: #666;\n padding: 2rem;\n line-height: 1.4;\n max-width: 360px;\n text-align: center;\n font-family: system-ui, sans-serif;\n user-select: text;\n ", n.textContent = e, t.appendChild(n), t.addEventListener("click", (e) => {
|
|
165
|
-
e.target === t && (t.remove(), p(), this.config.onClose?.());
|
|
166
|
-
}), document.body.appendChild(t), this.overlay = t;
|
|
167
|
-
}
|
|
168
|
-
close() {
|
|
169
|
-
this.handleMessage &&= (window.removeEventListener("message", this.handleMessage), null), this.handleEscapeKey &&= (document.removeEventListener("keydown", this.handleEscapeKey), null), p();
|
|
170
|
-
let e = this.overlay, t = this.iframe;
|
|
171
|
-
this.overlay = null, this.iframe = null, this.spinner = null, this.iframeLoaded = !1, this.pendingPaymentData = null, this.closable = !0, e && (e.style.display === "none" || m() ? e.remove() : (e.style.pointerEvents = "none", t?.animate([{
|
|
172
|
-
transform: "scale(1)",
|
|
173
|
-
opacity: 1
|
|
174
|
-
}, {
|
|
175
|
-
transform: "scale(0.95)",
|
|
176
|
-
opacity: 0
|
|
177
|
-
}], {
|
|
178
|
-
duration: i.PANEL_CLOSE_MS,
|
|
179
|
-
easing: "ease-out",
|
|
180
|
-
fill: "forwards"
|
|
181
|
-
}), e.animate([{ opacity: 1 }, { opacity: 0 }], {
|
|
182
|
-
duration: i.OVERLAY_FADE_OUT_MS,
|
|
183
|
-
delay: i.OVERLAY_FADE_OUT_DELAY_MS,
|
|
184
|
-
easing: "ease-out",
|
|
185
|
-
fill: "forwards"
|
|
186
|
-
}).finished.then(() => e.remove(), () => e.remove())));
|
|
187
|
-
}
|
|
188
|
-
}, b = {
|
|
189
|
-
every2min: 120,
|
|
190
|
-
weekly: 604800,
|
|
191
|
-
monthly: 2592e3,
|
|
192
|
-
yearly: 31536e3
|
|
193
|
-
}, x = 2592e3, S = [
|
|
194
|
-
3,
|
|
195
|
-
6,
|
|
196
|
-
12,
|
|
197
|
-
24
|
|
198
|
-
], C = .5, w = {
|
|
2
|
+
import { n as e, r as t, t as n } from "./admin-B1pVP25-.js";
|
|
3
|
+
import { t as r } from "./modal-BCDMoDW9.js";
|
|
4
|
+
var i = {
|
|
199
5
|
widget: "donate-widget",
|
|
200
6
|
recurring: "donate-widget-recurring"
|
|
201
|
-
}, T = (e) => {
|
|
202
|
-
if (!e || !e.includes("-")) return !0;
|
|
203
|
-
let [t = 0, n = 0] = e.split("-").map(Number), [r = 0, i = 0] = "1-0".split("-").map(Number);
|
|
204
|
-
return t < r || t === r && n < i;
|
|
205
7
|
};
|
|
206
|
-
|
|
207
|
-
let
|
|
8
|
+
function a(e, t) {
|
|
9
|
+
let n = (e) => {
|
|
10
|
+
let t = /^(\d+)-(\d+)$/.exec(e);
|
|
11
|
+
return t ? [Number(t[1]), Number(t[2])] : null;
|
|
12
|
+
}, r = n(e), i = n(t);
|
|
13
|
+
return !r || !i ? !1 : r[0] > i[0] || r[0] === i[0] && r[1] >= i[1];
|
|
14
|
+
}
|
|
15
|
+
async function o(e) {
|
|
16
|
+
let t = await fetch(e);
|
|
17
|
+
if (!t.ok) throw Error(`HTTP ${t.status} from ${e}`);
|
|
18
|
+
return await t.json();
|
|
19
|
+
}
|
|
20
|
+
async function s(t, n, r) {
|
|
21
|
+
let s = e[t], c = `https://${s.admin_core}.raw.icp0.io/widget-config`, l = `https://${s.admin_regs}.raw.icp0.io/widget-terms?site_url=${encodeURIComponent(n)}&principal=${encodeURIComponent(r)}`, u, d;
|
|
208
22
|
try {
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
show: !1,
|
|
212
|
-
reason: `This integration is temporarily unavailable (${o.key})`
|
|
213
|
-
};
|
|
214
|
-
if (!e.ok) return {
|
|
215
|
-
show: !1,
|
|
216
|
-
reason: `Site not verified (${e.status})`
|
|
217
|
-
};
|
|
218
|
-
let s = await e.json();
|
|
219
|
-
if (s.terms?.signed !== !0 || T(s.terms?.version)) {
|
|
220
|
-
let e = s.terms?.superseded_version;
|
|
221
|
-
return {
|
|
222
|
-
show: !1,
|
|
223
|
-
reason: e ? `Widget terms v${e} now apply — accept them in Pybara Wallet (Manage › Sites)` : "This site has not accepted the widget’s terms in Pybara Wallet (Manage › Sites)"
|
|
224
|
-
};
|
|
225
|
-
}
|
|
23
|
+
[u, d] = await Promise.all([o(c), o(l)]);
|
|
24
|
+
} catch (e) {
|
|
226
25
|
return {
|
|
227
|
-
show: !0,
|
|
228
|
-
reason: null
|
|
229
|
-
};
|
|
230
|
-
} catch {
|
|
231
|
-
return o ? {
|
|
232
26
|
show: !1,
|
|
233
|
-
reason: `
|
|
234
|
-
} : {
|
|
235
|
-
show: !0,
|
|
236
|
-
reason: null
|
|
27
|
+
reason: `could not read the widget's configuration (${e instanceof Error ? e.message : String(e)})`
|
|
237
28
|
};
|
|
238
29
|
}
|
|
30
|
+
let f = u.kill_switch?.plugins ?? {};
|
|
31
|
+
return f[i.widget]?.enabled === !0 ? !d.signed || !d.version ? {
|
|
32
|
+
show: !1,
|
|
33
|
+
reason: `${n} has not accepted the widget's terms in Pybara Wallet (Manage › Sites › Add a site without a plugin)`
|
|
34
|
+
} : a(d.version, "1-0") ? {
|
|
35
|
+
show: !0,
|
|
36
|
+
recurring: f[i.recurring]?.enabled === !0
|
|
37
|
+
} : {
|
|
38
|
+
show: !1,
|
|
39
|
+
reason: `this widget version requires terms 1-0, and ${n} accepted ${d.version}: accept the new terms in Pybara Wallet (Manage › Sites)`
|
|
40
|
+
} : {
|
|
41
|
+
show: !1,
|
|
42
|
+
reason: "the widget is switched off by Pybara for now"
|
|
43
|
+
};
|
|
239
44
|
}
|
|
240
45
|
//#endregion
|
|
241
46
|
//#region src/types.ts
|
|
242
|
-
var
|
|
47
|
+
var c = class extends Error {
|
|
243
48
|
constructor(e, t) {
|
|
244
49
|
super(t), this.name = "PybaraError", this.code = e;
|
|
245
50
|
}
|
|
246
|
-
},
|
|
51
|
+
}, l = /^(0|[1-9]\d*)(\.\d+)?$/, u = /^[a-z0-9-]{1,64}$/, d = class {
|
|
247
52
|
constructor(e) {
|
|
248
|
-
this.adminClient = null, this.
|
|
53
|
+
this.adminClient = null, this.modal = null, this.gateOutcome = null, this.isOpen = !1, this.completedPayment = !1, this.activePayment = null, this.config = m(e), this.ready = this.init();
|
|
54
|
+
}
|
|
55
|
+
get gate() {
|
|
56
|
+
return this.gateOutcome;
|
|
249
57
|
}
|
|
250
58
|
async open(e) {
|
|
251
|
-
if (await this.ready, this.
|
|
252
|
-
let t = e.amount;
|
|
253
|
-
if (
|
|
254
|
-
let n = e.currency ?? this.config.currency
|
|
255
|
-
if (
|
|
256
|
-
|
|
59
|
+
if (await this.ready, this.gateOutcome && !this.gateOutcome.show) throw new c("GATE_REFUSED", this.gateOutcome.reason ?? "This site cannot accept Pybara payments yet.");
|
|
60
|
+
let t = f(e.amount);
|
|
61
|
+
if (t === null) throw new c("INVALID_CONFIG", `open(): "amount" must be a decimal string in the currency's major units, e.g. "12.34", or a positive number — got ${JSON.stringify(e.amount)}`);
|
|
62
|
+
let n = e.currency ?? this.config.currency;
|
|
63
|
+
if (!n) throw new c("INVALID_CONFIG", "open(): \"currency\" is required — pass it to open(), or set it once in Pybara.checkout()");
|
|
64
|
+
if (!/^[A-Z]{3}$/.test(n)) throw new c("INVALID_CONFIG", `open(): "currency" must be an uppercase ISO 4217 code, e.g. "EUR" — got ${JSON.stringify(n)}`);
|
|
65
|
+
if (e.durationMonths != null && !e.frequency) throw new c("INVALID_CONFIG", "open(): \"durationMonths\" needs a \"frequency\"");
|
|
66
|
+
let r = e.frequency ? {
|
|
67
|
+
frequency: e.frequency,
|
|
68
|
+
...e.durationMonths == null ? {} : { durationMonths: e.durationMonths }
|
|
69
|
+
} : void 0;
|
|
70
|
+
if (r && this.gateOutcome && this.gateOutcome.show && !this.gateOutcome.recurring) throw new c("GATE_REFUSED", "Recurring payments are temporarily unavailable.");
|
|
257
71
|
if (this.isOpen) return;
|
|
258
72
|
this.isOpen = !0;
|
|
259
|
-
let
|
|
73
|
+
let i = !1;
|
|
260
74
|
try {
|
|
261
75
|
await this.adminClient?.getRecipientDataWithCache(this.config.siteUrl);
|
|
262
76
|
} catch (e) {
|
|
263
|
-
this.config.debug && console.warn("🧩 pybara-js: recipient access validation failed:", e),
|
|
77
|
+
this.config.debug && console.warn("🧩 pybara-js: recipient access validation failed:", e), i = !0;
|
|
264
78
|
}
|
|
265
79
|
this.modal || this.initCheckoutModal();
|
|
266
|
-
let
|
|
267
|
-
if (!
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
80
|
+
let a = this.modal;
|
|
81
|
+
if (!a) throw this.isOpen = !1, new c("CHECKOUT_FAILED", "The checkout modal could not be initialised.");
|
|
82
|
+
if (i) this.isOpen = !1, a.renderTerminalState("This recipient is currently unable to accept donations."), this.initCheckoutModal();
|
|
83
|
+
else {
|
|
84
|
+
this.activePayment = e;
|
|
85
|
+
try {
|
|
86
|
+
a.show({
|
|
87
|
+
modalData: {
|
|
88
|
+
beneficiary: this.config.recipientPrincipal,
|
|
89
|
+
salt: h(),
|
|
90
|
+
reference: this.config.siteName
|
|
91
|
+
},
|
|
92
|
+
recurring: r,
|
|
93
|
+
checkout: this.checkoutFor(e, t, n)
|
|
94
|
+
});
|
|
95
|
+
} catch (e) {
|
|
96
|
+
throw this.isOpen = !1, this.activePayment = null, g(e);
|
|
97
|
+
}
|
|
98
|
+
}
|
|
278
99
|
}
|
|
279
100
|
close() {
|
|
280
101
|
this.modal?.close();
|
|
281
102
|
}
|
|
282
103
|
async init() {
|
|
283
104
|
let t = this.config.staging ? "staging" : "prod", r = this.config.debug;
|
|
284
|
-
r && console.log("🧩 pybara-js: initializing checkout…"), this.
|
|
105
|
+
r && console.log("🧩 pybara-js: initializing checkout…"), this.preconnectWallet(t), this.initCheckoutModal();
|
|
106
|
+
let i = new n({
|
|
285
107
|
adminCoreCanisterId: e[t].admin_core,
|
|
286
108
|
debug: r
|
|
287
109
|
});
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
110
|
+
this.adminClient = i;
|
|
111
|
+
let a = (async () => {
|
|
112
|
+
try {
|
|
113
|
+
await i.init(), await i.getPybaraAdminConfig(), r && console.log("🧩 pybara-js: admin client ready"), i.getRecipientDataWithCache(this.config.siteUrl).catch((e) => {
|
|
114
|
+
r && console.warn("🧩 pybara-js: recipient prewarm failed:", e);
|
|
115
|
+
});
|
|
116
|
+
} catch (e) {
|
|
117
|
+
r && console.error("🧩 pybara-js: admin client init failed:", e);
|
|
118
|
+
}
|
|
119
|
+
})(), o = (async () => {
|
|
120
|
+
this.config.pluginVersion || (this.gateOutcome = await s(t, this.config.siteUrl, this.config.recipientPrincipal), !this.gateOutcome.show && r && console.warn("🧩 pybara-js: gate refused —", this.gateOutcome.reason));
|
|
121
|
+
})();
|
|
122
|
+
await Promise.all([a, o]);
|
|
296
123
|
}
|
|
297
124
|
initCheckoutModal() {
|
|
298
|
-
let e = this.config.staging ? "staging" : "prod", n = this.config,
|
|
299
|
-
this.modal = new
|
|
125
|
+
let e = this.config.staging ? "staging" : "prod", n = this.config, i = this;
|
|
126
|
+
this.modal = new r({
|
|
300
127
|
walletUrl: t[e],
|
|
301
128
|
context: "donation",
|
|
302
129
|
thankYouMessage: n.thankYouMessage,
|
|
303
130
|
onSuccess: (e) => {
|
|
304
|
-
|
|
131
|
+
i.completedPayment = !0;
|
|
132
|
+
let t = i.activePayment, r = t?.frequency != null, a = {
|
|
305
133
|
blockIndex: e.blockIndex,
|
|
306
134
|
reference: e.reference,
|
|
307
135
|
token: e.token,
|
|
308
|
-
recurring:
|
|
136
|
+
recurring: r,
|
|
309
137
|
frequency: t?.frequency,
|
|
310
|
-
durationMonths:
|
|
311
|
-
isUnlimited:
|
|
138
|
+
durationMonths: r ? t?.durationMonths ?? void 0 : void 0,
|
|
139
|
+
isUnlimited: r && t?.durationMonths == null,
|
|
312
140
|
payerPrincipal: e.payerPrincipal,
|
|
313
141
|
recipientPrincipal: n.recipientPrincipal
|
|
314
142
|
};
|
|
315
143
|
t?.onSuccess?.(a);
|
|
316
144
|
},
|
|
317
145
|
onError: (e) => {
|
|
318
|
-
|
|
319
|
-
let t =
|
|
320
|
-
|
|
146
|
+
i.isOpen = !1;
|
|
147
|
+
let t = i.activePayment;
|
|
148
|
+
i.activePayment = null, t?.onError?.(g(e)), i.modal = null, i.initCheckoutModal();
|
|
321
149
|
},
|
|
322
150
|
onClose: () => {
|
|
323
|
-
|
|
324
|
-
let e =
|
|
325
|
-
|
|
151
|
+
i.isOpen = !1;
|
|
152
|
+
let e = i.activePayment;
|
|
153
|
+
i.activePayment = null, e?.onClose?.(), i.completedPayment && n.thankYouRedirectUrl ? window.location.href = n.thankYouRedirectUrl : (i.completedPayment = !1, i.modal = null, i.initCheckoutModal());
|
|
326
154
|
}
|
|
327
155
|
});
|
|
328
156
|
}
|
|
329
|
-
|
|
330
|
-
let
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
157
|
+
checkoutFor(e, t, n) {
|
|
158
|
+
let r = this.config;
|
|
159
|
+
return {
|
|
160
|
+
v: 1,
|
|
161
|
+
amount: t,
|
|
162
|
+
currency: n,
|
|
163
|
+
site: {
|
|
164
|
+
url: r.siteUrl,
|
|
165
|
+
name: r.siteName,
|
|
166
|
+
country: r.siteCountry
|
|
167
|
+
},
|
|
168
|
+
platform: r.platform ?? "pybara-js",
|
|
169
|
+
pluginVersion: r.pluginVersion,
|
|
170
|
+
siteTerms: {
|
|
171
|
+
version: r.recipientTosVersion,
|
|
172
|
+
acceptedAt: r.recipientTosAcceptedAt
|
|
173
|
+
},
|
|
174
|
+
notify: {
|
|
175
|
+
email: r.notifyEmail,
|
|
176
|
+
enabled: r.notifyDonations
|
|
177
|
+
},
|
|
178
|
+
donation: {
|
|
179
|
+
donor: {
|
|
180
|
+
email: e.donorEmail,
|
|
181
|
+
firstName: e.donorFirstName,
|
|
182
|
+
lastName: e.donorLastName,
|
|
183
|
+
company: e.donorCompany,
|
|
184
|
+
country: e.donorCountry,
|
|
185
|
+
address: {
|
|
186
|
+
line1: e.donorAddressLine1,
|
|
187
|
+
line2: e.donorAddressLine2,
|
|
188
|
+
city: e.donorAddressCity,
|
|
189
|
+
state: e.donorAddressState,
|
|
190
|
+
postalCode: e.donorAddressPostalCode,
|
|
191
|
+
country: e.donorAddressCountry
|
|
192
|
+
},
|
|
193
|
+
tos: {
|
|
194
|
+
version: e.donorTosVersion,
|
|
195
|
+
acceptedAt: e.donorTosAcceptedAt
|
|
196
|
+
}
|
|
197
|
+
},
|
|
198
|
+
message: e.donorMessage,
|
|
199
|
+
isAnonymous: e.donorIsAnonymous,
|
|
200
|
+
wantsTaxReceipt: e.wantsTaxReceipt
|
|
201
|
+
}
|
|
202
|
+
};
|
|
357
203
|
}
|
|
358
204
|
preconnectWallet(e) {
|
|
359
205
|
let n = document.createElement("link");
|
|
360
206
|
n.rel = "preconnect", n.href = new URL(t[e]).origin, n.crossOrigin = "anonymous", document.head.appendChild(n);
|
|
361
207
|
}
|
|
362
208
|
};
|
|
363
|
-
function
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
if (n == null) return {
|
|
367
|
-
frequency: e.frequency,
|
|
368
|
-
totalPulls: 0
|
|
369
|
-
};
|
|
370
|
-
if (!S.includes(n)) throw new D("INVALID_CONFIG", `durationMonths must be one of ${S.join(", ")} — got ${n}.`);
|
|
371
|
-
return {
|
|
372
|
-
frequency: e.frequency,
|
|
373
|
-
totalPulls: Math.ceil(n * x / t),
|
|
374
|
-
durationMonths: n
|
|
375
|
-
};
|
|
209
|
+
function f(e) {
|
|
210
|
+
let t = typeof e == "number" && Number.isFinite(e) ? String(e) : e;
|
|
211
|
+
return typeof t != "string" || !l.test(t) || !/[1-9]/.test(t) ? null : t;
|
|
376
212
|
}
|
|
377
|
-
function
|
|
378
|
-
|
|
379
|
-
if (!
|
|
380
|
-
|
|
213
|
+
function p(e) {
|
|
214
|
+
let t = e.trim();
|
|
215
|
+
if (!t) return null;
|
|
216
|
+
let n;
|
|
217
|
+
try {
|
|
218
|
+
n = new URL(t.includes("://") ? t : `https://${t}`);
|
|
219
|
+
} catch {
|
|
220
|
+
return null;
|
|
221
|
+
}
|
|
222
|
+
return n.protocol !== "https:" && n.protocol !== "http:" ? null : n.origin + n.pathname.replace(/\/+$/, "");
|
|
223
|
+
}
|
|
224
|
+
function m(e) {
|
|
225
|
+
if (!e.recipientPrincipal) throw new c("INVALID_CONFIG", "Pybara.checkout: \"recipientPrincipal\" is required");
|
|
226
|
+
if (!e.siteUrl) throw new c("INVALID_CONFIG", "Pybara.checkout: \"siteUrl\" is required");
|
|
227
|
+
let t = p(e.siteUrl);
|
|
228
|
+
if (!t) throw new c("INVALID_CONFIG", `Pybara.checkout: "siteUrl" is not a valid http(s) URL: ${e.siteUrl}`);
|
|
229
|
+
if (!e.siteName) throw new c("INVALID_CONFIG", "Pybara.checkout: \"siteName\" is required");
|
|
230
|
+
if (e.currency != null && !/^[A-Z]{3}$/.test(e.currency)) throw new c("INVALID_CONFIG", `Pybara.checkout: "currency" must be an uppercase ISO 4217 code, e.g. "EUR" — got ${JSON.stringify(e.currency)}`);
|
|
231
|
+
if (e.platform != null && !u.test(e.platform)) throw new c("INVALID_CONFIG", "Pybara.checkout: \"platform\" must be a lowercase slug (a-z, 0-9, -), at most 64 characters");
|
|
381
232
|
return {
|
|
382
233
|
...e,
|
|
383
|
-
|
|
234
|
+
siteUrl: t,
|
|
384
235
|
staging: e.staging ?? !1,
|
|
385
236
|
debug: e.debug ?? !1
|
|
386
237
|
};
|
|
387
238
|
}
|
|
388
|
-
function
|
|
239
|
+
function h() {
|
|
389
240
|
let e = crypto.getRandomValues(/* @__PURE__ */ new Uint8Array(16));
|
|
390
241
|
return btoa(String.fromCharCode(...e));
|
|
391
242
|
}
|
|
392
|
-
function
|
|
243
|
+
function g(e) {
|
|
393
244
|
return e instanceof Error ? e : Error(String(e));
|
|
394
245
|
}
|
|
395
246
|
//#endregion
|
|
396
247
|
//#region src/index.ts
|
|
397
|
-
|
|
398
|
-
return new
|
|
399
|
-
}
|
|
248
|
+
function _(e) {
|
|
249
|
+
return new d(e);
|
|
250
|
+
}
|
|
251
|
+
var v = { checkout: _ };
|
|
400
252
|
//#endregion
|
|
401
|
-
export {
|
|
253
|
+
export { v as Pybara, d as PybaraCheckout, c as PybaraError, _ as checkout };
|
package/dist/types.d.ts
CHANGED
|
@@ -14,7 +14,7 @@ export interface CheckoutConfig {
|
|
|
14
14
|
siteUrl: string;
|
|
15
15
|
/** Site display name — shown in the checkout frame and stored as the subscription name on recurring payments. */
|
|
16
16
|
siteName: string;
|
|
17
|
-
/**
|
|
17
|
+
/** The currency open() charges in when its own `currency` is absent (ISO 4217, e.g. 'EUR'): set it once on a single-currency site. No default — open() refuses when neither is set. */
|
|
18
18
|
currency?: string;
|
|
19
19
|
/** Replaces the success screen's default title. */
|
|
20
20
|
thankYouMessage?: string;
|
|
@@ -22,6 +22,8 @@ export interface CheckoutConfig {
|
|
|
22
22
|
thankYouRedirectUrl?: string;
|
|
23
23
|
/** Site base country (ISO 3166-1 alpha-2). */
|
|
24
24
|
siteCountry?: string;
|
|
25
|
+
/** The integration surface reported in the payment log's `platform` field: a lowercase slug (a-z, 0-9, -), at most 64 characters — default 'pybara-js'. First-party consumers set their own (e.g. 'pybara-donate'). A label, never used for a decision. */
|
|
26
|
+
platform?: string;
|
|
25
27
|
/** Site operator's contact email — terms warnings, per-payment notification emails. */
|
|
26
28
|
notifyEmail?: string;
|
|
27
29
|
/** false silences the per-payment notification email at notifyEmail. Default true. */
|
|
@@ -39,13 +41,17 @@ export interface CheckoutConfig {
|
|
|
39
41
|
}
|
|
40
42
|
/** One payment attempt — the params of a single open() call. */
|
|
41
43
|
export interface PaymentParams {
|
|
42
|
-
/**
|
|
43
|
-
|
|
44
|
-
|
|
44
|
+
/**
|
|
45
|
+
* The amount in the currency's major units, as a decimal string — "12.34" for €12.34, "1000" for ¥1,000 — as PayPal's API takes it.
|
|
46
|
+
* A number is accepted and turned into its decimal text (12.34 → "12.34").
|
|
47
|
+
* The checkout reads it with the currency's ISO 4217 minor units, and refuses more decimals than the currency holds ("12.345" EUR, "1000.5" JPY), so the page never needs to know them.
|
|
48
|
+
*/
|
|
49
|
+
amount: string | number;
|
|
50
|
+
/** The currency charged (ISO 4217, e.g. 'EUR') — the checkout config's when absent; one of the two is required. A multi-currency site passes it on every call. */
|
|
45
51
|
currency?: string;
|
|
46
52
|
/** Recurring frequency — omit for a one-time payment. */
|
|
47
53
|
frequency?: Frequency;
|
|
48
|
-
/** Recurring length in months: 3 | 6 | 12 | 24. Omit with frequency for an unlimited subscription. */
|
|
54
|
+
/** Recurring length in months: 3 | 6 | 12 | 24, checked by the checkout. Omit with frequency for an unlimited subscription. */
|
|
49
55
|
durationMonths?: number;
|
|
50
56
|
/** Hide the payer's identity on the public record. */
|
|
51
57
|
donorIsAnonymous?: boolean;
|
|
@@ -95,8 +101,11 @@ export interface CheckoutResult {
|
|
|
95
101
|
/** The recipient's wallet principal — the checkout config's, echoed for convenience. */
|
|
96
102
|
recipientPrincipal: string;
|
|
97
103
|
}
|
|
98
|
-
/**
|
|
99
|
-
|
|
104
|
+
/**
|
|
105
|
+
* Typed codes for what Pybara.checkout() and open() throw before the checkout opens, as EmbeddedError's codes are for what the checkout reports once open.
|
|
106
|
+
* An amount below the minimum is not one: the checkout shows the minimum itself, in the payer's currency.
|
|
107
|
+
*/
|
|
108
|
+
export type PybaraErrorCode = 'INVALID_CONFIG' | 'GATE_REFUSED' | 'RECIPIENT_SUSPENDED' | 'CHECKOUT_FAILED';
|
|
100
109
|
export declare class PybaraError extends Error {
|
|
101
110
|
readonly code: PybaraErrorCode;
|
|
102
111
|
constructor(code: PybaraErrorCode, message: string);
|
package/dist/types.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,8IAA8I;AAC9I,MAAM,MAAM,SAAS,GAAG,QAAQ,GAAG,SAAS,GAAG,QAAQ,GAAG,WAAW,CAAC;AAEtE,iEAAiE;AACjE,MAAM,WAAW,cAAc;IAC7B,uKAAuK;IACvK,kBAAkB,EAAE,MAAM,CAAC;IAC3B,gIAAgI;IAChI,OAAO,EAAE,MAAM,CAAC;IAChB,iHAAiH;IACjH,QAAQ,EAAE,MAAM,CAAC;IACjB
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"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"}
|