@monetize.software/sdk 3.0.0-alpha.1 → 3.0.0-alpha.11
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 +266 -25
- package/dist/core.js +519 -313
- package/dist/core.js.map +1 -1
- package/dist/index.cjs +1 -1
- package/dist/index.d.ts +356 -44
- 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/core.d.ts
CHANGED
|
@@ -46,7 +46,9 @@ export declare class ApiGatewayClient {
|
|
|
46
46
|
|
|
47
47
|
export 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 @@ export 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
|
+
export declare type AuthChangeListener = (event: AuthChangeEvent, session: AuthSession | null) => void;
|
|
70
93
|
|
|
71
94
|
export declare class AuthClient {
|
|
72
95
|
readonly paywallId: string;
|
|
@@ -225,10 +248,8 @@ export 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 @@ export 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 @@ export 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 @@ export 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 @@ export declare class AuthClient {
|
|
|
424
468
|
|
|
425
469
|
export 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;
|
|
@@ -487,6 +533,8 @@ export declare class BillingClient {
|
|
|
487
533
|
private balancesStorageUnwatch;
|
|
488
534
|
private inflightBalances;
|
|
489
535
|
private balanceListeners;
|
|
536
|
+
private readonly previewMode;
|
|
537
|
+
private previewVersionCounter;
|
|
490
538
|
constructor(opts: BillingClientOptions);
|
|
491
539
|
/**
|
|
492
540
|
* Stable visitor_id (UUID v4). Первый вызов awaitит первичный резолв из
|
|
@@ -519,6 +567,24 @@ export declare class BillingClient {
|
|
|
519
567
|
* unsubscribe.
|
|
520
568
|
*/
|
|
521
569
|
onBootstrapChange(cb: (b: PaywallBootstrap) => void): () => void;
|
|
570
|
+
/**
|
|
571
|
+
* Заменить cachedBootstrap частичными или полными данными и эмитнуть всем
|
|
572
|
+
* подписчикам. Используется host'ом в preview-mode (редактор админки) для
|
|
573
|
+
* live-обновления открытой модалки без сетевого revalidate'а.
|
|
574
|
+
*
|
|
575
|
+
* Поведение:
|
|
576
|
+
* - Без `cachedBootstrap` ожидаются как минимум `settings` + `prices` —
|
|
577
|
+
* иначе PaywallRoot не сможет отрендерить тарифы и упадёт.
|
|
578
|
+
* - С существующим кешем партиал мёрджится поверх: `settings` глубокий мёрдж
|
|
579
|
+
* на 1 уровень (поля настроек), массивы `prices`/`offers` перезаписываются.
|
|
580
|
+
* - Каждый вызов бампит `version` ("preview:<n>"), чтобы applyBootstrap'овая
|
|
581
|
+
* проверка `versionChanged` всегда срабатывала и listener'ы дёргались.
|
|
582
|
+
* - Persist в storage НЕ делаем — preview не должен утекать в другие вкладки.
|
|
583
|
+
*
|
|
584
|
+
* В non-preview режиме метод доступен, но это редкий путь (например, для
|
|
585
|
+
* тестов host'а) — production-код должен полагаться на bootstrap() + revalidate.
|
|
586
|
+
*/
|
|
587
|
+
setBootstrap(partial: Partial<PaywallBootstrap>): void;
|
|
522
588
|
private fetchBootstrap;
|
|
523
589
|
private revalidateBootstrap;
|
|
524
590
|
private applyBootstrap;
|
|
@@ -544,6 +610,13 @@ export declare class BillingClient {
|
|
|
544
610
|
}): Promise<PaywallPrice[]>;
|
|
545
611
|
/** Sync-снимок цен из последнего bootstrap'а. null = ещё не загружали. */
|
|
546
612
|
getCachedPrices(): PaywallPrice[] | null;
|
|
613
|
+
/** Sync-снимок офферов из последнего bootstrap'а. null = bootstrap ещё не
|
|
614
|
+
* загружали, пустой массив = бэк отдал пейвол без офферов. Бэк уже
|
|
615
|
+
* применил серверный таргетинг (target_countries / target_emails /
|
|
616
|
+
* targeting_mode из offer_settings) — наружу выезжает только то, что
|
|
617
|
+
* применимо к текущему юзеру. Клиентская сторона остаётся ответственной
|
|
618
|
+
* за price_id-matching и countdown (см. core/offer.ts → resolveOffer). */
|
|
619
|
+
getCachedOffers(): PaywallOffer[] | null;
|
|
547
620
|
/**
|
|
548
621
|
* Снимок того, какой язык SDK сейчас считает «языком юзера». Полезно для
|
|
549
622
|
* синхронизации i18n хоста с тем, что фактически показывает пейвол — чтобы
|
|
@@ -718,21 +791,31 @@ export declare class BillingClient {
|
|
|
718
791
|
* `/api/v1/paywall/[id]/user` без unstable_cache, потому что list для UI
|
|
719
792
|
* должен быть свежим после cancel-а.
|
|
720
793
|
*
|
|
721
|
-
* Auth
|
|
722
|
-
*
|
|
794
|
+
* Auth (два пути):
|
|
795
|
+
* - Bearer (через AuthClient) — user.id резолвится из сессии, identity
|
|
796
|
+
* в query игнорируется.
|
|
797
|
+
* - `apiKey` + `identity.email`/`identity.userId` — server-SDK путь для
|
|
798
|
+
* интеграций со своей авторизацией. Бэк проверяет, что identity линкована
|
|
799
|
+
* к этому пейволу (защита от cross-paywall lookup).
|
|
800
|
+
* Без auth и без apiKey+identity — `identity_required`.
|
|
723
801
|
*/
|
|
724
802
|
listPurchases(opts?: {
|
|
725
803
|
signal?: AbortSignal;
|
|
726
804
|
}): Promise<PaywallPurchaseDetailed[]>;
|
|
727
805
|
/**
|
|
728
|
-
* Отменить подписку. Бэк
|
|
729
|
-
*
|
|
730
|
-
*
|
|
806
|
+
* Отменить подписку. Бэк проверит, что subscription принадлежит юзеру
|
|
807
|
+
* (Bearer-путь — из сессии; apiKey-путь — из identity), и сделает cancel у
|
|
808
|
+
* acquiring'а (Stripe/Paddle/Chargebee/Overpay). По умолчанию cancel в
|
|
809
|
+
* конце текущего периода — юзер сохраняет access до renewal date'ы.
|
|
731
810
|
*
|
|
732
|
-
* `reason` обязательна (валидация на бэке).
|
|
733
|
-
* причин в host-UI, как в legacy customer portal'е.
|
|
811
|
+
* `reason` обязательна (валидация на бэке).
|
|
734
812
|
*
|
|
735
|
-
* Auth
|
|
813
|
+
* Auth (два пути):
|
|
814
|
+
* - Bearer (через AuthClient) — стандартный путь для UI customer-portal'a.
|
|
815
|
+
* - `apiKey` + `identity.email`/`identity.userId` — для self-service UI на
|
|
816
|
+
* бэке клиента со своей авторизацией. Бэк дополнительно фильтрует
|
|
817
|
+
* subscription по paywall_id, чтобы owner пейвола A не отменил подписку
|
|
818
|
+
* пейвола B.
|
|
736
819
|
*/
|
|
737
820
|
cancelSubscription(params: {
|
|
738
821
|
subscriptionId: string;
|
|
@@ -769,7 +852,15 @@ export declare class BillingClient {
|
|
|
769
852
|
|
|
770
853
|
export declare interface BillingClientOptions {
|
|
771
854
|
paywallId: string;
|
|
772
|
-
|
|
855
|
+
/**
|
|
856
|
+
* Origin серверного API SDK — обязательное поле. Должно совпадать с
|
|
857
|
+
* `custom_domain`, заданным для пейвола в платформе (модерация привязывает
|
|
858
|
+
* домен к paywall_id). SDK сверяет это значение с `bootstrap.settings.custom_domain`
|
|
859
|
+
* на первом ответе и кидает `invalid_config` при расхождении — защита от
|
|
860
|
+
* опечаток интегратора. Промежуточный `appbox.space` в новом SDK НЕ
|
|
861
|
+
* используется (это только для legacy v2).
|
|
862
|
+
*/
|
|
863
|
+
apiOrigin: string;
|
|
773
864
|
identity?: Identity;
|
|
774
865
|
storage?: StorageAdapter;
|
|
775
866
|
capabilities?: string[];
|
|
@@ -790,6 +881,16 @@ export declare interface BillingClientOptions {
|
|
|
790
881
|
* через `setIdentity`, Bearer не отправляется.
|
|
791
882
|
*/
|
|
792
883
|
auth?: AuthClient;
|
|
884
|
+
/**
|
|
885
|
+
* Preview/editor-mode. Когда true:
|
|
886
|
+
* - `bootstrap()` НЕ ходит в сеть — отдаёт только `cachedBootstrap`, заданный
|
|
887
|
+
* через `setBootstrap()`. Без seed'а throw'ает (caller обязан засидить до open).
|
|
888
|
+
* - Storage.watch / persist отключены (preview редактора локален для текущей вкладки).
|
|
889
|
+
* - `setBootstrap(partial)` доступен как публичный setter — host'у разрешено
|
|
890
|
+
* мутировать кеш для live-обновления модалки в редакторе админки.
|
|
891
|
+
* Дефолт false — обычный production-режим.
|
|
892
|
+
*/
|
|
893
|
+
preview?: boolean;
|
|
793
894
|
}
|
|
794
895
|
|
|
795
896
|
export declare interface CheckoutResult {
|
|
@@ -845,6 +946,11 @@ export declare interface EventTrackerOptions {
|
|
|
845
946
|
sendBeacon?: (url: string, data: BodyInit) => boolean;
|
|
846
947
|
}
|
|
847
948
|
|
|
949
|
+
/** Pick the offer applicable to a price. Targeted (`price_id === id`) wins
|
|
950
|
+
* over the global default (`price_id === null`). Offers without a positive
|
|
951
|
+
* `discount_percent` are ignored. */
|
|
952
|
+
export declare function findApplicableOffer(offers: PaywallOffer[] | null | undefined, priceId: string): PaywallOffer | null;
|
|
953
|
+
|
|
848
954
|
export declare function generateVisitorId(): string;
|
|
849
955
|
|
|
850
956
|
export declare interface Identity {
|
|
@@ -853,6 +959,18 @@ export declare interface Identity {
|
|
|
853
959
|
anonymousId?: string;
|
|
854
960
|
}
|
|
855
961
|
|
|
962
|
+
export declare interface LastLogin {
|
|
963
|
+
method: LastLoginMethod;
|
|
964
|
+
email: string | null;
|
|
965
|
+
}
|
|
966
|
+
|
|
967
|
+
/** Метод, которым юзер залогинился в последний раз на этом пейволе.
|
|
968
|
+
* Хранится per-paywall в storage и используется UI чтобы:
|
|
969
|
+
* - предзаполнить email-инпут last-known email'ом;
|
|
970
|
+
* - подсветить ту же OAuth-кнопку / email-форму бейджем "Last used".
|
|
971
|
+
* `email` — email/password forms (signin или signup → confirm). */
|
|
972
|
+
export declare type LastLoginMethod = OAuthProvider | 'email';
|
|
973
|
+
|
|
856
974
|
export declare interface Layout {
|
|
857
975
|
type: 'modal';
|
|
858
976
|
blocks: LayoutBlock[];
|
|
@@ -868,9 +986,13 @@ export declare type LayoutBlock = {
|
|
|
868
986
|
} | {
|
|
869
987
|
type: 'price_grid';
|
|
870
988
|
priceIds?: string[];
|
|
871
|
-
/** Раскладка карточек
|
|
872
|
-
* `
|
|
873
|
-
|
|
989
|
+
/** Раскладка карточек цен:
|
|
990
|
+
* - `vertical` (default) — стек карточек сверху вниз;
|
|
991
|
+
* - `compact` — компактный список (одна строка на цену, без карточки,
|
|
992
|
+
* с разделителем); v2-аналог `view: 'telegram'`;
|
|
993
|
+
* - `horizontal` — несколько карточек рядом в ряд; v2-only с момента
|
|
994
|
+
* SDK 3.0 (legacy не показывает выбор этой опции в админке). */
|
|
995
|
+
view?: 'vertical' | 'compact' | 'horizontal';
|
|
874
996
|
/** ID цены, которая помечается лейблом «популярный план». v2-аналог
|
|
875
997
|
* пары `price_label_id` + `price_label`. */
|
|
876
998
|
popular_price_id?: string;
|
|
@@ -879,7 +1001,10 @@ export declare type LayoutBlock = {
|
|
|
879
1001
|
popular_label?: string;
|
|
880
1002
|
} | {
|
|
881
1003
|
type: 'cta_button';
|
|
882
|
-
|
|
1004
|
+
/** Текст на кнопке. Если не задан — рендерер сам подберёт по
|
|
1005
|
+
* selected price'у и `trial_days`: "Start N-Day Free Trial",
|
|
1006
|
+
* "Get Lifetime Access", "Get Monthly Plan" и т.п. */
|
|
1007
|
+
label?: string;
|
|
883
1008
|
action: 'checkout' | 'close';
|
|
884
1009
|
priceId?: string;
|
|
885
1010
|
} | {
|
|
@@ -898,8 +1023,23 @@ export declare type LayoutBlock = {
|
|
|
898
1023
|
/** Скрывать панель, если юзер уже залогинен. По умолчанию true.
|
|
899
1024
|
* false — показываем "Signed in as ... [Sign out]" даже после логина. */
|
|
900
1025
|
hide_when_authenticated?: boolean;
|
|
901
|
-
/**
|
|
1026
|
+
/** Кастомный заголовок над формой. Если задан — отображается вместо
|
|
1027
|
+
* дефолтного (определяется по mode'у — "Welcome back!" / "Welcome!" /
|
|
1028
|
+
* "Forgot password?" / ...). Без `submit_label` также используется как
|
|
1029
|
+
* submit-лейбл для signin (например `heading="Restore Purchases"` →
|
|
1030
|
+
* submit тоже "Restore Purchases"). Длинные heading (типа "Войдите,
|
|
1031
|
+
* чтобы продолжить покупку") в кнопку влезают плохо — задай
|
|
1032
|
+
* `submit_label` отдельно. */
|
|
902
1033
|
heading?: string;
|
|
1034
|
+
/** Подпись под заголовком. Если опущен — подставляется default-текст
|
|
1035
|
+
* для текущего mode'а. Передай пустую строку чтобы скрыть подпись. */
|
|
1036
|
+
subheading?: string;
|
|
1037
|
+
/** Явный текст submit-кнопки. Имеет приоритет над heading-эхо. Нужен
|
|
1038
|
+
* для интентов с длинным descriptive heading'ом (preauth: "Войдите,
|
|
1039
|
+
* чтобы продолжить покупку" — кнопка только "Войти"). Для коротких
|
|
1040
|
+
* action-headings (restore: "Restore Purchases") опускай — эхо
|
|
1041
|
+
* даёт правильный UX. */
|
|
1042
|
+
submit_label?: string;
|
|
903
1043
|
} | {
|
|
904
1044
|
/** Список фич/преимуществ продукта. v2-аналог `features_list` + `features_view`.
|
|
905
1045
|
* До 5 элементов — рендерим как чек-лист с заголовком и описанием. */
|
|
@@ -923,6 +1063,35 @@ export declare type LayoutBlock = {
|
|
|
923
1063
|
desc: string;
|
|
924
1064
|
count: number;
|
|
925
1065
|
}>;
|
|
1066
|
+
} | {
|
|
1067
|
+
/** Money-back guarantee badge под cta_button: иконка + жирный заголовок +
|
|
1068
|
+
* пояснение мелким шрифтом + bottom divider, который визуально стыкуется
|
|
1069
|
+
* с current_session ниже. v2-аналог inline-блока в `PaywallPricing`. */
|
|
1070
|
+
type: 'guarantee_badge';
|
|
1071
|
+
/** Заголовок жирным. По умолчанию "100% Money-Back Guarantee". */
|
|
1072
|
+
title?: string;
|
|
1073
|
+
/** Подзаголовок мелким серым. По умолчанию
|
|
1074
|
+
* "Not satisfied? We'll refund you — no questions asked.". */
|
|
1075
|
+
subtitle?: string;
|
|
1076
|
+
/** Иконка слева от заголовка. По умолчанию `dollar_shield` —
|
|
1077
|
+
* зелёный shield с долларом (legacy-вид). `none` — без иконки. */
|
|
1078
|
+
icon?: 'dollar_shield' | 'none';
|
|
1079
|
+
} | {
|
|
1080
|
+
/** Urgency-баннер с countdown'ом до конца offer'а. Берёт первый offer
|
|
1081
|
+
* из `bootstrap.offers` с валидным `expires_at` или `duration_minutes`.
|
|
1082
|
+
* Авто-скрывается по истечении, чтобы не показывать "0d 0h 0m 0s".
|
|
1083
|
+
* Размещение — обычно первый блок в layout (над heading). */
|
|
1084
|
+
type: 'offer_banner';
|
|
1085
|
+
/** ID конкретного offer'а из bootstrap.offers. Если не задано — берётся
|
|
1086
|
+
* первый offer с активным таймером. */
|
|
1087
|
+
offer_id?: string;
|
|
1088
|
+
/** Текст слева от countdown'а. Если опущен — берётся `offer.label`,
|
|
1089
|
+
* иначе fallback "Limited-time offer". К нему дописывается процент:
|
|
1090
|
+
* "{title} {discount_percent}%" если discount задан. */
|
|
1091
|
+
title?: string;
|
|
1092
|
+
/** В превью админки — игнорировать expired-state, всё равно показывать
|
|
1093
|
+
* banner с нулями. Прод-режим — false (banner исчезает). */
|
|
1094
|
+
force?: boolean;
|
|
926
1095
|
};
|
|
927
1096
|
|
|
928
1097
|
/** Локализационные оверрайды для одного языка. Накатываются поверх дефолтного
|
|
@@ -942,6 +1111,11 @@ export declare interface LocaleOverrides {
|
|
|
942
1111
|
|
|
943
1112
|
export declare type OAuthProvider = 'google' | 'apple' | 'github' | 'facebook';
|
|
944
1113
|
|
|
1114
|
+
/** Storage key under which a relative `duration_minutes` offer records its
|
|
1115
|
+
* first-view timestamp. Shared between the renderer (which writes the
|
|
1116
|
+
* start on first open) and the host SDK helpers (which read it). */
|
|
1117
|
+
export declare function offerStartStorageKey(offerId: string): string;
|
|
1118
|
+
|
|
945
1119
|
export declare type OtpVerifyType = 'email' | 'recovery' | 'signup' | 'magiclink' | 'invite';
|
|
946
1120
|
|
|
947
1121
|
export declare interface PaywallBootstrap {
|
|
@@ -977,7 +1151,15 @@ export declare class PaywallError extends Error {
|
|
|
977
1151
|
export declare interface PaywallOffer {
|
|
978
1152
|
id: string;
|
|
979
1153
|
discount_percent: number | null;
|
|
1154
|
+
/** Абсолютная expiration date (ISO 8601). Если задана — countdown отсчитывает
|
|
1155
|
+
* до этого момента, по истечении offer считается истёкшим. */
|
|
980
1156
|
expires_at: string | null;
|
|
1157
|
+
/** Относительный таймер: сколько минут offer живёт **от первого просмотра
|
|
1158
|
+
* пейвола** данным юзером. Старт хранится в clientStorage под ключом
|
|
1159
|
+
* `pw-offer-{id}-start`, по истечении — auto-cleanup. Используется, когда
|
|
1160
|
+
* бэк хочет показывать "remaining time" без жёсткой server-time, а считать
|
|
1161
|
+
* относительно сессии юзера. expires_at имеет приоритет если задано. */
|
|
1162
|
+
duration_minutes?: number | null;
|
|
981
1163
|
price_id: string | null;
|
|
982
1164
|
label?: string | null;
|
|
983
1165
|
}
|
|
@@ -1002,7 +1184,7 @@ export declare interface PaywallPrice {
|
|
|
1002
1184
|
* идёт из `/user-state` и имеет минимум для access-gate'а), этот shape
|
|
1003
1185
|
* включает цену/валюту/discount — чтобы host мог нарисовать список подписок
|
|
1004
1186
|
* как в legacy customer portal'е. */
|
|
1005
|
-
declare interface PaywallPurchaseDetailed {
|
|
1187
|
+
export declare interface PaywallPurchaseDetailed {
|
|
1006
1188
|
id: string;
|
|
1007
1189
|
status: string | null;
|
|
1008
1190
|
cancel_at: string | null;
|
|
@@ -1027,6 +1209,14 @@ export declare interface PaywallSettings {
|
|
|
1027
1209
|
brand_color?: string | null;
|
|
1028
1210
|
custom_css?: string | null;
|
|
1029
1211
|
locale_default?: string | null;
|
|
1212
|
+
/** Origin, на котором живёт бэк пейвола (тот же, что мерчант передаёт в
|
|
1213
|
+
* `BillingClientOptions.apiOrigin` при инициализации SDK). Бэк присылает
|
|
1214
|
+
* его на каждом bootstrap'е, SDK сверяет с init.apiOrigin — расхождение
|
|
1215
|
+
* даёт `invalid_config` (защита от опечатки интегратора). Без схемы:
|
|
1216
|
+
* "pay.your-domain.com" или "https://pay.your-domain.com" — оба валидны.
|
|
1217
|
+
* Для новых пейволов поле всегда заполнено (модерация требует custom_domain);
|
|
1218
|
+
* для legacy v2 может быть null/undefined. */
|
|
1219
|
+
custom_domain?: string | null;
|
|
1030
1220
|
runtime_mode?: 'client' | 'hybrid' | 'server' | 'client-native' | 'hybrid-native';
|
|
1031
1221
|
/** true, если эквайринг пейвола в test-mode — SDK рисует TEST MODE бейдж. */
|
|
1032
1222
|
is_test_mode?: boolean;
|
|
@@ -1084,6 +1274,12 @@ export declare interface PaywallUser {
|
|
|
1084
1274
|
started_at: string | null;
|
|
1085
1275
|
expires_at: string | null;
|
|
1086
1276
|
} | null;
|
|
1277
|
+
/** Был ли у юзера хотя бы один trial по этому пейволу когда-либо (включая
|
|
1278
|
+
* истёкшие и отменённые). Anti-abuse флаг для UI: CtaButton скрывает
|
|
1279
|
+
* "Start N-Day Free Trial" если true. Серверный enforcement в
|
|
1280
|
+
* `/start-checkout` дублирует — даже если UI обмануть, бэк не отдаст
|
|
1281
|
+
* trial_days в Stripe/Paddle. */
|
|
1282
|
+
had_previous_trial: boolean;
|
|
1087
1283
|
}
|
|
1088
1284
|
|
|
1089
1285
|
export declare interface PaywallUserPurchase {
|
|
@@ -1108,6 +1304,51 @@ export declare class QuotaExceededError extends PaywallError {
|
|
|
1108
1304
|
});
|
|
1109
1305
|
}
|
|
1110
1306
|
|
|
1307
|
+
/** Safe browser localStorage getter — returns null in SSR / private mode. */
|
|
1308
|
+
export declare function readBrowserOfferStart(offerId: string): string | null;
|
|
1309
|
+
|
|
1310
|
+
/**
|
|
1311
|
+
* Resolved view of a paywall offer — what host UI actually needs to render
|
|
1312
|
+
* a strike-through price + countdown without re-implementing the math.
|
|
1313
|
+
*
|
|
1314
|
+
* `remainingMs` ticks down with wall-clock time and reaches 0 on expiry.
|
|
1315
|
+
* `totalMs` stays constant — useful for progress bars / share-of-time UX.
|
|
1316
|
+
* `expiresAt` is the Date.now()-comparable epoch ms of expiry.
|
|
1317
|
+
*
|
|
1318
|
+
* For offers without an expiry mechanism (no `expires_at` and no
|
|
1319
|
+
* `duration_minutes`), `remainingMs`/`totalMs`/`expiresAt` are all `null`,
|
|
1320
|
+
* but the resolved view is still returned — discount badge / strike-through
|
|
1321
|
+
* still make sense for "perpetual sale" offers.
|
|
1322
|
+
*/
|
|
1323
|
+
export declare interface ResolvedOffer {
|
|
1324
|
+
offer: PaywallOffer;
|
|
1325
|
+
discountPercent: number;
|
|
1326
|
+
remainingMs: number | null;
|
|
1327
|
+
totalMs: number | null;
|
|
1328
|
+
expiresAt: number | null;
|
|
1329
|
+
}
|
|
1330
|
+
|
|
1331
|
+
/** Compute the resolved view of an offer. Pure, no side-effects. */
|
|
1332
|
+
export declare function resolveOffer(offer: PaywallOffer, opts?: ResolveOfferOptions): ResolvedOffer | null;
|
|
1333
|
+
|
|
1334
|
+
export declare interface ResolveOfferOptions {
|
|
1335
|
+
/** Current epoch ms. Inject for deterministic tests; default `Date.now()`. */
|
|
1336
|
+
now?: number;
|
|
1337
|
+
/**
|
|
1338
|
+
* Synchronous reader for the `duration_minutes` start-timestamp ISO string.
|
|
1339
|
+
* Host passes a closure over its sync storage (browser → `localStorage`,
|
|
1340
|
+
* memory → in-process map). Return `null` if no start has been recorded.
|
|
1341
|
+
*
|
|
1342
|
+
* Intentionally synchronous, because consumers call this from UI render —
|
|
1343
|
+
* an async StorageAdapter would force every price card to suspend.
|
|
1344
|
+
*
|
|
1345
|
+
* If omitted, `duration_minutes`-only offers return `expiresAt = null`,
|
|
1346
|
+
* which makes the resolved view treat them as "not yet started" (the
|
|
1347
|
+
* renderer is responsible for writing the start on first paywall view).
|
|
1348
|
+
*/
|
|
1349
|
+
readStart?: (offerId: string) => string | null;
|
|
1350
|
+
}
|
|
1351
|
+
|
|
1111
1352
|
export declare const SDK_VERSION = "3.0.0-alpha.0";
|
|
1112
1353
|
|
|
1113
1354
|
export declare type SignUpResult = {
|