@monetize.software/sdk 3.0.0-alpha.8 → 3.0.0-beta.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (213) hide show
  1. package/dist/chunks/PaywallUI-CCwYgagL.js +26 -0
  2. package/dist/chunks/PaywallUI-CCwYgagL.js.map +1 -0
  3. package/dist/chunks/PaywallUI-CDlJL5Em.js +3599 -0
  4. package/dist/chunks/PaywallUI-CDlJL5Em.js.map +1 -0
  5. package/dist/chunks/ar-CViBaj16.js +2 -0
  6. package/dist/chunks/ar-CViBaj16.js.map +1 -0
  7. package/dist/chunks/{ar-CHae8g-2.js → ar-ClwBmll7.js} +6 -2
  8. package/dist/chunks/ar-ClwBmll7.js.map +1 -0
  9. package/dist/chunks/{cs-eZTedzaK.js → cs-Cc_D0W4S.js} +6 -2
  10. package/dist/chunks/cs-Cc_D0W4S.js.map +1 -0
  11. package/dist/chunks/cs-DQJWP65K.js +2 -0
  12. package/dist/chunks/cs-DQJWP65K.js.map +1 -0
  13. package/dist/chunks/{da-Dca6j8fp.js → da-BtKcMSxH.js} +6 -2
  14. package/dist/chunks/da-BtKcMSxH.js.map +1 -0
  15. package/dist/chunks/da-Cyr_IXhb.js +2 -0
  16. package/dist/chunks/da-Cyr_IXhb.js.map +1 -0
  17. package/dist/chunks/de-BOCUj1pF.js +2 -0
  18. package/dist/chunks/de-BOCUj1pF.js.map +1 -0
  19. package/dist/chunks/{de-BCjn3PUI.js → de-iwQW5eYl.js} +6 -2
  20. package/dist/chunks/de-iwQW5eYl.js.map +1 -0
  21. package/dist/chunks/{el-BpXtDTez.js → el-BoH65CeJ.js} +6 -2
  22. package/dist/chunks/el-BoH65CeJ.js.map +1 -0
  23. package/dist/chunks/el-C6jLHiEF.js +2 -0
  24. package/dist/chunks/el-C6jLHiEF.js.map +1 -0
  25. package/dist/chunks/es-CARHLxHR.js +2 -0
  26. package/dist/chunks/es-CARHLxHR.js.map +1 -0
  27. package/dist/chunks/{es-B3P4nlMw.js → es-CkP16_8K.js} +6 -2
  28. package/dist/chunks/es-CkP16_8K.js.map +1 -0
  29. package/dist/chunks/fi-B8OhRbwY.js +2 -0
  30. package/dist/chunks/fi-B8OhRbwY.js.map +1 -0
  31. package/dist/chunks/{fi-BbQ_Bs0Z.js → fi-yUXSmK1E.js} +6 -2
  32. package/dist/chunks/fi-yUXSmK1E.js.map +1 -0
  33. package/dist/chunks/fr-CoM18zzM.js +2 -0
  34. package/dist/chunks/fr-CoM18zzM.js.map +1 -0
  35. package/dist/chunks/{fr-BKDUXceO.js → fr-DSZRGsxI.js} +6 -2
  36. package/dist/chunks/fr-DSZRGsxI.js.map +1 -0
  37. package/dist/chunks/he-DTDVc3lA.js +2 -0
  38. package/dist/chunks/he-DTDVc3lA.js.map +1 -0
  39. package/dist/chunks/{he-BVCHlTtT.js → he-ZUo7cQjk.js} +8 -4
  40. package/dist/chunks/he-ZUo7cQjk.js.map +1 -0
  41. package/dist/chunks/hi-BjnS9UeE.js +2 -0
  42. package/dist/chunks/hi-BjnS9UeE.js.map +1 -0
  43. package/dist/chunks/{hi-H_Hshh-7.js → hi-CEutBKiG.js} +6 -2
  44. package/dist/chunks/hi-CEutBKiG.js.map +1 -0
  45. package/dist/chunks/hu-CN06FMhV.js +2 -0
  46. package/dist/chunks/hu-CN06FMhV.js.map +1 -0
  47. package/dist/chunks/{hu-ZWiNfzvN.js → hu-DvEAWGS7.js} +6 -2
  48. package/dist/chunks/hu-DvEAWGS7.js.map +1 -0
  49. package/dist/chunks/id-BITgaBxq.js +2 -0
  50. package/dist/chunks/id-BITgaBxq.js.map +1 -0
  51. package/dist/chunks/{id-DeiRYsJ1.js → id-_eEMrYMW.js} +6 -2
  52. package/dist/chunks/id-_eEMrYMW.js.map +1 -0
  53. package/dist/chunks/index-CLB1AgLg.js +2074 -0
  54. package/dist/chunks/index-CLB1AgLg.js.map +1 -0
  55. package/dist/chunks/index-CzDSBl4d.js +2 -0
  56. package/dist/chunks/index-CzDSBl4d.js.map +1 -0
  57. package/dist/chunks/{it-UH9OzFhg.js → it-BAmsQbIl.js} +6 -2
  58. package/dist/chunks/it-BAmsQbIl.js.map +1 -0
  59. package/dist/chunks/it-DVcsq015.js +2 -0
  60. package/dist/chunks/it-DVcsq015.js.map +1 -0
  61. package/dist/chunks/ja-Bim7Ok2e.js +2 -0
  62. package/dist/chunks/ja-Bim7Ok2e.js.map +1 -0
  63. package/dist/chunks/{ja-BYC8FRN8.js → ja-BqCZWVKK.js} +8 -4
  64. package/dist/chunks/ja-BqCZWVKK.js.map +1 -0
  65. package/dist/chunks/{ko-Bjs2ZRcF.js → ko-CkIzeOzb.js} +8 -4
  66. package/dist/chunks/ko-CkIzeOzb.js.map +1 -0
  67. package/dist/chunks/ko-DqEfcVCB.js +2 -0
  68. package/dist/chunks/ko-DqEfcVCB.js.map +1 -0
  69. package/dist/chunks/nl-DSNuJWIo.js +2 -0
  70. package/dist/chunks/nl-DSNuJWIo.js.map +1 -0
  71. package/dist/chunks/{nl-Ch5HFWQO.js → nl-Mu_KNzli.js} +6 -2
  72. package/dist/chunks/nl-Mu_KNzli.js.map +1 -0
  73. package/dist/chunks/{no-CljpinWz.js → no-9HMjljBs.js} +6 -2
  74. package/dist/chunks/no-9HMjljBs.js.map +1 -0
  75. package/dist/chunks/no-B5HY_A8_.js +2 -0
  76. package/dist/chunks/no-B5HY_A8_.js.map +1 -0
  77. package/dist/chunks/{pl-CUcSS0zZ.js → pl-Cbr2qDwv.js} +6 -2
  78. package/dist/chunks/pl-Cbr2qDwv.js.map +1 -0
  79. package/dist/chunks/pl-ChGLn9Sy.js +2 -0
  80. package/dist/chunks/pl-ChGLn9Sy.js.map +1 -0
  81. package/dist/chunks/pt-CDLEktT9.js +2 -0
  82. package/dist/chunks/pt-CDLEktT9.js.map +1 -0
  83. package/dist/chunks/{pt-BHK0LwkC.js → pt-_jirA6IR.js} +6 -2
  84. package/dist/chunks/pt-_jirA6IR.js.map +1 -0
  85. package/dist/chunks/ro-BHCHiXY3.js +2 -0
  86. package/dist/chunks/ro-BHCHiXY3.js.map +1 -0
  87. package/dist/chunks/{ro-Bj8cwU2n.js → ro-oZLxhwHc.js} +6 -2
  88. package/dist/chunks/ro-oZLxhwHc.js.map +1 -0
  89. package/dist/chunks/ru-B6HgmINj.js +2 -0
  90. package/dist/chunks/ru-B6HgmINj.js.map +1 -0
  91. package/dist/chunks/{ru-CgqNy0Gb.js → ru-C2-sqY7B.js} +6 -2
  92. package/dist/chunks/ru-C2-sqY7B.js.map +1 -0
  93. package/dist/chunks/sv-DoSs4a9n.js +2 -0
  94. package/dist/chunks/sv-DoSs4a9n.js.map +1 -0
  95. package/dist/chunks/{sv-H7jroOQ5.js → sv-y385MWVy.js} +6 -2
  96. package/dist/chunks/sv-y385MWVy.js.map +1 -0
  97. package/dist/chunks/{th-Dqm-gpGe.js → th-Bjbv4M1s.js} +6 -2
  98. package/dist/chunks/th-Bjbv4M1s.js.map +1 -0
  99. package/dist/chunks/th-UeweOhwg.js +2 -0
  100. package/dist/chunks/th-UeweOhwg.js.map +1 -0
  101. package/dist/chunks/tr-BbBr5tyB.js +2 -0
  102. package/dist/chunks/tr-BbBr5tyB.js.map +1 -0
  103. package/dist/chunks/{tr-D3zPcNtT.js → tr-DmHo9F8i.js} +8 -4
  104. package/dist/chunks/tr-DmHo9F8i.js.map +1 -0
  105. package/dist/chunks/uk-CJTA1SJK.js +2 -0
  106. package/dist/chunks/uk-CJTA1SJK.js.map +1 -0
  107. package/dist/chunks/{uk-CoIIs3QI.js → uk-DwvAoTe5.js} +6 -2
  108. package/dist/chunks/uk-DwvAoTe5.js.map +1 -0
  109. package/dist/chunks/{vi-C_fruIbh.js → vi-BEpwsVLR.js} +6 -2
  110. package/dist/chunks/vi-BEpwsVLR.js.map +1 -0
  111. package/dist/chunks/vi-ZvBo7PbB.js +2 -0
  112. package/dist/chunks/vi-ZvBo7PbB.js.map +1 -0
  113. package/dist/chunks/zh-CPZBEb3d.js +2 -0
  114. package/dist/chunks/zh-CPZBEb3d.js.map +1 -0
  115. package/dist/chunks/{zh-LDkEV2D9.js → zh-DrG18oGe.js} +7 -3
  116. package/dist/chunks/zh-DrG18oGe.js.map +1 -0
  117. package/dist/core.cjs +1 -1
  118. package/dist/core.cjs.map +1 -1
  119. package/dist/core.d.ts +110 -17
  120. package/dist/core.js +17 -1984
  121. package/dist/core.js.map +1 -1
  122. package/dist/index.cjs +1 -1
  123. package/dist/index.d.ts +209 -18
  124. package/dist/index.js +17 -13
  125. package/dist/ui.cjs +1 -1
  126. package/dist/ui.d.ts +174 -17
  127. package/dist/ui.js +1 -1
  128. package/package.json +1 -1
  129. package/dist/chunks/PaywallUI-BrDiS6zg.js +0 -3219
  130. package/dist/chunks/PaywallUI-BrDiS6zg.js.map +0 -1
  131. package/dist/chunks/PaywallUI-Bvx8nRL0.js +0 -26
  132. package/dist/chunks/PaywallUI-Bvx8nRL0.js.map +0 -1
  133. package/dist/chunks/ar-CHae8g-2.js.map +0 -1
  134. package/dist/chunks/ar-E1mc8SO_.js +0 -2
  135. package/dist/chunks/ar-E1mc8SO_.js.map +0 -1
  136. package/dist/chunks/cs-Dccq6LAT.js +0 -2
  137. package/dist/chunks/cs-Dccq6LAT.js.map +0 -1
  138. package/dist/chunks/cs-eZTedzaK.js.map +0 -1
  139. package/dist/chunks/da-C_4MbEh5.js +0 -2
  140. package/dist/chunks/da-C_4MbEh5.js.map +0 -1
  141. package/dist/chunks/da-Dca6j8fp.js.map +0 -1
  142. package/dist/chunks/de-BCjn3PUI.js.map +0 -1
  143. package/dist/chunks/de-DulxcJj-.js +0 -2
  144. package/dist/chunks/de-DulxcJj-.js.map +0 -1
  145. package/dist/chunks/el-BpXtDTez.js.map +0 -1
  146. package/dist/chunks/el-CVG_1iKB.js +0 -2
  147. package/dist/chunks/el-CVG_1iKB.js.map +0 -1
  148. package/dist/chunks/es-B3P4nlMw.js.map +0 -1
  149. package/dist/chunks/es-ri0uKzUW.js +0 -2
  150. package/dist/chunks/es-ri0uKzUW.js.map +0 -1
  151. package/dist/chunks/fi-BbQ_Bs0Z.js.map +0 -1
  152. package/dist/chunks/fi-CNZqWHjw.js +0 -2
  153. package/dist/chunks/fi-CNZqWHjw.js.map +0 -1
  154. package/dist/chunks/fr-BKDUXceO.js.map +0 -1
  155. package/dist/chunks/fr-CfFOw4hD.js +0 -2
  156. package/dist/chunks/fr-CfFOw4hD.js.map +0 -1
  157. package/dist/chunks/he-BVCHlTtT.js.map +0 -1
  158. package/dist/chunks/he-DN2JEtQb.js +0 -2
  159. package/dist/chunks/he-DN2JEtQb.js.map +0 -1
  160. package/dist/chunks/hi-DxfOerNP.js +0 -2
  161. package/dist/chunks/hi-DxfOerNP.js.map +0 -1
  162. package/dist/chunks/hi-H_Hshh-7.js.map +0 -1
  163. package/dist/chunks/hu-BTImywuV.js +0 -2
  164. package/dist/chunks/hu-BTImywuV.js.map +0 -1
  165. package/dist/chunks/hu-ZWiNfzvN.js.map +0 -1
  166. package/dist/chunks/id-DeiRYsJ1.js.map +0 -1
  167. package/dist/chunks/id-YFuArJA6.js +0 -2
  168. package/dist/chunks/id-YFuArJA6.js.map +0 -1
  169. package/dist/chunks/it-UH9OzFhg.js.map +0 -1
  170. package/dist/chunks/it-mhkzXBM9.js +0 -2
  171. package/dist/chunks/it-mhkzXBM9.js.map +0 -1
  172. package/dist/chunks/ja-6l_z_G9k.js +0 -2
  173. package/dist/chunks/ja-6l_z_G9k.js.map +0 -1
  174. package/dist/chunks/ja-BYC8FRN8.js.map +0 -1
  175. package/dist/chunks/ko-Bjs2ZRcF.js.map +0 -1
  176. package/dist/chunks/ko-YAl4XwHu.js +0 -2
  177. package/dist/chunks/ko-YAl4XwHu.js.map +0 -1
  178. package/dist/chunks/nl-C-9zHtfb.js +0 -2
  179. package/dist/chunks/nl-C-9zHtfb.js.map +0 -1
  180. package/dist/chunks/nl-Ch5HFWQO.js.map +0 -1
  181. package/dist/chunks/no-CljpinWz.js.map +0 -1
  182. package/dist/chunks/no-qzPitLlx.js +0 -2
  183. package/dist/chunks/no-qzPitLlx.js.map +0 -1
  184. package/dist/chunks/pl-CUcSS0zZ.js.map +0 -1
  185. package/dist/chunks/pl-MAIYeuhW.js +0 -2
  186. package/dist/chunks/pl-MAIYeuhW.js.map +0 -1
  187. package/dist/chunks/pt-BHK0LwkC.js.map +0 -1
  188. package/dist/chunks/pt-DqDabE4v.js +0 -2
  189. package/dist/chunks/pt-DqDabE4v.js.map +0 -1
  190. package/dist/chunks/ro-BVs-lHH-.js +0 -2
  191. package/dist/chunks/ro-BVs-lHH-.js.map +0 -1
  192. package/dist/chunks/ro-Bj8cwU2n.js.map +0 -1
  193. package/dist/chunks/ru-CgqNy0Gb.js.map +0 -1
  194. package/dist/chunks/ru-DP7qDAmE.js +0 -2
  195. package/dist/chunks/ru-DP7qDAmE.js.map +0 -1
  196. package/dist/chunks/sv-B3QEYGgd.js +0 -2
  197. package/dist/chunks/sv-B3QEYGgd.js.map +0 -1
  198. package/dist/chunks/sv-H7jroOQ5.js.map +0 -1
  199. package/dist/chunks/th-Dqm-gpGe.js.map +0 -1
  200. package/dist/chunks/th-DzQau9aW.js +0 -2
  201. package/dist/chunks/th-DzQau9aW.js.map +0 -1
  202. package/dist/chunks/tr-D3zPcNtT.js.map +0 -1
  203. package/dist/chunks/tr-cG1YuE1E.js +0 -2
  204. package/dist/chunks/tr-cG1YuE1E.js.map +0 -1
  205. package/dist/chunks/uk-CoIIs3QI.js.map +0 -1
  206. package/dist/chunks/uk-Cvbo0IBW.js +0 -2
  207. package/dist/chunks/uk-Cvbo0IBW.js.map +0 -1
  208. package/dist/chunks/vi-BRtYSBUp.js +0 -2
  209. package/dist/chunks/vi-BRtYSBUp.js.map +0 -1
  210. package/dist/chunks/vi-C_fruIbh.js.map +0 -1
  211. package/dist/chunks/zh-CwczPMPp.js +0 -2
  212. package/dist/chunks/zh-CwczPMPp.js.map +0 -1
  213. package/dist/chunks/zh-LDkEV2D9.js.map +0 -1
