@monetize.software/sdk-extension 3.0.0-alpha.1 → 3.0.0-alpha.2
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/{chrome-port-BXHR4SOG.js → chrome-port-DPFUj1MP.js} +144 -98
- package/dist/chunks/chrome-port-DPFUj1MP.js.map +1 -0
- package/dist/chunks/{chrome-port-EtYqHf3p.js → chrome-port-MoMohiHB.js} +2 -2
- package/dist/chunks/chrome-port-MoMohiHB.js.map +1 -0
- package/dist/content.cjs +2 -2
- package/dist/content.cjs.map +1 -1
- package/dist/content.js +37 -17
- package/dist/content.js.map +1 -1
- package/dist/offscreen.cjs +1 -1
- package/dist/offscreen.js +1 -1
- package/package.json +1 -1
- package/dist/chunks/chrome-port-BXHR4SOG.js.map +0 -1
- package/dist/chunks/chrome-port-EtYqHf3p.js.map +0 -1
|
@@ -10,14 +10,14 @@ class N extends o {
|
|
|
10
10
|
}), this.name = "QuotaExceededError", this.balances = t.balances, this.queryType = t.queryType, this.currentBalance = t.currentBalance;
|
|
11
11
|
}
|
|
12
12
|
}
|
|
13
|
-
const
|
|
14
|
-
class
|
|
13
|
+
const m = "3.0.0-alpha.0";
|
|
14
|
+
class P {
|
|
15
15
|
constructor(t) {
|
|
16
16
|
this.opts = t;
|
|
17
17
|
}
|
|
18
18
|
async request(t, e = {}) {
|
|
19
19
|
const s = new URL(t, this.opts.apiOrigin).toString(), a = this.opts.fetch ?? fetch, n = new Headers(e.headers);
|
|
20
|
-
n.set("Accept", "application/json"), n.set("X-SDK-Version",
|
|
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 r = await this.opts.getAuthToken?.();
|
|
22
22
|
r && n.set("Authorization", `Bearer ${r}`);
|
|
23
23
|
const l = typeof FormData < "u" && e.body instanceof FormData;
|
|
@@ -40,10 +40,10 @@ class L {
|
|
|
40
40
|
return f;
|
|
41
41
|
}
|
|
42
42
|
}
|
|
43
|
-
function
|
|
43
|
+
function D() {
|
|
44
44
|
return typeof chrome < "u" && !!chrome?.storage?.local && !!chrome?.runtime?.id;
|
|
45
45
|
}
|
|
46
|
-
const
|
|
46
|
+
const x = {
|
|
47
47
|
getItem(i) {
|
|
48
48
|
return new Promise((t) => {
|
|
49
49
|
chrome.storage.local.get([i], (e) => {
|
|
@@ -73,7 +73,7 @@ const D = {
|
|
|
73
73
|
};
|
|
74
74
|
return e.addListener(s), () => e.removeListener(s);
|
|
75
75
|
}
|
|
76
|
-
},
|
|
76
|
+
}, J = {
|
|
77
77
|
async getItem(i) {
|
|
78
78
|
try {
|
|
79
79
|
return window.localStorage.getItem(i);
|
|
@@ -101,19 +101,19 @@ const D = {
|
|
|
101
101
|
};
|
|
102
102
|
return window.addEventListener("storage", e), () => window.removeEventListener("storage", e);
|
|
103
103
|
}
|
|
104
|
-
},
|
|
104
|
+
}, b = /* @__PURE__ */ new Map(), H = {
|
|
105
105
|
async getItem(i) {
|
|
106
|
-
return
|
|
106
|
+
return b.get(i) ?? null;
|
|
107
107
|
},
|
|
108
108
|
async setItem(i, t) {
|
|
109
|
-
|
|
109
|
+
b.set(i, t);
|
|
110
110
|
},
|
|
111
111
|
async removeItem(i) {
|
|
112
|
-
|
|
112
|
+
b.delete(i);
|
|
113
113
|
}
|
|
114
114
|
};
|
|
115
|
-
function
|
|
116
|
-
return i || (
|
|
115
|
+
function R(i) {
|
|
116
|
+
return i || (D() ? x : typeof window < "u" && "localStorage" in window ? J : H);
|
|
117
117
|
}
|
|
118
118
|
const y = {
|
|
119
119
|
visitorId: "pw-visitor-id",
|
|
@@ -145,7 +145,7 @@ const y = {
|
|
|
145
145
|
// (оптимистично через `decrementBalanceLocal`).
|
|
146
146
|
balances: (i, t) => `pw-${i}-${t}-balances-v1`
|
|
147
147
|
};
|
|
148
|
-
function
|
|
148
|
+
function M() {
|
|
149
149
|
const i = typeof globalThis < "u" ? globalThis.crypto : void 0;
|
|
150
150
|
if (i && typeof i.randomUUID == "function") return i.randomUUID();
|
|
151
151
|
const t = new Uint8Array(16);
|
|
@@ -157,13 +157,13 @@ function R() {
|
|
|
157
157
|
const e = Array.from(t, (s) => s.toString(16).padStart(2, "0")).join("");
|
|
158
158
|
return `${e.slice(0, 8)}-${e.slice(8, 12)}-${e.slice(12, 16)}-${e.slice(16, 20)}-${e.slice(20)}`;
|
|
159
159
|
}
|
|
160
|
-
async function
|
|
160
|
+
async function B(i) {
|
|
161
161
|
try {
|
|
162
162
|
const e = await i.getItem(y.visitorId);
|
|
163
163
|
if (e && typeof e == "string" && e.length >= 16) return e;
|
|
164
164
|
} catch {
|
|
165
165
|
}
|
|
166
|
-
const t =
|
|
166
|
+
const t = M();
|
|
167
167
|
try {
|
|
168
168
|
await i.setItem(y.visitorId, t);
|
|
169
169
|
} catch {
|
|
@@ -178,30 +178,30 @@ function q(i) {
|
|
|
178
178
|
for (let s = 0; s < i; s++) t[s] = Math.floor(Math.random() * 256);
|
|
179
179
|
return t;
|
|
180
180
|
}
|
|
181
|
-
function
|
|
181
|
+
function I(i) {
|
|
182
182
|
let t = "";
|
|
183
183
|
for (let e = 0; e < i.length; e++) t += String.fromCharCode(i[e]);
|
|
184
184
|
return btoa(t).replace(/\+/g, "-").replace(/\//g, "_").replace(/=+$/, "");
|
|
185
185
|
}
|
|
186
|
-
function
|
|
187
|
-
return
|
|
186
|
+
function V() {
|
|
187
|
+
return I(q(64));
|
|
188
188
|
}
|
|
189
|
-
async function
|
|
189
|
+
async function j(i) {
|
|
190
190
|
const t = new TextEncoder().encode(i), e = globalThis.crypto;
|
|
191
191
|
if (!e?.subtle?.digest)
|
|
192
192
|
throw new Error("crypto.subtle is required for PKCE");
|
|
193
193
|
const s = await e.subtle.digest("SHA-256", t);
|
|
194
|
-
return
|
|
194
|
+
return I(new Uint8Array(s));
|
|
195
195
|
}
|
|
196
|
-
function
|
|
197
|
-
return
|
|
196
|
+
function X() {
|
|
197
|
+
return I(q(16));
|
|
198
198
|
}
|
|
199
|
-
const
|
|
199
|
+
const z = "https://appbox.space", G = 6e4, Q = 600 * 1e3;
|
|
200
200
|
class mt {
|
|
201
201
|
constructor(t) {
|
|
202
202
|
if (this.session = null, this.inflightRefresh = null, this.inflightAnonSignin = null, this.listeners = /* @__PURE__ */ new Set(), this.storageUnwatch = null, this.destroyed = !1, this.oauthFlows = /* @__PURE__ */ new Map(), !t.paywallId)
|
|
203
203
|
throw new o("invalid_config", "paywallId is required");
|
|
204
|
-
this.paywallId = t.paywallId, this.apiOrigin = t.apiOrigin ??
|
|
204
|
+
this.paywallId = t.paywallId, this.apiOrigin = t.apiOrigin ?? z, this.storage = R(t.storage), this.api = new P({
|
|
205
205
|
apiOrigin: this.apiOrigin,
|
|
206
206
|
paywallId: t.paywallId,
|
|
207
207
|
fetch: t.fetch
|
|
@@ -596,7 +596,7 @@ class mt {
|
|
|
596
596
|
"browser blocked auth popup — call from a user gesture"
|
|
597
597
|
);
|
|
598
598
|
t.onPopupOpened?.();
|
|
599
|
-
const n = await
|
|
599
|
+
const n = await Z(a, s);
|
|
600
600
|
if (this.destroyed)
|
|
601
601
|
throw this.oauthFlows.delete(s), new o("aborted", "AuthClient destroyed mid-flow");
|
|
602
602
|
return this.completeOAuthFlow({ state: s, code: n });
|
|
@@ -617,7 +617,7 @@ class mt {
|
|
|
617
617
|
*/
|
|
618
618
|
async startOAuthFlow(t) {
|
|
619
619
|
await this.hydrated, this.gcOAuthFlows();
|
|
620
|
-
const e =
|
|
620
|
+
const e = V(), s = await j(e), a = X(), n = {}, r = await this.getAccessToken().catch(() => null);
|
|
621
621
|
r && (n.Authorization = `Bearer ${r}`);
|
|
622
622
|
const { authorize_url: l } = await this.api.request(
|
|
623
623
|
`/api/v1/paywall/${this.paywallId}/auth/oauth/init`,
|
|
@@ -674,7 +674,7 @@ class mt {
|
|
|
674
674
|
return this.setSession(n), n;
|
|
675
675
|
}
|
|
676
676
|
gcOAuthFlows() {
|
|
677
|
-
const t = Date.now() -
|
|
677
|
+
const t = Date.now() - Q;
|
|
678
678
|
for (const [e, s] of this.oauthFlows)
|
|
679
679
|
s.startedAt < t && this.oauthFlows.delete(e);
|
|
680
680
|
}
|
|
@@ -785,7 +785,7 @@ class mt {
|
|
|
785
785
|
};
|
|
786
786
|
}
|
|
787
787
|
isFresh(t) {
|
|
788
|
-
return t.expires_at - Date.now() >
|
|
788
|
+
return t.expires_at - Date.now() > G;
|
|
789
789
|
}
|
|
790
790
|
toSession(t, e) {
|
|
791
791
|
const s = t.expires_at != null ? t.expires_at * 1e3 : Date.now() + t.expires_in * 1e3;
|
|
@@ -799,7 +799,7 @@ class mt {
|
|
|
799
799
|
setSession(t, e = {}) {
|
|
800
800
|
if (this.destroyed) return;
|
|
801
801
|
const s = this.session;
|
|
802
|
-
this.session = t, e.skipPersist || this.persist(),
|
|
802
|
+
this.session = t, e.skipPersist || this.persist(), tt(s, t) || this.emit();
|
|
803
803
|
}
|
|
804
804
|
emit() {
|
|
805
805
|
for (const t of this.listeners)
|
|
@@ -903,8 +903,8 @@ class mt {
|
|
|
903
903
|
}
|
|
904
904
|
}
|
|
905
905
|
}
|
|
906
|
-
const
|
|
907
|
-
function
|
|
906
|
+
const W = 5 * 6e4, Y = 500;
|
|
907
|
+
function Z(i, t) {
|
|
908
908
|
return new Promise((e, s) => {
|
|
909
909
|
let a = !1;
|
|
910
910
|
const n = () => {
|
|
@@ -943,7 +943,7 @@ function Y(i, t) {
|
|
|
943
943
|
return;
|
|
944
944
|
}
|
|
945
945
|
d && (n(), s(new o("oauth_cancelled", "auth popup was closed")));
|
|
946
|
-
},
|
|
946
|
+
}, Y), u = setTimeout(() => {
|
|
947
947
|
if (!a) {
|
|
948
948
|
n();
|
|
949
949
|
try {
|
|
@@ -952,19 +952,19 @@ function Y(i, t) {
|
|
|
952
952
|
}
|
|
953
953
|
s(new o("oauth_timeout", "OAuth flow timed out"));
|
|
954
954
|
}
|
|
955
|
-
},
|
|
955
|
+
}, W);
|
|
956
956
|
window.addEventListener("message", r);
|
|
957
957
|
});
|
|
958
958
|
}
|
|
959
|
-
function
|
|
959
|
+
function tt(i, t) {
|
|
960
960
|
return i === t ? !0 : !i || !t ? !1 : i.access_token === t.access_token && i.refresh_token === t.refresh_token && i.expires_at === t.expires_at && i.user.id === t.user.id && i.user.email === t.user.email;
|
|
961
961
|
}
|
|
962
|
-
const
|
|
963
|
-
class
|
|
962
|
+
const et = "https://appbox.space";
|
|
963
|
+
class st {
|
|
964
964
|
constructor(t) {
|
|
965
965
|
if (!t.paywallId)
|
|
966
966
|
throw new o("invalid_config", "paywallId is required");
|
|
967
|
-
this.paywallId = t.paywallId, this.apiOrigin = t.apiOrigin ??
|
|
967
|
+
this.paywallId = t.paywallId, this.apiOrigin = t.apiOrigin ?? et, this.auth = t.auth, this.userId = t.userId, this.capabilities = t.capabilities, this.customFetch = t.fetch, this.onChargeSuccess = t.onChargeSuccess, this.onQuotaExceeded = t.onQuotaExceeded, t.userId && !t.auth && typeof window < "u" && typeof window.document < "u" && console.warn(
|
|
968
968
|
"[paywall] WARNING: ApiGatewayClient.userId set without auth in browser. Client can spoof userId. Use AuthClient + Bearer for trusted user.id."
|
|
969
969
|
);
|
|
970
970
|
}
|
|
@@ -975,7 +975,7 @@ class et {
|
|
|
975
975
|
);
|
|
976
976
|
s.searchParams.set("paywall_id", this.paywallId);
|
|
977
977
|
const a = new Headers(t.headers);
|
|
978
|
-
a.set("X-SDK-Version",
|
|
978
|
+
a.set("X-SDK-Version", m), a.set("X-Paywall-Id", this.paywallId), this.capabilities?.length && a.set("X-SDK-Capabilities", this.capabilities.join(","));
|
|
979
979
|
const n = await this.auth?.getAccessToken();
|
|
980
980
|
n ? a.set("Authorization", `Bearer ${n}`) : this.userId && a.set("X-User-ID", this.userId);
|
|
981
981
|
const r = typeof FormData < "u" && t.body instanceof FormData, l = typeof Blob < "u" && t.body instanceof Blob, u = typeof ReadableStream < "u" && t.body instanceof ReadableStream, d = typeof t.body == "string";
|
|
@@ -996,11 +996,11 @@ class et {
|
|
|
996
996
|
throw new o("network_error", `Network request failed: ${K}`, { cause: p });
|
|
997
997
|
}
|
|
998
998
|
if (h.status === 402) {
|
|
999
|
-
const p = await
|
|
999
|
+
const p = await it(h);
|
|
1000
1000
|
throw this.onQuotaExceeded?.(p), p;
|
|
1001
1001
|
}
|
|
1002
1002
|
if (!h.ok) {
|
|
1003
|
-
const p = await
|
|
1003
|
+
const p = await at(h.clone());
|
|
1004
1004
|
throw new o(
|
|
1005
1005
|
p ?? `http_${h.status}`,
|
|
1006
1006
|
h.statusText || "Gateway request failed",
|
|
@@ -1011,7 +1011,7 @@ class et {
|
|
|
1011
1011
|
return this.onChargeSuccess?.(g), h;
|
|
1012
1012
|
}
|
|
1013
1013
|
}
|
|
1014
|
-
async function
|
|
1014
|
+
async function it(i) {
|
|
1015
1015
|
let t = {};
|
|
1016
1016
|
try {
|
|
1017
1017
|
t = await i.json();
|
|
@@ -1029,7 +1029,7 @@ async function st(i) {
|
|
|
1029
1029
|
currentBalance: t.details?.currentBalance ?? null
|
|
1030
1030
|
});
|
|
1031
1031
|
}
|
|
1032
|
-
async function
|
|
1032
|
+
async function at(i) {
|
|
1033
1033
|
if (!(i.headers.get("content-type") ?? "").includes("application/json")) return null;
|
|
1034
1034
|
try {
|
|
1035
1035
|
const e = await i.json();
|
|
@@ -1038,7 +1038,7 @@ async function it(i) {
|
|
|
1038
1038
|
return null;
|
|
1039
1039
|
}
|
|
1040
1040
|
}
|
|
1041
|
-
const
|
|
1041
|
+
const nt = 5e3, rt = 30 * 6e4, _ = 60 * 6e4, ot = 5 * 6e4, k = {
|
|
1042
1042
|
has_active_subscription: !1,
|
|
1043
1043
|
purchases: [],
|
|
1044
1044
|
trial: null
|
|
@@ -1046,27 +1046,27 @@ const at = 5e3, nt = 30 * 6e4, B = 60 * 6e4, rt = 5 * 6e4, k = {
|
|
|
1046
1046
|
function A(i) {
|
|
1047
1047
|
return i && (i.email || i.userId || i.anonymousId) || "guest";
|
|
1048
1048
|
}
|
|
1049
|
-
function
|
|
1049
|
+
function ct(i, t) {
|
|
1050
1050
|
return i === t ? !0 : !i || !t ? !1 : JSON.stringify(i) === JSON.stringify(t);
|
|
1051
1051
|
}
|
|
1052
|
-
const
|
|
1053
|
-
function
|
|
1052
|
+
const ht = 5e3, T = 5 * 6e4, lt = 3e4;
|
|
1053
|
+
function ut(i, t) {
|
|
1054
1054
|
if (i === t) return !0;
|
|
1055
1055
|
if (!i || !t || i.length !== t.length) return !1;
|
|
1056
1056
|
for (let e = 0; e < i.length; e++)
|
|
1057
1057
|
if (i[e].type !== t[e].type || i[e].count !== t[e].count) return !1;
|
|
1058
1058
|
return !0;
|
|
1059
1059
|
}
|
|
1060
|
-
const
|
|
1060
|
+
const dt = "https://appbox.space";
|
|
1061
1061
|
class bt {
|
|
1062
1062
|
constructor(t) {
|
|
1063
|
-
if (this.cachedBootstrap = null, this.cachedBootstrapAt = 0, this.inflightBootstrap = null, this.bootstrapListeners = /* @__PURE__ */ new Set(), this.bootstrapStorageUnwatch = null, this.authUnsubscribe = null, this.cachedUser = null, this.cachedUserAt = 0, this.inflightUser = null, this.userListeners = /* @__PURE__ */ new Set(), this.visitorIdPromise = null, this.visitorId = null, this.inflightCheckouts = /* @__PURE__ */ new Map(), this.cachedBalances = null, this.cachedBalancesAt = 0, this.balancesStorageUnwatch = null, this.inflightBalances = null, this.balanceListeners = /* @__PURE__ */ new Set(), !t.paywallId)
|
|
1063
|
+
if (this.cachedBootstrap = null, this.cachedBootstrapAt = 0, this.inflightBootstrap = null, this.bootstrapListeners = /* @__PURE__ */ new Set(), this.bootstrapStorageUnwatch = null, this.authUnsubscribe = null, this.cachedUser = null, this.cachedUserAt = 0, this.inflightUser = null, this.userListeners = /* @__PURE__ */ new Set(), this.visitorIdPromise = null, this.visitorId = null, this.inflightCheckouts = /* @__PURE__ */ new Map(), this.cachedBalances = null, this.cachedBalancesAt = 0, this.balancesStorageUnwatch = null, this.inflightBalances = null, this.balanceListeners = /* @__PURE__ */ new Set(), this.previewVersionCounter = 0, !t.paywallId)
|
|
1064
1064
|
throw new o("invalid_config", "paywallId is required");
|
|
1065
|
-
this.paywallId = t.paywallId, this.apiOrigin = t.apiOrigin ??
|
|
1065
|
+
this.paywallId = t.paywallId, this.apiOrigin = t.apiOrigin ?? dt, this.capabilities = t.capabilities, this.auth = t.auth, this.previewMode = t.preview === !0;
|
|
1066
1066
|
const e = t.auth?.getCachedUser();
|
|
1067
1067
|
this.identity = t.identity ?? (e ? U(e) : void 0), this.apiKey = t.apiKey, this.fetchImpl = t.fetch, t.apiKey && typeof window < "u" && typeof window.document < "u" && console.error(
|
|
1068
1068
|
"[paywall] SECURITY: BillingClient.apiKey detected in browser context. This is a server-SDK key and exposes your account. Remove apiKey or move BillingClient to a trusted backend."
|
|
1069
|
-
), this.storage =
|
|
1069
|
+
), this.storage = R(t.storage), this.api = new P({
|
|
1070
1070
|
apiOrigin: this.apiOrigin,
|
|
1071
1071
|
paywallId: t.paywallId,
|
|
1072
1072
|
capabilities: t.capabilities,
|
|
@@ -1077,8 +1077,8 @@ class bt {
|
|
|
1077
1077
|
getAuthToken: t.auth ? () => t.auth.getAccessToken() : void 0
|
|
1078
1078
|
}), t.auth && (this.authUnsubscribe = t.auth.onAuthChange((s) => {
|
|
1079
1079
|
const a = s ? U(s.user) : void 0;
|
|
1080
|
-
|
|
1081
|
-
})), this.hydrateUserFromStorage(), this.hydrateBootstrapFromStorage(), this.subscribeBootstrapStorage(), this.hydrateBalancesFromStorage(), this.subscribeBalancesStorage(), this.visitorIdPromise =
|
|
1080
|
+
ft(this.identity, a) || this.setIdentity(a);
|
|
1081
|
+
})), this.hydrateUserFromStorage(), this.hydrateBootstrapFromStorage(), this.subscribeBootstrapStorage(), this.hydrateBalancesFromStorage(), this.subscribeBalancesStorage(), this.visitorIdPromise = B(this.storage).then((s) => (this.visitorId = s, s));
|
|
1082
1082
|
}
|
|
1083
1083
|
/**
|
|
1084
1084
|
* Stable visitor_id (UUID v4). Первый вызов awaitит первичный резолв из
|
|
@@ -1086,7 +1086,7 @@ class bt {
|
|
|
1086
1086
|
* EventTracker'ом для атрибуции аналитики.
|
|
1087
1087
|
*/
|
|
1088
1088
|
async getVisitorId() {
|
|
1089
|
-
return this.visitorId ? this.visitorId : (this.visitorIdPromise || (this.visitorIdPromise =
|
|
1089
|
+
return this.visitorId ? this.visitorId : (this.visitorIdPromise || (this.visitorIdPromise = B(this.storage).then((t) => (this.visitorId = t, t))), this.visitorIdPromise);
|
|
1090
1090
|
}
|
|
1091
1091
|
/** Sync-доступ к visitor_id. null если ещё не зарезолвили (первые ms жизни). */
|
|
1092
1092
|
getCachedVisitorId() {
|
|
@@ -1114,8 +1114,16 @@ class bt {
|
|
|
1114
1114
|
return this.storage;
|
|
1115
1115
|
}
|
|
1116
1116
|
async bootstrap(t = !1) {
|
|
1117
|
-
const e = typeof t == "boolean" ? { force: t } : t
|
|
1118
|
-
|
|
1117
|
+
const e = typeof t == "boolean" ? { force: t } : t;
|
|
1118
|
+
if (this.previewMode) {
|
|
1119
|
+
if (this.cachedBootstrap) return this.cachedBootstrap;
|
|
1120
|
+
throw new o(
|
|
1121
|
+
"invalid_config",
|
|
1122
|
+
"BillingClient in preview mode but cachedBootstrap is not seeded. Call setBootstrap(bootstrap) before open()."
|
|
1123
|
+
);
|
|
1124
|
+
}
|
|
1125
|
+
const s = Date.now(), a = this.cachedBootstrap && this.cachedBootstrapAt > 0 && s - this.cachedBootstrapAt < _;
|
|
1126
|
+
return !e.force && a ? (s - this.cachedBootstrapAt > ot && this.revalidateBootstrap(e.signal).catch(() => {
|
|
1119
1127
|
}), this.cachedBootstrap) : this.inflightBootstrap ? this.inflightBootstrap : (this.inflightBootstrap = this.fetchBootstrap({
|
|
1120
1128
|
ifVersion: e.force ? void 0 : this.cachedBootstrap?.version,
|
|
1121
1129
|
signal: e.signal
|
|
@@ -1134,6 +1142,44 @@ class bt {
|
|
|
1134
1142
|
this.bootstrapListeners.delete(t);
|
|
1135
1143
|
};
|
|
1136
1144
|
}
|
|
1145
|
+
/**
|
|
1146
|
+
* Заменить cachedBootstrap частичными или полными данными и эмитнуть всем
|
|
1147
|
+
* подписчикам. Используется host'ом в preview-mode (редактор админки) для
|
|
1148
|
+
* live-обновления открытой модалки без сетевого revalidate'а.
|
|
1149
|
+
*
|
|
1150
|
+
* Поведение:
|
|
1151
|
+
* - Без `cachedBootstrap` ожидаются как минимум `settings` + `prices` —
|
|
1152
|
+
* иначе PaywallRoot не сможет отрендерить тарифы и упадёт.
|
|
1153
|
+
* - С существующим кешем партиал мёрджится поверх: `settings` глубокий мёрдж
|
|
1154
|
+
* на 1 уровень (поля настроек), массивы `prices`/`offers` перезаписываются.
|
|
1155
|
+
* - Каждый вызов бампит `version` ("preview:<n>"), чтобы applyBootstrap'овая
|
|
1156
|
+
* проверка `versionChanged` всегда срабатывала и listener'ы дёргались.
|
|
1157
|
+
* - Persist в storage НЕ делаем — preview не должен утекать в другие вкладки.
|
|
1158
|
+
*
|
|
1159
|
+
* В non-preview режиме метод доступен, но это редкий путь (например, для
|
|
1160
|
+
* тестов host'а) — production-код должен полагаться на bootstrap() + revalidate.
|
|
1161
|
+
*/
|
|
1162
|
+
setBootstrap(t) {
|
|
1163
|
+
const e = this.cachedBootstrap ?? {
|
|
1164
|
+
settings: { id: this.paywallId, name: "" },
|
|
1165
|
+
prices: [],
|
|
1166
|
+
offers: []
|
|
1167
|
+
}, s = {
|
|
1168
|
+
...e,
|
|
1169
|
+
...t,
|
|
1170
|
+
settings: t.settings !== void 0 ? { ...e.settings, ...t.settings } : e.settings,
|
|
1171
|
+
prices: t.prices !== void 0 ? t.prices : e.prices,
|
|
1172
|
+
offers: t.offers !== void 0 ? t.offers : e.offers,
|
|
1173
|
+
version: `preview:${++this.previewVersionCounter}`
|
|
1174
|
+
};
|
|
1175
|
+
s.layout || (s.layout = O(s.settings, s.prices)), w(s), this.cachedBootstrap = s, this.cachedBootstrapAt = Date.now();
|
|
1176
|
+
for (const a of this.bootstrapListeners)
|
|
1177
|
+
try {
|
|
1178
|
+
a(s);
|
|
1179
|
+
} catch (n) {
|
|
1180
|
+
console.warn("[paywall] onBootstrapChange listener threw", n);
|
|
1181
|
+
}
|
|
1182
|
+
}
|
|
1137
1183
|
// Network primitive — единая точка для force-запроса, revalidate'а и
|
|
1138
1184
|
// первого холодного bootstrap'а. `ifVersion` шлёт server-side short-circuit:
|
|
1139
1185
|
// если совпала — бэк отвечает `{unchanged: true, version, user}` и мы лишь
|
|
@@ -1148,7 +1194,7 @@ class bt {
|
|
|
1148
1194
|
if ("unchanged" in a && a.unchanged)
|
|
1149
1195
|
return this.cachedBootstrap ? (this.cachedBootstrapAt = Date.now(), a.user && this.applyUser(a.user), this.cachedBootstrap) : this.fetchBootstrap({ signal: t.signal });
|
|
1150
1196
|
const n = a;
|
|
1151
|
-
return n.layout || (n.layout =
|
|
1197
|
+
return n.layout || (n.layout = O(n.settings, n.prices)), w(n), this.applyBootstrap(n, { persist: !0 }), n.user && this.applyUser(n.user), n;
|
|
1152
1198
|
}
|
|
1153
1199
|
// Фоновый revalidate из stale-while-revalidate ветки. Дедуплицируется через
|
|
1154
1200
|
// `inflightBootstrap`, чтобы параллельные revalidate'ы не пересекались.
|
|
@@ -1181,8 +1227,8 @@ class bt {
|
|
|
1181
1227
|
const t = await this.storage.getItem(y.bootstrap(this.paywallId));
|
|
1182
1228
|
if (!t) return;
|
|
1183
1229
|
const e = JSON.parse(t);
|
|
1184
|
-
if (!e?.bootstrap || Date.now() - e.at >
|
|
1185
|
-
|
|
1230
|
+
if (!e?.bootstrap || Date.now() - e.at > _ || this.cachedBootstrap) return;
|
|
1231
|
+
w(e.bootstrap), this.cachedBootstrap = e.bootstrap, this.cachedBootstrapAt = e.at;
|
|
1186
1232
|
for (const s of this.bootstrapListeners)
|
|
1187
1233
|
try {
|
|
1188
1234
|
s(e.bootstrap);
|
|
@@ -1218,7 +1264,7 @@ class bt {
|
|
|
1218
1264
|
this.cachedBootstrapAt = e.at;
|
|
1219
1265
|
return;
|
|
1220
1266
|
}
|
|
1221
|
-
|
|
1267
|
+
w(e.bootstrap), this.applyBootstrap(e.bootstrap, { persist: !1 });
|
|
1222
1268
|
} catch {
|
|
1223
1269
|
}
|
|
1224
1270
|
}
|
|
@@ -1265,7 +1311,7 @@ class bt {
|
|
|
1265
1311
|
* есть `navigator.language`.
|
|
1266
1312
|
*/
|
|
1267
1313
|
getUserLanguage() {
|
|
1268
|
-
const t = typeof navigator < "u" && navigator.language ? navigator.language : null, e = this.cachedBootstrap?.settings.locale_default ?? null, s = this.cachedBootstrap ?
|
|
1314
|
+
const t = typeof navigator < "u" && navigator.language ? navigator.language : null, e = this.cachedBootstrap?.settings.locale_default ?? null, s = this.cachedBootstrap ? $(this.cachedBootstrap) : null;
|
|
1269
1315
|
return { tag: s ?? t ?? e, applied: s, browserLanguage: t, countryLanguage: e };
|
|
1270
1316
|
}
|
|
1271
1317
|
/**
|
|
@@ -1277,7 +1323,7 @@ class bt {
|
|
|
1277
1323
|
* - Без identity возвращает empty-state (сервер тоже так делает).
|
|
1278
1324
|
*/
|
|
1279
1325
|
async getUser({ force: t = !1, signal: e } = {}) {
|
|
1280
|
-
return !t && this.cachedUser && Date.now() - this.cachedUserAt <
|
|
1326
|
+
return !t && this.cachedUser && Date.now() - this.cachedUserAt < nt ? this.cachedUser : this.inflightUser ? this.inflightUser : (this.inflightUser = (async () => {
|
|
1281
1327
|
try {
|
|
1282
1328
|
if (!this.identity?.email)
|
|
1283
1329
|
return this.applyUser(k), k;
|
|
@@ -1333,7 +1379,7 @@ class bt {
|
|
|
1333
1379
|
return this.cachedUser;
|
|
1334
1380
|
}
|
|
1335
1381
|
applyUser(t) {
|
|
1336
|
-
const e = !
|
|
1382
|
+
const e = !ct(this.cachedUser, t);
|
|
1337
1383
|
if (this.cachedUser = t, this.cachedUserAt = Date.now(), e) {
|
|
1338
1384
|
this.persistUser(t);
|
|
1339
1385
|
for (const s of this.userListeners)
|
|
@@ -1353,7 +1399,7 @@ class bt {
|
|
|
1353
1399
|
const t = await this.storage.getItem(this.storageKey());
|
|
1354
1400
|
if (!t) return;
|
|
1355
1401
|
const e = JSON.parse(t);
|
|
1356
|
-
if (!e?.user || Date.now() - e.at >
|
|
1402
|
+
if (!e?.user || Date.now() - e.at > rt || this.cachedUser) return;
|
|
1357
1403
|
this.applyUser(e.user);
|
|
1358
1404
|
} catch {
|
|
1359
1405
|
}
|
|
@@ -1382,7 +1428,7 @@ class bt {
|
|
|
1382
1428
|
*/
|
|
1383
1429
|
async getBalances({ force: t = !1, signal: e } = {}) {
|
|
1384
1430
|
const s = Date.now(), a = this.cachedBalances ? s - this.cachedBalancesAt : 1 / 0;
|
|
1385
|
-
return !t && this.cachedBalances && (a <
|
|
1431
|
+
return !t && this.cachedBalances && (a < ht || a < lt) ? this.cachedBalances : !t && this.cachedBalances && a < T ? (this.fetchBalances({ signal: e }).catch(() => {
|
|
1386
1432
|
}), this.cachedBalances) : this.inflightBalances ? this.inflightBalances : this.fetchBalances({ signal: e });
|
|
1387
1433
|
}
|
|
1388
1434
|
// Network primitive — единая точка для force/stale-revalidate/cold-start.
|
|
@@ -1473,7 +1519,7 @@ class bt {
|
|
|
1473
1519
|
*/
|
|
1474
1520
|
createApiGatewayClient(t = {}) {
|
|
1475
1521
|
const e = t.onChargeSuccess, s = t.onQuotaExceeded;
|
|
1476
|
-
return new
|
|
1522
|
+
return new st({
|
|
1477
1523
|
paywallId: this.paywallId,
|
|
1478
1524
|
apiOrigin: this.apiOrigin,
|
|
1479
1525
|
auth: this.auth,
|
|
@@ -1490,7 +1536,7 @@ class bt {
|
|
|
1490
1536
|
});
|
|
1491
1537
|
}
|
|
1492
1538
|
applyBalances(t, { persist: e = !0 } = {}) {
|
|
1493
|
-
const s = !
|
|
1539
|
+
const s = !ut(this.cachedBalances, t);
|
|
1494
1540
|
if (this.cachedBalances = t, this.cachedBalancesAt = Date.now(), e && this.persistBalances(t), s)
|
|
1495
1541
|
for (const a of this.balanceListeners)
|
|
1496
1542
|
try {
|
|
@@ -1554,7 +1600,7 @@ class bt {
|
|
|
1554
1600
|
const e = t.idempotencyKey ?? `auto:${t.priceId}`, s = this.inflightCheckouts.get(e);
|
|
1555
1601
|
if (s) return s;
|
|
1556
1602
|
const n = {
|
|
1557
|
-
"Idempotency-Key": t.idempotencyKey ??
|
|
1603
|
+
"Idempotency-Key": t.idempotencyKey ?? M()
|
|
1558
1604
|
};
|
|
1559
1605
|
this.apiKey && (n["X-Api-Key"] = this.apiKey);
|
|
1560
1606
|
const r = this.cachedBootstrap?.settings, l = t.successUrl ?? r?.success_redirect_url ?? void 0, u = t.shopUrl ?? r?.checkout_shop_url ?? void 0, d = this.api.request(`/api/v1/paywall/${this.paywallId}/start-checkout`, {
|
|
@@ -1701,10 +1747,10 @@ class bt {
|
|
|
1701
1747
|
function U(i) {
|
|
1702
1748
|
return { email: i.email, userId: i.id };
|
|
1703
1749
|
}
|
|
1704
|
-
function
|
|
1750
|
+
function ft(i, t) {
|
|
1705
1751
|
return i === t ? !0 : !i || !t ? !1 : i.email === t.email && i.userId === t.userId && i.anonymousId === t.anonymousId;
|
|
1706
1752
|
}
|
|
1707
|
-
function
|
|
1753
|
+
function O(i, t) {
|
|
1708
1754
|
return {
|
|
1709
1755
|
type: "modal",
|
|
1710
1756
|
blocks: [
|
|
@@ -1714,7 +1760,7 @@ function ft(i, t) {
|
|
|
1714
1760
|
]
|
|
1715
1761
|
};
|
|
1716
1762
|
}
|
|
1717
|
-
function
|
|
1763
|
+
function $(i) {
|
|
1718
1764
|
const t = i.locales;
|
|
1719
1765
|
if (!t) return null;
|
|
1720
1766
|
const e = [];
|
|
@@ -1729,8 +1775,8 @@ function M(i) {
|
|
|
1729
1775
|
if (a && Object.prototype.hasOwnProperty.call(t, a)) return a;
|
|
1730
1776
|
return null;
|
|
1731
1777
|
}
|
|
1732
|
-
function
|
|
1733
|
-
const t =
|
|
1778
|
+
function w(i) {
|
|
1779
|
+
const t = $(i);
|
|
1734
1780
|
if (!t) return;
|
|
1735
1781
|
const e = i.locales?.[t];
|
|
1736
1782
|
e && (e.layout && (i.layout = e.layout), e.prices && (i.prices = i.prices.map((s) => {
|
|
@@ -1740,8 +1786,8 @@ function b(i) {
|
|
|
1740
1786
|
return "label" in a && (n.label = a.label ?? null), "description" in a && (n.description = a.description ?? null), n;
|
|
1741
1787
|
})));
|
|
1742
1788
|
}
|
|
1743
|
-
const yt = 1500, pt = 20,
|
|
1744
|
-
class
|
|
1789
|
+
const yt = 1500, pt = 20, C = 200;
|
|
1790
|
+
class vt {
|
|
1745
1791
|
constructor(t) {
|
|
1746
1792
|
this.buffer = [], this.flushTimer = null, this.destroyed = !1, this.unloadHandler = null, this.visibilityHandler = null, this.opts = t, this.isEnabled() && this.attachUnloadHandlers();
|
|
1747
1793
|
}
|
|
@@ -1756,7 +1802,7 @@ class St {
|
|
|
1756
1802
|
this.flush();
|
|
1757
1803
|
return;
|
|
1758
1804
|
}
|
|
1759
|
-
this.buffer.length >
|
|
1805
|
+
this.buffer.length > C && (this.buffer = this.buffer.slice(-C)), this.scheduleFlush();
|
|
1760
1806
|
}
|
|
1761
1807
|
scheduleFlush() {
|
|
1762
1808
|
if (this.flushTimer || this.destroyed) return;
|
|
@@ -1804,7 +1850,7 @@ class St {
|
|
|
1804
1850
|
// body-level дубликаты для beacon-flow, читаются сервером как fallback.
|
|
1805
1851
|
visitor_id: e,
|
|
1806
1852
|
user_id: s,
|
|
1807
|
-
sdk_version:
|
|
1853
|
+
sdk_version: m,
|
|
1808
1854
|
paywall_id: this.opts.paywallId,
|
|
1809
1855
|
capabilities: this.opts.capabilities?.join(",") ?? ""
|
|
1810
1856
|
}), n = this.opts.sendBeacon ?? (typeof navigator < "u" && typeof navigator.sendBeacon == "function" ? navigator.sendBeacon.bind(navigator) : null);
|
|
@@ -1821,7 +1867,7 @@ class St {
|
|
|
1821
1867
|
buildHeaders(t, e) {
|
|
1822
1868
|
const s = {
|
|
1823
1869
|
"Content-Type": "application/json",
|
|
1824
|
-
"X-SDK-Version":
|
|
1870
|
+
"X-SDK-Version": m,
|
|
1825
1871
|
"X-Paywall-Id": this.opts.paywallId,
|
|
1826
1872
|
"X-Visitor-Id": t
|
|
1827
1873
|
};
|
|
@@ -1839,11 +1885,11 @@ class St {
|
|
|
1839
1885
|
this.destroyed || (this.destroyed = !0, this.flushTimer && (clearTimeout(this.flushTimer), this.flushTimer = null), this.flush(), this.detachUnloadHandlers());
|
|
1840
1886
|
}
|
|
1841
1887
|
}
|
|
1842
|
-
const
|
|
1843
|
-
function
|
|
1888
|
+
const E = 3600 * 1e3;
|
|
1889
|
+
function v(i) {
|
|
1844
1890
|
return `paywall-${i}-trial-time-first-open`;
|
|
1845
1891
|
}
|
|
1846
|
-
function
|
|
1892
|
+
function S(i) {
|
|
1847
1893
|
return `paywall-${i}-skip-times`;
|
|
1848
1894
|
}
|
|
1849
1895
|
class F {
|
|
@@ -1857,10 +1903,10 @@ class F {
|
|
|
1857
1903
|
return this.config.mode === "time" ? this.recordTime() : this.recordOpens();
|
|
1858
1904
|
}
|
|
1859
1905
|
async reset() {
|
|
1860
|
-
await this.storage.removeItem(this.config.mode === "time" ?
|
|
1906
|
+
await this.storage.removeItem(this.config.mode === "time" ? v(this.paywallId) : S(this.paywallId));
|
|
1861
1907
|
}
|
|
1862
1908
|
async checkTime() {
|
|
1863
|
-
const t = this.config.payload *
|
|
1909
|
+
const t = this.config.payload * E, e = await this.storage.getItem(v(this.paywallId)), s = e ? Number(e) : null;
|
|
1864
1910
|
if (!s || !Number.isFinite(s))
|
|
1865
1911
|
return {
|
|
1866
1912
|
mode: "time",
|
|
@@ -1881,7 +1927,7 @@ class F {
|
|
|
1881
1927
|
};
|
|
1882
1928
|
}
|
|
1883
1929
|
async checkOpens() {
|
|
1884
|
-
const t = this.config.payload, e = await this.storage.getItem(
|
|
1930
|
+
const t = this.config.payload, e = await this.storage.getItem(S(this.paywallId)), s = e ? Number(e) : 0, a = Number.isFinite(s) ? s : 0, n = a < t, r = Math.max(0, t - a);
|
|
1885
1931
|
return {
|
|
1886
1932
|
mode: "opens",
|
|
1887
1933
|
blocked: n,
|
|
@@ -1890,7 +1936,7 @@ class F {
|
|
|
1890
1936
|
};
|
|
1891
1937
|
}
|
|
1892
1938
|
async recordTime() {
|
|
1893
|
-
const t = this.config.payload *
|
|
1939
|
+
const t = this.config.payload * E, e = v(this.paywallId), s = await this.storage.getItem(e);
|
|
1894
1940
|
let a = s ? Number(s) : null;
|
|
1895
1941
|
(!a || !Number.isFinite(a)) && (a = Date.now(), await this.storage.setItem(e, String(a)));
|
|
1896
1942
|
const n = a + t, r = Math.max(0, n - Date.now());
|
|
@@ -1904,7 +1950,7 @@ class F {
|
|
|
1904
1950
|
};
|
|
1905
1951
|
}
|
|
1906
1952
|
async recordOpens() {
|
|
1907
|
-
const t = this.config.payload, e =
|
|
1953
|
+
const t = this.config.payload, e = S(this.paywallId), s = await this.storage.getItem(e), a = s ? Number(s) : 0, n = Number.isFinite(a) ? a : 0, r = Math.min(t, n + 1);
|
|
1908
1954
|
await this.storage.setItem(e, String(r));
|
|
1909
1955
|
const l = Math.max(0, t - r);
|
|
1910
1956
|
return {
|
|
@@ -1915,10 +1961,10 @@ class F {
|
|
|
1915
1961
|
};
|
|
1916
1962
|
}
|
|
1917
1963
|
}
|
|
1918
|
-
let
|
|
1964
|
+
let L = !1;
|
|
1919
1965
|
class gt {
|
|
1920
1966
|
constructor(t, e, s) {
|
|
1921
|
-
|
|
1967
|
+
L || (L = !0, console.warn(
|
|
1922
1968
|
'[paywall] trial.storage="server" is not implemented yet — falling back to client storage. State lives in localStorage; users can reset trial by clearing site data.'
|
|
1923
1969
|
)), this.fallback = new F(t, e, s);
|
|
1924
1970
|
}
|
|
@@ -1932,11 +1978,11 @@ class gt {
|
|
|
1932
1978
|
return this.fallback.reset();
|
|
1933
1979
|
}
|
|
1934
1980
|
}
|
|
1935
|
-
function
|
|
1981
|
+
function St(i, t, e) {
|
|
1936
1982
|
return e.storage === "server" ? new gt(i, t, e) : new F(i, t, e);
|
|
1937
1983
|
}
|
|
1938
|
-
const
|
|
1939
|
-
function
|
|
1984
|
+
const It = 1;
|
|
1985
|
+
function Bt(i) {
|
|
1940
1986
|
return i instanceof o ? {
|
|
1941
1987
|
name: "PaywallError",
|
|
1942
1988
|
code: i.code,
|
|
@@ -1954,7 +2000,7 @@ function _t(i) {
|
|
|
1954
2000
|
message: typeof i == "string" ? i : "Unknown error"
|
|
1955
2001
|
};
|
|
1956
2002
|
}
|
|
1957
|
-
function
|
|
2003
|
+
function _t(i) {
|
|
1958
2004
|
if (i.name === "PaywallError") {
|
|
1959
2005
|
const e = new o(i.code, i.message, { status: i.status });
|
|
1960
2006
|
return i.stack && (e.stack = i.stack), e;
|
|
@@ -2001,14 +2047,14 @@ function kt(i) {
|
|
|
2001
2047
|
export {
|
|
2002
2048
|
mt as A,
|
|
2003
2049
|
bt as B,
|
|
2004
|
-
|
|
2050
|
+
vt as E,
|
|
2005
2051
|
o as P,
|
|
2006
|
-
|
|
2052
|
+
It as a,
|
|
2007
2053
|
kt as b,
|
|
2008
|
-
|
|
2054
|
+
St as c,
|
|
2009
2055
|
wt as p,
|
|
2010
|
-
|
|
2011
|
-
|
|
2012
|
-
|
|
2056
|
+
_t as r,
|
|
2057
|
+
Bt as s,
|
|
2058
|
+
Z as w
|
|
2013
2059
|
};
|
|
2014
|
-
//# sourceMappingURL=chrome-port-
|
|
2060
|
+
//# sourceMappingURL=chrome-port-DPFUj1MP.js.map
|