@monetize.software/sdk-extension 3.0.0-alpha.2 → 3.0.0-alpha.20

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.
Files changed (156) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +21 -20
  3. package/dist/chunks/ar-7cgIM-Vl.js +2 -0
  4. package/dist/chunks/ar-7cgIM-Vl.js.map +1 -0
  5. package/dist/chunks/ar-B2Wg_IrC.js +126 -0
  6. package/dist/chunks/ar-B2Wg_IrC.js.map +1 -0
  7. package/dist/chunks/chrome-port-BEMjZQAH.js +2 -0
  8. package/dist/chunks/chrome-port-BEMjZQAH.js.map +1 -0
  9. package/dist/chunks/{chrome-port-DPFUj1MP.js → chrome-port-bfTUUDz_.js} +332 -211
  10. package/dist/chunks/chrome-port-bfTUUDz_.js.map +1 -0
  11. package/dist/chunks/cs-BNo9Dx0Q.js +122 -0
  12. package/dist/chunks/cs-BNo9Dx0Q.js.map +1 -0
  13. package/dist/chunks/cs-S05PC5AC.js +2 -0
  14. package/dist/chunks/cs-S05PC5AC.js.map +1 -0
  15. package/dist/chunks/da-Bi4zBG14.js +2 -0
  16. package/dist/chunks/da-Bi4zBG14.js.map +1 -0
  17. package/dist/chunks/da-Do9Lq6En.js +122 -0
  18. package/dist/chunks/da-Do9Lq6En.js.map +1 -0
  19. package/dist/chunks/de-C8pDZNvx.js +141 -0
  20. package/dist/chunks/de-C8pDZNvx.js.map +1 -0
  21. package/dist/chunks/de-nCDB6D2W.js +2 -0
  22. package/dist/chunks/de-nCDB6D2W.js.map +1 -0
  23. package/dist/chunks/el-BrKaa978.js +2 -0
  24. package/dist/chunks/el-BrKaa978.js.map +1 -0
  25. package/dist/chunks/el-DzMNX-_P.js +126 -0
  26. package/dist/chunks/el-DzMNX-_P.js.map +1 -0
  27. package/dist/chunks/es-B-Wtyzrl.js +2 -0
  28. package/dist/chunks/es-B-Wtyzrl.js.map +1 -0
  29. package/dist/chunks/es-YrKt-q4w.js +141 -0
  30. package/dist/chunks/es-YrKt-q4w.js.map +1 -0
  31. package/dist/chunks/fi-Bh44pwZ4.js +122 -0
  32. package/dist/chunks/fi-Bh44pwZ4.js.map +1 -0
  33. package/dist/chunks/fi-D1SGXjnO.js +2 -0
  34. package/dist/chunks/fi-D1SGXjnO.js.map +1 -0
  35. package/dist/chunks/fr-Bc0pw4ws.js +141 -0
  36. package/dist/chunks/fr-Bc0pw4ws.js.map +1 -0
  37. package/dist/chunks/fr-BhYf-iKk.js +2 -0
  38. package/dist/chunks/fr-BhYf-iKk.js.map +1 -0
  39. package/dist/chunks/he-BXAaFv6Y.js +2 -0
  40. package/dist/chunks/he-BXAaFv6Y.js.map +1 -0
  41. package/dist/chunks/he-Bfm-bhe3.js +126 -0
  42. package/dist/chunks/he-Bfm-bhe3.js.map +1 -0
  43. package/dist/chunks/hi-D-O-B9Dn.js +126 -0
  44. package/dist/chunks/hi-D-O-B9Dn.js.map +1 -0
  45. package/dist/chunks/hi-xblDO0O7.js +2 -0
  46. package/dist/chunks/hi-xblDO0O7.js.map +1 -0
  47. package/dist/chunks/hu-CmIuAbLL.js +122 -0
  48. package/dist/chunks/hu-CmIuAbLL.js.map +1 -0
  49. package/dist/chunks/hu-Wa46p0y4.js +2 -0
  50. package/dist/chunks/hu-Wa46p0y4.js.map +1 -0
  51. package/dist/chunks/id-CQEo5X94.js +2 -0
  52. package/dist/chunks/id-CQEo5X94.js.map +1 -0
  53. package/dist/chunks/id-DN7IES-A.js +122 -0
  54. package/dist/chunks/id-DN7IES-A.js.map +1 -0
  55. package/dist/chunks/it-8AYCm0xz.js +2 -0
  56. package/dist/chunks/it-8AYCm0xz.js.map +1 -0
  57. package/dist/chunks/it-Cz5Nmqx5.js +141 -0
  58. package/dist/chunks/it-Cz5Nmqx5.js.map +1 -0
  59. package/dist/chunks/ja-BH9BlBh2.js +145 -0
  60. package/dist/chunks/ja-BH9BlBh2.js.map +1 -0
  61. package/dist/chunks/ja-q-COVayn.js +2 -0
  62. package/dist/chunks/ja-q-COVayn.js.map +1 -0
  63. package/dist/chunks/ko-B6HRCscZ.js +2 -0
  64. package/dist/chunks/ko-B6HRCscZ.js.map +1 -0
  65. package/dist/chunks/ko-CYV9QuYs.js +145 -0
  66. package/dist/chunks/ko-CYV9QuYs.js.map +1 -0
  67. package/dist/chunks/nl-BvkB900D.js +141 -0
  68. package/dist/chunks/nl-BvkB900D.js.map +1 -0
  69. package/dist/chunks/nl-CAd6_xlm.js +2 -0
  70. package/dist/chunks/nl-CAd6_xlm.js.map +1 -0
  71. package/dist/chunks/no-3s9_ormb.js +122 -0
  72. package/dist/chunks/no-3s9_ormb.js.map +1 -0
  73. package/dist/chunks/no-CAmz6bz6.js +2 -0
  74. package/dist/chunks/no-CAmz6bz6.js.map +1 -0
  75. package/dist/chunks/pl-C9WTGQtb.js +122 -0
  76. package/dist/chunks/pl-C9WTGQtb.js.map +1 -0
  77. package/dist/chunks/pl-DqUSTCaF.js +2 -0
  78. package/dist/chunks/pl-DqUSTCaF.js.map +1 -0
  79. package/dist/chunks/port-name-CF4WQQ3-.js +2 -0
  80. package/dist/chunks/port-name-CF4WQQ3-.js.map +1 -0
  81. package/dist/chunks/port-name-ervLBWAQ.js +6 -0
  82. package/dist/chunks/port-name-ervLBWAQ.js.map +1 -0
  83. package/dist/chunks/pt-8ARZnH0_.js +2 -0
  84. package/dist/chunks/pt-8ARZnH0_.js.map +1 -0
  85. package/dist/chunks/pt-uFVUv_Op.js +141 -0
  86. package/dist/chunks/pt-uFVUv_Op.js.map +1 -0
  87. package/dist/chunks/ro-BrqQ8Au-.js +122 -0
  88. package/dist/chunks/ro-BrqQ8Au-.js.map +1 -0
  89. package/dist/chunks/ro-D-NMbp2F.js +2 -0
  90. package/dist/chunks/ro-D-NMbp2F.js.map +1 -0
  91. package/dist/chunks/ru-8gbHPh0g.js +2 -0
  92. package/dist/chunks/ru-8gbHPh0g.js.map +1 -0
  93. package/dist/chunks/ru-DK594dA8.js +144 -0
  94. package/dist/chunks/ru-DK594dA8.js.map +1 -0
  95. package/dist/chunks/sv-CHNH8-mq.js +122 -0
  96. package/dist/chunks/sv-CHNH8-mq.js.map +1 -0
  97. package/dist/chunks/sv-D8a8hmx9.js +2 -0
  98. package/dist/chunks/sv-D8a8hmx9.js.map +1 -0
  99. package/dist/chunks/th-DfjUK0Y7.js +2 -0
  100. package/dist/chunks/th-DfjUK0Y7.js.map +1 -0
  101. package/dist/chunks/th-l24Pm5q-.js +126 -0
  102. package/dist/chunks/th-l24Pm5q-.js.map +1 -0
  103. package/dist/chunks/tr-ADpigSY5.js +122 -0
  104. package/dist/chunks/tr-ADpigSY5.js.map +1 -0
  105. package/dist/chunks/tr-BdBpz4tL.js +2 -0
  106. package/dist/chunks/tr-BdBpz4tL.js.map +1 -0
  107. package/dist/chunks/uk-CGqo4jek.js +144 -0
  108. package/dist/chunks/uk-CGqo4jek.js.map +1 -0
  109. package/dist/chunks/uk-Cx1zv1ao.js +2 -0
  110. package/dist/chunks/uk-Cx1zv1ao.js.map +1 -0
  111. package/dist/chunks/vi-Dk9bTu6f.js +122 -0
  112. package/dist/chunks/vi-Dk9bTu6f.js.map +1 -0
  113. package/dist/chunks/vi-oe2dW21I.js +2 -0
  114. package/dist/chunks/vi-oe2dW21I.js.map +1 -0
  115. package/dist/chunks/zh-CwczPMPp.js +2 -0
  116. package/dist/chunks/zh-CwczPMPp.js.map +1 -0
  117. package/dist/chunks/zh-LDkEV2D9.js +145 -0
  118. package/dist/chunks/zh-LDkEV2D9.js.map +1 -0
  119. package/dist/content/PaywallUI.d.ts +1 -1
  120. package/dist/content/RemoteAuthClient.d.ts +8 -4
  121. package/dist/content/RemoteAuthClient.d.ts.map +1 -1
  122. package/dist/content/RemoteAuthClient.test-d.d.ts +2 -0
  123. package/dist/content/RemoteAuthClient.test-d.d.ts.map +1 -0
  124. package/dist/content/RemoteBillingClient.d.ts +36 -3
  125. package/dist/content/RemoteBillingClient.d.ts.map +1 -1
  126. package/dist/content/RemoteBillingClient.test-d.d.ts +2 -0
  127. package/dist/content/RemoteBillingClient.test-d.d.ts.map +1 -0
  128. package/dist/content/RemoteTrialStore.d.ts +2 -2
  129. package/dist/content.cjs +3 -3
  130. package/dist/content.cjs.map +1 -1
  131. package/dist/content.js +2441 -1059
  132. package/dist/content.js.map +1 -1
  133. package/dist/offscreen/server.d.ts +3 -3
  134. package/dist/offscreen/server.d.ts.map +1 -1
  135. package/dist/offscreen.cjs +1 -1
  136. package/dist/offscreen.cjs.map +1 -1
  137. package/dist/offscreen.js +18 -15
  138. package/dist/offscreen.js.map +1 -1
  139. package/dist/shared/messages.d.ts +28 -5
  140. package/dist/shared/messages.d.ts.map +1 -1
  141. package/dist/shared/port-name.d.ts +1 -0
  142. package/dist/shared/port-name.d.ts.map +1 -1
  143. package/dist/shared/protocol.d.ts +1 -1
  144. package/dist/shared/protocol.d.ts.map +1 -1
  145. package/dist/sw.cjs +1 -1
  146. package/dist/sw.cjs.map +1 -1
  147. package/dist/sw.js +14 -14
  148. package/dist/sw.js.map +1 -1
  149. package/package.json +39 -21
  150. package/dist/chunks/chrome-port-DPFUj1MP.js.map +0 -1
  151. package/dist/chunks/chrome-port-MoMohiHB.js +0 -2
  152. package/dist/chunks/chrome-port-MoMohiHB.js.map +0 -1
  153. package/dist/chunks/port-name-BPfQKtdb.js +0 -5
  154. package/dist/chunks/port-name-BPfQKtdb.js.map +0 -1
  155. package/dist/chunks/port-name-qwB109u9.js +0 -2
  156. package/dist/chunks/port-name-qwB109u9.js.map +0 -1