package/dist/index.cjs CHANGED
@@ -1,2 +1,2 @@
1
- "use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const e=require("./core.cjs"),r=require("./chunks/PaywallUI-Bvx8nRL0.js");exports.ApiClient=e.ApiClient;exports.ApiGatewayClient=e.ApiGatewayClient;exports.AuthClient=e.AuthClient;exports.BillingClient=e.BillingClient;exports.EventTracker=e.EventTracker;exports.PaywallError=e.PaywallError;exports.QuotaExceededError=e.QuotaExceededError;exports.SDK_VERSION=e.SDK_VERSION;exports.STORAGE_KEYS=e.STORAGE_KEYS;exports.createStorage=e.createStorage;exports.ensureVisitorId=e.ensureVisitorId;exports.generateVisitorId=e.generateVisitorId;exports.PaywallUI=r.PaywallUI;exports.blockRegistry=r.blockRegistry;
1
+ "use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const e=require("./chunks/index-CzDSBl4d.js"),r=require("./chunks/PaywallUI-CCwYgagL.js");exports.ApiClient=e.ApiClient;exports.ApiGatewayClient=e.ApiGatewayClient;exports.AuthClient=e.AuthClient;exports.BillingClient=e.BillingClient;exports.EventTracker=e.EventTracker;exports.PaywallError=e.PaywallError;exports.QuotaExceededError=e.QuotaExceededError;exports.SDK_VERSION=e.SDK_VERSION;exports.STORAGE_KEYS=e.STORAGE_KEYS;exports.createStorage=e.createStorage;exports.ensureVisitorId=e.ensureVisitorId;exports.findApplicableOffer=e.findApplicableOffer;exports.generateVisitorId=e.generateVisitorId;exports.offerStartStorageKey=e.offerStartStorageKey;exports.readBrowserOfferStart=e.readBrowserOfferStart;exports.resolveOffer=e.resolveOffer;exports.PaywallUI=r.PaywallUI;exports.blockRegistry=r.blockRegistry;
2
2
  //# sourceMappingURL=index.cjs.map
