@monetize.software/sdk 3.0.0-alpha.12 → 3.0.0-alpha.14
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/dist/chunks/PaywallUI-DA8Kj9fJ.js +26 -0
- package/dist/chunks/PaywallUI-DA8Kj9fJ.js.map +1 -0
- package/dist/chunks/{PaywallUI-pb7JpLr6.js → PaywallUI-vv6Hw8su.js} +1255 -1091
- package/dist/chunks/PaywallUI-vv6Hw8su.js.map +1 -0
- package/dist/core.cjs +1 -1
- package/dist/core.cjs.map +1 -1
- package/dist/core.d.ts +11 -0
- package/dist/core.js +76 -72
- package/dist/core.js.map +1 -1
- package/dist/index.cjs +1 -1
- package/dist/index.d.ts +73 -25
- package/dist/index.js +1 -1
- package/dist/ui.cjs +1 -1
- package/dist/ui.d.ts +73 -25
- package/dist/ui.js +1 -1
- package/package.json +1 -1
- package/dist/chunks/PaywallUI-CSgfmhHq.js +0 -26
- package/dist/chunks/PaywallUI-CSgfmhHq.js.map +0 -1
- package/dist/chunks/PaywallUI-pb7JpLr6.js.map +0 -1
package/dist/core.d.ts
CHANGED
|
@@ -743,6 +743,17 @@ export declare class BillingClient {
|
|
|
743
743
|
errorUrl?: string;
|
|
744
744
|
shopUrl?: string;
|
|
745
745
|
trialDays?: number;
|
|
746
|
+
/** Активный offer для этой цены — резолвится host'ом через
|
|
747
|
+
* `paywall.getOfferForPrice(priceId)?.offer.id` или
|
|
748
|
+
* `findApplicableOffer(client.getCachedOffers(), priceId)?.id`. Без
|
|
749
|
+
* явной передачи бэк сделает auto-resolve по email — но только для
|
|
750
|
+
* end_date-офферов. duration_minutes-офферы тикают в clientStorage и
|
|
751
|
+
* сервер их не видит: для них offerId ОБЯЗАН прийти от клиента, иначе
|
|
752
|
+
* скидка не применится на чекауте, хотя UI её показывал.
|
|
753
|
+
*
|
|
754
|
+
* Передавать offer-id всегда безопасно — бэк сам проверит applicable
|
|
755
|
+
* ли offer к этому юзеру (страна/email/режим) и игнорирует если нет. */
|
|
756
|
+
offerId?: string;
|
|
746
757
|
/**
|
|
747
758
|
* Stage 1 защиты от дубликатов покупок. Идемпотентный ключ запроса
|
|
748
759
|
* (UUID). Повторный вызов с тем же ключом вернёт тот же checkout-URL
|
package/dist/core.js
CHANGED
|
@@ -20,24 +20,24 @@ class E {
|
|
|
20
20
|
n.set("Accept", "application/json"), n.set("X-SDK-Version", m), n.set("X-Paywall-Id", this.opts.paywallId), this.opts.capabilities?.length && n.set("X-SDK-Capabilities", this.opts.capabilities.join(","));
|
|
21
21
|
const o = await this.opts.getAuthToken?.();
|
|
22
22
|
o && n.set("Authorization", `Bearer ${o}`);
|
|
23
|
-
const
|
|
24
|
-
e.body && !n.has("Content-Type") && !
|
|
25
|
-
let
|
|
23
|
+
const d = typeof FormData < "u" && e.body instanceof FormData;
|
|
24
|
+
e.body && !n.has("Content-Type") && !d && n.set("Content-Type", "application/json");
|
|
25
|
+
let f;
|
|
26
26
|
try {
|
|
27
|
-
|
|
27
|
+
f = await a(s, {
|
|
28
28
|
...e,
|
|
29
29
|
headers: n,
|
|
30
30
|
credentials: "omit"
|
|
31
31
|
});
|
|
32
|
-
} catch (
|
|
33
|
-
throw (
|
|
32
|
+
} catch (h) {
|
|
33
|
+
throw (h && typeof h == "object" && "name" in h ? h.name : void 0) === "AbortError" ? new r("aborted", "Request aborted", { cause: h }) : new r("network_error", "Network request failed", { cause: h });
|
|
34
34
|
}
|
|
35
|
-
const
|
|
36
|
-
if (!
|
|
37
|
-
const
|
|
38
|
-
throw new r(
|
|
35
|
+
const l = (f.headers.get("content-type") ?? "").includes("application/json") ? await f.json().catch(() => null) : null;
|
|
36
|
+
if (!f.ok) {
|
|
37
|
+
const h = l && typeof l == "object" && "code" in l && String(l.code) || `http_${f.status}`, g = l && typeof l == "object" && "message" in l && String(l.message) || f.statusText || "Request failed";
|
|
38
|
+
throw new r(h, g, { status: f.status, cause: l });
|
|
39
39
|
}
|
|
40
|
-
return
|
|
40
|
+
return l;
|
|
41
41
|
}
|
|
42
42
|
}
|
|
43
43
|
class D {
|
|
@@ -63,37 +63,37 @@ class D {
|
|
|
63
63
|
a.set("X-SDK-Version", m), a.set("X-Paywall-Id", this.paywallId), this.capabilities?.length && a.set("X-SDK-Capabilities", this.capabilities.join(","));
|
|
64
64
|
const n = await this.auth?.getAccessToken();
|
|
65
65
|
n ? a.set("Authorization", `Bearer ${n}`) : this.userId && a.set("X-User-ID", this.userId);
|
|
66
|
-
const o = typeof FormData < "u" && t.body instanceof FormData,
|
|
67
|
-
let h;
|
|
68
|
-
t.body === void 0 || t.body === null ? h = void 0 : o || u || d || f ? h = t.body : (h = JSON.stringify(t.body), a.has("Content-Type") || a.set("Content-Type", "application/json"));
|
|
69
|
-
const y = this.customFetch ?? fetch;
|
|
66
|
+
const o = typeof FormData < "u" && t.body instanceof FormData, d = typeof Blob < "u" && t.body instanceof Blob, f = typeof ReadableStream < "u" && t.body instanceof ReadableStream, p = typeof t.body == "string";
|
|
70
67
|
let c;
|
|
68
|
+
t.body === void 0 || t.body === null ? c = void 0 : o || d || f || p ? c = t.body : (c = JSON.stringify(t.body), a.has("Content-Type") || a.set("Content-Type", "application/json"));
|
|
69
|
+
const l = this.customFetch ?? fetch;
|
|
70
|
+
let h;
|
|
71
71
|
try {
|
|
72
|
-
|
|
72
|
+
h = await l(s.toString(), {
|
|
73
73
|
method: t.method ?? "POST",
|
|
74
74
|
headers: a,
|
|
75
|
-
body:
|
|
75
|
+
body: c,
|
|
76
76
|
signal: t.signal,
|
|
77
77
|
credentials: "omit"
|
|
78
78
|
});
|
|
79
|
-
} catch (
|
|
80
|
-
const P =
|
|
81
|
-
throw new r("network_error", `Network request failed: ${P}`, { cause:
|
|
79
|
+
} catch (y) {
|
|
80
|
+
const P = y instanceof Error ? y.message : String(y);
|
|
81
|
+
throw new r("network_error", `Network request failed: ${P}`, { cause: y });
|
|
82
82
|
}
|
|
83
|
-
if (
|
|
84
|
-
const
|
|
85
|
-
throw this.onQuotaExceeded?.(
|
|
83
|
+
if (h.status === 402) {
|
|
84
|
+
const y = await q(h);
|
|
85
|
+
throw this.onQuotaExceeded?.(y), y;
|
|
86
86
|
}
|
|
87
|
-
if (!
|
|
88
|
-
const
|
|
87
|
+
if (!h.ok) {
|
|
88
|
+
const y = await $(h.clone());
|
|
89
89
|
throw new r(
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
{ status:
|
|
90
|
+
y ?? `http_${h.status}`,
|
|
91
|
+
h.statusText || "Gateway request failed",
|
|
92
|
+
{ status: h.status }
|
|
93
93
|
);
|
|
94
94
|
}
|
|
95
|
-
const g =
|
|
96
|
-
return this.onChargeSuccess?.(g),
|
|
95
|
+
const g = h.headers.get("X-Query-Type") ?? void 0;
|
|
96
|
+
return this.onChargeSuccess?.(g), h;
|
|
97
97
|
}
|
|
98
98
|
}
|
|
99
99
|
async function q(i) {
|
|
@@ -198,7 +198,7 @@ const M = {
|
|
|
198
198
|
function L(i) {
|
|
199
199
|
return i || (F() ? M : typeof window < "u" && "localStorage" in window ? x : J);
|
|
200
200
|
}
|
|
201
|
-
const
|
|
201
|
+
const u = {
|
|
202
202
|
visitorId: "pw-visitor-id",
|
|
203
203
|
lastLoginMethod: (i) => `pw-${i}-last-login-method`,
|
|
204
204
|
lastLoginEmail: (i) => `pw-${i}-last-login-email`,
|
|
@@ -242,13 +242,13 @@ function C() {
|
|
|
242
242
|
}
|
|
243
243
|
async function b(i) {
|
|
244
244
|
try {
|
|
245
|
-
const e = await i.getItem(
|
|
245
|
+
const e = await i.getItem(u.visitorId);
|
|
246
246
|
if (e && typeof e == "string" && e.length >= 16) return e;
|
|
247
247
|
} catch {
|
|
248
248
|
}
|
|
249
249
|
const t = C();
|
|
250
250
|
try {
|
|
251
|
-
await i.setItem(
|
|
251
|
+
await i.setItem(u.visitorId, t);
|
|
252
252
|
} catch {
|
|
253
253
|
}
|
|
254
254
|
return t;
|
|
@@ -444,7 +444,7 @@ class yt {
|
|
|
444
444
|
async hydrateBootstrapFromStorage() {
|
|
445
445
|
if (!this.cachedBootstrap)
|
|
446
446
|
try {
|
|
447
|
-
const t = await this.storage.getItem(
|
|
447
|
+
const t = await this.storage.getItem(u.bootstrap(this.paywallId));
|
|
448
448
|
if (!t) return;
|
|
449
449
|
const e = JSON.parse(t);
|
|
450
450
|
if (!e?.bootstrap || Date.now() - e.at > _ || this.cachedBootstrap) return;
|
|
@@ -463,7 +463,7 @@ class yt {
|
|
|
463
463
|
try {
|
|
464
464
|
const { user: e, ...s } = t;
|
|
465
465
|
await this.storage.setItem(
|
|
466
|
-
|
|
466
|
+
u.bootstrap(this.paywallId),
|
|
467
467
|
JSON.stringify({ at: Date.now(), bootstrap: s })
|
|
468
468
|
);
|
|
469
469
|
} catch {
|
|
@@ -474,7 +474,7 @@ class yt {
|
|
|
474
474
|
// no-op, всё работает как раньше через сеть.
|
|
475
475
|
subscribeBootstrapStorage() {
|
|
476
476
|
typeof this.storage.watch == "function" && (this.bootstrapStorageUnwatch = this.storage.watch(
|
|
477
|
-
|
|
477
|
+
u.bootstrap(this.paywallId),
|
|
478
478
|
(t) => {
|
|
479
479
|
if (t)
|
|
480
480
|
try {
|
|
@@ -620,7 +620,7 @@ class yt {
|
|
|
620
620
|
}
|
|
621
621
|
}
|
|
622
622
|
storageKey() {
|
|
623
|
-
return
|
|
623
|
+
return u.userState(this.paywallId, B(this.identity));
|
|
624
624
|
}
|
|
625
625
|
async hydrateUserFromStorage() {
|
|
626
626
|
if (!this.cachedUser)
|
|
@@ -775,7 +775,7 @@ class yt {
|
|
|
775
775
|
}
|
|
776
776
|
}
|
|
777
777
|
balancesStorageKey() {
|
|
778
|
-
return
|
|
778
|
+
return u.balances(this.paywallId, B(this.identity));
|
|
779
779
|
}
|
|
780
780
|
async hydrateBalancesFromStorage() {
|
|
781
781
|
if (!this.cachedBalances)
|
|
@@ -832,20 +832,24 @@ class yt {
|
|
|
832
832
|
"Idempotency-Key": t.idempotencyKey ?? C()
|
|
833
833
|
};
|
|
834
834
|
this.apiKey && (n["X-Api-Key"] = this.apiKey);
|
|
835
|
-
const o = this.cachedBootstrap?.settings,
|
|
835
|
+
const o = this.cachedBootstrap?.settings, d = t.successUrl ?? o?.success_redirect_url ?? void 0, f = t.shopUrl ?? o?.checkout_shop_url ?? void 0, c = this.cachedBootstrap?.prices.find(
|
|
836
|
+
(h) => h.id === t.priceId
|
|
837
|
+
)?.local?.currency ?? void 0, l = this.api.request(`/api/v1/paywall/${this.paywallId}/start-checkout`, {
|
|
836
838
|
method: "POST",
|
|
837
839
|
headers: n,
|
|
838
840
|
signal: t.signal,
|
|
839
841
|
body: JSON.stringify({
|
|
840
842
|
email: this.identity.email,
|
|
841
843
|
priceId: Number(t.priceId),
|
|
842
|
-
|
|
844
|
+
offerId: t.offerId,
|
|
845
|
+
successUrl: d,
|
|
843
846
|
errorUrl: t.errorUrl,
|
|
844
|
-
shopUrl:
|
|
847
|
+
shopUrl: f,
|
|
845
848
|
productName: o?.checkout_product_name ?? void 0,
|
|
846
849
|
trial_days: t.trialDays,
|
|
847
850
|
ignoreActivePurchase: t.ignoreActivePurchase ? !0 : void 0,
|
|
848
|
-
userMeta: this.identity.userId ? { userId: this.identity.userId } : void 0
|
|
851
|
+
userMeta: this.identity.userId ? { userId: this.identity.userId } : void 0,
|
|
852
|
+
localCurrency: c
|
|
849
853
|
})
|
|
850
854
|
}).then((h) => ({ url: h.checkoutUrl, acquiring: h.acquiring })).catch((h) => {
|
|
851
855
|
throw h instanceof r && h.status === 409 && h.cause && typeof h.cause == "object" && h.cause.hasActivePurchase === !0 ? new r(
|
|
@@ -854,10 +858,10 @@ class yt {
|
|
|
854
858
|
{ status: 409, cause: h.cause }
|
|
855
859
|
) : h;
|
|
856
860
|
});
|
|
857
|
-
return this.inflightCheckouts.set(e,
|
|
858
|
-
this.inflightCheckouts.get(e) ===
|
|
861
|
+
return this.inflightCheckouts.set(e, l), l.finally(() => {
|
|
862
|
+
this.inflightCheckouts.get(e) === l && this.inflightCheckouts.delete(e);
|
|
859
863
|
}).catch(() => {
|
|
860
|
-
}),
|
|
864
|
+
}), l;
|
|
861
865
|
}
|
|
862
866
|
/**
|
|
863
867
|
* URL Stripe/Paddle/Chargebee customer portal — место, где залогиненный
|
|
@@ -1453,8 +1457,8 @@ class pt {
|
|
|
1453
1457
|
id: a.user.id,
|
|
1454
1458
|
email: a.user.email,
|
|
1455
1459
|
is_anonymous: a.user.is_anonymous ?? !1
|
|
1456
|
-
},
|
|
1457
|
-
return this.setSession(
|
|
1460
|
+
}, d = { ...n, user: o };
|
|
1461
|
+
return this.setSession(d, { event: "USER_UPDATED" }), await this.clearAnonRefreshToken(), { kind: "updated", session: d };
|
|
1458
1462
|
}
|
|
1459
1463
|
/**
|
|
1460
1464
|
* OAuth signin через popup с PKCE. Жизненный цикл:
|
|
@@ -1513,7 +1517,7 @@ class pt {
|
|
|
1513
1517
|
await this.hydrated, this.gcOAuthFlows();
|
|
1514
1518
|
const e = Z(), s = await tt(e), a = et(), n = {}, o = await this.getAccessToken().catch(() => null);
|
|
1515
1519
|
o && (n.Authorization = `Bearer ${o}`);
|
|
1516
|
-
const { authorize_url:
|
|
1520
|
+
const { authorize_url: d } = await this.api.request(
|
|
1517
1521
|
`/api/v1/paywall/${this.paywallId}/auth/oauth/init`,
|
|
1518
1522
|
{
|
|
1519
1523
|
method: "POST",
|
|
@@ -1531,7 +1535,7 @@ class pt {
|
|
|
1531
1535
|
userMeta: t.userMeta,
|
|
1532
1536
|
provider: t.provider,
|
|
1533
1537
|
startedAt: Date.now()
|
|
1534
|
-
}), this.recordLastLoginMethod(t.provider), { authorize_url:
|
|
1538
|
+
}), this.recordLastLoginMethod(t.provider), { authorize_url: d, state: a };
|
|
1535
1539
|
}
|
|
1536
1540
|
/**
|
|
1537
1541
|
* Шаг 2 OAuth split-API: обменивает code (полученный из popup) на session,
|
|
@@ -1718,7 +1722,7 @@ class pt {
|
|
|
1718
1722
|
}
|
|
1719
1723
|
}
|
|
1720
1724
|
storageKey() {
|
|
1721
|
-
return
|
|
1725
|
+
return u.authSession(this.paywallId);
|
|
1722
1726
|
}
|
|
1723
1727
|
async hydrate() {
|
|
1724
1728
|
try {
|
|
@@ -1772,7 +1776,7 @@ class pt {
|
|
|
1772
1776
|
}
|
|
1773
1777
|
async readAnonRefreshToken() {
|
|
1774
1778
|
try {
|
|
1775
|
-
const t = await this.storage.getItem(
|
|
1779
|
+
const t = await this.storage.getItem(u.anonRefreshToken(this.paywallId));
|
|
1776
1780
|
return typeof t == "string" && t.length > 0 ? t : null;
|
|
1777
1781
|
} catch {
|
|
1778
1782
|
return null;
|
|
@@ -1781,7 +1785,7 @@ class pt {
|
|
|
1781
1785
|
async writeAnonRefreshToken(t) {
|
|
1782
1786
|
try {
|
|
1783
1787
|
await this.storage.setItem(
|
|
1784
|
-
|
|
1788
|
+
u.anonRefreshToken(this.paywallId),
|
|
1785
1789
|
t
|
|
1786
1790
|
);
|
|
1787
1791
|
} catch {
|
|
@@ -1790,7 +1794,7 @@ class pt {
|
|
|
1790
1794
|
async clearAnonRefreshToken() {
|
|
1791
1795
|
try {
|
|
1792
1796
|
await this.storage.removeItem(
|
|
1793
|
-
|
|
1797
|
+
u.anonRefreshToken(this.paywallId)
|
|
1794
1798
|
);
|
|
1795
1799
|
} catch {
|
|
1796
1800
|
}
|
|
@@ -1803,8 +1807,8 @@ class pt {
|
|
|
1803
1807
|
async getLastLogin() {
|
|
1804
1808
|
try {
|
|
1805
1809
|
const [t, e] = await Promise.all([
|
|
1806
|
-
this.storage.getItem(
|
|
1807
|
-
this.storage.getItem(
|
|
1810
|
+
this.storage.getItem(u.lastLoginMethod(this.paywallId)),
|
|
1811
|
+
this.storage.getItem(u.lastLoginEmail(this.paywallId))
|
|
1808
1812
|
]);
|
|
1809
1813
|
return !t || !ot(t) ? null : { method: t, email: typeof e == "string" && e ? e : null };
|
|
1810
1814
|
} catch {
|
|
@@ -1818,11 +1822,11 @@ class pt {
|
|
|
1818
1822
|
this.recordLastLoginMethod(t), e && this.recordLastLoginEmail(e);
|
|
1819
1823
|
}
|
|
1820
1824
|
recordLastLoginMethod(t) {
|
|
1821
|
-
this.storage.setItem(
|
|
1825
|
+
this.storage.setItem(u.lastLoginMethod(this.paywallId), t).catch(() => {
|
|
1822
1826
|
});
|
|
1823
1827
|
}
|
|
1824
1828
|
recordLastLoginEmail(t) {
|
|
1825
|
-
this.storage.setItem(
|
|
1829
|
+
this.storage.setItem(u.lastLoginEmail(this.paywallId), t).catch(() => {
|
|
1826
1830
|
});
|
|
1827
1831
|
}
|
|
1828
1832
|
/**
|
|
@@ -1834,7 +1838,7 @@ class pt {
|
|
|
1834
1838
|
*/
|
|
1835
1839
|
async readVisitorId() {
|
|
1836
1840
|
try {
|
|
1837
|
-
const t = await this.storage.getItem(
|
|
1841
|
+
const t = await this.storage.getItem(u.visitorId);
|
|
1838
1842
|
return typeof t == "string" && t.length >= 16 ? t : void 0;
|
|
1839
1843
|
} catch {
|
|
1840
1844
|
return;
|
|
@@ -1846,19 +1850,19 @@ function rt(i, t) {
|
|
|
1846
1850
|
return new Promise((e, s) => {
|
|
1847
1851
|
let a = !1;
|
|
1848
1852
|
const n = () => {
|
|
1849
|
-
a = !0, window.removeEventListener("message", o), clearInterval(
|
|
1850
|
-
}, o = (
|
|
1853
|
+
a = !0, window.removeEventListener("message", o), clearInterval(d), clearTimeout(f);
|
|
1854
|
+
}, o = (p) => {
|
|
1851
1855
|
if (a) return;
|
|
1852
|
-
const
|
|
1853
|
-
if (!(!
|
|
1854
|
-
if (
|
|
1856
|
+
const c = p.data;
|
|
1857
|
+
if (!(!c || c.type !== "pw-oauth") && c.messageId === t) {
|
|
1858
|
+
if (c.status === "success" && c.code) {
|
|
1855
1859
|
n();
|
|
1856
1860
|
try {
|
|
1857
1861
|
i.close();
|
|
1858
1862
|
} catch {
|
|
1859
1863
|
}
|
|
1860
|
-
e(
|
|
1861
|
-
} else if (
|
|
1864
|
+
e(c.code);
|
|
1865
|
+
} else if (c.status === "error") {
|
|
1862
1866
|
n();
|
|
1863
1867
|
try {
|
|
1864
1868
|
i.close();
|
|
@@ -1867,21 +1871,21 @@ function rt(i, t) {
|
|
|
1867
1871
|
s(
|
|
1868
1872
|
new r(
|
|
1869
1873
|
"oauth_failed",
|
|
1870
|
-
|
|
1874
|
+
c.description || c.error || "OAuth provider returned error"
|
|
1871
1875
|
)
|
|
1872
1876
|
);
|
|
1873
1877
|
}
|
|
1874
1878
|
}
|
|
1875
|
-
},
|
|
1879
|
+
}, d = setInterval(() => {
|
|
1876
1880
|
if (a) return;
|
|
1877
|
-
let
|
|
1881
|
+
let p;
|
|
1878
1882
|
try {
|
|
1879
|
-
|
|
1883
|
+
p = i.closed;
|
|
1880
1884
|
} catch {
|
|
1881
1885
|
return;
|
|
1882
1886
|
}
|
|
1883
|
-
|
|
1884
|
-
}, nt),
|
|
1887
|
+
p && (n(), s(new r("oauth_cancelled", "auth popup was closed")));
|
|
1888
|
+
}, nt), f = setTimeout(() => {
|
|
1885
1889
|
if (!a) {
|
|
1886
1890
|
n();
|
|
1887
1891
|
try {
|
|
@@ -2050,7 +2054,7 @@ export {
|
|
|
2050
2054
|
r as PaywallError,
|
|
2051
2055
|
R as QuotaExceededError,
|
|
2052
2056
|
m as SDK_VERSION,
|
|
2053
|
-
|
|
2057
|
+
u as STORAGE_KEYS,
|
|
2054
2058
|
L as createStorage,
|
|
2055
2059
|
b as ensureVisitorId,
|
|
2056
2060
|
wt as findApplicableOffer,
|