@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.
@@ -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 w = "3.0.0-alpha.0";
14
- class L {
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", w), n.set("X-Paywall-Id", this.opts.paywallId), this.opts.capabilities?.length && n.set("X-SDK-Capabilities", this.opts.capabilities.join(","));
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 D = {
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
- }, x = {
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
- }, m = /* @__PURE__ */ new Map(), J = {
104
+ }, b = /* @__PURE__ */ new Map(), H = {
105
105
  async getItem(i) {
106
- return m.get(i) ?? null;
106
+ return b.get(i) ?? null;
107
107
  },
108
108
  async setItem(i, t) {
109
- m.set(i, t);
109
+ b.set(i, t);
110
110
  },
111
111
  async removeItem(i) {
112
- m.delete(i);
112
+ b.delete(i);
113
113
  }
114
114
  };
115
- function P(i) {
116
- return i || ($() ? D : typeof window < "u" && "localStorage" in window ? x : J);
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 R() {
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 _(i) {
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 = R();
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 v(i) {
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 H() {
187
- return v(q(64));
186
+ function V() {
187
+ return I(q(64));
188
188
  }
189
- async function V(i) {
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 v(new Uint8Array(s));
194
+ return I(new Uint8Array(s));
195
195
  }
196
- function j() {
197
- return v(q(16));
196
+ function X() {
197
+ return I(q(16));
198
198
  }
199
- const X = "https://appbox.space", z = 6e4, G = 600 * 1e3;
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 ?? X, this.storage = P(t.storage), this.api = new L({
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 Y(a, s);
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 = H(), s = await V(e), a = j(), n = {}, r = await this.getAccessToken().catch(() => null);
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() - G;
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() > z;
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(), Z(s, t) || this.emit();
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 Q = 5 * 6e4, W = 500;
907
- function Y(i, t) {
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
- }, W), u = setTimeout(() => {
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
- }, Q);
955
+ }, W);
956
956
  window.addEventListener("message", r);
957
957
  });
958
958
  }
959
- function Z(i, t) {
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 tt = "https://appbox.space";
963
- class et {
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 ?? tt, 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(
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", w), a.set("X-Paywall-Id", this.paywallId), this.capabilities?.length && a.set("X-SDK-Capabilities", this.capabilities.join(","));
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 st(h);
999
+ const p = await it(h);
1000
1000
  throw this.onQuotaExceeded?.(p), p;
1001
1001
  }
1002
1002
  if (!h.ok) {
1003
- const p = await it(h.clone());
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 st(i) {
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 it(i) {
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 at = 5e3, nt = 30 * 6e4, B = 60 * 6e4, rt = 5 * 6e4, k = {
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 ot(i, t) {
1049
+ function ct(i, t) {
1050
1050
  return i === t ? !0 : !i || !t ? !1 : JSON.stringify(i) === JSON.stringify(t);
1051
1051
  }
1052
- const ct = 5e3, T = 5 * 6e4, ht = 3e4;
1053
- function lt(i, t) {
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 ut = "https://appbox.space";
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 ?? ut, this.capabilities = t.capabilities, this.auth = t.auth;
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 = P(t.storage), this.api = new L({
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
- dt(this.identity, a) || this.setIdentity(a);
1081
- })), this.hydrateUserFromStorage(), this.hydrateBootstrapFromStorage(), this.subscribeBootstrapStorage(), this.hydrateBalancesFromStorage(), this.subscribeBalancesStorage(), this.visitorIdPromise = _(this.storage).then((s) => (this.visitorId = s, s));
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 = _(this.storage).then((t) => (this.visitorId = t, t))), 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, s = Date.now(), a = this.cachedBootstrap && this.cachedBootstrapAt > 0 && s - this.cachedBootstrapAt < B;
1118
- return !e.force && a ? (s - this.cachedBootstrapAt > rt && this.revalidateBootstrap(e.signal).catch(() => {
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 = ft(n.settings, n.prices)), b(n), this.applyBootstrap(n, { persist: !0 }), n.user && this.applyUser(n.user), n;
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 > B || this.cachedBootstrap) return;
1185
- b(e.bootstrap), this.cachedBootstrap = e.bootstrap, this.cachedBootstrapAt = e.at;
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
- b(e.bootstrap), this.applyBootstrap(e.bootstrap, { persist: !1 });
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 ? M(this.cachedBootstrap) : null;
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 < at ? this.cachedUser : this.inflightUser ? this.inflightUser : (this.inflightUser = (async () => {
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 = !ot(this.cachedUser, t);
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 > nt || this.cachedUser) return;
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 < ct || a < ht) ? this.cachedBalances : !t && this.cachedBalances && a < T ? (this.fetchBalances({ signal: e }).catch(() => {
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 et({
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 = !lt(this.cachedBalances, t);
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 ?? R()
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 dt(i, t) {
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 ft(i, t) {
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 M(i) {
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 b(i) {
1733
- const t = M(i);
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, O = 200;
1744
- class St {
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 > O && (this.buffer = this.buffer.slice(-O)), this.scheduleFlush();
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: w,
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": w,
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 C = 3600 * 1e3;
1843
- function S(i) {
1888
+ const E = 3600 * 1e3;
1889
+ function v(i) {
1844
1890
  return `paywall-${i}-trial-time-first-open`;
1845
1891
  }
1846
- function I(i) {
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" ? S(this.paywallId) : I(this.paywallId));
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 * C, e = await this.storage.getItem(S(this.paywallId)), s = e ? Number(e) : null;
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(I(this.paywallId)), s = e ? Number(e) : 0, a = Number.isFinite(s) ? s : 0, n = a < t, r = Math.max(0, t - a);
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 * C, e = S(this.paywallId), s = await this.storage.getItem(e);
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 = I(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);
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 E = !1;
1964
+ let L = !1;
1919
1965
  class gt {
1920
1966
  constructor(t, e, s) {
1921
- E || (E = !0, console.warn(
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 It(i, t, e) {
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 vt = 1;
1939
- function _t(i) {
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 Bt(i) {
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
- St as E,
2050
+ vt as E,
2005
2051
  o as P,
2006
- vt as a,
2052
+ It as a,
2007
2053
  kt as b,
2008
- It as c,
2054
+ St as c,
2009
2055
  wt as p,
2010
- Bt as r,
2011
- _t as s,
2012
- Y as w
2056
+ _t as r,
2057
+ Bt as s,
2058
+ Z as w
2013
2059
  };
2014
- //# sourceMappingURL=chrome-port-BXHR4SOG.js.map
2060
+ //# sourceMappingURL=chrome-port-DPFUj1MP.js.map