@monetize.software/sdk 3.0.0-alpha.11 → 3.0.0-alpha.13

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/index.cjs CHANGED
@@ -1,2 +1,2 @@
1
- "use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const e=require("./core.cjs"),r=require("./chunks/PaywallUI-DQ1Jke8b.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;
1
+ "use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const e=require("./core.cjs"),r=require("./chunks/PaywallUI-DA8Kj9fJ.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
@@ -770,6 +770,17 @@ export declare class BillingClient {
770
770
  errorUrl?: string;
771
771
  shopUrl?: string;
772
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;
773
784
  /**
774
785
  * Stage 1 защиты от дубликатов покупок. Идемпотентный ключ запроса
775
786
  * (UUID). Повторный вызов с тем же ключом вернёт тот же checkout-URL
@@ -1469,12 +1480,25 @@ declare type PaywallStateListener = (state: PaywallStateSnapshot) => void;
1469
1480
  * один call onState; повторы (`useSyncExternalStore`-friendly).
1470
1481
  */
1471
1482
  export declare interface PaywallStateSnapshot {
1472
- /** Модалка отрендерена и видна. False — closed (или ещё не открывалась). */
1483
+ /** Модалка отрендерена и видна. False — closed (или ещё не открывалась).
1484
+ * Может быть false при `processing=true` — direct-checkout (paywall.checkout)
1485
+ * делает bootstrap + createCheckout headless до того, как решит надо ли
1486
+ * монтировать модалку. */
1473
1487
  open: boolean;
1474
1488
  /** Что показывается в модалке. null когда `open=false`. */
1475
1489
  view: 'loading' | 'error' | 'layout' | 'auth' | 'support' | 'awaiting_payment' | 'popup_blocked' | 'purchased' | null;
1476
1490
  /** Заполнено только когда `view === 'error'`. */
1477
1491
  error: PaywallError | null;
1492
+ /** SDK делает фоновую работу для `paywall.checkout(priceId)` — bootstrap,
1493
+ * visibility/trial-gates, createCheckout — до того, как реально нужна
1494
+ * UI-модалка. Хост на этой фазе может задизейблить свою кнопку и
1495
+ * показать спиннер прямо на ней, чтобы у юзера не было ощущения «клик
1496
+ * ничего не сделал». Сбрасывается в false сразу после mountAndShow
1497
+ * (модалка взяла на себя UI), либо после headless reject (already-paid,
1498
+ * ошибка createCheckout без модалки). Для `paywall.open()`-flow всегда
1499
+ * false: там модалка появляется мгновенно со своим LoadingView и
1500
+ * отдельный «processing» не нужен. */
1501
+ processing: boolean;
1478
1502
  }
1479
1503
 
1480
1504
  export declare class PaywallUI {
@@ -1615,6 +1639,65 @@ export declare class PaywallUI {
1615
1639
  * Без managed-auth — no-op.
1616
1640
  */
1617
1641
  openSignup(opts?: OpenOptions): void;
1642
+ /**
1643
+ * Direct-checkout: создать checkout-URL по конкретной цене и сразу открыть
1644
+ * платёжного провайдера, минуя layout с тарифами. Полезно когда
1645
+ * host-приложение рендерит pricing-карточки/таблицу собственным UI и
1646
+ * хочет, чтобы клик по «Buy / Get this plan» вёл прямо в Stripe/Paddle.
1647
+ *
1648
+ * **Late-mount UX.** В отличие от `open()`, модалка не появляется во время
1649
+ * фоновой работы (bootstrap + visibility/trial gates + createCheckout).
1650
+ * Хост на этой фазе показывает busy-state прямо на своей кнопке (через
1651
+ * `state.processing === true` из `paywall.getState()` — или автоматически
1652
+ * через `<PaywallButton priceId>` в sdk-react). Модалка монтируется
1653
+ * ТОЛЬКО когда реально нужна UI:
1654
+ * - `checkout_mode='preauth'` + managed-auth + не залогинен → auth-gate
1655
+ * (форма signin'а); после успеха auto-resume в createCheckout.
1656
+ * - popup провайдера заблокирован браузером → popup_blocked view с
1657
+ * retry-кнопкой под fresh user gesture.
1658
+ * - popup открылся успешно → awaiting_payment view (индикатор «оплати
1659
+ * в новой вкладке» + I've paid).
1660
+ *
1661
+ * Что эмитится без модалки:
1662
+ * - `purchase_completed{restored:true, priceId}` когда юзер уже подписан
1663
+ * (cached user, fresh bootstrap, или 409 hasActivePurchase от бэка) —
1664
+ * headless reject;
1665
+ * - `error` когда createCheckout упал или identity.email отсутствует;
1666
+ * - `visibility_blocked` / `trial_blocked` — стандартные gate-эвенты.
1667
+ *
1668
+ * Что эмитится одновременно с модалкой:
1669
+ * - `checkout_started{priceId, url, acquiring}` ровно когда headless URL
1670
+ * получен, ДО mount'а awaiting_payment/popup_blocked.
1671
+ *
1672
+ * Offer (countdown-скидка) автоматически резолвится из cached offers'ов
1673
+ * через `getOfferForPrice(priceId)` и передаётся в createCheckout как
1674
+ * `offerId` — чтобы duration_minutes-офферы тоже применились на бэке
1675
+ * (для них нет server-side таймера, без явного offer-id скидка теряется).
1676
+ *
1677
+ * Требования:
1678
+ * - `identity.email` должен быть выставлен (через `opts.identity`, либо
1679
+ * managed-auth, либо ранний `setIdentity`/`paywall.open({identity})`).
1680
+ * Без email бэк `/start-checkout` 400'нёт; SDK эмитнет `error`.
1681
+ * - В `checkout_mode='preauth'` без managed-auth — backend требует
1682
+ * email-юзера; убедись что `identity.email` явно задан.
1683
+ *
1684
+ * Без модалки совсем (когда host рендерит свой awaiting-payment экран) —
1685
+ * используй `paywall.billing.createCheckout({priceId, offerId})` напрямую,
1686
+ * но тогда auth-gate / popup_blocked / awaiting_payment придётся рисовать
1687
+ * самостоятельно.
1688
+ */
1689
+ checkout(priceId: string, opts?: OpenOptions): void;
1690
+ /** Headless prep-work для `checkout(priceId, opts)`: bootstrap → gates →
1691
+ * preauth check → createCheckout → mount модалки с финальным view.
1692
+ * Вынесено отдельным методом ради чистого async/await flow вместо вложенных
1693
+ * then-chain'ов (5+ ветвей). Любая ошибка не пробрасывается наружу: эмитим
1694
+ * через `paywall.emit('error')` и выходим — host подписан на `error`-event. */
1695
+ private runDirectCheckout;
1696
+ /** Trial-check без mount'а (для late-mount direct-checkout). Возвращает
1697
+ * true если trial заблокировал — caller должен прекратить flow. На любой
1698
+ * storage-ошибке log+продолжаем (не блокируем продажу). */
1699
+ private checkTrialBeforeCheckout;
1700
+ private applyProcessing;
1618
1701
  /**
1619
1702
  * Headless anonymous signin без открытия модалки. Внутри:
1620
1703
  * idempotent (если уже анон — instant return) → resume через сохранённый
package/dist/index.js CHANGED
@@ -1,5 +1,5 @@
1
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";
2
+ import { P as w, b as C } from "./chunks/PaywallUI-vv6Hw8su.js";
3
3
  export {
4
4
  t as ApiClient,
5
5
  a as ApiGatewayClient,
package/dist/ui.cjs CHANGED
@@ -1,2 +1,2 @@
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;
1
+ "use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const e=require("./chunks/PaywallUI-DA8Kj9fJ.js");exports.PaywallUI=e.PaywallUI;exports.blockRegistry=e.blockRegistry;
2
2
  //# sourceMappingURL=ui.cjs.map
package/dist/ui.d.ts CHANGED
@@ -756,6 +756,17 @@ declare class BillingClient {
756
756
  errorUrl?: string;
757
757
  shopUrl?: string;
758
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;
759
770
  /**
760
771
  * Stage 1 защиты от дубликатов покупок. Идемпотентный ключ запроса
761
772
  * (UUID). Повторный вызов с тем же ключом вернёт тот же checkout-URL
@@ -1398,12 +1409,25 @@ declare type PaywallStateListener = (state: PaywallStateSnapshot) => void;
1398
1409
  * один call onState; повторы (`useSyncExternalStore`-friendly).
1399
1410
  */
1400
1411
  export declare interface PaywallStateSnapshot {
1401
- /** Модалка отрендерена и видна. False — closed (или ещё не открывалась). */
1412
+ /** Модалка отрендерена и видна. False — closed (или ещё не открывалась).
1413
+ * Может быть false при `processing=true` — direct-checkout (paywall.checkout)
1414
+ * делает bootstrap + createCheckout headless до того, как решит надо ли
1415
+ * монтировать модалку. */
1402
1416
  open: boolean;
1403
1417
  /** Что показывается в модалке. null когда `open=false`. */
1404
1418
  view: 'loading' | 'error' | 'layout' | 'auth' | 'support' | 'awaiting_payment' | 'popup_blocked' | 'purchased' | null;
1405
1419
  /** Заполнено только когда `view === 'error'`. */
1406
1420
  error: PaywallError | null;
1421
+ /** SDK делает фоновую работу для `paywall.checkout(priceId)` — bootstrap,
1422
+ * visibility/trial-gates, createCheckout — до того, как реально нужна
1423
+ * UI-модалка. Хост на этой фазе может задизейблить свою кнопку и
1424
+ * показать спиннер прямо на ней, чтобы у юзера не было ощущения «клик
1425
+ * ничего не сделал». Сбрасывается в false сразу после mountAndShow
1426
+ * (модалка взяла на себя UI), либо после headless reject (already-paid,
1427
+ * ошибка createCheckout без модалки). Для `paywall.open()`-flow всегда
1428
+ * false: там модалка появляется мгновенно со своим LoadingView и
1429
+ * отдельный «processing» не нужен. */
1430
+ processing: boolean;
1407
1431
  }
1408
1432
 
1409
1433
  export declare class PaywallUI {
@@ -1544,6 +1568,65 @@ export declare class PaywallUI {
1544
1568
  * Без managed-auth — no-op.
1545
1569
  */
1546
1570
  openSignup(opts?: OpenOptions): void;
1571
+ /**
1572
+ * Direct-checkout: создать checkout-URL по конкретной цене и сразу открыть
1573
+ * платёжного провайдера, минуя layout с тарифами. Полезно когда
1574
+ * host-приложение рендерит pricing-карточки/таблицу собственным UI и
1575
+ * хочет, чтобы клик по «Buy / Get this plan» вёл прямо в Stripe/Paddle.
1576
+ *
1577
+ * **Late-mount UX.** В отличие от `open()`, модалка не появляется во время
1578
+ * фоновой работы (bootstrap + visibility/trial gates + createCheckout).
1579
+ * Хост на этой фазе показывает busy-state прямо на своей кнопке (через
1580
+ * `state.processing === true` из `paywall.getState()` — или автоматически
1581
+ * через `<PaywallButton priceId>` в sdk-react). Модалка монтируется
1582
+ * ТОЛЬКО когда реально нужна UI:
1583
+ * - `checkout_mode='preauth'` + managed-auth + не залогинен → auth-gate
1584
+ * (форма signin'а); после успеха auto-resume в createCheckout.
1585
+ * - popup провайдера заблокирован браузером → popup_blocked view с
1586
+ * retry-кнопкой под fresh user gesture.
1587
+ * - popup открылся успешно → awaiting_payment view (индикатор «оплати
1588
+ * в новой вкладке» + I've paid).
1589
+ *
1590
+ * Что эмитится без модалки:
1591
+ * - `purchase_completed{restored:true, priceId}` когда юзер уже подписан
1592
+ * (cached user, fresh bootstrap, или 409 hasActivePurchase от бэка) —
1593
+ * headless reject;
1594
+ * - `error` когда createCheckout упал или identity.email отсутствует;
1595
+ * - `visibility_blocked` / `trial_blocked` — стандартные gate-эвенты.
1596
+ *
1597
+ * Что эмитится одновременно с модалкой:
1598
+ * - `checkout_started{priceId, url, acquiring}` ровно когда headless URL
1599
+ * получен, ДО mount'а awaiting_payment/popup_blocked.
1600
+ *
1601
+ * Offer (countdown-скидка) автоматически резолвится из cached offers'ов
1602
+ * через `getOfferForPrice(priceId)` и передаётся в createCheckout как
1603
+ * `offerId` — чтобы duration_minutes-офферы тоже применились на бэке
1604
+ * (для них нет server-side таймера, без явного offer-id скидка теряется).
1605
+ *
1606
+ * Требования:
1607
+ * - `identity.email` должен быть выставлен (через `opts.identity`, либо
1608
+ * managed-auth, либо ранний `setIdentity`/`paywall.open({identity})`).
1609
+ * Без email бэк `/start-checkout` 400'нёт; SDK эмитнет `error`.
1610
+ * - В `checkout_mode='preauth'` без managed-auth — backend требует
1611
+ * email-юзера; убедись что `identity.email` явно задан.
1612
+ *
1613
+ * Без модалки совсем (когда host рендерит свой awaiting-payment экран) —
1614
+ * используй `paywall.billing.createCheckout({priceId, offerId})` напрямую,
1615
+ * но тогда auth-gate / popup_blocked / awaiting_payment придётся рисовать
1616
+ * самостоятельно.
1617
+ */
1618
+ checkout(priceId: string, opts?: OpenOptions): void;
1619
+ /** Headless prep-work для `checkout(priceId, opts)`: bootstrap → gates →
1620
+ * preauth check → createCheckout → mount модалки с финальным view.
1621
+ * Вынесено отдельным методом ради чистого async/await flow вместо вложенных
1622
+ * then-chain'ов (5+ ветвей). Любая ошибка не пробрасывается наружу: эмитим
1623
+ * через `paywall.emit('error')` и выходим — host подписан на `error`-event. */
1624
+ private runDirectCheckout;
1625
+ /** Trial-check без mount'а (для late-mount direct-checkout). Возвращает
1626
+ * true если trial заблокировал — caller должен прекратить flow. На любой
1627
+ * storage-ошибке log+продолжаем (не блокируем продажу). */
1628
+ private checkTrialBeforeCheckout;
1629
+ private applyProcessing;
1547
1630
  /**
1548
1631
  * Headless anonymous signin без открытия модалки. Внутри:
1549
1632
  * idempotent (если уже анон — instant return) → resume через сохранённый
package/dist/ui.js CHANGED
@@ -1,4 +1,4 @@
1
- import { P as o, b as r } from "./chunks/PaywallUI-CQG9HCwo.js";
1
+ import { P as o, b as r } from "./chunks/PaywallUI-vv6Hw8su.js";
2
2
  export {
3
3
  o as PaywallUI,
4
4
  r as blockRegistry
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@monetize.software/sdk",
3
- "version": "3.0.0-alpha.11",
3
+ "version": "3.0.0-alpha.13",
4
4
  "description": "Monetize SDK — bundled billing client and paywall render engine for web and Chrome extensions",
5
5
  "type": "module",
6
6
  "sideEffects": false,