@monetize.software/sdk 3.0.0-alpha.9 → 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.
- package/dist/chunks/PaywallUI-CCwYgagL.js +26 -0
- package/dist/chunks/PaywallUI-CCwYgagL.js.map +1 -0
- package/dist/chunks/PaywallUI-CDlJL5Em.js +3599 -0
- package/dist/chunks/PaywallUI-CDlJL5Em.js.map +1 -0
- package/dist/chunks/ar-CViBaj16.js +2 -0
- package/dist/chunks/ar-CViBaj16.js.map +1 -0
- package/dist/chunks/{ar-B2Wg_IrC.js → ar-ClwBmll7.js} +5 -1
- package/dist/chunks/ar-ClwBmll7.js.map +1 -0
- package/dist/chunks/{cs-BNo9Dx0Q.js → cs-Cc_D0W4S.js} +5 -1
- package/dist/chunks/cs-Cc_D0W4S.js.map +1 -0
- package/dist/chunks/cs-DQJWP65K.js +2 -0
- package/dist/chunks/cs-DQJWP65K.js.map +1 -0
- package/dist/chunks/{da-Do9Lq6En.js → da-BtKcMSxH.js} +5 -1
- package/dist/chunks/da-BtKcMSxH.js.map +1 -0
- package/dist/chunks/da-Cyr_IXhb.js +2 -0
- package/dist/chunks/da-Cyr_IXhb.js.map +1 -0
- package/dist/chunks/de-BOCUj1pF.js +2 -0
- package/dist/chunks/de-BOCUj1pF.js.map +1 -0
- package/dist/chunks/{de-C8pDZNvx.js → de-iwQW5eYl.js} +5 -1
- package/dist/chunks/de-iwQW5eYl.js.map +1 -0
- package/dist/chunks/{el-DzMNX-_P.js → el-BoH65CeJ.js} +5 -1
- package/dist/chunks/el-BoH65CeJ.js.map +1 -0
- package/dist/chunks/el-C6jLHiEF.js +2 -0
- package/dist/chunks/el-C6jLHiEF.js.map +1 -0
- package/dist/chunks/es-CARHLxHR.js +2 -0
- package/dist/chunks/es-CARHLxHR.js.map +1 -0
- package/dist/chunks/{es-YrKt-q4w.js → es-CkP16_8K.js} +5 -1
- package/dist/chunks/es-CkP16_8K.js.map +1 -0
- package/dist/chunks/fi-B8OhRbwY.js +2 -0
- package/dist/chunks/fi-B8OhRbwY.js.map +1 -0
- package/dist/chunks/{fi-Bh44pwZ4.js → fi-yUXSmK1E.js} +5 -1
- package/dist/chunks/fi-yUXSmK1E.js.map +1 -0
- package/dist/chunks/{fr-BhYf-iKk.js → fr-CoM18zzM.js} +2 -2
- package/dist/chunks/fr-CoM18zzM.js.map +1 -0
- package/dist/chunks/{fr-Bc0pw4ws.js → fr-DSZRGsxI.js} +5 -1
- package/dist/chunks/fr-DSZRGsxI.js.map +1 -0
- package/dist/chunks/he-DTDVc3lA.js +2 -0
- package/dist/chunks/he-DTDVc3lA.js.map +1 -0
- package/dist/chunks/{he-Bfm-bhe3.js → he-ZUo7cQjk.js} +7 -3
- package/dist/chunks/he-ZUo7cQjk.js.map +1 -0
- package/dist/chunks/hi-BjnS9UeE.js +2 -0
- package/dist/chunks/hi-BjnS9UeE.js.map +1 -0
- package/dist/chunks/{hi-D-O-B9Dn.js → hi-CEutBKiG.js} +5 -1
- package/dist/chunks/hi-CEutBKiG.js.map +1 -0
- package/dist/chunks/hu-CN06FMhV.js +2 -0
- package/dist/chunks/hu-CN06FMhV.js.map +1 -0
- package/dist/chunks/{hu-CmIuAbLL.js → hu-DvEAWGS7.js} +5 -1
- package/dist/chunks/hu-DvEAWGS7.js.map +1 -0
- package/dist/chunks/id-BITgaBxq.js +2 -0
- package/dist/chunks/id-BITgaBxq.js.map +1 -0
- package/dist/chunks/{id-DN7IES-A.js → id-_eEMrYMW.js} +5 -1
- package/dist/chunks/id-_eEMrYMW.js.map +1 -0
- package/dist/chunks/index-CLB1AgLg.js +2074 -0
- package/dist/chunks/index-CLB1AgLg.js.map +1 -0
- package/dist/chunks/index-CzDSBl4d.js +2 -0
- package/dist/chunks/index-CzDSBl4d.js.map +1 -0
- package/dist/chunks/{it-Cz5Nmqx5.js → it-BAmsQbIl.js} +5 -1
- package/dist/chunks/it-BAmsQbIl.js.map +1 -0
- package/dist/chunks/it-DVcsq015.js +2 -0
- package/dist/chunks/it-DVcsq015.js.map +1 -0
- package/dist/chunks/ja-Bim7Ok2e.js +2 -0
- package/dist/chunks/ja-Bim7Ok2e.js.map +1 -0
- package/dist/chunks/{ja-BH9BlBh2.js → ja-BqCZWVKK.js} +7 -3
- package/dist/chunks/ja-BqCZWVKK.js.map +1 -0
- package/dist/chunks/{ko-CYV9QuYs.js → ko-CkIzeOzb.js} +7 -3
- package/dist/chunks/ko-CkIzeOzb.js.map +1 -0
- package/dist/chunks/ko-DqEfcVCB.js +2 -0
- package/dist/chunks/ko-DqEfcVCB.js.map +1 -0
- package/dist/chunks/nl-DSNuJWIo.js +2 -0
- package/dist/chunks/nl-DSNuJWIo.js.map +1 -0
- package/dist/chunks/{nl-BvkB900D.js → nl-Mu_KNzli.js} +5 -1
- package/dist/chunks/nl-Mu_KNzli.js.map +1 -0
- package/dist/chunks/{no-3s9_ormb.js → no-9HMjljBs.js} +5 -1
- package/dist/chunks/no-9HMjljBs.js.map +1 -0
- package/dist/chunks/no-B5HY_A8_.js +2 -0
- package/dist/chunks/no-B5HY_A8_.js.map +1 -0
- package/dist/chunks/{pl-C9WTGQtb.js → pl-Cbr2qDwv.js} +5 -1
- package/dist/chunks/pl-Cbr2qDwv.js.map +1 -0
- package/dist/chunks/pl-ChGLn9Sy.js +2 -0
- package/dist/chunks/pl-ChGLn9Sy.js.map +1 -0
- package/dist/chunks/pt-CDLEktT9.js +2 -0
- package/dist/chunks/pt-CDLEktT9.js.map +1 -0
- package/dist/chunks/{pt-uFVUv_Op.js → pt-_jirA6IR.js} +5 -1
- package/dist/chunks/pt-_jirA6IR.js.map +1 -0
- package/dist/chunks/ro-BHCHiXY3.js +2 -0
- package/dist/chunks/ro-BHCHiXY3.js.map +1 -0
- package/dist/chunks/{ro-BrqQ8Au-.js → ro-oZLxhwHc.js} +5 -1
- package/dist/chunks/ro-oZLxhwHc.js.map +1 -0
- package/dist/chunks/ru-B6HgmINj.js +2 -0
- package/dist/chunks/ru-B6HgmINj.js.map +1 -0
- package/dist/chunks/{ru-DK594dA8.js → ru-C2-sqY7B.js} +5 -1
- package/dist/chunks/ru-C2-sqY7B.js.map +1 -0
- package/dist/chunks/sv-DoSs4a9n.js +2 -0
- package/dist/chunks/sv-DoSs4a9n.js.map +1 -0
- package/dist/chunks/{sv-CHNH8-mq.js → sv-y385MWVy.js} +5 -1
- package/dist/chunks/sv-y385MWVy.js.map +1 -0
- package/dist/chunks/{th-l24Pm5q-.js → th-Bjbv4M1s.js} +5 -1
- package/dist/chunks/th-Bjbv4M1s.js.map +1 -0
- package/dist/chunks/th-UeweOhwg.js +2 -0
- package/dist/chunks/th-UeweOhwg.js.map +1 -0
- package/dist/chunks/tr-BbBr5tyB.js +2 -0
- package/dist/chunks/tr-BbBr5tyB.js.map +1 -0
- package/dist/chunks/{tr-ADpigSY5.js → tr-DmHo9F8i.js} +7 -3
- package/dist/chunks/tr-DmHo9F8i.js.map +1 -0
- package/dist/chunks/uk-CJTA1SJK.js +2 -0
- package/dist/chunks/uk-CJTA1SJK.js.map +1 -0
- package/dist/chunks/{uk-CGqo4jek.js → uk-DwvAoTe5.js} +5 -1
- package/dist/chunks/uk-DwvAoTe5.js.map +1 -0
- package/dist/chunks/{vi-Dk9bTu6f.js → vi-BEpwsVLR.js} +5 -1
- package/dist/chunks/vi-BEpwsVLR.js.map +1 -0
- package/dist/chunks/vi-ZvBo7PbB.js +2 -0
- package/dist/chunks/vi-ZvBo7PbB.js.map +1 -0
- package/dist/chunks/zh-CPZBEb3d.js +2 -0
- package/dist/chunks/zh-CPZBEb3d.js.map +1 -0
- package/dist/chunks/{zh-LDkEV2D9.js → zh-DrG18oGe.js} +7 -3
- package/dist/chunks/zh-DrG18oGe.js.map +1 -0
- package/dist/core.cjs +1 -1
- package/dist/core.cjs.map +1 -1
- package/dist/core.d.ts +89 -4
- package/dist/core.js +17 -2004
- package/dist/core.js.map +1 -1
- package/dist/index.cjs +1 -1
- package/dist/index.d.ts +188 -5
- package/dist/index.js +17 -13
- package/dist/ui.cjs +1 -1
- package/dist/ui.d.ts +153 -4
- package/dist/ui.js +1 -1
- package/package.json +1 -1
- package/dist/chunks/PaywallUI-BhQpWSWN.js +0 -3224
- package/dist/chunks/PaywallUI-BhQpWSWN.js.map +0 -1
- package/dist/chunks/PaywallUI-C7Wp2TiR.js +0 -26
- package/dist/chunks/PaywallUI-C7Wp2TiR.js.map +0 -1
- package/dist/chunks/ar-7cgIM-Vl.js +0 -2
- package/dist/chunks/ar-7cgIM-Vl.js.map +0 -1
- package/dist/chunks/ar-B2Wg_IrC.js.map +0 -1
- package/dist/chunks/cs-BNo9Dx0Q.js.map +0 -1
- package/dist/chunks/cs-S05PC5AC.js +0 -2
- package/dist/chunks/cs-S05PC5AC.js.map +0 -1
- package/dist/chunks/da-Bi4zBG14.js +0 -2
- package/dist/chunks/da-Bi4zBG14.js.map +0 -1
- package/dist/chunks/da-Do9Lq6En.js.map +0 -1
- package/dist/chunks/de-C8pDZNvx.js.map +0 -1
- package/dist/chunks/de-nCDB6D2W.js +0 -2
- package/dist/chunks/de-nCDB6D2W.js.map +0 -1
- package/dist/chunks/el-BrKaa978.js +0 -2
- package/dist/chunks/el-BrKaa978.js.map +0 -1
- package/dist/chunks/el-DzMNX-_P.js.map +0 -1
- package/dist/chunks/es-B-Wtyzrl.js +0 -2
- package/dist/chunks/es-B-Wtyzrl.js.map +0 -1
- package/dist/chunks/es-YrKt-q4w.js.map +0 -1
- package/dist/chunks/fi-Bh44pwZ4.js.map +0 -1
- package/dist/chunks/fi-D1SGXjnO.js +0 -2
- package/dist/chunks/fi-D1SGXjnO.js.map +0 -1
- package/dist/chunks/fr-Bc0pw4ws.js.map +0 -1
- package/dist/chunks/fr-BhYf-iKk.js.map +0 -1
- package/dist/chunks/he-BXAaFv6Y.js +0 -2
- package/dist/chunks/he-BXAaFv6Y.js.map +0 -1
- package/dist/chunks/he-Bfm-bhe3.js.map +0 -1
- package/dist/chunks/hi-D-O-B9Dn.js.map +0 -1
- package/dist/chunks/hi-xblDO0O7.js +0 -2
- package/dist/chunks/hi-xblDO0O7.js.map +0 -1
- package/dist/chunks/hu-CmIuAbLL.js.map +0 -1
- package/dist/chunks/hu-Wa46p0y4.js +0 -2
- package/dist/chunks/hu-Wa46p0y4.js.map +0 -1
- package/dist/chunks/id-CQEo5X94.js +0 -2
- package/dist/chunks/id-CQEo5X94.js.map +0 -1
- package/dist/chunks/id-DN7IES-A.js.map +0 -1
- package/dist/chunks/it-8AYCm0xz.js +0 -2
- package/dist/chunks/it-8AYCm0xz.js.map +0 -1
- package/dist/chunks/it-Cz5Nmqx5.js.map +0 -1
- package/dist/chunks/ja-BH9BlBh2.js.map +0 -1
- package/dist/chunks/ja-q-COVayn.js +0 -2
- package/dist/chunks/ja-q-COVayn.js.map +0 -1
- package/dist/chunks/ko-B6HRCscZ.js +0 -2
- package/dist/chunks/ko-B6HRCscZ.js.map +0 -1
- package/dist/chunks/ko-CYV9QuYs.js.map +0 -1
- package/dist/chunks/nl-BvkB900D.js.map +0 -1
- package/dist/chunks/nl-CAd6_xlm.js +0 -2
- package/dist/chunks/nl-CAd6_xlm.js.map +0 -1
- package/dist/chunks/no-3s9_ormb.js.map +0 -1
- package/dist/chunks/no-CAmz6bz6.js +0 -2
- package/dist/chunks/no-CAmz6bz6.js.map +0 -1
- package/dist/chunks/pl-C9WTGQtb.js.map +0 -1
- package/dist/chunks/pl-DqUSTCaF.js +0 -2
- package/dist/chunks/pl-DqUSTCaF.js.map +0 -1
- package/dist/chunks/pt-8ARZnH0_.js +0 -2
- package/dist/chunks/pt-8ARZnH0_.js.map +0 -1
- package/dist/chunks/pt-uFVUv_Op.js.map +0 -1
- package/dist/chunks/ro-BrqQ8Au-.js.map +0 -1
- package/dist/chunks/ro-D-NMbp2F.js +0 -2
- package/dist/chunks/ro-D-NMbp2F.js.map +0 -1
- package/dist/chunks/ru-8gbHPh0g.js +0 -2
- package/dist/chunks/ru-8gbHPh0g.js.map +0 -1
- package/dist/chunks/ru-DK594dA8.js.map +0 -1
- package/dist/chunks/sv-CHNH8-mq.js.map +0 -1
- package/dist/chunks/sv-D8a8hmx9.js +0 -2
- package/dist/chunks/sv-D8a8hmx9.js.map +0 -1
- package/dist/chunks/th-DfjUK0Y7.js +0 -2
- package/dist/chunks/th-DfjUK0Y7.js.map +0 -1
- package/dist/chunks/th-l24Pm5q-.js.map +0 -1
- package/dist/chunks/tr-ADpigSY5.js.map +0 -1
- package/dist/chunks/tr-BdBpz4tL.js +0 -2
- package/dist/chunks/tr-BdBpz4tL.js.map +0 -1
- package/dist/chunks/uk-CGqo4jek.js.map +0 -1
- package/dist/chunks/uk-Cx1zv1ao.js +0 -2
- package/dist/chunks/uk-Cx1zv1ao.js.map +0 -1
- package/dist/chunks/vi-Dk9bTu6f.js.map +0 -1
- package/dist/chunks/vi-oe2dW21I.js +0 -2
- package/dist/chunks/vi-oe2dW21I.js.map +0 -1
- package/dist/chunks/zh-CwczPMPp.js +0 -2
- package/dist/chunks/zh-CwczPMPp.js.map +0 -1
- 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("./
|
|
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
|
@@ -637,6 +637,13 @@ export declare class BillingClient {
|
|
|
637
637
|
}): Promise<PaywallPrice[]>;
|
|
638
638
|
/** Sync-снимок цен из последнего bootstrap'а. null = ещё не загружали. */
|
|
639
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;
|
|
640
647
|
/**
|
|
641
648
|
* Снимок того, какой язык SDK сейчас считает «языком юзера». Полезно для
|
|
642
649
|
* синхронизации i18n хоста с тем, что фактически показывает пейвол — чтобы
|
|
@@ -763,6 +770,17 @@ export declare class BillingClient {
|
|
|
763
770
|
errorUrl?: string;
|
|
764
771
|
shopUrl?: string;
|
|
765
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;
|
|
766
784
|
/**
|
|
767
785
|
* Stage 1 защиты от дубликатов покупок. Идемпотентный ключ запроса
|
|
768
786
|
* (UUID). Повторный вызов с тем же ключом вернёт тот же checkout-URL
|
|
@@ -789,7 +807,9 @@ export declare class BillingClient {
|
|
|
789
807
|
* инвойсы). Опен-флоу управляется host'ом:
|
|
790
808
|
*
|
|
791
809
|
* ```ts
|
|
792
|
-
* const { url } = await billing.getCustomerPortalUrl(
|
|
810
|
+
* const { url } = await billing.getCustomerPortalUrl({
|
|
811
|
+
* returnUrl: 'https://your-app.com/account'
|
|
812
|
+
* });
|
|
793
813
|
* window.open(url, '_blank');
|
|
794
814
|
* ```
|
|
795
815
|
*
|
|
@@ -801,6 +821,14 @@ export declare class BillingClient {
|
|
|
801
821
|
*/
|
|
802
822
|
getCustomerPortalUrl(opts?: {
|
|
803
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;
|
|
804
832
|
}): Promise<{
|
|
805
833
|
url: string;
|
|
806
834
|
}>;
|
|
@@ -992,6 +1020,11 @@ export declare interface EventTrackerOptions {
|
|
|
992
1020
|
sendBeacon?: (url: string, data: BodyInit) => boolean;
|
|
993
1021
|
}
|
|
994
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
|
+
|
|
995
1028
|
export declare function generateVisitorId(): string;
|
|
996
1029
|
|
|
997
1030
|
export declare interface GetAccessOptions {
|
|
@@ -1158,6 +1191,11 @@ export declare interface LocaleOverrides {
|
|
|
1158
1191
|
|
|
1159
1192
|
export declare type OAuthProvider = 'google' | 'apple' | 'github' | 'facebook';
|
|
1160
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
|
+
|
|
1161
1199
|
export declare interface OpenOptions {
|
|
1162
1200
|
identity?: Identity;
|
|
1163
1201
|
/** Принудительно открыть, минуя pre-paywall trial check. По умолчанию SDK
|
|
@@ -1335,8 +1373,10 @@ export declare interface PaywallOffer {
|
|
|
1335
1373
|
expires_at: string | null;
|
|
1336
1374
|
/** Относительный таймер: сколько минут offer живёт **от первого просмотра
|
|
1337
1375
|
* пейвола** данным юзером. Старт хранится в clientStorage под ключом
|
|
1338
|
-
* `pw-offer-{id}-start
|
|
1339
|
-
*
|
|
1376
|
+
* `pw-offer-{id}-start` и остаётся там **после** expiry — это
|
|
1377
|
+
* forever-marker, чтобы юзер не мог «фармить» offer (re-open пейвола
|
|
1378
|
+
* не запускает countdown заново). Используется, когда бэк хочет
|
|
1379
|
+
* показывать "remaining time" без жёсткой server-time, а считать
|
|
1340
1380
|
* относительно сессии юзера. expires_at имеет приоритет если задано. */
|
|
1341
1381
|
duration_minutes?: number | null;
|
|
1342
1382
|
price_id: string | null;
|
|
@@ -1363,7 +1403,7 @@ export declare interface PaywallPrice {
|
|
|
1363
1403
|
* идёт из `/user-state` и имеет минимум для access-gate'а), этот shape
|
|
1364
1404
|
* включает цену/валюту/discount — чтобы host мог нарисовать список подписок
|
|
1365
1405
|
* как в legacy customer portal'е. */
|
|
1366
|
-
declare interface PaywallPurchaseDetailed {
|
|
1406
|
+
export declare interface PaywallPurchaseDetailed {
|
|
1367
1407
|
id: string;
|
|
1368
1408
|
status: string | null;
|
|
1369
1409
|
cancel_at: string | null;
|
|
@@ -1452,12 +1492,25 @@ declare type PaywallStateListener = (state: PaywallStateSnapshot) => void;
|
|
|
1452
1492
|
* один call onState; повторы (`useSyncExternalStore`-friendly).
|
|
1453
1493
|
*/
|
|
1454
1494
|
export declare interface PaywallStateSnapshot {
|
|
1455
|
-
/** Модалка отрендерена и видна. False — closed (или ещё не открывалась).
|
|
1495
|
+
/** Модалка отрендерена и видна. False — closed (или ещё не открывалась).
|
|
1496
|
+
* Может быть false при `processing=true` — direct-checkout (paywall.checkout)
|
|
1497
|
+
* делает bootstrap + createCheckout headless до того, как решит надо ли
|
|
1498
|
+
* монтировать модалку. */
|
|
1456
1499
|
open: boolean;
|
|
1457
1500
|
/** Что показывается в модалке. null когда `open=false`. */
|
|
1458
1501
|
view: 'loading' | 'error' | 'layout' | 'auth' | 'support' | 'awaiting_payment' | 'popup_blocked' | 'purchased' | null;
|
|
1459
1502
|
/** Заполнено только когда `view === 'error'`. */
|
|
1460
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;
|
|
1461
1514
|
}
|
|
1462
1515
|
|
|
1463
1516
|
export declare class PaywallUI {
|
|
@@ -1477,6 +1530,12 @@ export declare class PaywallUI {
|
|
|
1477
1530
|
private watcher;
|
|
1478
1531
|
private tracker;
|
|
1479
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;
|
|
1480
1539
|
/** Lazy-инстанс TrialStore. Резолвится при первом open(), когда уже знаем
|
|
1481
1540
|
* `bootstrap.settings.trial`. null — триал отключён в конфиге пейвола. */
|
|
1482
1541
|
private trialStore;
|
|
@@ -1598,6 +1657,65 @@ export declare class PaywallUI {
|
|
|
1598
1657
|
* Без managed-auth — no-op.
|
|
1599
1658
|
*/
|
|
1600
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;
|
|
1601
1719
|
/**
|
|
1602
1720
|
* Headless anonymous signin без открытия модалки. Внутри:
|
|
1603
1721
|
* idempotent (если уже анон — instant return) → resume через сохранённый
|
|
@@ -1664,6 +1782,26 @@ export declare class PaywallUI {
|
|
|
1664
1782
|
}): Promise<PaywallPrice[]>;
|
|
1665
1783
|
/** Sync-снимок цен. null — bootstrap ещё не загружали. */
|
|
1666
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;
|
|
1667
1805
|
/** Снимок текущего «языка юзера» — proxy над `billing.getUserLanguage()`.
|
|
1668
1806
|
* Используй, чтобы синхронизировать i18n host'а с тем, что фактически
|
|
1669
1807
|
* показывает пейвол. См. подробности в `BillingClient.getUserLanguage`. */
|
|
@@ -1783,6 +1921,51 @@ export declare class QuotaExceededError extends PaywallError {
|
|
|
1783
1921
|
});
|
|
1784
1922
|
}
|
|
1785
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
|
+
|
|
1786
1969
|
export declare const SDK_VERSION = "3.0.0-alpha.0";
|
|
1787
1970
|
|
|
1788
1971
|
export declare type SignUpResult = {
|
package/dist/index.js
CHANGED
|
@@ -1,19 +1,23 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import { P as
|
|
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
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
4
|
+
r as ApiClient,
|
|
5
|
+
s as ApiGatewayClient,
|
|
6
|
+
t as AuthClient,
|
|
7
|
+
i as BillingClient,
|
|
8
8
|
o as EventTracker,
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
9
|
+
l as PaywallError,
|
|
10
|
+
b as PaywallUI,
|
|
11
|
+
f as QuotaExceededError,
|
|
12
|
+
n as SDK_VERSION,
|
|
13
13
|
S as STORAGE_KEYS,
|
|
14
|
-
|
|
15
|
-
|
|
14
|
+
w as blockRegistry,
|
|
15
|
+
E as createStorage,
|
|
16
16
|
d as ensureVisitorId,
|
|
17
|
-
|
|
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-
|
|
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
|
package/dist/ui.d.ts
CHANGED
|
@@ -623,6 +623,13 @@ declare class BillingClient {
|
|
|
623
623
|
}): Promise<PaywallPrice[]>;
|
|
624
624
|
/** Sync-снимок цен из последнего bootstrap'а. null = ещё не загружали. */
|
|
625
625
|
getCachedPrices(): PaywallPrice[] | null;
|
|
626
|
+
/** Sync-снимок офферов из последнего bootstrap'а. null = bootstrap ещё не
|
|
627
|
+
* загружали, пустой массив = бэк отдал пейвол без офферов. Бэк уже
|
|
628
|
+
* применил серверный таргетинг (target_countries / target_emails /
|
|
629
|
+
* targeting_mode из offer_settings) — наружу выезжает только то, что
|
|
630
|
+
* применимо к текущему юзеру. Клиентская сторона остаётся ответственной
|
|
631
|
+
* за price_id-matching и countdown (см. core/offer.ts → resolveOffer). */
|
|
632
|
+
getCachedOffers(): PaywallOffer[] | null;
|
|
626
633
|
/**
|
|
627
634
|
* Снимок того, какой язык SDK сейчас считает «языком юзера». Полезно для
|
|
628
635
|
* синхронизации i18n хоста с тем, что фактически показывает пейвол — чтобы
|
|
@@ -749,6 +756,17 @@ declare class BillingClient {
|
|
|
749
756
|
errorUrl?: string;
|
|
750
757
|
shopUrl?: string;
|
|
751
758
|
trialDays?: number;
|
|
759
|
+
/** Активный offer для этой цены — резолвится host'ом через
|
|
760
|
+
* `paywall.getOfferForPrice(priceId)?.offer.id` или
|
|
761
|
+
* `findApplicableOffer(client.getCachedOffers(), priceId)?.id`. Без
|
|
762
|
+
* явной передачи бэк сделает auto-resolve по email — но только для
|
|
763
|
+
* end_date-офферов. duration_minutes-офферы тикают в clientStorage и
|
|
764
|
+
* сервер их не видит: для них offerId ОБЯЗАН прийти от клиента, иначе
|
|
765
|
+
* скидка не применится на чекауте, хотя UI её показывал.
|
|
766
|
+
*
|
|
767
|
+
* Передавать offer-id всегда безопасно — бэк сам проверит applicable
|
|
768
|
+
* ли offer к этому юзеру (страна/email/режим) и игнорирует если нет. */
|
|
769
|
+
offerId?: string;
|
|
752
770
|
/**
|
|
753
771
|
* Stage 1 защиты от дубликатов покупок. Идемпотентный ключ запроса
|
|
754
772
|
* (UUID). Повторный вызов с тем же ключом вернёт тот же checkout-URL
|
|
@@ -775,7 +793,9 @@ declare class BillingClient {
|
|
|
775
793
|
* инвойсы). Опен-флоу управляется host'ом:
|
|
776
794
|
*
|
|
777
795
|
* ```ts
|
|
778
|
-
* const { url } = await billing.getCustomerPortalUrl(
|
|
796
|
+
* const { url } = await billing.getCustomerPortalUrl({
|
|
797
|
+
* returnUrl: 'https://your-app.com/account'
|
|
798
|
+
* });
|
|
779
799
|
* window.open(url, '_blank');
|
|
780
800
|
* ```
|
|
781
801
|
*
|
|
@@ -787,6 +807,14 @@ declare class BillingClient {
|
|
|
787
807
|
*/
|
|
788
808
|
getCustomerPortalUrl(opts?: {
|
|
789
809
|
signal?: AbortSignal;
|
|
810
|
+
/** URL для return-button у провайдера (Stripe «Return to ...», Paddle
|
|
811
|
+
* и Chargebee redirect_url'ы). Передавай туда страницу-аккаунт твоего
|
|
812
|
+
* app'а — `https://your-app.com/account`. Без явного returnUrl бэк
|
|
813
|
+
* применяет fallback в порядке: `paywall_settings.shop_url` →
|
|
814
|
+
* custom_domain пейвола → NEXT_PUBLIC_ONLINE_ORIGIN (последнее — это
|
|
815
|
+
* страница в самом online-сервисе, годится только для legacy
|
|
816
|
+
* v2-iframe-флоу). */
|
|
817
|
+
returnUrl?: string;
|
|
790
818
|
}): Promise<{
|
|
791
819
|
url: string;
|
|
792
820
|
}>;
|
|
@@ -1274,8 +1302,10 @@ declare interface PaywallOffer {
|
|
|
1274
1302
|
expires_at: string | null;
|
|
1275
1303
|
/** Относительный таймер: сколько минут offer живёт **от первого просмотра
|
|
1276
1304
|
* пейвола** данным юзером. Старт хранится в clientStorage под ключом
|
|
1277
|
-
* `pw-offer-{id}-start
|
|
1278
|
-
*
|
|
1305
|
+
* `pw-offer-{id}-start` и остаётся там **после** expiry — это
|
|
1306
|
+
* forever-marker, чтобы юзер не мог «фармить» offer (re-open пейвола
|
|
1307
|
+
* не запускает countdown заново). Используется, когда бэк хочет
|
|
1308
|
+
* показывать "remaining time" без жёсткой server-time, а считать
|
|
1279
1309
|
* относительно сессии юзера. expires_at имеет приоритет если задано. */
|
|
1280
1310
|
duration_minutes?: number | null;
|
|
1281
1311
|
price_id: string | null;
|
|
@@ -1391,12 +1421,25 @@ declare type PaywallStateListener = (state: PaywallStateSnapshot) => void;
|
|
|
1391
1421
|
* один call onState; повторы (`useSyncExternalStore`-friendly).
|
|
1392
1422
|
*/
|
|
1393
1423
|
export declare interface PaywallStateSnapshot {
|
|
1394
|
-
/** Модалка отрендерена и видна. False — closed (или ещё не открывалась).
|
|
1424
|
+
/** Модалка отрендерена и видна. False — closed (или ещё не открывалась).
|
|
1425
|
+
* Может быть false при `processing=true` — direct-checkout (paywall.checkout)
|
|
1426
|
+
* делает bootstrap + createCheckout headless до того, как решит надо ли
|
|
1427
|
+
* монтировать модалку. */
|
|
1395
1428
|
open: boolean;
|
|
1396
1429
|
/** Что показывается в модалке. null когда `open=false`. */
|
|
1397
1430
|
view: 'loading' | 'error' | 'layout' | 'auth' | 'support' | 'awaiting_payment' | 'popup_blocked' | 'purchased' | null;
|
|
1398
1431
|
/** Заполнено только когда `view === 'error'`. */
|
|
1399
1432
|
error: PaywallError | null;
|
|
1433
|
+
/** SDK делает фоновую работу для `paywall.checkout(priceId)` — bootstrap,
|
|
1434
|
+
* visibility/trial-gates, createCheckout — до того, как реально нужна
|
|
1435
|
+
* UI-модалка. Хост на этой фазе может задизейблить свою кнопку и
|
|
1436
|
+
* показать спиннер прямо на ней, чтобы у юзера не было ощущения «клик
|
|
1437
|
+
* ничего не сделал». Сбрасывается в false сразу после mountAndShow
|
|
1438
|
+
* (модалка взяла на себя UI), либо после headless reject (already-paid,
|
|
1439
|
+
* ошибка createCheckout без модалки). Для `paywall.open()`-flow всегда
|
|
1440
|
+
* false: там модалка появляется мгновенно со своим LoadingView и
|
|
1441
|
+
* отдельный «processing» не нужен. */
|
|
1442
|
+
processing: boolean;
|
|
1400
1443
|
}
|
|
1401
1444
|
|
|
1402
1445
|
export declare class PaywallUI {
|
|
@@ -1416,6 +1459,12 @@ export declare class PaywallUI {
|
|
|
1416
1459
|
private watcher;
|
|
1417
1460
|
private tracker;
|
|
1418
1461
|
private purchased;
|
|
1462
|
+
/** View, с которым последний раз монтировалась модалка. Гейтит аналитику
|
|
1463
|
+
* `paywall_opened`/`paywall_viewed` на реальный пейвол (`'layout'`): открытие
|
|
1464
|
+
* support / standalone-auth / awaiting_payment эмитит публичный `'open'` и
|
|
1465
|
+
* `'ready'`, но это не «пейвол открыт/просмотрен» — иначе саппорт-клик шлёт
|
|
1466
|
+
* ложный `paywall_opened`. */
|
|
1467
|
+
private lastMountedView;
|
|
1419
1468
|
/** Lazy-инстанс TrialStore. Резолвится при первом open(), когда уже знаем
|
|
1420
1469
|
* `bootstrap.settings.trial`. null — триал отключён в конфиге пейвола. */
|
|
1421
1470
|
private trialStore;
|
|
@@ -1537,6 +1586,65 @@ export declare class PaywallUI {
|
|
|
1537
1586
|
* Без managed-auth — no-op.
|
|
1538
1587
|
*/
|
|
1539
1588
|
openSignup(opts?: OpenOptions): void;
|
|
1589
|
+
/**
|
|
1590
|
+
* Direct-checkout: создать checkout-URL по конкретной цене и сразу открыть
|
|
1591
|
+
* платёжного провайдера, минуя layout с тарифами. Полезно когда
|
|
1592
|
+
* host-приложение рендерит pricing-карточки/таблицу собственным UI и
|
|
1593
|
+
* хочет, чтобы клик по «Buy / Get this plan» вёл прямо в Stripe/Paddle.
|
|
1594
|
+
*
|
|
1595
|
+
* **Late-mount UX.** В отличие от `open()`, модалка не появляется во время
|
|
1596
|
+
* фоновой работы (bootstrap + visibility/trial gates + createCheckout).
|
|
1597
|
+
* Хост на этой фазе показывает busy-state прямо на своей кнопке (через
|
|
1598
|
+
* `state.processing === true` из `paywall.getState()` — или автоматически
|
|
1599
|
+
* через `<PaywallButton priceId>` в sdk-react). Модалка монтируется
|
|
1600
|
+
* ТОЛЬКО когда реально нужна UI:
|
|
1601
|
+
* - `checkout_mode='preauth'` + managed-auth + не залогинен → auth-gate
|
|
1602
|
+
* (форма signin'а); после успеха auto-resume в createCheckout.
|
|
1603
|
+
* - popup провайдера заблокирован браузером → popup_blocked view с
|
|
1604
|
+
* retry-кнопкой под fresh user gesture.
|
|
1605
|
+
* - popup открылся успешно → awaiting_payment view (индикатор «оплати
|
|
1606
|
+
* в новой вкладке» + I've paid).
|
|
1607
|
+
*
|
|
1608
|
+
* Что эмитится без модалки:
|
|
1609
|
+
* - `purchase_completed{restored:true, priceId}` когда юзер уже подписан
|
|
1610
|
+
* (cached user, fresh bootstrap, или 409 hasActivePurchase от бэка) —
|
|
1611
|
+
* headless reject;
|
|
1612
|
+
* - `error` когда createCheckout упал или identity.email отсутствует;
|
|
1613
|
+
* - `visibility_blocked` / `trial_blocked` — стандартные gate-эвенты.
|
|
1614
|
+
*
|
|
1615
|
+
* Что эмитится одновременно с модалкой:
|
|
1616
|
+
* - `checkout_started{priceId, url, acquiring}` ровно когда headless URL
|
|
1617
|
+
* получен, ДО mount'а awaiting_payment/popup_blocked.
|
|
1618
|
+
*
|
|
1619
|
+
* Offer (countdown-скидка) автоматически резолвится из cached offers'ов
|
|
1620
|
+
* через `getOfferForPrice(priceId)` и передаётся в createCheckout как
|
|
1621
|
+
* `offerId` — чтобы duration_minutes-офферы тоже применились на бэке
|
|
1622
|
+
* (для них нет server-side таймера, без явного offer-id скидка теряется).
|
|
1623
|
+
*
|
|
1624
|
+
* Требования:
|
|
1625
|
+
* - `identity.email` должен быть выставлен (через `opts.identity`, либо
|
|
1626
|
+
* managed-auth, либо ранний `setIdentity`/`paywall.open({identity})`).
|
|
1627
|
+
* Без email бэк `/start-checkout` 400'нёт; SDK эмитнет `error`.
|
|
1628
|
+
* - В `checkout_mode='preauth'` без managed-auth — backend требует
|
|
1629
|
+
* email-юзера; убедись что `identity.email` явно задан.
|
|
1630
|
+
*
|
|
1631
|
+
* Без модалки совсем (когда host рендерит свой awaiting-payment экран) —
|
|
1632
|
+
* используй `paywall.billing.createCheckout({priceId, offerId})` напрямую,
|
|
1633
|
+
* но тогда auth-gate / popup_blocked / awaiting_payment придётся рисовать
|
|
1634
|
+
* самостоятельно.
|
|
1635
|
+
*/
|
|
1636
|
+
checkout(priceId: string, opts?: OpenOptions): void;
|
|
1637
|
+
/** Headless prep-work для `checkout(priceId, opts)`: bootstrap → gates →
|
|
1638
|
+
* preauth check → createCheckout → mount модалки с финальным view.
|
|
1639
|
+
* Вынесено отдельным методом ради чистого async/await flow вместо вложенных
|
|
1640
|
+
* then-chain'ов (5+ ветвей). Любая ошибка не пробрасывается наружу: эмитим
|
|
1641
|
+
* через `paywall.emit('error')` и выходим — host подписан на `error`-event. */
|
|
1642
|
+
private runDirectCheckout;
|
|
1643
|
+
/** Trial-check без mount'а (для late-mount direct-checkout). Возвращает
|
|
1644
|
+
* true если trial заблокировал — caller должен прекратить flow. На любой
|
|
1645
|
+
* storage-ошибке log+продолжаем (не блокируем продажу). */
|
|
1646
|
+
private checkTrialBeforeCheckout;
|
|
1647
|
+
private applyProcessing;
|
|
1540
1648
|
/**
|
|
1541
1649
|
* Headless anonymous signin без открытия модалки. Внутри:
|
|
1542
1650
|
* idempotent (если уже анон — instant return) → resume через сохранённый
|
|
@@ -1603,6 +1711,26 @@ export declare class PaywallUI {
|
|
|
1603
1711
|
}): Promise<PaywallPrice[]>;
|
|
1604
1712
|
/** Sync-снимок цен. null — bootstrap ещё не загружали. */
|
|
1605
1713
|
getCachedPrices(): PaywallPrice[] | null;
|
|
1714
|
+
/** Sync-снимок офферов. null = bootstrap не загружали, [] = пейвол без офферов.
|
|
1715
|
+
* Бэк уже применил серверный targeting (страны/email/режим) — наружу
|
|
1716
|
+
* выезжает только то, что применимо к текущему юзеру. */
|
|
1717
|
+
getCachedOffers(): PaywallOffer[] | null;
|
|
1718
|
+
/**
|
|
1719
|
+
* Резолвит активный offer для конкретной цены: price_id-таргетинг +
|
|
1720
|
+
* countdown (`expires_at` ИЛИ `duration_minutes` от первого открытия
|
|
1721
|
+
* пейвола, см. clientStorage `pw-offer-{id}-start`).
|
|
1722
|
+
*
|
|
1723
|
+
* Read-only — НЕ записывает start для `duration_minutes`-офферов. Запись
|
|
1724
|
+
* стартует только когда модалка реально открыта (renderer'ом). До этого
|
|
1725
|
+
* `getOfferForPrice` вернёт `null` для duration-only офферов, чтобы
|
|
1726
|
+
* страницы-хосты вне модалки (pricing, landing) не активировали countdown
|
|
1727
|
+
* раньше времени.
|
|
1728
|
+
*
|
|
1729
|
+
* Хост-странице нужен countdown, который тикает каждую секунду — для
|
|
1730
|
+
* этого использовать React-хук `usePaywallOffer(priceId)` из sdk-react
|
|
1731
|
+
* либо обёртку поверх `setInterval(1000)` + повторный вызов этого метода.
|
|
1732
|
+
*/
|
|
1733
|
+
getOfferForPrice(priceId: string): ResolvedOffer | null;
|
|
1606
1734
|
/** Снимок текущего «языка юзера» — proxy над `billing.getUserLanguage()`.
|
|
1607
1735
|
* Используй, чтобы синхронизировать i18n host'а с тем, что фактически
|
|
1608
1736
|
* показывает пейвол. См. подробности в `BillingClient.getUserLanguage`. */
|
|
@@ -1722,6 +1850,27 @@ declare class QuotaExceededError extends PaywallError {
|
|
|
1722
1850
|
});
|
|
1723
1851
|
}
|
|
1724
1852
|
|
|
1853
|
+
/**
|
|
1854
|
+
* Resolved view of a paywall offer — what host UI actually needs to render
|
|
1855
|
+
* a strike-through price + countdown without re-implementing the math.
|
|
1856
|
+
*
|
|
1857
|
+
* `remainingMs` ticks down with wall-clock time and reaches 0 on expiry.
|
|
1858
|
+
* `totalMs` stays constant — useful for progress bars / share-of-time UX.
|
|
1859
|
+
* `expiresAt` is the Date.now()-comparable epoch ms of expiry.
|
|
1860
|
+
*
|
|
1861
|
+
* For offers without an expiry mechanism (no `expires_at` and no
|
|
1862
|
+
* `duration_minutes`), `remainingMs`/`totalMs`/`expiresAt` are all `null`,
|
|
1863
|
+
* but the resolved view is still returned — discount badge / strike-through
|
|
1864
|
+
* still make sense for "perpetual sale" offers.
|
|
1865
|
+
*/
|
|
1866
|
+
declare interface ResolvedOffer {
|
|
1867
|
+
offer: PaywallOffer;
|
|
1868
|
+
discountPercent: number;
|
|
1869
|
+
remainingMs: number | null;
|
|
1870
|
+
totalMs: number | null;
|
|
1871
|
+
expiresAt: number | null;
|
|
1872
|
+
}
|
|
1873
|
+
|
|
1725
1874
|
declare type SignUpResult = {
|
|
1726
1875
|
kind: 'signed_in';
|
|
1727
1876
|
session: AuthSession;
|
package/dist/ui.js
CHANGED
package/package.json
CHANGED