@@ -3,7 +3,7 @@ class o extends Error {
3
3
  super(e), this.name = "PaywallError", this.code = t, this.status = s.status, this.cause = s.cause;
4
4
  }
5
5
  }
6
- class N extends o {
6
+ class F extends o {
7
7
  constructor(t) {
8
8
  super("not_enough_queries", t.message ?? "Not enough queries", {
9
9
  status: 402
@@ -20,30 +20,30 @@ class P {
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 r = await this.opts.getAuthToken?.();
22
22
  r && n.set("Authorization", `Bearer ${r}`);
23
- const l = typeof FormData < "u" && e.body instanceof FormData;
24
- e.body && !n.has("Content-Type") && !l && n.set("Content-Type", "application/json");
25
- let u;
23
+ const h = typeof FormData < "u" && e.body instanceof FormData;
24
+ e.body && !n.has("Content-Type") && !h && n.set("Content-Type", "application/json");
25
+ let f;
26
26
  try {
27
- u = await a(s, {
27
+ f = await a(s, {
28
28
  ...e,
29
29
  headers: n,
30
30
  credentials: "omit"
31
31
  });
32
- } catch (h) {
33
- throw (h && typeof h == "object" && "name" in h ? h.name : void 0) === "AbortError" ? new o("aborted", "Request aborted", { cause: h }) : new o("network_error", "Network request failed", { cause: h });
32
+ } catch (c) {
33
+ throw (c && typeof c == "object" && "name" in c ? c.name : void 0) === "AbortError" ? new o("aborted", "Request aborted", { cause: c }) : new o("network_error", "Network request failed", { cause: c });
34
34
  }
35
- const f = (u.headers.get("content-type") ?? "").includes("application/json") ? await u.json().catch(() => null) : null;
36
- if (!u.ok) {
37
- const h = f && typeof f == "object" && "code" in f && String(f.code) || `http_${u.status}`, g = f && typeof f == "object" && "message" in f && String(f.message) || u.statusText || "Request failed";
38
- throw new o(h, g, { status: u.status, cause: f });
35
+ const d = (f.headers.get("content-type") ?? "").includes("application/json") ? await f.json().catch(() => null) : null;
36
+ if (!f.ok) {
37
+ const c = d && typeof d == "object" && "code" in d && String(d.code) || `http_${f.status}`, g = d && typeof d == "object" && "message" in d && String(d.message) || f.statusText || "Request failed";
38
+ throw new o(c, g, { status: f.status, cause: d });
39
39
  }
40
- return f;
40
+ return d;
41
41
  }
42
42
  }
43
- function D() {
43
+ function x() {
44
44
  return typeof chrome < "u" && !!chrome?.storage?.local && !!chrome?.runtime?.id;
45
45
  }
46
- const x = {
46
+ const H = {
47
47
  getItem(i) {
48
48
  return new Promise((t) => {
49
49
  chrome.storage.local.get([i], (e) => {
@@ -101,21 +101,21 @@ const x = {
101
101
  };
102
102
  return window.addEventListener("storage", e), () => window.removeEventListener("storage", e);
103
103
  }
104
- }, b = /* @__PURE__ */ new Map(), H = {
104
+ }, I = /* @__PURE__ */ new Map(), V = {
105
105
  async getItem(i) {
106
- return b.get(i) ?? null;
106
+ return I.get(i) ?? null;
107
107
  },
108
108
  async setItem(i, t) {
109
- b.set(i, t);
109
+ I.set(i, t);
110
110
  },
111
111
  async removeItem(i) {
112
- b.delete(i);
112
+ I.delete(i);
113
113
  }
114
114
  };
115
- function R(i) {
116
- return i || (D() ? x : typeof window < "u" && "localStorage" in window ? J : H);
115
+ function K(i) {
116
+ return i || (x() ? H : typeof window < "u" && "localStorage" in window ? J : V);
117
117
  }
118
- const y = {
118
+ const u = {
119
119
  visitorId: "pw-visitor-id",
120
120
  lastLoginMethod: (i) => `pw-${i}-last-login-method`,
121
121
  lastLoginEmail: (i) => `pw-${i}-last-login-email`,
@@ -145,7 +145,7 @@ const y = {
145
145
  // (оптимистично через `decrementBalanceLocal`).
146
146
  balances: (i, t) => `pw-${i}-${t}-balances-v1`
147
147
  };
148
- function M() {
148
+ function R() {
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);
@@ -159,18 +159,18 @@ function M() {
159
159
  }
160
160
  async function B(i) {
161
161
  try {
162
- const e = await i.getItem(y.visitorId);
162
+ const e = await i.getItem(u.visitorId);
163
163
  if (e && typeof e == "string" && e.length >= 16) return e;
164
164
  } catch {
165
165
  }
166
- const t = M();
166
+ const t = R();
167
167
  try {
168
- await i.setItem(y.visitorId, t);
168
+ await i.setItem(u.visitorId, t);
169
169
  } catch {
170
170
  }
171
171
  return t;
172
172
  }
173
- function q(i) {
173
+ function D(i) {
174
174
  const t = new Uint8Array(i), e = typeof globalThis < "u" ? globalThis.crypto : void 0;
175
175
  if (e && typeof e.getRandomValues == "function")
176
176
  e.getRandomValues(t);
@@ -178,30 +178,35 @@ 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 I(i) {
181
+ function _(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 V() {
187
- return I(q(64));
186
+ function j() {
187
+ return _(D(64));
188
188
  }
189
- async function j(i) {
189
+ async function X(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 I(new Uint8Array(s));
194
+ return _(new Uint8Array(s));
195
195
  }
196
- function X() {
197
- return I(q(16));
196
+ function G() {
197
+ return _(D(16));
198
198
  }
199
- const z = "https://appbox.space", G = 6e4, Q = 600 * 1e3;
199
+ const z = 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 ?? z, this.storage = R(t.storage), this.api = new P({
204
+ if (!t.apiOrigin)
205
+ throw new o(
206
+ "invalid_config",
207
+ "apiOrigin is required. Pass the paywall custom_domain configured in the platform."
208
+ );
209
+ this.paywallId = t.paywallId, this.apiOrigin = t.apiOrigin, this.storage = K(t.storage), this.api = new P({
205
210
  apiOrigin: this.apiOrigin,
206
211
  paywallId: t.paywallId,
207
212
  fetch: t.fetch
@@ -227,14 +232,15 @@ class mt {
227
232
  async applyExternalSession(t) {
228
233
  if (!this.destroyed && (await this.hydrated, !this.destroyed)) {
229
234
  if (t == null) {
230
- this.session && this.setSession(null, { skipPersist: !0 });
235
+ this.session && this.setSession(null, { skipPersist: !0, event: "SIGNED_OUT" });
231
236
  return;
232
237
  }
233
238
  try {
234
239
  const e = JSON.parse(t);
235
240
  if (!e || typeof e.access_token != "string" || typeof e.refresh_token != "string" || typeof e.expires_at != "number" || !e.user)
236
241
  return;
237
- this.setSession(e, { skipPersist: !0 });
242
+ const s = !this.session || this.session.user.id !== e.user.id ? "SIGNED_IN" : "TOKEN_REFRESHED";
243
+ this.setSession(e, { skipPersist: !0, event: s });
238
244
  } catch {
239
245
  }
240
246
  }
@@ -291,7 +297,7 @@ class mt {
291
297
  })
292
298
  }
293
299
  ), n = this.toSession(a, a.user);
294
- return this.setSession(n), n;
300
+ return this.setSession(n, { event: "SIGNED_IN" }), this.recordLastLogin("email", t.email), n;
295
301
  }
296
302
  /**
297
303
  * Signup. Если в Supabase включён email confirm — сервер возвращает
@@ -317,9 +323,9 @@ class mt {
317
323
  }
318
324
  );
319
325
  if (a.status === "confirmation_required")
320
- return { kind: "confirmation_required", user: a.user };
326
+ return this.recordLastLogin("email", t.email), { kind: "confirmation_required", user: a.user };
321
327
  const n = this.toSession(a, a.user);
322
- return this.setSession(n), { kind: "signed_in", session: n };
328
+ return this.setSession(n, { event: "SIGNED_IN" }), this.recordLastLogin("email", t.email), { kind: "signed_in", session: n };
323
329
  }
324
330
  /**
325
331
  * Повторная отправка confirmation-email после signUp с включённым
@@ -382,8 +388,8 @@ class mt {
382
388
  user_meta: t.userMeta
383
389
  })
384
390
  }
385
- ), a = this.toSession(s, s.user);
386
- return this.setSession(a), a;
391
+ ), a = this.toSession(s, s.user), n = t.type === "recovery" ? "PASSWORD_RECOVERY" : "SIGNED_IN";
392
+ return this.setSession(a, { event: n }), a;
387
393
  }
388
394
  /**
389
395
  * Запрос recovery email. Бэк всегда ok, чтобы не палить enumeration.
@@ -442,10 +448,8 @@ class mt {
442
448
  * когда сервер начнёт возвращать challenge_required в риск-сценариях,
443
449
  * SDK сможет передать proof-of-something обратно без breaking change.
444
450
  *
445
- * `forceCaptcha: true` пропускает шаги 1-2 и сразу делает /signin (создаёт
446
- * нового anon-юзера). Используется в switch-account flow. Имя поля исторически
447
- * остаётся `forceCaptcha`, хотя капчи там больше нет — менять имя ломает
448
- * host-сигнатуру; смысл «принудительно новая anon-сессия» сохранён.
451
+ * `forceNewAnon: true` пропускает шаги 1-2 и сразу делает /signin (создаёт
452
+ * нового anon-юзера). Используется в switch-account flow.
449
453
  *
450
454
  * Параллельные вызовы дедуплицируются через `inflightAnonSignin` — два
451
455
  * click'а на «Войти как гость» не создадут двух anon-юзеров (два /signup =
@@ -454,9 +458,9 @@ class mt {
454
458
  async signInAnonymously(t = {}) {
455
459
  if (this.inflightAnonSignin) return this.inflightAnonSignin;
456
460
  this.inflightAnonSignin = (async () => {
457
- if (await this.hydrated, !t.forceCaptcha && this.session?.user.is_anonymous === !0)
461
+ if (await this.hydrated, !t.forceNewAnon && this.session?.user.is_anonymous === !0)
458
462
  return this.session;
459
- if (!t.forceCaptcha) {
463
+ if (!t.forceNewAnon) {
460
464
  const r = await this.resumeAnonymous();
461
465
  if (r) return r;
462
466
  }
@@ -475,7 +479,7 @@ class mt {
475
479
  email: s.user.email ?? null,
476
480
  is_anonymous: !0
477
481
  }, n = this.toSession(s, a);
478
- return this.setSession(n), await this.writeAnonRefreshToken(n.refresh_token), n;
482
+ return this.setSession(n, { event: "SIGNED_IN" }), await this.writeAnonRefreshToken(n.refresh_token), n;
479
483
  })();
480
484
  try {
481
485
  return await this.inflightAnonSignin;
@@ -497,7 +501,7 @@ class mt {
497
501
  `/api/v1/paywall/${this.paywallId}/auth/refresh`,
498
502
  { method: "POST", body: JSON.stringify({ refresh_token: t }) }
499
503
  ), s = this.session?.user.is_anonymous === !0 ? this.session.user : { id: "", email: null, is_anonymous: !0 }, a = this.toSession(e, s);
500
- return this.setSession(a), await this.writeAnonRefreshToken(a.refresh_token), a;
504
+ return this.setSession(a, { event: "SIGNED_IN" }), await this.writeAnonRefreshToken(a.refresh_token), a;
501
505
  } catch (e) {
502
506
  if (e instanceof o && e.status === 401)
503
507
  return await this.clearAnonRefreshToken(), null;
@@ -559,8 +563,8 @@ class mt {
559
563
  id: a.user.id,
560
564
  email: a.user.email,
561
565
  is_anonymous: a.user.is_anonymous ?? !1
562
- }, l = { ...n, user: r };
563
- return this.setSession(l), await this.clearAnonRefreshToken(), { kind: "updated", session: l };
566
+ }, h = { ...n, user: r };
567
+ return this.setSession(h, { event: "USER_UPDATED" }), await this.clearAnonRefreshToken(), { kind: "updated", session: h };
564
568
  }
565
569
  /**
566
570
  * OAuth signin через popup с PKCE. Жизненный цикл:
@@ -617,9 +621,9 @@ class mt {
617
621
  */
618
622
  async startOAuthFlow(t) {
619
623
  await this.hydrated, this.gcOAuthFlows();
620
- const e = V(), s = await j(e), a = X(), n = {}, r = await this.getAccessToken().catch(() => null);
624
+ const e = j(), s = await X(e), a = G(), n = {}, r = await this.getAccessToken().catch(() => null);
621
625
  r && (n.Authorization = `Bearer ${r}`);
622
- const { authorize_url: l } = await this.api.request(
626
+ const { authorize_url: h } = await this.api.request(
623
627
  `/api/v1/paywall/${this.paywallId}/auth/oauth/init`,
624
628
  {
625
629
  method: "POST",
@@ -635,8 +639,9 @@ class mt {
635
639
  return this.oauthFlows.set(a, {
636
640
  verifier: e,
637
641
  userMeta: t.userMeta,
642
+ provider: t.provider,
638
643
  startedAt: Date.now()
639
- }), { authorize_url: l, state: a };
644
+ }), this.recordLastLoginMethod(t.provider), { authorize_url: h, state: a };
640
645
  }
641
646
  /**
642
647
  * Шаг 2 OAuth split-API: обменивает code (полученный из popup) на session,
@@ -671,7 +676,7 @@ class mt {
671
676
  if (this.destroyed)
672
677
  throw new o("aborted", "AuthClient destroyed mid-flow");
673
678
  const n = this.toSession(a, a.user);
674
- return this.setSession(n), n;
679
+ return this.setSession(n, { event: "SIGNED_IN" }), n.user.email && this.recordLastLoginEmail(n.user.email), n;
675
680
  }
676
681
  gcOAuthFlows() {
677
682
  const t = Date.now() - Q;
@@ -700,10 +705,10 @@ class mt {
700
705
  body: JSON.stringify({ refresh_token: t })
701
706
  }
702
707
  ), a = this.toSession(s, e);
703
- return this.setSession(a), e.is_anonymous === !0 && await this.writeAnonRefreshToken(a.refresh_token), a;
708
+ return this.setSession(a, { event: "TOKEN_REFRESHED" }), e.is_anonymous === !0 && await this.writeAnonRefreshToken(a.refresh_token), a;
704
709
  } catch (s) {
705
710
  if (s instanceof o && s.status === 401)
706
- return e.is_anonymous === !0 && await this.clearAnonRefreshToken(), this.setSession(null), null;
711
+ return e.is_anonymous === !0 && await this.clearAnonRefreshToken(), this.setSession(null, { event: "SIGNED_OUT" }), null;
707
712
  throw s;
708
713
  } finally {
709
714
  this.inflightRefresh = null;
@@ -736,7 +741,7 @@ class mt {
736
741
  method: "POST",
737
742
  headers: { Authorization: `Bearer ${t}` }
738
743
  }
739
- ), this.setSession(null);
744
+ ), this.setSession(null, { event: "SIGNED_OUT" });
740
745
  }
741
746
  /**
742
747
  * Signout: чистит локальную session СРАЗУ (UX — мгновенный logout без
@@ -756,7 +761,7 @@ class mt {
756
761
  async signOut(t = {}) {
757
762
  await this.hydrated;
758
763
  const e = this.session?.access_token, s = this.session?.user.is_anonymous === !0;
759
- if (this.setSession(null), t.forgetAnonymous && await this.clearAnonRefreshToken(), !!e && !(s && !t.forgetAnonymous))
764
+ if (this.setSession(null, { event: "SIGNED_OUT" }), t.forgetAnonymous && await this.clearAnonRefreshToken(), !!e && !(s && !t.forgetAnonymous))
760
765
  try {
761
766
  await this.api.request(
762
767
  `/api/v1/paywall/${this.paywallId}/auth/signout`,
@@ -770,22 +775,35 @@ class mt {
770
775
  }
771
776
  /**
772
777
  * Подписка на изменения session: signin/signup/refresh/signOut/expired-401.
773
- * Колбек вызывается с текущим snapshot через microtask (если session есть)
774
- * + на каждое реальное изменение. Возвращает unsubscribe.
778
+ *
779
+ * Гарантированный контракт: ПЕРВЫЙ callback каждому subscriber'у — всегда
780
+ * `event = 'INITIAL_SESSION'`, дёргается асинхронно после resolve hydrate'а
781
+ * (даже если session=null — listener получает explicit «нет сессии», а не
782
+ * молчание). Все последующие callback'и — реальные переходы с конкретным
783
+ * event'ом (SIGNED_IN / SIGNED_OUT / TOKEN_REFRESHED / USER_UPDATED /
784
+ * PASSWORD_RECOVERY).
785
+ *
786
+ * Это позволяет listener'у безопасно делать «only on real signin» побочные
787
+ * эффекты (force refetch balances и т.п.) через `event === 'SIGNED_IN'`,
788
+ * не путая их с восстановлением из storage.
789
+ *
790
+ * Возвращает unsubscribe.
775
791
  */
776
792
  onAuthChange(t) {
777
- if (this.listeners.add(t), this.session) {
793
+ return this.listeners.add(t), this.hydrated.then(() => {
794
+ if (this.destroyed || !this.listeners.has(t)) return;
778
795
  const e = this.session;
779
- queueMicrotask(() => {
780
- this.listeners.has(t) && t(e);
781
- });
782
- }
783
- return () => {
796
+ try {
797
+ t("INITIAL_SESSION", e);
798
+ } catch (s) {
799
+ console.warn("[paywall] onAuthChange INITIAL_SESSION threw", s);
800
+ }
801
+ }), () => {
784
802
  this.listeners.delete(t);
785
803
  };
786
804
  }
787
805
  isFresh(t) {
788
- return t.expires_at - Date.now() > G;
806
+ return t.expires_at - Date.now() > z;
789
807
  }
790
808
  toSession(t, e) {
791
809
  const s = t.expires_at != null ? t.expires_at * 1e3 : Date.now() + t.expires_in * 1e3;
@@ -796,21 +814,21 @@ class mt {
796
814
  user: e
797
815
  };
798
816
  }
799
- setSession(t, e = {}) {
817
+ setSession(t, e) {
800
818
  if (this.destroyed) return;
801
819
  const s = this.session;
802
- this.session = t, e.skipPersist || this.persist(), tt(s, t) || this.emit();
820
+ this.session = t, e.skipPersist || this.persist(), et(s, t) || this.emit(e.event);
803
821
  }
804
- emit() {
805
- for (const t of this.listeners)
822
+ emit(t) {
823
+ for (const e of this.listeners)
806
824
  try {
807
- t(this.session);
808
- } catch (e) {
809
- console.warn("[paywall] onAuthChange listener threw", e);
825
+ e(t, this.session);
826
+ } catch (s) {
827
+ console.warn("[paywall] onAuthChange listener threw", s);
810
828
  }
811
829
  }
812
830
  storageKey() {
813
- return y.authSession(this.paywallId);
831
+ return u.authSession(this.paywallId);
814
832
  }
815
833
  async hydrate() {
816
834
  try {
@@ -819,7 +837,7 @@ class mt {
819
837
  const e = JSON.parse(t);
820
838
  if (!e || typeof e.access_token != "string" || typeof e.refresh_token != "string" || typeof e.expires_at != "number" || !e.user)
821
839
  return;
822
- this.session = e, this.emit();
840
+ this.session = e;
823
841
  } catch {
824
842
  }
825
843
  }
@@ -833,7 +851,7 @@ class mt {
833
851
  const e = JSON.parse(t);
834
852
  if (!e || typeof e.access_token != "string" || typeof e.refresh_token != "string" || typeof e.expires_at != "number" || !e.user)
835
853
  return;
836
- this.setSession(e, { skipPersist: !0 });
854
+ this.setSession(e, { skipPersist: !0, event: "SIGNED_IN" });
837
855
  } catch {
838
856
  }
839
857
  }
@@ -864,7 +882,7 @@ class mt {
864
882
  }
865
883
  async readAnonRefreshToken() {
866
884
  try {
867
- const t = await this.storage.getItem(y.anonRefreshToken(this.paywallId));
885
+ const t = await this.storage.getItem(u.anonRefreshToken(this.paywallId));
868
886
  return typeof t == "string" && t.length > 0 ? t : null;
869
887
  } catch {
870
888
  return null;
@@ -873,7 +891,7 @@ class mt {
873
891
  async writeAnonRefreshToken(t) {
874
892
  try {
875
893
  await this.storage.setItem(
876
- y.anonRefreshToken(this.paywallId),
894
+ u.anonRefreshToken(this.paywallId),
877
895
  t
878
896
  );
879
897
  } catch {
@@ -882,11 +900,41 @@ class mt {
882
900
  async clearAnonRefreshToken() {
883
901
  try {
884
902
  await this.storage.removeItem(
885
- y.anonRefreshToken(this.paywallId)
903
+ u.anonRefreshToken(this.paywallId)
886
904
  );
887
905
  } catch {
888
906
  }
889
907
  }
908
+ /**
909
+ * Last-used auth method + email — для UI бейджа "Last used" и pre-fill'а
910
+ * email-инпута. Storage paywall-scoped, поэтому переключение между
911
+ * пейволами на одном host'е не пересекает данные. Чтение всегда возвращает
912
+ * объект — отсутствующие поля = null. */
913
+ async getLastLogin() {
914
+ try {
915
+ const [t, e] = await Promise.all([
916
+ this.storage.getItem(u.lastLoginMethod(this.paywallId)),
917
+ this.storage.getItem(u.lastLoginEmail(this.paywallId))
918
+ ]);
919
+ return !t || !tt(t) ? null : { method: t, email: typeof e == "string" && e ? e : null };
920
+ } catch {
921
+ return null;
922
+ }
923
+ }
924
+ /** Запись method и email атомарно (для email/password flows — оба известны
925
+ * на момент signin/signup'а). OAuth-flows используют раздельные
926
+ * recordLastLoginMethod (до popup) и recordLastLoginEmail (после exchange). */
927
+ recordLastLogin(t, e) {
928
+ this.recordLastLoginMethod(t), e && this.recordLastLoginEmail(e);
929
+ }
930
+ recordLastLoginMethod(t) {
931
+ this.storage.setItem(u.lastLoginMethod(this.paywallId), t).catch(() => {
932
+ });
933
+ }
934
+ recordLastLoginEmail(t) {
935
+ this.storage.setItem(u.lastLoginEmail(this.paywallId), t).catch(() => {
936
+ });
937
+ }
890
938
  /**
891
939
  * Читает stable visitor_id из storage если он там уже есть. НЕ генерит:
892
940
  * AuthClient может быть инстанцирован раньше BillingClient, а синтетический
@@ -896,7 +944,7 @@ class mt {
896
944
  */
897
945
  async readVisitorId() {
898
946
  try {
899
- const t = await this.storage.getItem(y.visitorId);
947
+ const t = await this.storage.getItem(u.visitorId);
900
948
  return typeof t == "string" && t.length >= 16 ? t : void 0;
901
949
  } catch {
902
950
  return;
@@ -908,19 +956,19 @@ function Z(i, t) {
908
956
  return new Promise((e, s) => {
909
957
  let a = !1;
910
958
  const n = () => {
911
- a = !0, window.removeEventListener("message", r), clearInterval(l), clearTimeout(u);
912
- }, r = (d) => {
959
+ a = !0, window.removeEventListener("message", r), clearInterval(h), clearTimeout(f);
960
+ }, r = (p) => {
913
961
  if (a) return;
914
- const c = d.data;
915
- if (!(!c || c.type !== "pw-oauth") && c.messageId === t) {
916
- if (c.status === "success" && c.code) {
962
+ const l = p.data;
963
+ if (!(!l || l.type !== "pw-oauth") && l.messageId === t) {
964
+ if (l.status === "success" && l.code) {
917
965
  n();
918
966
  try {
919
967
  i.close();
920
968
  } catch {
921
969
  }
922
- e(c.code);
923
- } else if (c.status === "error") {
970
+ e(l.code);
971
+ } else if (l.status === "error") {
924
972
  n();
925
973
  try {
926
974
  i.close();
@@ -929,21 +977,21 @@ function Z(i, t) {
929
977
  s(
930
978
  new o(
931
979
  "oauth_failed",
932
- c.description || c.error || "OAuth provider returned error"
980
+ l.description || l.error || "OAuth provider returned error"
933
981
  )
934
982
  );
935
983
  }
936
984
  }
937
- }, l = setInterval(() => {
985
+ }, h = setInterval(() => {
938
986
  if (a) return;
939
- let d;
987
+ let p;
940
988
  try {
941
- d = i.closed;
989
+ p = i.closed;
942
990
  } catch {
943
991
  return;
944
992
  }
945
- d && (n(), s(new o("oauth_cancelled", "auth popup was closed")));
946
- }, Y), u = setTimeout(() => {
993
+ p && (n(), s(new o("oauth_cancelled", "auth popup was closed")));
994
+ }, Y), f = setTimeout(() => {
947
995
  if (!a) {
948
996
  n();
949
997
  try {
@@ -956,15 +1004,22 @@ function Z(i, t) {
956
1004
  window.addEventListener("message", r);
957
1005
  });
958
1006
  }
959
- function tt(i, t) {
1007
+ function tt(i) {
1008
+ return i === "google" || i === "apple" || i === "github" || i === "facebook" || i === "email";
1009
+ }
1010
+ function et(i, t) {
960
1011
  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
1012
  }
962
- const et = "https://appbox.space";
963
1013
  class st {
964
1014
  constructor(t) {
965
1015
  if (!t.paywallId)
966
1016
  throw new o("invalid_config", "paywallId is required");
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(
1017
+ if (!t.apiOrigin)
1018
+ throw new o(
1019
+ "invalid_config",
1020
+ "apiOrigin is required. Pass the paywall custom_domain configured in the platform."
1021
+ );
1022
+ this.paywallId = t.paywallId, this.apiOrigin = t.apiOrigin, 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
1023
  "[paywall] WARNING: ApiGatewayClient.userId set without auth in browser. Client can spoof userId. Use AuthClient + Bearer for trusted user.id."
969
1024
  );
970
1025
  }
@@ -978,37 +1033,37 @@ class st {
978
1033
  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
1034
  const n = await this.auth?.getAccessToken();
980
1035
  n ? a.set("Authorization", `Bearer ${n}`) : this.userId && a.set("X-User-ID", this.userId);
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";
1036
+ const r = typeof FormData < "u" && t.body instanceof FormData, h = typeof Blob < "u" && t.body instanceof Blob, f = typeof ReadableStream < "u" && t.body instanceof ReadableStream, p = typeof t.body == "string";
1037
+ let l;
1038
+ t.body === void 0 || t.body === null ? l = void 0 : r || h || f || p ? l = t.body : (l = JSON.stringify(t.body), a.has("Content-Type") || a.set("Content-Type", "application/json"));
1039
+ const d = this.customFetch ?? fetch;
982
1040
  let c;
983
- t.body === void 0 || t.body === null ? c = void 0 : r || l || u || d ? c = t.body : (c = JSON.stringify(t.body), a.has("Content-Type") || a.set("Content-Type", "application/json"));
984
- const f = this.customFetch ?? fetch;
985
- let h;
986
1041
  try {
987
- h = await f(s.toString(), {
1042
+ c = await d(s.toString(), {
988
1043
  method: t.method ?? "POST",
989
1044
  headers: a,
990
- body: c,
1045
+ body: l,
991
1046
  signal: t.signal,
992
1047
  credentials: "omit"
993
1048
  });
994
- } catch (p) {
995
- const K = p instanceof Error ? p.message : String(p);
996
- throw new o("network_error", `Network request failed: ${K}`, { cause: p });
1049
+ } catch (y) {
1050
+ const $ = y instanceof Error ? y.message : String(y);
1051
+ throw new o("network_error", `Network request failed: ${$}`, { cause: y });
997
1052
  }
998
- if (h.status === 402) {
999
- const p = await it(h);
1000
- throw this.onQuotaExceeded?.(p), p;
1053
+ if (c.status === 402) {
1054
+ const y = await it(c);
1055
+ throw this.onQuotaExceeded?.(y), y;
1001
1056
  }
1002
- if (!h.ok) {
1003
- const p = await at(h.clone());
1057
+ if (!c.ok) {
1058
+ const y = await at(c.clone());
1004
1059
  throw new o(
1005
- p ?? `http_${h.status}`,
1006
- h.statusText || "Gateway request failed",
1007
- { status: h.status }
1060
+ y ?? `http_${c.status}`,
1061
+ c.statusText || "Gateway request failed",
1062
+ { status: c.status }
1008
1063
  );
1009
1064
  }
1010
- const g = h.headers.get("X-Query-Type") ?? void 0;
1011
- return this.onChargeSuccess?.(g), h;
1065
+ const g = c.headers.get("X-Query-Type") ?? void 0;
1066
+ return this.onChargeSuccess?.(g), c;
1012
1067
  }
1013
1068
  }
1014
1069
  async function it(i) {
@@ -1023,7 +1078,7 @@ async function it(i) {
1023
1078
  const a = e[0];
1024
1079
  Array.isArray(a) ? s = a : a && Array.isArray(a.balances) && (s = a.balances);
1025
1080
  }
1026
- return new N({
1081
+ return new F({
1027
1082
  balances: s,
1028
1083
  queryType: t.details?.queryType ?? "",
1029
1084
  currentBalance: t.details?.currentBalance ?? null
@@ -1038,10 +1093,11 @@ async function at(i) {
1038
1093
  return null;
1039
1094
  }
1040
1095
  }
1041
- const nt = 5e3, rt = 30 * 6e4, _ = 60 * 6e4, ot = 5 * 6e4, k = {
1096
+ const nt = 5e3, rt = 30 * 6e4, k = 60 * 6e4, ot = 5 * 6e4, S = {
1042
1097
  has_active_subscription: !1,
1043
1098
  purchases: [],
1044
- trial: null
1099
+ trial: null,
1100
+ had_previous_trial: !1
1045
1101
  };
1046
1102
  function A(i) {
1047
1103
  return i && (i.email || i.userId || i.anonymousId) || "guest";
@@ -1050,23 +1106,27 @@ function ct(i, t) {
1050
1106
  return i === t ? !0 : !i || !t ? !1 : JSON.stringify(i) === JSON.stringify(t);
1051
1107
  }
1052
1108
  const ht = 5e3, T = 5 * 6e4, lt = 3e4;
1053
- function ut(i, t) {
1109
+ function dt(i, t) {
1054
1110
  if (i === t) return !0;
1055
1111
  if (!i || !t || i.length !== t.length) return !1;
1056
1112
  for (let e = 0; e < i.length; e++)
1057
1113
  if (i[e].type !== t[e].type || i[e].count !== t[e].count) return !1;
1058
1114
  return !0;
1059
1115
  }
1060
- const dt = "https://appbox.space";
1061
- class bt {
1116
+ class It {
1062
1117
  constructor(t) {
1063
1118
  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
1119
  throw new o("invalid_config", "paywallId is required");
1065
- this.paywallId = t.paywallId, this.apiOrigin = t.apiOrigin ?? dt, this.capabilities = t.capabilities, this.auth = t.auth, this.previewMode = t.preview === !0;
1120
+ if (!t.apiOrigin)
1121
+ throw new o(
1122
+ "invalid_config",
1123
+ 'apiOrigin is required. Pass the paywall custom_domain configured in the platform (e.g. "https://pay.your-domain.com"). The legacy "appbox.space" fallback is not used in SDK 3.0.'
1124
+ );
1125
+ this.paywallId = t.paywallId, this.apiOrigin = t.apiOrigin, this.capabilities = t.capabilities, this.auth = t.auth, this.previewMode = t.preview === !0;
1066
1126
  const e = t.auth?.getCachedUser();
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(
1127
+ this.identity = t.identity ?? (e ? O(e) : void 0), this.apiKey = t.apiKey, this.fetchImpl = t.fetch, t.apiKey && typeof window < "u" && typeof window.document < "u" && console.error(
1068
1128
  "[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 = R(t.storage), this.api = new P({
1129
+ ), this.storage = K(t.storage), this.api = new P({
1070
1130
  apiOrigin: this.apiOrigin,
1071
1131
  paywallId: t.paywallId,
1072
1132
  capabilities: t.capabilities,
@@ -1075,9 +1135,9 @@ class bt {
1075
1135
  // делает lazy refresh, дедупит, на 401 возвращает null — тогда
1076
1136
  // Authorization-хедер просто не выставится.
1077
1137
  getAuthToken: t.auth ? () => t.auth.getAccessToken() : void 0
1078
- }), t.auth && (this.authUnsubscribe = t.auth.onAuthChange((s) => {
1079
- const a = s ? U(s.user) : void 0;
1080
- ft(this.identity, a) || this.setIdentity(a);
1138
+ }), t.auth && (this.authUnsubscribe = t.auth.onAuthChange((s, a) => {
1139
+ const n = a ? O(a.user) : void 0;
1140
+ ut(this.identity, n) || this.setIdentity(n);
1081
1141
  })), this.hydrateUserFromStorage(), this.hydrateBootstrapFromStorage(), this.subscribeBootstrapStorage(), this.hydrateBalancesFromStorage(), this.subscribeBalancesStorage(), this.visitorIdPromise = B(this.storage).then((s) => (this.visitorId = s, s));
1082
1142
  }
1083
1143
  /**
@@ -1093,8 +1153,8 @@ class bt {
1093
1153
  return this.visitorId;
1094
1154
  }
1095
1155
  setIdentity(t) {
1096
- this.identity = t, this.cachedUser = null, this.cachedUserAt = 0, this.inflightUser = null, this.cachedBalances = null, this.cachedBalancesAt = 0, this.inflightBalances = null, this.balancesStorageUnwatch && (this.balancesStorageUnwatch(), this.balancesStorageUnwatch = null), this.hydrateBalancesFromStorage(), this.subscribeBalancesStorage(), this.hydrateUserFromStorage(), t && this.getUser({ force: !0 }).catch(() => {
1097
- });
1156
+ this.identity = t, this.cachedUser = null, this.cachedUserAt = 0, this.inflightUser = null, this.cachedBalances = null, this.cachedBalancesAt = 0, this.inflightBalances = null, this.balancesStorageUnwatch && (this.balancesStorageUnwatch(), this.balancesStorageUnwatch = null), this.hydrateBalancesFromStorage(), this.subscribeBalancesStorage(), this.hydrateUserFromStorage(), t ? this.getUser({ force: !0 }).catch(() => {
1157
+ }) : (this.applyUser(S), this.applyBalances([]));
1098
1158
  }
1099
1159
  /**
1100
1160
  * Отписаться от auth-event'ов и сбросить listener'ы. Вызывать когда
@@ -1122,9 +1182,9 @@ class bt {
1122
1182
  "BillingClient in preview mode but cachedBootstrap is not seeded. Call setBootstrap(bootstrap) before open()."
1123
1183
  );
1124
1184
  }
1125
- const s = Date.now(), a = this.cachedBootstrap && this.cachedBootstrapAt > 0 && s - this.cachedBootstrapAt < _;
1185
+ const s = Date.now(), a = this.cachedBootstrap && this.cachedBootstrapAt > 0 && s - this.cachedBootstrapAt < k;
1126
1186
  return !e.force && a ? (s - this.cachedBootstrapAt > ot && this.revalidateBootstrap(e.signal).catch(() => {
1127
- }), this.cachedBootstrap) : this.inflightBootstrap ? this.inflightBootstrap : (this.inflightBootstrap = this.fetchBootstrap({
1187
+ }), { ...this.cachedBootstrap, user: this.cachedUser ?? void 0 }) : this.inflightBootstrap ? this.inflightBootstrap : (this.inflightBootstrap = this.fetchBootstrap({
1128
1188
  ifVersion: e.force ? void 0 : this.cachedBootstrap?.version,
1129
1189
  signal: e.signal
1130
1190
  }).finally(() => {
@@ -1172,7 +1232,7 @@ class bt {
1172
1232
  offers: t.offers !== void 0 ? t.offers : e.offers,
1173
1233
  version: `preview:${++this.previewVersionCounter}`
1174
1234
  };
1175
- s.layout || (s.layout = O(s.settings, s.prices)), w(s), this.cachedBootstrap = s, this.cachedBootstrapAt = Date.now();
1235
+ s.layout || (s.layout = E(s.settings, s.prices)), w(s), this.cachedBootstrap = s, this.cachedBootstrapAt = Date.now();
1176
1236
  for (const a of this.bootstrapListeners)
1177
1237
  try {
1178
1238
  a(s);
@@ -1194,7 +1254,7 @@ class bt {
1194
1254
  if ("unchanged" in a && a.unchanged)
1195
1255
  return this.cachedBootstrap ? (this.cachedBootstrapAt = Date.now(), a.user && this.applyUser(a.user), this.cachedBootstrap) : this.fetchBootstrap({ signal: t.signal });
1196
1256
  const n = a;
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;
1257
+ return ft(n.settings.custom_domain, this.apiOrigin), n.layout || (n.layout = E(n.settings, n.prices)), w(n), this.applyBootstrap(n, { persist: !0 }), n.user && this.applyUser(n.user), n;
1198
1258
  }
1199
1259
  // Фоновый revalidate из stale-while-revalidate ветки. Дедуплицируется через
1200
1260
  // `inflightBootstrap`, чтобы параллельные revalidate'ы не пересекались.
@@ -1224,10 +1284,10 @@ class bt {
1224
1284
  async hydrateBootstrapFromStorage() {
1225
1285
  if (!this.cachedBootstrap)
1226
1286
  try {
1227
- const t = await this.storage.getItem(y.bootstrap(this.paywallId));
1287
+ const t = await this.storage.getItem(u.bootstrap(this.paywallId));
1228
1288
  if (!t) return;
1229
1289
  const e = JSON.parse(t);
1230
- if (!e?.bootstrap || Date.now() - e.at > _ || this.cachedBootstrap) return;
1290
+ if (!e?.bootstrap || Date.now() - e.at > k || this.cachedBootstrap) return;
1231
1291
  w(e.bootstrap), this.cachedBootstrap = e.bootstrap, this.cachedBootstrapAt = e.at;
1232
1292
  for (const s of this.bootstrapListeners)
1233
1293
  try {
@@ -1243,7 +1303,7 @@ class bt {
1243
1303
  try {
1244
1304
  const { user: e, ...s } = t;
1245
1305
  await this.storage.setItem(
1246
- y.bootstrap(this.paywallId),
1306
+ u.bootstrap(this.paywallId),
1247
1307
  JSON.stringify({ at: Date.now(), bootstrap: s })
1248
1308
  );
1249
1309
  } catch {
@@ -1254,7 +1314,7 @@ class bt {
1254
1314
  // no-op, всё работает как раньше через сеть.
1255
1315
  subscribeBootstrapStorage() {
1256
1316
  typeof this.storage.watch == "function" && (this.bootstrapStorageUnwatch = this.storage.watch(
1257
- y.bootstrap(this.paywallId),
1317
+ u.bootstrap(this.paywallId),
1258
1318
  (t) => {
1259
1319
  if (t)
1260
1320
  try {
@@ -1292,6 +1352,15 @@ class bt {
1292
1352
  getCachedPrices() {
1293
1353
  return this.cachedBootstrap?.prices ?? null;
1294
1354
  }
1355
+ /** Sync-снимок офферов из последнего bootstrap'а. null = bootstrap ещё не
1356
+ * загружали, пустой массив = бэк отдал пейвол без офферов. Бэк уже
1357
+ * применил серверный таргетинг (target_countries / target_emails /
1358
+ * targeting_mode из offer_settings) — наружу выезжает только то, что
1359
+ * применимо к текущему юзеру. Клиентская сторона остаётся ответственной
1360
+ * за price_id-matching и countdown (см. core/offer.ts → resolveOffer). */
1361
+ getCachedOffers() {
1362
+ return this.cachedBootstrap?.offers ?? null;
1363
+ }
1295
1364
  /**
1296
1365
  * Снимок того, какой язык SDK сейчас считает «языком юзера». Полезно для
1297
1366
  * синхронизации i18n хоста с тем, что фактически показывает пейвол — чтобы
@@ -1311,7 +1380,7 @@ class bt {
1311
1380
  * есть `navigator.language`.
1312
1381
  */
1313
1382
  getUserLanguage() {
1314
- const t = typeof navigator < "u" && navigator.language ? navigator.language : null, e = this.cachedBootstrap?.settings.locale_default ?? null, s = this.cachedBootstrap ? $(this.cachedBootstrap) : null;
1383
+ const t = typeof navigator < "u" && navigator.language ? navigator.language : null, e = this.cachedBootstrap?.settings.locale_default ?? null, s = this.cachedBootstrap ? M(this.cachedBootstrap) : null;
1315
1384
  return { tag: s ?? t ?? e, applied: s, browserLanguage: t, countryLanguage: e };
1316
1385
  }
1317
1386
  /**
@@ -1326,7 +1395,7 @@ class bt {
1326
1395
  return !t && this.cachedUser && Date.now() - this.cachedUserAt < nt ? this.cachedUser : this.inflightUser ? this.inflightUser : (this.inflightUser = (async () => {
1327
1396
  try {
1328
1397
  if (!this.identity?.email)
1329
- return this.applyUser(k), k;
1398
+ return this.applyUser(S), S;
1330
1399
  const s = await this.api.request(
1331
1400
  `/api/v1/paywall/${this.paywallId}/user-state`,
1332
1401
  { headers: { "X-User-Email": this.identity.email }, signal: e }
@@ -1391,7 +1460,7 @@ class bt {
1391
1460
  }
1392
1461
  }
1393
1462
  storageKey() {
1394
- return y.userState(this.paywallId, A(this.identity));
1463
+ return u.userState(this.paywallId, A(this.identity));
1395
1464
  }
1396
1465
  async hydrateUserFromStorage() {
1397
1466
  if (!this.cachedUser)
@@ -1536,7 +1605,7 @@ class bt {
1536
1605
  });
1537
1606
  }
1538
1607
  applyBalances(t, { persist: e = !0 } = {}) {
1539
- const s = !ut(this.cachedBalances, t);
1608
+ const s = !dt(this.cachedBalances, t);
1540
1609
  if (this.cachedBalances = t, this.cachedBalancesAt = Date.now(), e && this.persistBalances(t), s)
1541
1610
  for (const a of this.balanceListeners)
1542
1611
  try {
@@ -1546,7 +1615,7 @@ class bt {
1546
1615
  }
1547
1616
  }
1548
1617
  balancesStorageKey() {
1549
- return y.balances(this.paywallId, A(this.identity));
1618
+ return u.balances(this.paywallId, A(this.identity));
1550
1619
  }
1551
1620
  async hydrateBalancesFromStorage() {
1552
1621
  if (!this.cachedBalances)
@@ -1600,23 +1669,27 @@ class bt {
1600
1669
  const e = t.idempotencyKey ?? `auto:${t.priceId}`, s = this.inflightCheckouts.get(e);
1601
1670
  if (s) return s;
1602
1671
  const n = {
1603
- "Idempotency-Key": t.idempotencyKey ?? M()
1672
+ "Idempotency-Key": t.idempotencyKey ?? R()
1604
1673
  };
1605
1674
  this.apiKey && (n["X-Api-Key"] = this.apiKey);
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`, {
1675
+ const r = this.cachedBootstrap?.settings, h = t.successUrl ?? r?.success_redirect_url ?? void 0, f = t.shopUrl ?? r?.checkout_shop_url ?? void 0, l = this.cachedBootstrap?.prices.find(
1676
+ (c) => c.id === t.priceId
1677
+ )?.local?.currency ?? void 0, d = this.api.request(`/api/v1/paywall/${this.paywallId}/start-checkout`, {
1607
1678
  method: "POST",
1608
1679
  headers: n,
1609
1680
  signal: t.signal,
1610
1681
  body: JSON.stringify({
1611
1682
  email: this.identity.email,
1612
1683
  priceId: Number(t.priceId),
1613
- successUrl: l,
1684
+ offerId: t.offerId,
1685
+ successUrl: h,
1614
1686
  errorUrl: t.errorUrl,
1615
- shopUrl: u,
1687
+ shopUrl: f,
1616
1688
  productName: r?.checkout_product_name ?? void 0,
1617
1689
  trial_days: t.trialDays,
1618
1690
  ignoreActivePurchase: t.ignoreActivePurchase ? !0 : void 0,
1619
- userMeta: this.identity.userId ? { userId: this.identity.userId } : void 0
1691
+ userMeta: this.identity.userId ? { userId: this.identity.userId } : void 0,
1692
+ localCurrency: l
1620
1693
  })
1621
1694
  }).then((c) => ({ url: c.checkoutUrl, acquiring: c.acquiring })).catch((c) => {
1622
1695
  throw c instanceof o && c.status === 409 && c.cause && typeof c.cause == "object" && c.cause.hasActivePurchase === !0 ? new o(
@@ -1636,7 +1709,9 @@ class bt {
1636
1709
  * инвойсы). Опен-флоу управляется host'ом:
1637
1710
  *
1638
1711
  * ```ts
1639
- * const { url } = await billing.getCustomerPortalUrl();
1712
+ * const { url } = await billing.getCustomerPortalUrl({
1713
+ * returnUrl: 'https://your-app.com/account'
1714
+ * });
1640
1715
  * window.open(url, '_blank');
1641
1716
  * ```
1642
1717
  *
@@ -1654,9 +1729,10 @@ class bt {
1654
1729
  );
1655
1730
  const e = {};
1656
1731
  this.apiKey && (e["X-Api-Key"] = this.apiKey);
1657
- const s = this.auth && this.auth.getCachedSession() ? {} : {
1732
+ const s = this.auth && this.auth.getCachedSession() ? { returnUrl: t.returnUrl } : {
1658
1733
  email: this.identity?.email,
1659
- userMeta: this.identity?.userId ? { userId: this.identity.userId } : void 0
1734
+ userMeta: this.identity?.userId ? { userId: this.identity.userId } : void 0,
1735
+ returnUrl: t.returnUrl
1660
1736
  };
1661
1737
  return { url: (await this.api.request(
1662
1738
  `/api/v1/paywall/${this.paywallId}/get-customer-portal`,
@@ -1675,43 +1751,65 @@ class bt {
1675
1751
  * `/api/v1/paywall/[id]/user` без unstable_cache, потому что list для UI
1676
1752
  * должен быть свежим после cancel-а.
1677
1753
  *
1678
- * Auth: Bearer обязателен (через AuthClient). Без Bearer — 401 от бэка,
1679
- * пробрасываем как PaywallError('http_401'). Гость пустой список.
1754
+ * Auth (два пути):
1755
+ * - Bearer (через AuthClient) — user.id резолвится из сессии, identity
1756
+ * в query игнорируется.
1757
+ * - `apiKey` + `identity.email`/`identity.userId` — server-SDK путь для
1758
+ * интеграций со своей авторизацией. Бэк проверяет, что identity линкована
1759
+ * к этому пейволу (защита от cross-paywall lookup).
1760
+ * Без auth и без apiKey+identity — `identity_required`.
1680
1761
  */
1681
1762
  async listPurchases(t = {}) {
1682
- if (!this.auth)
1763
+ const e = !!(this.identity?.email || this.identity?.userId);
1764
+ if (!this.auth && !(this.apiKey && e))
1683
1765
  throw new o(
1684
- "auth_required",
1685
- "listPurchases requires AuthClient (Bearer auth)"
1766
+ "identity_required",
1767
+ "listPurchases requires AuthClient (Bearer) or apiKey + identity.email/userId"
1686
1768
  );
1687
- return (await this.api.request(`/api/v1/paywall/${this.paywallId}/user`, {
1769
+ const s = {};
1770
+ this.apiKey && (s["X-Api-Key"] = this.apiKey);
1771
+ const a = new URLSearchParams();
1772
+ this.apiKey && this.identity?.email && a.set("email", this.identity.email), this.apiKey && this.identity?.userId && a.set("user_id", this.identity.userId);
1773
+ const n = a.toString(), r = n ? `/api/v1/paywall/${this.paywallId}/user?${n}` : `/api/v1/paywall/${this.paywallId}/user`;
1774
+ return (await this.api.request(r, {
1688
1775
  method: "GET",
1776
+ headers: s,
1689
1777
  signal: t.signal
1690
1778
  })).purchases ?? [];
1691
1779
  }
1692
1780
  /**
1693
- * Отменить подписку. Бэк проверит что subscription принадлежит auth-юзеру
1694
- * и сделает cancel у acquiring'а (Stripe/Paddle/Chargebee). По умолчанию
1695
- * cancel в конце текущего периода — юзер сохраняет access до renewal date'ы.
1781
+ * Отменить подписку. Бэк проверит, что subscription принадлежит юзеру
1782
+ * (Bearer-путь из сессии; apiKey-путь — из identity), и сделает cancel у
1783
+ * acquiring'а (Stripe/Paddle/Chargebee/Overpay). По умолчанию cancel в
1784
+ * конце текущего периода — юзер сохраняет access до renewal date'ы.
1696
1785
  *
1697
- * `reason` обязательна (валидация на бэке). Удобно собрать через select
1698
- * причин в host-UI, как в legacy customer portal'е.
1786
+ * `reason` обязательна (валидация на бэке).
1699
1787
  *
1700
- * Auth: Bearer обязателен.
1788
+ * Auth (два пути):
1789
+ * - Bearer (через AuthClient) — стандартный путь для UI customer-portal'a.
1790
+ * - `apiKey` + `identity.email`/`identity.userId` — для self-service UI на
1791
+ * бэке клиента со своей авторизацией. Бэк дополнительно фильтрует
1792
+ * subscription по paywall_id, чтобы owner пейвола A не отменил подписку
1793
+ * пейвола B.
1701
1794
  */
1702
1795
  async cancelSubscription(t) {
1703
- if (!this.auth)
1796
+ const e = !!(this.identity?.email || this.identity?.userId);
1797
+ if (!this.auth && !(this.apiKey && e))
1704
1798
  throw new o(
1705
- "auth_required",
1706
- "cancelSubscription requires AuthClient (Bearer auth)"
1799
+ "identity_required",
1800
+ "cancelSubscription requires AuthClient (Bearer) or apiKey + identity.email/userId"
1707
1801
  );
1708
- return this.api.request("/api/paywall/cancel-subscription", {
1802
+ const s = {};
1803
+ this.apiKey && (s["X-Api-Key"] = this.apiKey);
1804
+ const a = {
1805
+ subscriptionId: t.subscriptionId,
1806
+ paywallId: this.paywallId,
1807
+ cancellationReason: t.reason
1808
+ };
1809
+ return this.apiKey && this.identity?.email && (a.email = this.identity.email), this.apiKey && this.identity?.userId && (a.userId = this.identity.userId), this.api.request("/api/paywall/cancel-subscription", {
1709
1810
  method: "POST",
1710
- body: JSON.stringify({
1711
- subscriptionId: t.subscriptionId,
1712
- paywallId: this.paywallId,
1713
- cancellationReason: t.reason
1714
- }),
1811
+ headers: s,
1812
+ body: JSON.stringify(a),
1715
1813
  signal: t.signal
1716
1814
  });
1717
1815
  }
@@ -1744,23 +1842,46 @@ class bt {
1744
1842
  });
1745
1843
  }
1746
1844
  }
1747
- function U(i) {
1845
+ function O(i) {
1748
1846
  return { email: i.email, userId: i.id };
1749
1847
  }
1750
- function ft(i, t) {
1848
+ function ut(i, t) {
1751
1849
  return i === t ? !0 : !i || !t ? !1 : i.email === t.email && i.userId === t.userId && i.anonymousId === t.anonymousId;
1752
1850
  }
1753
- function O(i, t) {
1851
+ function U(i) {
1852
+ if (!i) return null;
1853
+ const t = i.trim();
1854
+ if (!t) return null;
1855
+ try {
1856
+ return new URL(t.includes("://") ? t : `https://${t}`).origin;
1857
+ } catch {
1858
+ return null;
1859
+ }
1860
+ }
1861
+ function ft(i, t) {
1862
+ const e = U(i);
1863
+ if (!(!e || U(t) === e))
1864
+ throw new o(
1865
+ "invalid_config",
1866
+ `apiOrigin mismatch: SDK initialized with "${t}" but paywall is configured with custom_domain "${i}". Use the custom_domain from the platform paywall settings.`
1867
+ );
1868
+ }
1869
+ function E(i, t) {
1754
1870
  return {
1755
1871
  type: "modal",
1756
1872
  blocks: [
1873
+ // offer_banner НЕ в default layout — PaywallRoot рендерит его как
1874
+ // top-tab над dialog'ом (rounded-top, negative margin), за пределами
1875
+ // scrollable area. Блок остаётся в registry для opt-in inline-вариантa.
1757
1876
  { type: "heading", text: i.name || "Upgrade", level: 1 },
1758
1877
  { type: "price_grid", priceIds: t.map((e) => e.id) },
1759
- { type: "cta_button", label: "Continue", action: "checkout" }
1878
+ { type: "cta_button", action: "checkout" },
1879
+ { type: "guarantee_badge" },
1880
+ { type: "current_session" }
1760
1881
  ]
1761
1882
  };
1762
1883
  }
1763
- function $(i) {
1884
+ function M(i) {
1764
1885
  const t = i.locales;
1765
1886
  if (!t) return null;
1766
1887
  const e = [];
@@ -1776,7 +1897,7 @@ function $(i) {
1776
1897
  return null;
1777
1898
  }
1778
1899
  function w(i) {
1779
- const t = $(i);
1900
+ const t = M(i);
1780
1901
  if (!t) return;
1781
1902
  const e = i.locales?.[t];
1782
1903
  e && (e.layout && (i.layout = e.layout), e.prices && (i.prices = i.prices.map((s) => {
@@ -1786,8 +1907,8 @@ function w(i) {
1786
1907
  return "label" in a && (n.label = a.label ?? null), "description" in a && (n.description = a.description ?? null), n;
1787
1908
  })));
1788
1909
  }
1789
- const yt = 1500, pt = 20, C = 200;
1790
- class vt {
1910
+ const yt = 1500, pt = 20, L = 200;
1911
+ class St {
1791
1912
  constructor(t) {
1792
1913
  this.buffer = [], this.flushTimer = null, this.destroyed = !1, this.unloadHandler = null, this.visibilityHandler = null, this.opts = t, this.isEnabled() && this.attachUnloadHandlers();
1793
1914
  }
@@ -1802,7 +1923,7 @@ class vt {
1802
1923
  this.flush();
1803
1924
  return;
1804
1925
  }
1805
- this.buffer.length > C && (this.buffer = this.buffer.slice(-C)), this.scheduleFlush();
1926
+ this.buffer.length > L && (this.buffer = this.buffer.slice(-L)), this.scheduleFlush();
1806
1927
  }
1807
1928
  scheduleFlush() {
1808
1929
  if (this.flushTimer || this.destroyed) return;
@@ -1885,14 +2006,14 @@ class vt {
1885
2006
  this.destroyed || (this.destroyed = !0, this.flushTimer && (clearTimeout(this.flushTimer), this.flushTimer = null), this.flush(), this.detachUnloadHandlers());
1886
2007
  }
1887
2008
  }
1888
- const E = 3600 * 1e3;
2009
+ const C = 3600 * 1e3;
1889
2010
  function v(i) {
1890
2011
  return `paywall-${i}-trial-time-first-open`;
1891
2012
  }
1892
- function S(i) {
2013
+ function b(i) {
1893
2014
  return `paywall-${i}-skip-times`;
1894
2015
  }
1895
- class F {
2016
+ class q {
1896
2017
  constructor(t, e, s) {
1897
2018
  this.storage = t, this.paywallId = e, this.config = s;
1898
2019
  }
@@ -1903,10 +2024,10 @@ class F {
1903
2024
  return this.config.mode === "time" ? this.recordTime() : this.recordOpens();
1904
2025
  }
1905
2026
  async reset() {
1906
- await this.storage.removeItem(this.config.mode === "time" ? v(this.paywallId) : S(this.paywallId));
2027
+ await this.storage.removeItem(this.config.mode === "time" ? v(this.paywallId) : b(this.paywallId));
1907
2028
  }
1908
2029
  async checkTime() {
1909
- const t = this.config.payload * E, e = await this.storage.getItem(v(this.paywallId)), s = e ? Number(e) : null;
2030
+ const t = this.config.payload * C, e = await this.storage.getItem(v(this.paywallId)), s = e ? Number(e) : null;
1910
2031
  if (!s || !Number.isFinite(s))
1911
2032
  return {
1912
2033
  mode: "time",
@@ -1927,7 +2048,7 @@ class F {
1927
2048
  };
1928
2049
  }
1929
2050
  async checkOpens() {
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);
2051
+ const t = this.config.payload, e = await this.storage.getItem(b(this.paywallId)), s = e ? Number(e) : 0, a = Number.isFinite(s) ? s : 0, n = a < t, r = Math.max(0, t - a);
1931
2052
  return {
1932
2053
  mode: "opens",
1933
2054
  blocked: n,
@@ -1936,7 +2057,7 @@ class F {
1936
2057
  };
1937
2058
  }
1938
2059
  async recordTime() {
1939
- const t = this.config.payload * E, e = v(this.paywallId), s = await this.storage.getItem(e);
2060
+ const t = this.config.payload * C, e = v(this.paywallId), s = await this.storage.getItem(e);
1940
2061
  let a = s ? Number(s) : null;
1941
2062
  (!a || !Number.isFinite(a)) && (a = Date.now(), await this.storage.setItem(e, String(a)));
1942
2063
  const n = a + t, r = Math.max(0, n - Date.now());
@@ -1950,23 +2071,23 @@ class F {
1950
2071
  };
1951
2072
  }
1952
2073
  async recordOpens() {
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);
2074
+ const t = this.config.payload, e = b(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);
1954
2075
  await this.storage.setItem(e, String(r));
1955
- const l = Math.max(0, t - r);
2076
+ const h = Math.max(0, t - r);
1956
2077
  return {
1957
2078
  mode: "opens",
1958
2079
  blocked: r < t,
1959
- remainingActions: l,
2080
+ remainingActions: h,
1960
2081
  totalActions: t
1961
2082
  };
1962
2083
  }
1963
2084
  }
1964
- let L = !1;
2085
+ let N = !1;
1965
2086
  class gt {
1966
2087
  constructor(t, e, s) {
1967
- L || (L = !0, console.warn(
2088
+ N || (N = !0, console.warn(
1968
2089
  '[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.'
1969
- )), this.fallback = new F(t, e, s);
2090
+ )), this.fallback = new q(t, e, s);
1970
2091
  }
1971
2092
  check() {
1972
2093
  return this.fallback.check();
@@ -1978,11 +2099,11 @@ class gt {
1978
2099
  return this.fallback.reset();
1979
2100
  }
1980
2101
  }
1981
- function St(i, t, e) {
1982
- return e.storage === "server" ? new gt(i, t, e) : new F(i, t, e);
2102
+ function vt(i, t, e) {
2103
+ return e.storage === "server" ? new gt(i, t, e) : new q(i, t, e);
1983
2104
  }
1984
- const It = 1;
1985
- function Bt(i) {
2105
+ const bt = 1;
2106
+ function _t(i) {
1986
2107
  return i instanceof o ? {
1987
2108
  name: "PaywallError",
1988
2109
  code: i.code,
@@ -2000,7 +2121,7 @@ function Bt(i) {
2000
2121
  message: typeof i == "string" ? i : "Unknown error"
2001
2122
  };
2002
2123
  }
2003
- function _t(i) {
2124
+ function Bt(i) {
2004
2125
  if (i.name === "PaywallError") {
2005
2126
  const e = new o(i.code, i.message, { status: i.status });
2006
2127
  return i.stack && (e.stack = i.stack), e;
@@ -2011,7 +2132,7 @@ function _t(i) {
2011
2132
  function wt(i) {
2012
2133
  let t = !1;
2013
2134
  const e = /* @__PURE__ */ new Set(), s = /* @__PURE__ */ new Set(), a = (r) => {
2014
- for (const l of e) l(r);
2135
+ for (const h of e) h(r);
2015
2136
  }, n = () => {
2016
2137
  if (!t) {
2017
2138
  t = !0;
@@ -2024,8 +2145,8 @@ function wt(i) {
2024
2145
  if (!t)
2025
2146
  try {
2026
2147
  i.postMessage(r);
2027
- } catch (l) {
2028
- throw n(), l;
2148
+ } catch (h) {
2149
+ throw n(), h;
2029
2150
  }
2030
2151
  },
2031
2152
  onMessage(r) {
@@ -2046,15 +2167,15 @@ function kt(i) {
2046
2167
  }
2047
2168
  export {
2048
2169
  mt as A,
2049
- bt as B,
2050
- vt as E,
2170
+ It as B,
2171
+ St as E,
2051
2172
  o as P,
2052
- It as a,
2173
+ bt as a,
2053
2174
  kt as b,
2054
- St as c,
2175
+ vt as c,
2055
2176
  wt as p,
2056
- _t as r,
2057
- Bt as s,
2177
+ Bt as r,
2178
+ _t as s,
2058
2179
  Z as w
2059
2180
  };
2060
- //# sourceMappingURL=chrome-port-DPFUj1MP.js.map
2181
+ //# sourceMappingURL=chrome-port-bfTUUDz_.js.map