package/dist/index.d.ts CHANGED
@@ -262,10 +262,8 @@ export declare class AuthClient {
262
262
  * когда сервер начнёт возвращать challenge_required в риск-сценариях,
263
263
  * SDK сможет передать proof-of-something обратно без breaking change.
264
264
  *
265
- * `forceCaptcha: true` пропускает шаги 1-2 и сразу делает /signin (создаёт
266
- * нового anon-юзера). Используется в switch-account flow. Имя поля исторически
267
- * остаётся `forceCaptcha`, хотя капчи там больше нет — менять имя ломает
268
- * host-сигнатуру; смысл «принудительно новая anon-сессия» сохранён.
265
+ * `forceNewAnon: true` пропускает шаги 1-2 и сразу делает /signin (создаёт
266
+ * нового anon-юзера). Используется в switch-account flow.
269
267
  *
270
268
  * Параллельные вызовы дедуплицируются через `inflightAnonSignin` — два
271
269
  * click'а на «Войти как гость» не создадут двух anon-юзеров (два /signup =
@@ -274,7 +272,7 @@ export declare class AuthClient {
274
272
  signInAnonymously(input?: {
275
273
  captchaToken?: string;
276
274
  userMeta?: Record<string, string>;
277
- forceCaptcha?: boolean;
275
+ forceNewAnon?: boolean;
278
276
  }): Promise<AuthSession>;
279
277
  /**
280
278
  * Внутренний resume — пробует /auth/refresh с сохранённым anon refresh_token.
@@ -639,6 +637,13 @@ export declare class BillingClient {
639
637
  }): Promise<PaywallPrice[]>;
640
638
  /** Sync-снимок цен из последнего bootstrap'а. null = ещё не загружали. */
641
639
  getCachedPrices(): PaywallPrice[] | null;
640
+ /** Sync-снимок офферов из последнего bootstrap'а. null = bootstrap ещё не
641
+ * загружали, пустой массив = бэк отдал пейвол без офферов. Бэк уже
642
+ * применил серверный таргетинг (target_countries / target_emails /
643
+ * targeting_mode из offer_settings) — наружу выезжает только то, что
644
+ * применимо к текущему юзеру. Клиентская сторона остаётся ответственной
645
+ * за price_id-matching и countdown (см. core/offer.ts → resolveOffer). */
646
+ getCachedOffers(): PaywallOffer[] | null;
642
647
  /**
643
648
  * Снимок того, какой язык SDK сейчас считает «языком юзера». Полезно для
644
649
  * синхронизации i18n хоста с тем, что фактически показывает пейвол — чтобы
@@ -765,6 +770,17 @@ export declare class BillingClient {
765
770
  errorUrl?: string;
766
771
  shopUrl?: string;
767
772
  trialDays?: number;
773
+ /** Активный offer для этой цены — резолвится host'ом через
774
+ * `paywall.getOfferForPrice(priceId)?.offer.id` или
775
+ * `findApplicableOffer(client.getCachedOffers(), priceId)?.id`. Без
776
+ * явной передачи бэк сделает auto-resolve по email — но только для
777
+ * end_date-офферов. duration_minutes-офферы тикают в clientStorage и
778
+ * сервер их не видит: для них offerId ОБЯЗАН прийти от клиента, иначе
779
+ * скидка не применится на чекауте, хотя UI её показывал.
780
+ *
781
+ * Передавать offer-id всегда безопасно — бэк сам проверит applicable
782
+ * ли offer к этому юзеру (страна/email/режим) и игнорирует если нет. */
783
+ offerId?: string;
768
784
  /**
769
785
  * Stage 1 защиты от дубликатов покупок. Идемпотентный ключ запроса
770
786
  * (UUID). Повторный вызов с тем же ключом вернёт тот же checkout-URL
@@ -791,7 +807,9 @@ export declare class BillingClient {
791
807
  * инвойсы). Опен-флоу управляется host'ом:
792
808
  *
793
809
  * ```ts
794
- * const { url } = await billing.getCustomerPortalUrl();
810
+ * const { url } = await billing.getCustomerPortalUrl({
811
+ * returnUrl: 'https://your-app.com/account'
812
+ * });
795
813
  * window.open(url, '_blank');
796
814
  * ```
797
815
  *
@@ -803,6 +821,14 @@ export declare class BillingClient {
803
821
  */
804
822
  getCustomerPortalUrl(opts?: {
805
823
  signal?: AbortSignal;
824
+ /** URL для return-button у провайдера (Stripe «Return to ...», Paddle
825
+ * и Chargebee redirect_url'ы). Передавай туда страницу-аккаунт твоего
826
+ * app'а — `https://your-app.com/account`. Без явного returnUrl бэк
827
+ * применяет fallback в порядке: `paywall_settings.shop_url` →
828
+ * custom_domain пейвола → NEXT_PUBLIC_ONLINE_ORIGIN (последнее — это
829
+ * страница в самом online-сервисе, годится только для legacy
830
+ * v2-iframe-флоу). */
831
+ returnUrl?: string;
806
832
  }): Promise<{
807
833
  url: string;
808
834
  }>;
@@ -813,21 +839,31 @@ export declare class BillingClient {
813
839
  * `/api/v1/paywall/[id]/user` без unstable_cache, потому что list для UI
814
840
  * должен быть свежим после cancel-а.
815
841
  *
816
- * Auth: Bearer обязателен (через AuthClient). Без Bearer — 401 от бэка,
817
- * пробрасываем как PaywallError('http_401'). Гость пустой список.
842
+ * Auth (два пути):
843
+ * - Bearer (через AuthClient) — user.id резолвится из сессии, identity
844
+ * в query игнорируется.
845
+ * - `apiKey` + `identity.email`/`identity.userId` — server-SDK путь для
846
+ * интеграций со своей авторизацией. Бэк проверяет, что identity линкована
847
+ * к этому пейволу (защита от cross-paywall lookup).
848
+ * Без auth и без apiKey+identity — `identity_required`.
818
849
  */
819
850
  listPurchases(opts?: {
820
851
  signal?: AbortSignal;
821
852
  }): Promise<PaywallPurchaseDetailed[]>;
822
853
  /**
823
- * Отменить подписку. Бэк проверит что subscription принадлежит auth-юзеру
824
- * и сделает cancel у acquiring'а (Stripe/Paddle/Chargebee). По умолчанию
825
- * cancel в конце текущего периода — юзер сохраняет access до renewal date'ы.
854
+ * Отменить подписку. Бэк проверит, что subscription принадлежит юзеру
855
+ * (Bearer-путь из сессии; apiKey-путь — из identity), и сделает cancel у
856
+ * acquiring'а (Stripe/Paddle/Chargebee/Overpay). По умолчанию cancel в
857
+ * конце текущего периода — юзер сохраняет access до renewal date'ы.
826
858
  *
827
- * `reason` обязательна (валидация на бэке). Удобно собрать через select
828
- * причин в host-UI, как в legacy customer portal'е.
859
+ * `reason` обязательна (валидация на бэке).
829
860
  *
830
- * Auth: Bearer обязателен.
861
+ * Auth (два пути):
862
+ * - Bearer (через AuthClient) — стандартный путь для UI customer-portal'a.
863
+ * - `apiKey` + `identity.email`/`identity.userId` — для self-service UI на
864
+ * бэке клиента со своей авторизацией. Бэк дополнительно фильтрует
865
+ * subscription по paywall_id, чтобы owner пейвола A не отменил подписку
866
+ * пейвола B.
831
867
  */
832
868
  cancelSubscription(params: {
833
869
  subscriptionId: string;
@@ -984,6 +1020,11 @@ export declare interface EventTrackerOptions {
984
1020
  sendBeacon?: (url: string, data: BodyInit) => boolean;
985
1021
  }
986
1022
 
1023
+ /** Pick the offer applicable to a price. Targeted (`price_id === id`) wins
1024
+ * over the global default (`price_id === null`). Offers without a positive
1025
+ * `discount_percent` are ignored. */
1026
+ export declare function findApplicableOffer(offers: PaywallOffer[] | null | undefined, priceId: string): PaywallOffer | null;
1027
+
987
1028
  export declare function generateVisitorId(): string;
988
1029
 
989
1030
  export declare interface GetAccessOptions {
@@ -1150,6 +1191,11 @@ export declare interface LocaleOverrides {
1150
1191
 
1151
1192
  export declare type OAuthProvider = 'google' | 'apple' | 'github' | 'facebook';
1152
1193
 
1194
+ /** Storage key under which a relative `duration_minutes` offer records its
1195
+ * first-view timestamp. Shared between the renderer (which writes the
1196
+ * start on first open) and the host SDK helpers (which read it). */
1197
+ export declare function offerStartStorageKey(offerId: string): string;
1198
+
1153
1199
  export declare interface OpenOptions {
1154
1200
  identity?: Identity;
1155
1201
  /** Принудительно открыть, минуя pre-paywall trial check. По умолчанию SDK
@@ -1327,8 +1373,10 @@ export declare interface PaywallOffer {
1327
1373
  expires_at: string | null;
1328
1374
  /** Относительный таймер: сколько минут offer живёт **от первого просмотра
1329
1375
  * пейвола** данным юзером. Старт хранится в clientStorage под ключом
1330
- * `pw-offer-{id}-start`, по истечении auto-cleanup. Используется, когда
1331
- * бэк хочет показывать "remaining time" без жёсткой server-time, а считать
1376
+ * `pw-offer-{id}-start` и остаётся там **после** expiry — это
1377
+ * forever-marker, чтобы юзер не мог «фармить» offer (re-open пейвола
1378
+ * не запускает countdown заново). Используется, когда бэк хочет
1379
+ * показывать "remaining time" без жёсткой server-time, а считать
1332
1380
  * относительно сессии юзера. expires_at имеет приоритет если задано. */
1333
1381
  duration_minutes?: number | null;
1334
1382
  price_id: string | null;
@@ -1355,7 +1403,7 @@ export declare interface PaywallPrice {
1355
1403
  * идёт из `/user-state` и имеет минимум для access-gate'а), этот shape
1356
1404
  * включает цену/валюту/discount — чтобы host мог нарисовать список подписок
1357
1405
  * как в legacy customer portal'е. */
1358
- declare interface PaywallPurchaseDetailed {
1406
+ export declare interface PaywallPurchaseDetailed {
1359
1407
  id: string;
1360
1408
  status: string | null;
1361
1409
  cancel_at: string | null;
@@ -1444,12 +1492,25 @@ declare type PaywallStateListener = (state: PaywallStateSnapshot) => void;
1444
1492
  * один call onState; повторы (`useSyncExternalStore`-friendly).
1445
1493
  */
1446
1494
  export declare interface PaywallStateSnapshot {
1447
- /** Модалка отрендерена и видна. False — closed (или ещё не открывалась). */
1495
+ /** Модалка отрендерена и видна. False — closed (или ещё не открывалась).
1496
+ * Может быть false при `processing=true` — direct-checkout (paywall.checkout)
1497
+ * делает bootstrap + createCheckout headless до того, как решит надо ли
1498
+ * монтировать модалку. */
1448
1499
  open: boolean;
1449
1500
  /** Что показывается в модалке. null когда `open=false`. */
1450
1501
  view: 'loading' | 'error' | 'layout' | 'auth' | 'support' | 'awaiting_payment' | 'popup_blocked' | 'purchased' | null;
1451
1502
  /** Заполнено только когда `view === 'error'`. */
1452
1503
  error: PaywallError | null;
1504
+ /** SDK делает фоновую работу для `paywall.checkout(priceId)` — bootstrap,
1505
+ * visibility/trial-gates, createCheckout — до того, как реально нужна
1506
+ * UI-модалка. Хост на этой фазе может задизейблить свою кнопку и
1507
+ * показать спиннер прямо на ней, чтобы у юзера не было ощущения «клик
1508
+ * ничего не сделал». Сбрасывается в false сразу после mountAndShow
1509
+ * (модалка взяла на себя UI), либо после headless reject (already-paid,
1510
+ * ошибка createCheckout без модалки). Для `paywall.open()`-flow всегда
1511
+ * false: там модалка появляется мгновенно со своим LoadingView и
1512
+ * отдельный «processing» не нужен. */
1513
+ processing: boolean;
1453
1514
  }
1454
1515
 
1455
1516
  export declare class PaywallUI {
@@ -1469,6 +1530,12 @@ export declare class PaywallUI {
1469
1530
  private watcher;
1470
1531
  private tracker;
1471
1532
  private purchased;
1533
+ /** View, с которым последний раз монтировалась модалка. Гейтит аналитику
1534
+ * `paywall_opened`/`paywall_viewed` на реальный пейвол (`'layout'`): открытие
1535
+ * support / standalone-auth / awaiting_payment эмитит публичный `'open'` и
1536
+ * `'ready'`, но это не «пейвол открыт/просмотрен» — иначе саппорт-клик шлёт
1537
+ * ложный `paywall_opened`. */
1538
+ private lastMountedView;
1472
1539
  /** Lazy-инстанс TrialStore. Резолвится при первом open(), когда уже знаем
1473
1540
  * `bootstrap.settings.trial`. null — триал отключён в конфиге пейвола. */
1474
1541
  private trialStore;
@@ -1590,6 +1657,65 @@ export declare class PaywallUI {
1590
1657
  * Без managed-auth — no-op.
1591
1658
  */
1592
1659
  openSignup(opts?: OpenOptions): void;
1660
+ /**
1661
+ * Direct-checkout: создать checkout-URL по конкретной цене и сразу открыть
1662
+ * платёжного провайдера, минуя layout с тарифами. Полезно когда
1663
+ * host-приложение рендерит pricing-карточки/таблицу собственным UI и
1664
+ * хочет, чтобы клик по «Buy / Get this plan» вёл прямо в Stripe/Paddle.
1665
+ *
1666
+ * **Late-mount UX.** В отличие от `open()`, модалка не появляется во время
1667
+ * фоновой работы (bootstrap + visibility/trial gates + createCheckout).
1668
+ * Хост на этой фазе показывает busy-state прямо на своей кнопке (через
1669
+ * `state.processing === true` из `paywall.getState()` — или автоматически
1670
+ * через `<PaywallButton priceId>` в sdk-react). Модалка монтируется
1671
+ * ТОЛЬКО когда реально нужна UI:
1672
+ * - `checkout_mode='preauth'` + managed-auth + не залогинен → auth-gate
1673
+ * (форма signin'а); после успеха auto-resume в createCheckout.
1674
+ * - popup провайдера заблокирован браузером → popup_blocked view с
1675
+ * retry-кнопкой под fresh user gesture.
1676
+ * - popup открылся успешно → awaiting_payment view (индикатор «оплати
1677
+ * в новой вкладке» + I've paid).
1678
+ *
1679
+ * Что эмитится без модалки:
1680
+ * - `purchase_completed{restored:true, priceId}` когда юзер уже подписан
1681
+ * (cached user, fresh bootstrap, или 409 hasActivePurchase от бэка) —
1682
+ * headless reject;
1683
+ * - `error` когда createCheckout упал или identity.email отсутствует;
1684
+ * - `visibility_blocked` / `trial_blocked` — стандартные gate-эвенты.
1685
+ *
1686
+ * Что эмитится одновременно с модалкой:
1687
+ * - `checkout_started{priceId, url, acquiring}` ровно когда headless URL
1688
+ * получен, ДО mount'а awaiting_payment/popup_blocked.
1689
+ *
1690
+ * Offer (countdown-скидка) автоматически резолвится из cached offers'ов
1691
+ * через `getOfferForPrice(priceId)` и передаётся в createCheckout как
1692
+ * `offerId` — чтобы duration_minutes-офферы тоже применились на бэке
1693
+ * (для них нет server-side таймера, без явного offer-id скидка теряется).
1694
+ *
1695
+ * Требования:
1696
+ * - `identity.email` должен быть выставлен (через `opts.identity`, либо
1697
+ * managed-auth, либо ранний `setIdentity`/`paywall.open({identity})`).
1698
+ * Без email бэк `/start-checkout` 400'нёт; SDK эмитнет `error`.
1699
+ * - В `checkout_mode='preauth'` без managed-auth — backend требует
1700
+ * email-юзера; убедись что `identity.email` явно задан.
1701
+ *
1702
+ * Без модалки совсем (когда host рендерит свой awaiting-payment экран) —
1703
+ * используй `paywall.billing.createCheckout({priceId, offerId})` напрямую,
1704
+ * но тогда auth-gate / popup_blocked / awaiting_payment придётся рисовать
1705
+ * самостоятельно.
1706
+ */
1707
+ checkout(priceId: string, opts?: OpenOptions): void;
1708
+ /** Headless prep-work для `checkout(priceId, opts)`: bootstrap → gates →
1709
+ * preauth check → createCheckout → mount модалки с финальным view.
1710
+ * Вынесено отдельным методом ради чистого async/await flow вместо вложенных
1711
+ * then-chain'ов (5+ ветвей). Любая ошибка не пробрасывается наружу: эмитим
1712
+ * через `paywall.emit('error')` и выходим — host подписан на `error`-event. */
1713
+ private runDirectCheckout;
1714
+ /** Trial-check без mount'а (для late-mount direct-checkout). Возвращает
1715
+ * true если trial заблокировал — caller должен прекратить flow. На любой
1716
+ * storage-ошибке log+продолжаем (не блокируем продажу). */
1717
+ private checkTrialBeforeCheckout;
1718
+ private applyProcessing;
1593
1719
  /**
1594
1720
  * Headless anonymous signin без открытия модалки. Внутри:
1595
1721
  * idempotent (если уже анон — instant return) → resume через сохранённый
@@ -1656,6 +1782,26 @@ export declare class PaywallUI {
1656
1782
  }): Promise<PaywallPrice[]>;
1657
1783
  /** Sync-снимок цен. null — bootstrap ещё не загружали. */
1658
1784
  getCachedPrices(): PaywallPrice[] | null;
1785
+ /** Sync-снимок офферов. null = bootstrap не загружали, [] = пейвол без офферов.
1786
+ * Бэк уже применил серверный targeting (страны/email/режим) — наружу
1787
+ * выезжает только то, что применимо к текущему юзеру. */
1788
+ getCachedOffers(): PaywallOffer[] | null;
1789
+ /**
1790
+ * Резолвит активный offer для конкретной цены: price_id-таргетинг +
1791
+ * countdown (`expires_at` ИЛИ `duration_minutes` от первого открытия
1792
+ * пейвола, см. clientStorage `pw-offer-{id}-start`).
1793
+ *
1794
+ * Read-only — НЕ записывает start для `duration_minutes`-офферов. Запись
1795
+ * стартует только когда модалка реально открыта (renderer'ом). До этого
1796
+ * `getOfferForPrice` вернёт `null` для duration-only офферов, чтобы
1797
+ * страницы-хосты вне модалки (pricing, landing) не активировали countdown
1798
+ * раньше времени.
1799
+ *
1800
+ * Хост-странице нужен countdown, который тикает каждую секунду — для
1801
+ * этого использовать React-хук `usePaywallOffer(priceId)` из sdk-react
1802
+ * либо обёртку поверх `setInterval(1000)` + повторный вызов этого метода.
1803
+ */
1804
+ getOfferForPrice(priceId: string): ResolvedOffer | null;
1659
1805
  /** Снимок текущего «языка юзера» — proxy над `billing.getUserLanguage()`.
1660
1806
  * Используй, чтобы синхронизировать i18n host'а с тем, что фактически
1661
1807
  * показывает пейвол. См. подробности в `BillingClient.getUserLanguage`. */
@@ -1775,6 +1921,51 @@ export declare class QuotaExceededError extends PaywallError {
1775
1921
  });
1776
1922
  }
1777
1923
 
1924
+ /** Safe browser localStorage getter — returns null in SSR / private mode. */
1925
+ export declare function readBrowserOfferStart(offerId: string): string | null;
1926
+
1927
+ /**
1928
+ * Resolved view of a paywall offer — what host UI actually needs to render
1929
+ * a strike-through price + countdown without re-implementing the math.
1930
+ *
1931
+ * `remainingMs` ticks down with wall-clock time and reaches 0 on expiry.
1932
+ * `totalMs` stays constant — useful for progress bars / share-of-time UX.
1933
+ * `expiresAt` is the Date.now()-comparable epoch ms of expiry.
1934
+ *
1935
+ * For offers without an expiry mechanism (no `expires_at` and no
1936
+ * `duration_minutes`), `remainingMs`/`totalMs`/`expiresAt` are all `null`,
1937
+ * but the resolved view is still returned — discount badge / strike-through
1938
+ * still make sense for "perpetual sale" offers.
1939
+ */
1940
+ export declare interface ResolvedOffer {
1941
+ offer: PaywallOffer;
1942
+ discountPercent: number;
1943
+ remainingMs: number | null;
1944
+ totalMs: number | null;
1945
+ expiresAt: number | null;
1946
+ }
1947
+
1948
+ /** Compute the resolved view of an offer. Pure, no side-effects. */
1949
+ export declare function resolveOffer(offer: PaywallOffer, opts?: ResolveOfferOptions): ResolvedOffer | null;
1950
+
1951
+ export declare interface ResolveOfferOptions {
1952
+ /** Current epoch ms. Inject for deterministic tests; default `Date.now()`. */
1953
+ now?: number;
1954
+ /**
1955
+ * Synchronous reader for the `duration_minutes` start-timestamp ISO string.
1956
+ * Host passes a closure over its sync storage (browser → `localStorage`,
1957
+ * memory → in-process map). Return `null` if no start has been recorded.
1958
+ *
1959
+ * Intentionally synchronous, because consumers call this from UI render —
1960
+ * an async StorageAdapter would force every price card to suspend.
1961
+ *
1962
+ * If omitted, `duration_minutes`-only offers return `expiresAt = null`,
1963
+ * which makes the resolved view treat them as "not yet started" (the
1964
+ * renderer is responsible for writing the start on first paywall view).
1965
+ */
1966
+ readStart?: (offerId: string) => string | null;
1967
+ }
1968
+
1778
1969
  export declare const SDK_VERSION = "3.0.0-alpha.0";
1779
1970
 
1780
1971
  export declare type SignUpResult = {
package/dist/index.js CHANGED
@@ -1,19 +1,23 @@
1
- import { ApiClient as t, ApiGatewayClient as a, AuthClient as i, BillingClient as l, EventTracker as o, PaywallError as n, QuotaExceededError as E, SDK_VERSION as s, STORAGE_KEYS as S, createStorage as c, ensureVisitorId as d, generateVisitorId as g } from "./core.js";
2
- import { P as y, b as A } from "./chunks/PaywallUI-BrDiS6zg.js";
1
+ import { A as r, a as s, b as t, B as i, E as o, P as l, Q as f, S as n, c as S, d as E, e as d, f as c, h as p, o as A, r as g, i as y } from "./chunks/index-CLB1AgLg.js";
2
+ import { P as b, b as w } from "./chunks/PaywallUI-CDlJL5Em.js";
3
3
  export {
4
- t as ApiClient,
5
- a as ApiGatewayClient,
6
- i as AuthClient,
7
- l as BillingClient,
4
+ r as ApiClient,
5
+ s as ApiGatewayClient,
6
+ t as AuthClient,
7
+ i as BillingClient,
8
8
  o as EventTracker,
9
- n as PaywallError,
10
- y as PaywallUI,
11
- E as QuotaExceededError,
12
- s as SDK_VERSION,
9
+ l as PaywallError,
10
+ b as PaywallUI,
11
+ f as QuotaExceededError,
12
+ n as SDK_VERSION,
13
13
  S as STORAGE_KEYS,
14
- A as blockRegistry,
15
- c as createStorage,
14
+ w as blockRegistry,
15
+ E as createStorage,
16
16
  d as ensureVisitorId,
17
- g as generateVisitorId
17
+ c as findApplicableOffer,
18
+ p as generateVisitorId,
19
+ A as offerStartStorageKey,
20
+ g as readBrowserOfferStart,
21
+ y as resolveOffer
18
22
  };
19
23
  //# sourceMappingURL=index.js.map
package/dist/ui.cjs CHANGED
@@ -1,2 +1,2 @@
1
- "use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const e=require("./chunks/PaywallUI-Bvx8nRL0.js");exports.PaywallUI=e.PaywallUI;exports.blockRegistry=e.blockRegistry;
1
+ "use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const e=require("./chunks/PaywallUI-CCwYgagL.js");exports.PaywallUI=e.PaywallUI;exports.blockRegistry=e.blockRegistry;
2
2
  //# sourceMappingURL=ui.cjs.map