@monetize.software/sdk 3.0.0-alpha.1 → 3.0.0-alpha.10
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/README.md +34 -13
- package/dist/chunks/PaywallUI-CQG9HCwo.js +3245 -0
- package/dist/chunks/PaywallUI-CQG9HCwo.js.map +1 -0
- package/dist/chunks/PaywallUI-DQ1Jke8b.js +26 -0
- package/dist/chunks/PaywallUI-DQ1Jke8b.js.map +1 -0
- package/dist/chunks/ar-7cgIM-Vl.js +2 -0
- package/dist/chunks/ar-7cgIM-Vl.js.map +1 -0
- package/dist/chunks/ar-B2Wg_IrC.js +126 -0
- package/dist/chunks/ar-B2Wg_IrC.js.map +1 -0
- package/dist/chunks/cs-BNo9Dx0Q.js +122 -0
- package/dist/chunks/cs-BNo9Dx0Q.js.map +1 -0
- package/dist/chunks/cs-S05PC5AC.js +2 -0
- package/dist/chunks/cs-S05PC5AC.js.map +1 -0
- package/dist/chunks/da-Bi4zBG14.js +2 -0
- package/dist/chunks/da-Bi4zBG14.js.map +1 -0
- package/dist/chunks/da-Do9Lq6En.js +122 -0
- package/dist/chunks/da-Do9Lq6En.js.map +1 -0
- package/dist/chunks/de-C8pDZNvx.js +141 -0
- package/dist/chunks/de-C8pDZNvx.js.map +1 -0
- package/dist/chunks/de-nCDB6D2W.js +2 -0
- package/dist/chunks/de-nCDB6D2W.js.map +1 -0
- package/dist/chunks/el-BrKaa978.js +2 -0
- package/dist/chunks/el-BrKaa978.js.map +1 -0
- package/dist/chunks/el-DzMNX-_P.js +126 -0
- package/dist/chunks/el-DzMNX-_P.js.map +1 -0
- package/dist/chunks/es-B-Wtyzrl.js +2 -0
- package/dist/chunks/es-B-Wtyzrl.js.map +1 -0
- package/dist/chunks/es-YrKt-q4w.js +141 -0
- package/dist/chunks/es-YrKt-q4w.js.map +1 -0
- package/dist/chunks/fi-Bh44pwZ4.js +122 -0
- package/dist/chunks/fi-Bh44pwZ4.js.map +1 -0
- package/dist/chunks/fi-D1SGXjnO.js +2 -0
- package/dist/chunks/fi-D1SGXjnO.js.map +1 -0
- package/dist/chunks/fr-Bc0pw4ws.js +141 -0
- package/dist/chunks/fr-Bc0pw4ws.js.map +1 -0
- package/dist/chunks/fr-BhYf-iKk.js +2 -0
- package/dist/chunks/fr-BhYf-iKk.js.map +1 -0
- package/dist/chunks/he-BXAaFv6Y.js +2 -0
- package/dist/chunks/he-BXAaFv6Y.js.map +1 -0
- package/dist/chunks/he-Bfm-bhe3.js +126 -0
- package/dist/chunks/he-Bfm-bhe3.js.map +1 -0
- package/dist/chunks/hi-D-O-B9Dn.js +126 -0
- package/dist/chunks/hi-D-O-B9Dn.js.map +1 -0
- package/dist/chunks/hi-xblDO0O7.js +2 -0
- package/dist/chunks/hi-xblDO0O7.js.map +1 -0
- package/dist/chunks/hu-CmIuAbLL.js +122 -0
- package/dist/chunks/hu-CmIuAbLL.js.map +1 -0
- package/dist/chunks/hu-Wa46p0y4.js +2 -0
- package/dist/chunks/hu-Wa46p0y4.js.map +1 -0
- package/dist/chunks/id-CQEo5X94.js +2 -0
- package/dist/chunks/id-CQEo5X94.js.map +1 -0
- package/dist/chunks/id-DN7IES-A.js +122 -0
- package/dist/chunks/id-DN7IES-A.js.map +1 -0
- package/dist/chunks/it-8AYCm0xz.js +2 -0
- package/dist/chunks/it-8AYCm0xz.js.map +1 -0
- package/dist/chunks/it-Cz5Nmqx5.js +141 -0
- package/dist/chunks/it-Cz5Nmqx5.js.map +1 -0
- package/dist/chunks/ja-BH9BlBh2.js +145 -0
- package/dist/chunks/ja-BH9BlBh2.js.map +1 -0
- package/dist/chunks/ja-q-COVayn.js +2 -0
- package/dist/chunks/ja-q-COVayn.js.map +1 -0
- package/dist/chunks/ko-B6HRCscZ.js +2 -0
- package/dist/chunks/ko-B6HRCscZ.js.map +1 -0
- package/dist/chunks/ko-CYV9QuYs.js +145 -0
- package/dist/chunks/ko-CYV9QuYs.js.map +1 -0
- package/dist/chunks/nl-BvkB900D.js +141 -0
- package/dist/chunks/nl-BvkB900D.js.map +1 -0
- package/dist/chunks/nl-CAd6_xlm.js +2 -0
- package/dist/chunks/nl-CAd6_xlm.js.map +1 -0
- package/dist/chunks/no-3s9_ormb.js +122 -0
- package/dist/chunks/no-3s9_ormb.js.map +1 -0
- package/dist/chunks/no-CAmz6bz6.js +2 -0
- package/dist/chunks/no-CAmz6bz6.js.map +1 -0
- package/dist/chunks/pl-C9WTGQtb.js +122 -0
- package/dist/chunks/pl-C9WTGQtb.js.map +1 -0
- package/dist/chunks/pl-DqUSTCaF.js +2 -0
- package/dist/chunks/pl-DqUSTCaF.js.map +1 -0
- package/dist/chunks/pt-8ARZnH0_.js +2 -0
- package/dist/chunks/pt-8ARZnH0_.js.map +1 -0
- package/dist/chunks/pt-uFVUv_Op.js +141 -0
- package/dist/chunks/pt-uFVUv_Op.js.map +1 -0
- package/dist/chunks/ro-BrqQ8Au-.js +122 -0
- package/dist/chunks/ro-BrqQ8Au-.js.map +1 -0
- package/dist/chunks/ro-D-NMbp2F.js +2 -0
- package/dist/chunks/ro-D-NMbp2F.js.map +1 -0
- package/dist/chunks/ru-8gbHPh0g.js +2 -0
- package/dist/chunks/ru-8gbHPh0g.js.map +1 -0
- package/dist/chunks/ru-DK594dA8.js +144 -0
- package/dist/chunks/ru-DK594dA8.js.map +1 -0
- package/dist/chunks/sv-CHNH8-mq.js +122 -0
- package/dist/chunks/sv-CHNH8-mq.js.map +1 -0
- package/dist/chunks/sv-D8a8hmx9.js +2 -0
- package/dist/chunks/sv-D8a8hmx9.js.map +1 -0
- package/dist/chunks/th-DfjUK0Y7.js +2 -0
- package/dist/chunks/th-DfjUK0Y7.js.map +1 -0
- package/dist/chunks/th-l24Pm5q-.js +126 -0
- package/dist/chunks/th-l24Pm5q-.js.map +1 -0
- package/dist/chunks/tr-ADpigSY5.js +122 -0
- package/dist/chunks/tr-ADpigSY5.js.map +1 -0
- package/dist/chunks/tr-BdBpz4tL.js +2 -0
- package/dist/chunks/tr-BdBpz4tL.js.map +1 -0
- package/dist/chunks/uk-CGqo4jek.js +144 -0
- package/dist/chunks/uk-CGqo4jek.js.map +1 -0
- package/dist/chunks/uk-Cx1zv1ao.js +2 -0
- package/dist/chunks/uk-Cx1zv1ao.js.map +1 -0
- package/dist/chunks/vi-Dk9bTu6f.js +122 -0
- package/dist/chunks/vi-Dk9bTu6f.js.map +1 -0
- package/dist/chunks/vi-oe2dW21I.js +2 -0
- package/dist/chunks/vi-oe2dW21I.js.map +1 -0
- package/dist/chunks/zh-CwczPMPp.js +2 -0
- package/dist/chunks/zh-CwczPMPp.js.map +1 -0
- package/dist/chunks/zh-LDkEV2D9.js +145 -0
- package/dist/chunks/zh-LDkEV2D9.js.map +1 -0
- package/dist/core.cjs +1 -1
- package/dist/core.cjs.map +1 -1
- package/dist/core.d.ts +265 -24
- package/dist/core.js +519 -313
- package/dist/core.js.map +1 -1
- package/dist/index.cjs +1 -1
- package/dist/index.d.ts +355 -43
- package/dist/index.js +14 -10
- package/dist/ui.cjs +1 -1
- package/dist/ui.d.ts +322 -44
- package/dist/ui.js +1 -1
- package/package.json +32 -31
- package/dist/chunks/PaywallUI-BHp9afFC.js +0 -2209
- package/dist/chunks/PaywallUI-BHp9afFC.js.map +0 -1
- package/dist/chunks/PaywallUI-Dr-6q-HL.js +0 -26
- package/dist/chunks/PaywallUI-Dr-6q-HL.js.map +0 -1
package/dist/index.js
CHANGED
|
@@ -1,19 +1,23 @@
|
|
|
1
|
-
import { ApiClient as t, ApiGatewayClient as a, AuthClient as i, BillingClient as
|
|
2
|
-
import { P as
|
|
1
|
+
import { ApiClient as t, ApiGatewayClient as a, AuthClient as i, BillingClient as o, EventTracker as l, PaywallError as f, QuotaExceededError as n, SDK_VERSION as s, STORAGE_KEYS as S, createStorage as E, ensureVisitorId as d, findApplicableOffer as p, generateVisitorId as c, offerStartStorageKey as g, readBrowserOfferStart as y, resolveOffer as A } from "./core.js";
|
|
2
|
+
import { P as w, b as C } from "./chunks/PaywallUI-CQG9HCwo.js";
|
|
3
3
|
export {
|
|
4
4
|
t as ApiClient,
|
|
5
5
|
a as ApiGatewayClient,
|
|
6
6
|
i as AuthClient,
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
7
|
+
o as BillingClient,
|
|
8
|
+
l as EventTracker,
|
|
9
|
+
f as PaywallError,
|
|
10
|
+
w as PaywallUI,
|
|
11
|
+
n as QuotaExceededError,
|
|
12
12
|
s as SDK_VERSION,
|
|
13
13
|
S as STORAGE_KEYS,
|
|
14
|
-
|
|
15
|
-
|
|
14
|
+
C as blockRegistry,
|
|
15
|
+
E as createStorage,
|
|
16
16
|
d as ensureVisitorId,
|
|
17
|
-
|
|
17
|
+
p as findApplicableOffer,
|
|
18
|
+
c as generateVisitorId,
|
|
19
|
+
g as offerStartStorageKey,
|
|
20
|
+
y as readBrowserOfferStart,
|
|
21
|
+
A 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-DQ1Jke8b.js");exports.PaywallUI=e.PaywallUI;exports.blockRegistry=e.blockRegistry;
|
|
2
2
|
//# sourceMappingURL=ui.cjs.map
|
package/dist/ui.d.ts
CHANGED
|
@@ -46,7 +46,9 @@ declare class ApiGatewayClient {
|
|
|
46
46
|
|
|
47
47
|
declare interface ApiGatewayClientOptions {
|
|
48
48
|
paywallId: string;
|
|
49
|
-
|
|
49
|
+
/** Origin серверного API SDK — обязательное поле, тот же `custom_domain`, что
|
|
50
|
+
* у BillingClient/AuthClient. См. {@link BillingClientOptions.apiOrigin}. */
|
|
51
|
+
apiOrigin: string;
|
|
50
52
|
/** AuthClient — Bearer добавляется автоматически. На 401 от gateway клиент
|
|
51
53
|
* не делает refresh: AuthClient уже сделал lazy-refresh в getAccessToken. */
|
|
52
54
|
auth?: AuthClient;
|
|
@@ -66,7 +68,28 @@ declare interface ApiGatewayClientOptions {
|
|
|
66
68
|
onQuotaExceeded?: (err: QuotaExceededError) => void;
|
|
67
69
|
}
|
|
68
70
|
|
|
69
|
-
|
|
71
|
+
/** Дискриминатор для `onAuthChange`. Позволяет listener'у отличать первый
|
|
72
|
+
* callback (восстановление сессии из storage / синтетический snapshot для
|
|
73
|
+
* свежей подписки) от реальных переходов. Конвенция Supabase, минус события,
|
|
74
|
+
* которых у нас нет (MFA, EMAIL_VERIFIED).
|
|
75
|
+
*
|
|
76
|
+
* - INITIAL_SESSION — единственный гарантированный первый callback на каждую
|
|
77
|
+
* подписку. Дёргается через microtask после resolve hydrated-promise, даже
|
|
78
|
+
* если session=null. Listener'ы по этому event'у НЕ должны делать побочные
|
|
79
|
+
* эффекты типа force-refetch — это просто доставка стартового state'а.
|
|
80
|
+
* - SIGNED_IN — свежий вход: email/OAuth/anon, или появление session в этом
|
|
81
|
+
* инстансе из другого контекста (storage.watch), когда раньше был null.
|
|
82
|
+
* - SIGNED_OUT — signOut, revokeAllSessions, 401 на refresh, удаление session
|
|
83
|
+
* из другого контекста.
|
|
84
|
+
* - TOKEN_REFRESHED — тот же user, обновлённые токены: refresh(), либо
|
|
85
|
+
* storage.watch когда содержимое сменилось но user.id остался.
|
|
86
|
+
* - USER_UPDATED — изменился user.email / user.user_metadata (updatePassword,
|
|
87
|
+
* upgradeAnonymousToEmail) при том же user.id.
|
|
88
|
+
* - PASSWORD_RECOVERY — verifyOtp(type='recovery'). Listener знает, что надо
|
|
89
|
+
* показать «set new password» UI вместо обычного post-login flow'а. */
|
|
90
|
+
declare type AuthChangeEvent = 'INITIAL_SESSION' | 'SIGNED_IN' | 'SIGNED_OUT' | 'TOKEN_REFRESHED' | 'USER_UPDATED' | 'PASSWORD_RECOVERY';
|
|
91
|
+
|
|
92
|
+
declare type AuthChangeListener = (event: AuthChangeEvent, session: AuthSession | null) => void;
|
|
70
93
|
|
|
71
94
|
declare class AuthClient {
|
|
72
95
|
readonly paywallId: string;
|
|
@@ -225,10 +248,8 @@ declare class AuthClient {
|
|
|
225
248
|
* когда сервер начнёт возвращать challenge_required в риск-сценариях,
|
|
226
249
|
* SDK сможет передать proof-of-something обратно без breaking change.
|
|
227
250
|
*
|
|
228
|
-
* `
|
|
229
|
-
* нового anon-юзера). Используется в switch-account flow.
|
|
230
|
-
* остаётся `forceCaptcha`, хотя капчи там больше нет — менять имя ломает
|
|
231
|
-
* host-сигнатуру; смысл «принудительно новая anon-сессия» сохранён.
|
|
251
|
+
* `forceNewAnon: true` пропускает шаги 1-2 и сразу делает /signin (создаёт
|
|
252
|
+
* нового anon-юзера). Используется в switch-account flow.
|
|
232
253
|
*
|
|
233
254
|
* Параллельные вызовы дедуплицируются через `inflightAnonSignin` — два
|
|
234
255
|
* click'а на «Войти как гость» не создадут двух anon-юзеров (два /signup =
|
|
@@ -237,7 +258,7 @@ declare class AuthClient {
|
|
|
237
258
|
signInAnonymously(input?: {
|
|
238
259
|
captchaToken?: string;
|
|
239
260
|
userMeta?: Record<string, string>;
|
|
240
|
-
|
|
261
|
+
forceNewAnon?: boolean;
|
|
241
262
|
}): Promise<AuthSession>;
|
|
242
263
|
/**
|
|
243
264
|
* Внутренний resume — пробует /auth/refresh с сохранённым anon refresh_token.
|
|
@@ -385,8 +406,19 @@ declare class AuthClient {
|
|
|
385
406
|
}): Promise<void>;
|
|
386
407
|
/**
|
|
387
408
|
* Подписка на изменения session: signin/signup/refresh/signOut/expired-401.
|
|
388
|
-
*
|
|
389
|
-
*
|
|
409
|
+
*
|
|
410
|
+
* Гарантированный контракт: ПЕРВЫЙ callback каждому subscriber'у — всегда
|
|
411
|
+
* `event = 'INITIAL_SESSION'`, дёргается асинхронно после resolve hydrate'а
|
|
412
|
+
* (даже если session=null — listener получает explicit «нет сессии», а не
|
|
413
|
+
* молчание). Все последующие callback'и — реальные переходы с конкретным
|
|
414
|
+
* event'ом (SIGNED_IN / SIGNED_OUT / TOKEN_REFRESHED / USER_UPDATED /
|
|
415
|
+
* PASSWORD_RECOVERY).
|
|
416
|
+
*
|
|
417
|
+
* Это позволяет listener'у безопасно делать «only on real signin» побочные
|
|
418
|
+
* эффекты (force refetch balances и т.п.) через `event === 'SIGNED_IN'`,
|
|
419
|
+
* не путая их с восстановлением из storage.
|
|
420
|
+
*
|
|
421
|
+
* Возвращает unsubscribe.
|
|
390
422
|
*/
|
|
391
423
|
onAuthChange(cb: AuthChangeListener): () => void;
|
|
392
424
|
private isFresh;
|
|
@@ -412,6 +444,18 @@ declare class AuthClient {
|
|
|
412
444
|
private readAnonRefreshToken;
|
|
413
445
|
private writeAnonRefreshToken;
|
|
414
446
|
private clearAnonRefreshToken;
|
|
447
|
+
/**
|
|
448
|
+
* Last-used auth method + email — для UI бейджа "Last used" и pre-fill'а
|
|
449
|
+
* email-инпута. Storage paywall-scoped, поэтому переключение между
|
|
450
|
+
* пейволами на одном host'е не пересекает данные. Чтение всегда возвращает
|
|
451
|
+
* объект — отсутствующие поля = null. */
|
|
452
|
+
getLastLogin(): Promise<LastLogin | null>;
|
|
453
|
+
/** Запись method и email атомарно (для email/password flows — оба известны
|
|
454
|
+
* на момент signin/signup'а). OAuth-flows используют раздельные
|
|
455
|
+
* recordLastLoginMethod (до popup) и recordLastLoginEmail (после exchange). */
|
|
456
|
+
private recordLastLogin;
|
|
457
|
+
private recordLastLoginMethod;
|
|
458
|
+
private recordLastLoginEmail;
|
|
415
459
|
/**
|
|
416
460
|
* Читает stable visitor_id из storage если он там уже есть. НЕ генерит:
|
|
417
461
|
* AuthClient может быть инстанцирован раньше BillingClient, а синтетический
|
|
@@ -424,7 +468,9 @@ declare class AuthClient {
|
|
|
424
468
|
|
|
425
469
|
declare interface AuthClientOptions {
|
|
426
470
|
paywallId: string;
|
|
427
|
-
|
|
471
|
+
/** Origin серверного API SDK — обязательное поле, тот же `custom_domain`, что
|
|
472
|
+
* у BillingClient. См. {@link BillingClientOptions.apiOrigin}. */
|
|
473
|
+
apiOrigin: string;
|
|
428
474
|
storage?: StorageAdapter;
|
|
429
475
|
fetch?: typeof fetch;
|
|
430
476
|
openPopup?: (url: string, name: string) => Window | null;
|
|
@@ -500,6 +546,8 @@ declare class BillingClient {
|
|
|
500
546
|
private balancesStorageUnwatch;
|
|
501
547
|
private inflightBalances;
|
|
502
548
|
private balanceListeners;
|
|
549
|
+
private readonly previewMode;
|
|
550
|
+
private previewVersionCounter;
|
|
503
551
|
constructor(opts: BillingClientOptions);
|
|
504
552
|
/**
|
|
505
553
|
* Stable visitor_id (UUID v4). Первый вызов awaitит первичный резолв из
|
|
@@ -532,6 +580,24 @@ declare class BillingClient {
|
|
|
532
580
|
* unsubscribe.
|
|
533
581
|
*/
|
|
534
582
|
onBootstrapChange(cb: (b: PaywallBootstrap) => void): () => void;
|
|
583
|
+
/**
|
|
584
|
+
* Заменить cachedBootstrap частичными или полными данными и эмитнуть всем
|
|
585
|
+
* подписчикам. Используется host'ом в preview-mode (редактор админки) для
|
|
586
|
+
* live-обновления открытой модалки без сетевого revalidate'а.
|
|
587
|
+
*
|
|
588
|
+
* Поведение:
|
|
589
|
+
* - Без `cachedBootstrap` ожидаются как минимум `settings` + `prices` —
|
|
590
|
+
* иначе PaywallRoot не сможет отрендерить тарифы и упадёт.
|
|
591
|
+
* - С существующим кешем партиал мёрджится поверх: `settings` глубокий мёрдж
|
|
592
|
+
* на 1 уровень (поля настроек), массивы `prices`/`offers` перезаписываются.
|
|
593
|
+
* - Каждый вызов бампит `version` ("preview:<n>"), чтобы applyBootstrap'овая
|
|
594
|
+
* проверка `versionChanged` всегда срабатывала и listener'ы дёргались.
|
|
595
|
+
* - Persist в storage НЕ делаем — preview не должен утекать в другие вкладки.
|
|
596
|
+
*
|
|
597
|
+
* В non-preview режиме метод доступен, но это редкий путь (например, для
|
|
598
|
+
* тестов host'а) — production-код должен полагаться на bootstrap() + revalidate.
|
|
599
|
+
*/
|
|
600
|
+
setBootstrap(partial: Partial<PaywallBootstrap>): void;
|
|
535
601
|
private fetchBootstrap;
|
|
536
602
|
private revalidateBootstrap;
|
|
537
603
|
private applyBootstrap;
|
|
@@ -557,6 +623,13 @@ declare class BillingClient {
|
|
|
557
623
|
}): Promise<PaywallPrice[]>;
|
|
558
624
|
/** Sync-снимок цен из последнего bootstrap'а. null = ещё не загружали. */
|
|
559
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;
|
|
560
633
|
/**
|
|
561
634
|
* Снимок того, какой язык SDK сейчас считает «языком юзера». Полезно для
|
|
562
635
|
* синхронизации i18n хоста с тем, что фактически показывает пейвол — чтобы
|
|
@@ -731,21 +804,31 @@ declare class BillingClient {
|
|
|
731
804
|
* `/api/v1/paywall/[id]/user` без unstable_cache, потому что list для UI
|
|
732
805
|
* должен быть свежим после cancel-а.
|
|
733
806
|
*
|
|
734
|
-
* Auth
|
|
735
|
-
*
|
|
807
|
+
* Auth (два пути):
|
|
808
|
+
* - Bearer (через AuthClient) — user.id резолвится из сессии, identity
|
|
809
|
+
* в query игнорируется.
|
|
810
|
+
* - `apiKey` + `identity.email`/`identity.userId` — server-SDK путь для
|
|
811
|
+
* интеграций со своей авторизацией. Бэк проверяет, что identity линкована
|
|
812
|
+
* к этому пейволу (защита от cross-paywall lookup).
|
|
813
|
+
* Без auth и без apiKey+identity — `identity_required`.
|
|
736
814
|
*/
|
|
737
815
|
listPurchases(opts?: {
|
|
738
816
|
signal?: AbortSignal;
|
|
739
817
|
}): Promise<PaywallPurchaseDetailed[]>;
|
|
740
818
|
/**
|
|
741
|
-
* Отменить подписку. Бэк
|
|
742
|
-
*
|
|
743
|
-
*
|
|
819
|
+
* Отменить подписку. Бэк проверит, что subscription принадлежит юзеру
|
|
820
|
+
* (Bearer-путь — из сессии; apiKey-путь — из identity), и сделает cancel у
|
|
821
|
+
* acquiring'а (Stripe/Paddle/Chargebee/Overpay). По умолчанию cancel в
|
|
822
|
+
* конце текущего периода — юзер сохраняет access до renewal date'ы.
|
|
744
823
|
*
|
|
745
|
-
* `reason` обязательна (валидация на бэке).
|
|
746
|
-
* причин в host-UI, как в legacy customer portal'е.
|
|
824
|
+
* `reason` обязательна (валидация на бэке).
|
|
747
825
|
*
|
|
748
|
-
* Auth
|
|
826
|
+
* Auth (два пути):
|
|
827
|
+
* - Bearer (через AuthClient) — стандартный путь для UI customer-portal'a.
|
|
828
|
+
* - `apiKey` + `identity.email`/`identity.userId` — для self-service UI на
|
|
829
|
+
* бэке клиента со своей авторизацией. Бэк дополнительно фильтрует
|
|
830
|
+
* subscription по paywall_id, чтобы owner пейвола A не отменил подписку
|
|
831
|
+
* пейвола B.
|
|
749
832
|
*/
|
|
750
833
|
cancelSubscription(params: {
|
|
751
834
|
subscriptionId: string;
|
|
@@ -782,7 +865,15 @@ declare class BillingClient {
|
|
|
782
865
|
|
|
783
866
|
declare interface BillingClientOptions {
|
|
784
867
|
paywallId: string;
|
|
785
|
-
|
|
868
|
+
/**
|
|
869
|
+
* Origin серверного API SDK — обязательное поле. Должно совпадать с
|
|
870
|
+
* `custom_domain`, заданным для пейвола в платформе (модерация привязывает
|
|
871
|
+
* домен к paywall_id). SDK сверяет это значение с `bootstrap.settings.custom_domain`
|
|
872
|
+
* на первом ответе и кидает `invalid_config` при расхождении — защита от
|
|
873
|
+
* опечаток интегратора. Промежуточный `appbox.space` в новом SDK НЕ
|
|
874
|
+
* используется (это только для legacy v2).
|
|
875
|
+
*/
|
|
876
|
+
apiOrigin: string;
|
|
786
877
|
identity?: Identity;
|
|
787
878
|
storage?: StorageAdapter;
|
|
788
879
|
capabilities?: string[];
|
|
@@ -803,6 +894,16 @@ declare interface BillingClientOptions {
|
|
|
803
894
|
* через `setIdentity`, Bearer не отправляется.
|
|
804
895
|
*/
|
|
805
896
|
auth?: AuthClient;
|
|
897
|
+
/**
|
|
898
|
+
* Preview/editor-mode. Когда true:
|
|
899
|
+
* - `bootstrap()` НЕ ходит в сеть — отдаёт только `cachedBootstrap`, заданный
|
|
900
|
+
* через `setBootstrap()`. Без seed'а throw'ает (caller обязан засидить до open).
|
|
901
|
+
* - Storage.watch / persist отключены (preview редактора локален для текущей вкладки).
|
|
902
|
+
* - `setBootstrap(partial)` доступен как публичный setter — host'у разрешено
|
|
903
|
+
* мутировать кеш для live-обновления модалки в редакторе админки.
|
|
904
|
+
* Дефолт false — обычный production-режим.
|
|
905
|
+
*/
|
|
906
|
+
preview?: boolean;
|
|
806
907
|
}
|
|
807
908
|
|
|
808
909
|
export declare type BlockComponent<B extends LayoutBlock = LayoutBlock> = ComponentType<BlockProps<B>>;
|
|
@@ -818,6 +919,10 @@ export declare interface BlockContext {
|
|
|
818
919
|
/** Текущая auth-session (snapshot из AuthClient). null = разлогинен. PaywallRoot
|
|
819
920
|
* подписан на onAuthChange и пробрасывает свежий snapshot сюда. */
|
|
820
921
|
authSession: AuthSession | null;
|
|
922
|
+
/** Стартовый mode для AuthPanel — переопределяет дефолт 'signin'.
|
|
923
|
+
* Выставляется AuthGate'ом когда host вызвал openSignup()/openSignin().
|
|
924
|
+
* Остальные блоки игнорируют. */
|
|
925
|
+
initialAuthMode?: 'signin' | 'signup';
|
|
821
926
|
}
|
|
822
927
|
|
|
823
928
|
export declare interface BlockProps<B extends LayoutBlock = LayoutBlock> {
|
|
@@ -847,6 +952,18 @@ declare interface Identity {
|
|
|
847
952
|
anonymousId?: string;
|
|
848
953
|
}
|
|
849
954
|
|
|
955
|
+
declare interface LastLogin {
|
|
956
|
+
method: LastLoginMethod;
|
|
957
|
+
email: string | null;
|
|
958
|
+
}
|
|
959
|
+
|
|
960
|
+
/** Метод, которым юзер залогинился в последний раз на этом пейволе.
|
|
961
|
+
* Хранится per-paywall в storage и используется UI чтобы:
|
|
962
|
+
* - предзаполнить email-инпут last-known email'ом;
|
|
963
|
+
* - подсветить ту же OAuth-кнопку / email-форму бейджем "Last used".
|
|
964
|
+
* `email` — email/password forms (signin или signup → confirm). */
|
|
965
|
+
declare type LastLoginMethod = OAuthProvider | 'email';
|
|
966
|
+
|
|
850
967
|
declare interface Layout {
|
|
851
968
|
type: 'modal';
|
|
852
969
|
blocks: LayoutBlock[];
|
|
@@ -862,9 +979,13 @@ declare type LayoutBlock = {
|
|
|
862
979
|
} | {
|
|
863
980
|
type: 'price_grid';
|
|
864
981
|
priceIds?: string[];
|
|
865
|
-
/** Раскладка карточек
|
|
866
|
-
* `
|
|
867
|
-
|
|
982
|
+
/** Раскладка карточек цен:
|
|
983
|
+
* - `vertical` (default) — стек карточек сверху вниз;
|
|
984
|
+
* - `compact` — компактный список (одна строка на цену, без карточки,
|
|
985
|
+
* с разделителем); v2-аналог `view: 'telegram'`;
|
|
986
|
+
* - `horizontal` — несколько карточек рядом в ряд; v2-only с момента
|
|
987
|
+
* SDK 3.0 (legacy не показывает выбор этой опции в админке). */
|
|
988
|
+
view?: 'vertical' | 'compact' | 'horizontal';
|
|
868
989
|
/** ID цены, которая помечается лейблом «популярный план». v2-аналог
|
|
869
990
|
* пары `price_label_id` + `price_label`. */
|
|
870
991
|
popular_price_id?: string;
|
|
@@ -873,7 +994,10 @@ declare type LayoutBlock = {
|
|
|
873
994
|
popular_label?: string;
|
|
874
995
|
} | {
|
|
875
996
|
type: 'cta_button';
|
|
876
|
-
|
|
997
|
+
/** Текст на кнопке. Если не задан — рендерер сам подберёт по
|
|
998
|
+
* selected price'у и `trial_days`: "Start N-Day Free Trial",
|
|
999
|
+
* "Get Lifetime Access", "Get Monthly Plan" и т.п. */
|
|
1000
|
+
label?: string;
|
|
877
1001
|
action: 'checkout' | 'close';
|
|
878
1002
|
priceId?: string;
|
|
879
1003
|
} | {
|
|
@@ -892,8 +1016,23 @@ declare type LayoutBlock = {
|
|
|
892
1016
|
/** Скрывать панель, если юзер уже залогинен. По умолчанию true.
|
|
893
1017
|
* false — показываем "Signed in as ... [Sign out]" даже после логина. */
|
|
894
1018
|
hide_when_authenticated?: boolean;
|
|
895
|
-
/**
|
|
1019
|
+
/** Кастомный заголовок над формой. Если задан — отображается вместо
|
|
1020
|
+
* дефолтного (определяется по mode'у — "Welcome back!" / "Welcome!" /
|
|
1021
|
+
* "Forgot password?" / ...). Без `submit_label` также используется как
|
|
1022
|
+
* submit-лейбл для signin (например `heading="Restore Purchases"` →
|
|
1023
|
+
* submit тоже "Restore Purchases"). Длинные heading (типа "Войдите,
|
|
1024
|
+
* чтобы продолжить покупку") в кнопку влезают плохо — задай
|
|
1025
|
+
* `submit_label` отдельно. */
|
|
896
1026
|
heading?: string;
|
|
1027
|
+
/** Подпись под заголовком. Если опущен — подставляется default-текст
|
|
1028
|
+
* для текущего mode'а. Передай пустую строку чтобы скрыть подпись. */
|
|
1029
|
+
subheading?: string;
|
|
1030
|
+
/** Явный текст submit-кнопки. Имеет приоритет над heading-эхо. Нужен
|
|
1031
|
+
* для интентов с длинным descriptive heading'ом (preauth: "Войдите,
|
|
1032
|
+
* чтобы продолжить покупку" — кнопка только "Войти"). Для коротких
|
|
1033
|
+
* action-headings (restore: "Restore Purchases") опускай — эхо
|
|
1034
|
+
* даёт правильный UX. */
|
|
1035
|
+
submit_label?: string;
|
|
897
1036
|
} | {
|
|
898
1037
|
/** Список фич/преимуществ продукта. v2-аналог `features_list` + `features_view`.
|
|
899
1038
|
* До 5 элементов — рендерим как чек-лист с заголовком и описанием. */
|
|
@@ -917,6 +1056,35 @@ declare type LayoutBlock = {
|
|
|
917
1056
|
desc: string;
|
|
918
1057
|
count: number;
|
|
919
1058
|
}>;
|
|
1059
|
+
} | {
|
|
1060
|
+
/** Money-back guarantee badge под cta_button: иконка + жирный заголовок +
|
|
1061
|
+
* пояснение мелким шрифтом + bottom divider, который визуально стыкуется
|
|
1062
|
+
* с current_session ниже. v2-аналог inline-блока в `PaywallPricing`. */
|
|
1063
|
+
type: 'guarantee_badge';
|
|
1064
|
+
/** Заголовок жирным. По умолчанию "100% Money-Back Guarantee". */
|
|
1065
|
+
title?: string;
|
|
1066
|
+
/** Подзаголовок мелким серым. По умолчанию
|
|
1067
|
+
* "Not satisfied? We'll refund you — no questions asked.". */
|
|
1068
|
+
subtitle?: string;
|
|
1069
|
+
/** Иконка слева от заголовка. По умолчанию `dollar_shield` —
|
|
1070
|
+
* зелёный shield с долларом (legacy-вид). `none` — без иконки. */
|
|
1071
|
+
icon?: 'dollar_shield' | 'none';
|
|
1072
|
+
} | {
|
|
1073
|
+
/** Urgency-баннер с countdown'ом до конца offer'а. Берёт первый offer
|
|
1074
|
+
* из `bootstrap.offers` с валидным `expires_at` или `duration_minutes`.
|
|
1075
|
+
* Авто-скрывается по истечении, чтобы не показывать "0d 0h 0m 0s".
|
|
1076
|
+
* Размещение — обычно первый блок в layout (над heading). */
|
|
1077
|
+
type: 'offer_banner';
|
|
1078
|
+
/** ID конкретного offer'а из bootstrap.offers. Если не задано — берётся
|
|
1079
|
+
* первый offer с активным таймером. */
|
|
1080
|
+
offer_id?: string;
|
|
1081
|
+
/** Текст слева от countdown'а. Если опущен — берётся `offer.label`,
|
|
1082
|
+
* иначе fallback "Limited-time offer". К нему дописывается процент:
|
|
1083
|
+
* "{title} {discount_percent}%" если discount задан. */
|
|
1084
|
+
title?: string;
|
|
1085
|
+
/** В превью админки — игнорировать expired-state, всё равно показывать
|
|
1086
|
+
* banner с нулями. Прод-режим — false (banner исчезает). */
|
|
1087
|
+
force?: boolean;
|
|
920
1088
|
};
|
|
921
1089
|
|
|
922
1090
|
/** Локализационные оверрайды для одного языка. Накатываются поверх дефолтного
|
|
@@ -1076,9 +1244,19 @@ declare interface PaywallEventPayloads {
|
|
|
1076
1244
|
/** User-state изменился (bootstrap snapshot, getUser refresh, watcher tick).
|
|
1077
1245
|
* Дёргается также сразу с last-known user после первой подписки. */
|
|
1078
1246
|
userChange: PaywallUser;
|
|
1079
|
-
/** Auth-session
|
|
1080
|
-
*
|
|
1081
|
-
|
|
1247
|
+
/** Auth-session изменилась. Payload содержит `event` (см. AuthChangeEvent —
|
|
1248
|
+
* INITIAL_SESSION / SIGNED_IN / SIGNED_OUT / TOKEN_REFRESHED / USER_UPDATED /
|
|
1249
|
+
* PASSWORD_RECOVERY) и `session` (null = разлогинен).
|
|
1250
|
+
*
|
|
1251
|
+
* Гарантированный контракт: первый callback каждому subscriber'у — всегда
|
|
1252
|
+
* INITIAL_SESSION с восстановленной из storage сессией (или null если нет).
|
|
1253
|
+
* Дальше — реальные переходы. Listener'у с побочными эффектами вроде
|
|
1254
|
+
* force-refetch balances ловить SIGNED_IN, а не любой truthy session,
|
|
1255
|
+
* иначе reload страницы будет триггерить лишний запрос. */
|
|
1256
|
+
authChange: {
|
|
1257
|
+
event: AuthChangeEvent;
|
|
1258
|
+
session: AuthSession | null;
|
|
1259
|
+
};
|
|
1082
1260
|
/** Триал заблокировал показ модалки. payload содержит свежий статус (после
|
|
1083
1261
|
* recordBlock). Для `mode: 'time'` — startedAt/expiresAt/remainingMs;
|
|
1084
1262
|
* для `mode: 'opens'` — remainingActions/totalActions. Хост может
|
|
@@ -1098,7 +1276,15 @@ declare interface PaywallEventPayloads {
|
|
|
1098
1276
|
declare interface PaywallOffer {
|
|
1099
1277
|
id: string;
|
|
1100
1278
|
discount_percent: number | null;
|
|
1279
|
+
/** Абсолютная expiration date (ISO 8601). Если задана — countdown отсчитывает
|
|
1280
|
+
* до этого момента, по истечении offer считается истёкшим. */
|
|
1101
1281
|
expires_at: string | null;
|
|
1282
|
+
/** Относительный таймер: сколько минут offer живёт **от первого просмотра
|
|
1283
|
+
* пейвола** данным юзером. Старт хранится в clientStorage под ключом
|
|
1284
|
+
* `pw-offer-{id}-start`, по истечении — auto-cleanup. Используется, когда
|
|
1285
|
+
* бэк хочет показывать "remaining time" без жёсткой server-time, а считать
|
|
1286
|
+
* относительно сессии юзера. expires_at имеет приоритет если задано. */
|
|
1287
|
+
duration_minutes?: number | null;
|
|
1102
1288
|
price_id: string | null;
|
|
1103
1289
|
label?: string | null;
|
|
1104
1290
|
}
|
|
@@ -1148,6 +1334,14 @@ declare interface PaywallSettings {
|
|
|
1148
1334
|
brand_color?: string | null;
|
|
1149
1335
|
custom_css?: string | null;
|
|
1150
1336
|
locale_default?: string | null;
|
|
1337
|
+
/** Origin, на котором живёт бэк пейвола (тот же, что мерчант передаёт в
|
|
1338
|
+
* `BillingClientOptions.apiOrigin` при инициализации SDK). Бэк присылает
|
|
1339
|
+
* его на каждом bootstrap'е, SDK сверяет с init.apiOrigin — расхождение
|
|
1340
|
+
* даёт `invalid_config` (защита от опечатки интегратора). Без схемы:
|
|
1341
|
+
* "pay.your-domain.com" или "https://pay.your-domain.com" — оба валидны.
|
|
1342
|
+
* Для новых пейволов поле всегда заполнено (модерация требует custom_domain);
|
|
1343
|
+
* для legacy v2 может быть null/undefined. */
|
|
1344
|
+
custom_domain?: string | null;
|
|
1151
1345
|
runtime_mode?: 'client' | 'hybrid' | 'server' | 'client-native' | 'hybrid-native';
|
|
1152
1346
|
/** true, если эквайринг пейвола в test-mode — SDK рисует TEST MODE бейдж. */
|
|
1153
1347
|
is_test_mode?: boolean;
|
|
@@ -1207,7 +1401,7 @@ export declare interface PaywallStateSnapshot {
|
|
|
1207
1401
|
/** Модалка отрендерена и видна. False — closed (или ещё не открывалась). */
|
|
1208
1402
|
open: boolean;
|
|
1209
1403
|
/** Что показывается в модалке. null когда `open=false`. */
|
|
1210
|
-
view: 'loading' | 'error' | 'layout' | 'auth' | '
|
|
1404
|
+
view: 'loading' | 'error' | 'layout' | 'auth' | 'support' | 'awaiting_payment' | 'popup_blocked' | 'purchased' | null;
|
|
1211
1405
|
/** Заполнено только когда `view === 'error'`. */
|
|
1212
1406
|
error: PaywallError | null;
|
|
1213
1407
|
}
|
|
@@ -1244,6 +1438,10 @@ export declare class PaywallUI {
|
|
|
1244
1438
|
private lastVisibility;
|
|
1245
1439
|
/** Поведение open() при холодном bootstrap'е. См. PaywallUIOptions.mountThenLoad. */
|
|
1246
1440
|
private mountThenLoad;
|
|
1441
|
+
/** Inline-режим (live-preview редактора). См. PaywallUIOptions.inline. */
|
|
1442
|
+
private inline;
|
|
1443
|
+
/** Force-locale для I18nProvider. См. PaywallUIOptions.locale. */
|
|
1444
|
+
private forceLocale;
|
|
1247
1445
|
/** Текущий snapshot UI state-machine. Обновляется PaywallRoot'ом через
|
|
1248
1446
|
* `onState` prop; при close сбрасывается обратно в CLOSED_STATE. */
|
|
1249
1447
|
private currentState;
|
|
@@ -1266,6 +1464,26 @@ export declare class PaywallUI {
|
|
|
1266
1464
|
* last-known user из кеша синхронно через microtask, если он есть.
|
|
1267
1465
|
*/
|
|
1268
1466
|
onUserChange(handler: PaywallEventHandler<'userChange'>): () => void;
|
|
1467
|
+
/**
|
|
1468
|
+
* Заменить cachedBootstrap живыми данными — для preview-режима в редакторе
|
|
1469
|
+
* админки. Если модалка открыта, PaywallRoot подписан на onBootstrapChange
|
|
1470
|
+
* и перерендерится мгновенно. До open() — затравка для bootstrap()-effect'а.
|
|
1471
|
+
*
|
|
1472
|
+
* См. {@link BillingClientOptions.preview} — обычно эту опцию ставят на
|
|
1473
|
+
* клиент, чтобы заодно отключить сетевой revalidate. setBootstrap технически
|
|
1474
|
+
* работает и в production-режиме, но конкуренция с revalidate'ом из сети
|
|
1475
|
+
* почти всегда нежелательна.
|
|
1476
|
+
*/
|
|
1477
|
+
setBootstrap(partial: Partial<PaywallBootstrap>): void;
|
|
1478
|
+
/**
|
|
1479
|
+
* Сменить force-locale на лету — для live-preview редактора админки, когда
|
|
1480
|
+
* юзер переключает «Preview as user from <country>». Грузит соответствующий
|
|
1481
|
+
* static-чанк и форсит re-render через handle.update. См. PaywallUIOptions.locale.
|
|
1482
|
+
*
|
|
1483
|
+
* Передай `null`/`undefined`, чтобы вернуть автоматическую резолв-логику
|
|
1484
|
+
* (navigator.language → locale_default).
|
|
1485
|
+
*/
|
|
1486
|
+
setLocale(locale: string | null | undefined): void;
|
|
1269
1487
|
on<E extends PaywallEvent>(event: E, handler: PaywallEventHandler<E>): () => void;
|
|
1270
1488
|
off<E extends PaywallEvent>(event: E, handler: PaywallEventHandler<E>): void;
|
|
1271
1489
|
private emit;
|
|
@@ -1310,23 +1528,34 @@ export declare class PaywallUI {
|
|
|
1310
1528
|
*/
|
|
1311
1529
|
openAuth(opts?: OpenOptions): void;
|
|
1312
1530
|
/**
|
|
1313
|
-
*
|
|
1314
|
-
* `
|
|
1315
|
-
*
|
|
1316
|
-
*
|
|
1317
|
-
*
|
|
1318
|
-
*
|
|
1319
|
-
|
|
1320
|
-
|
|
1321
|
-
|
|
1322
|
-
*
|
|
1323
|
-
*
|
|
1324
|
-
*
|
|
1325
|
-
*
|
|
1326
|
-
*
|
|
1327
|
-
|
|
1531
|
+
* Шорткат над `openAuth()` — открывает модалку сразу на signin-форме.
|
|
1532
|
+
* Эквивалент `openAuth()` (signin — дефолт). Существует для симметрии с
|
|
1533
|
+
* `openSignup()` и читаемости host-кода:
|
|
1534
|
+
* - `paywall.openSignin()` — «вход в существующий аккаунт»
|
|
1535
|
+
* - `paywall.openSignup()` — «новая регистрация»
|
|
1536
|
+
* Без managed-auth — no-op.
|
|
1537
|
+
*/
|
|
1538
|
+
openSignin(opts?: OpenOptions): void;
|
|
1539
|
+
/**
|
|
1540
|
+
* Открывает модалку с auth-gate сразу в режиме регистрации (signup-mode
|
|
1541
|
+
* AuthPanel'а — email/password/repeat). Если в paywall layout админ
|
|
1542
|
+
* отключил allow_signup, AuthPanel игнорит mode и стартует с signin —
|
|
1543
|
+
* соблюдается admin-конфиг.
|
|
1544
|
+
* Без managed-auth — no-op.
|
|
1545
|
+
*/
|
|
1546
|
+
openSignup(opts?: OpenOptions): void;
|
|
1547
|
+
/**
|
|
1548
|
+
* Headless anonymous signin без открытия модалки. Внутри:
|
|
1549
|
+
* idempotent (если уже анон — instant return) → resume через сохранённый
|
|
1550
|
+
* refresh_token → fresh /auth/anonymous/signin. Дедуплицирует
|
|
1551
|
+
* параллельные вызовы внутри AuthClient'а.
|
|
1552
|
+
*
|
|
1553
|
+
* Удобно для host-кнопок типа «Continue as guest» — host сам управляет
|
|
1554
|
+
* loading-стейтом на своей кнопке, без полупустой модалки со спиннером.
|
|
1555
|
+
* Без managed-auth — резолвится rejected promise'ом (нет AuthClient'а
|
|
1556
|
+
* чтобы делать signin).
|
|
1328
1557
|
*/
|
|
1329
|
-
|
|
1558
|
+
signInAnonymously(): Promise<AuthSession>;
|
|
1330
1559
|
private openInternal;
|
|
1331
1560
|
/** Применить gates ПОСЛЕ того, как модалка уже смонтирована (mount-then-load
|
|
1332
1561
|
* путь). Если gate блокирует — close() + emit. Если юзер уже сам закрыл
|
|
@@ -1381,6 +1610,26 @@ export declare class PaywallUI {
|
|
|
1381
1610
|
}): Promise<PaywallPrice[]>;
|
|
1382
1611
|
/** Sync-снимок цен. null — bootstrap ещё не загружали. */
|
|
1383
1612
|
getCachedPrices(): PaywallPrice[] | null;
|
|
1613
|
+
/** Sync-снимок офферов. null = bootstrap не загружали, [] = пейвол без офферов.
|
|
1614
|
+
* Бэк уже применил серверный targeting (страны/email/режим) — наружу
|
|
1615
|
+
* выезжает только то, что применимо к текущему юзеру. */
|
|
1616
|
+
getCachedOffers(): PaywallOffer[] | null;
|
|
1617
|
+
/**
|
|
1618
|
+
* Резолвит активный offer для конкретной цены: price_id-таргетинг +
|
|
1619
|
+
* countdown (`expires_at` ИЛИ `duration_minutes` от первого открытия
|
|
1620
|
+
* пейвола, см. clientStorage `pw-offer-{id}-start`).
|
|
1621
|
+
*
|
|
1622
|
+
* Read-only — НЕ записывает start для `duration_minutes`-офферов. Запись
|
|
1623
|
+
* стартует только когда модалка реально открыта (renderer'ом). До этого
|
|
1624
|
+
* `getOfferForPrice` вернёт `null` для duration-only офферов, чтобы
|
|
1625
|
+
* страницы-хосты вне модалки (pricing, landing) не активировали countdown
|
|
1626
|
+
* раньше времени.
|
|
1627
|
+
*
|
|
1628
|
+
* Хост-странице нужен countdown, который тикает каждую секунду — для
|
|
1629
|
+
* этого использовать React-хук `usePaywallOffer(priceId)` из sdk-react
|
|
1630
|
+
* либо обёртку поверх `setInterval(1000)` + повторный вызов этого метода.
|
|
1631
|
+
*/
|
|
1632
|
+
getOfferForPrice(priceId: string): ResolvedOffer | null;
|
|
1384
1633
|
/** Снимок текущего «языка юзера» — proxy над `billing.getUserLanguage()`.
|
|
1385
1634
|
* Используй, чтобы синхронизировать i18n host'а с тем, что фактически
|
|
1386
1635
|
* показывает пейвол. См. подробности в `BillingClient.getUserLanguage`. */
|
|
@@ -1457,6 +1706,8 @@ export declare interface PaywallUIOptions extends Omit<BillingClientOptions, 'au
|
|
|
1457
1706
|
* флеш на blocked-странах/устройствах хуже воспринимаемой латентности.
|
|
1458
1707
|
*/
|
|
1459
1708
|
mountThenLoad?: boolean;
|
|
1709
|
+
/* Excluded from this release type: inline */
|
|
1710
|
+
/* Excluded from this release type: locale */
|
|
1460
1711
|
}
|
|
1461
1712
|
|
|
1462
1713
|
declare interface PaywallUser {
|
|
@@ -1468,6 +1719,12 @@ declare interface PaywallUser {
|
|
|
1468
1719
|
started_at: string | null;
|
|
1469
1720
|
expires_at: string | null;
|
|
1470
1721
|
} | null;
|
|
1722
|
+
/** Был ли у юзера хотя бы один trial по этому пейволу когда-либо (включая
|
|
1723
|
+
* истёкшие и отменённые). Anti-abuse флаг для UI: CtaButton скрывает
|
|
1724
|
+
* "Start N-Day Free Trial" если true. Серверный enforcement в
|
|
1725
|
+
* `/start-checkout` дублирует — даже если UI обмануть, бэк не отдаст
|
|
1726
|
+
* trial_days в Stripe/Paddle. */
|
|
1727
|
+
had_previous_trial: boolean;
|
|
1471
1728
|
}
|
|
1472
1729
|
|
|
1473
1730
|
declare interface PaywallUserPurchase {
|
|
@@ -1492,6 +1749,27 @@ declare class QuotaExceededError extends PaywallError {
|
|
|
1492
1749
|
});
|
|
1493
1750
|
}
|
|
1494
1751
|
|
|
1752
|
+
/**
|
|
1753
|
+
* Resolved view of a paywall offer — what host UI actually needs to render
|
|
1754
|
+
* a strike-through price + countdown without re-implementing the math.
|
|
1755
|
+
*
|
|
1756
|
+
* `remainingMs` ticks down with wall-clock time and reaches 0 on expiry.
|
|
1757
|
+
* `totalMs` stays constant — useful for progress bars / share-of-time UX.
|
|
1758
|
+
* `expiresAt` is the Date.now()-comparable epoch ms of expiry.
|
|
1759
|
+
*
|
|
1760
|
+
* For offers without an expiry mechanism (no `expires_at` and no
|
|
1761
|
+
* `duration_minutes`), `remainingMs`/`totalMs`/`expiresAt` are all `null`,
|
|
1762
|
+
* but the resolved view is still returned — discount badge / strike-through
|
|
1763
|
+
* still make sense for "perpetual sale" offers.
|
|
1764
|
+
*/
|
|
1765
|
+
declare interface ResolvedOffer {
|
|
1766
|
+
offer: PaywallOffer;
|
|
1767
|
+
discountPercent: number;
|
|
1768
|
+
remainingMs: number | null;
|
|
1769
|
+
totalMs: number | null;
|
|
1770
|
+
expiresAt: number | null;
|
|
1771
|
+
}
|
|
1772
|
+
|
|
1495
1773
|
declare type SignUpResult = {
|
|
1496
1774
|
kind: 'signed_in';
|
|
1497
1775
|
session: AuthSession;
|
package/dist/ui.js
CHANGED