Package Exports
- @monetize.software/sdk-extension
- @monetize.software/sdk-extension/offscreen
- @monetize.software/sdk-extension/offscreen.html
- @monetize.software/sdk-extension/sw
Readme
@monetize.software/sdk-extension
SDK для Chrome-расширений. Один offscreen-документ держит BillingClient, AuthClient, EventTracker — единственный source of truth для всех вкладок, popup'ов, side-panel'ов и extension-страниц расширения.
Public API content-script'а drop-in совместим с @monetize.software/sdk —
host пишет import { PaywallUI } from '@monetize.software/sdk-extension' и получает
тот же класс, тот же метод-сет.
Архитектура
content script (per tab) ──port──▶ service worker ──port──▶ offscreen
│ (forwarder) │
Shadow DOM modal BillingClient
RemoteBillingClient AuthClient
EventTracker
UserWatcher- content-script: UI + RemoteBillingClient (proxy через port в offscreen).
- service worker: маршрутизатор content↔offscreen, OAuth-флоу через
chrome.identity(offscreen его не видит). - offscreen: реальный SDK state, переживает закрытие вкладок, единственная точка координации auth-refresh / trial-counter / analytics-batch.
Статус
Phase 0 — скелет: package.json, vite multi-entry, wire-protocol типы, заглушки на content/offscreen/sw + demo-extension манифест. Реальная маршрутизация и RemoteBillingClient — следующие фазы.
См. TODO в репозитории и src/shared/protocol.ts для контракта сообщений.
Использование (целевое, в финале)
В extension'е:
// service-worker.ts
import { installRouter } from '@monetize.software/sdk-extension/sw';
installRouter({ offscreenUrl: chrome.runtime.getURL('offscreen.html') });// offscreen.html → offscreen.ts
import { startOffscreenServer } from '@monetize.software/sdk-extension/offscreen';
startOffscreenServer({ paywallId: '...', apiOrigin: 'https://...' });// content-script.ts (на каждой вкладке)
import { PaywallUI } from '@monetize.software/sdk-extension';
const paywall = new PaywallUI({ paywallId: '...', apiOrigin: '...' });
paywall.open(); // ровно как в @monetize.software/sdkНа сайтах — продолжаем использовать @monetize.software/sdk, не меняется.
Manifest: что прописывать в host extension'е
SDK сам по себе ничего в манифест не добавляет — host extension решает permissions под свой UX. Минимум для работы SDK:
{
"permissions": ["offscreen", "storage"],
"host_permissions": ["https://api.monetize.software/*"],
"background": { "service_worker": "sw.js", "type": "module" }
}Опционально:
"permissions": ["identity"]— если включаете OAuth-флоу (auth: true+ Google/etc.).web_accessible_resourcesдляoffscreen.htmlне нужен — документ создаётся service worker'ом черезchrome.offscreen.createDocument, это chrome-API и WAR не требует. Указывать его — лишняя attack surface (любой сайт сможет<iframe>-нить ваш offscreen, плюс это fingerprint вашего extension ID).
host_permissions — что выбрать
host_permissions управляют двумя вещами: куда extension может делать fetch (из
offscreen / SW / content-script) и на какие origin'ы content-script может
инжектиться (вместе с content_scripts.matches).
| Сценарий | Рекомендация |
|---|---|
Host extension'у <all_urls> уже нужен (рекордер, тулза-на-всех-сайтах, ассистент) |
Оставляйте <all_urls>. SDK работает как есть. Риск: Chrome Web Store review для <all_urls> идёт через ручной audit и занимает дольше; AV-вендоры (Avast/Kaspersky/etc.) активнее метят такие расширения как PUA. Это «цена» широкого инжекта — не SDK'шный риск, а вашего use-case'а. |
| Host extension ходит только на ваш бекенд и paywall'ит свои фичи (popup-tool, side-panel app) | НЕ ставьте <all_urls>. Достаточно вашего apiOrigin: ["https://api.your-domain.com/*"]. Никакого content-script инжекта на все сайты не нужно. |
| Хотите гибрид — popup-tool, но иногда content-script нужен на узком списке доменов | host_permissions + content_scripts.matches ограничьте до этих доменов: ["https://*.your-target.com/*", "https://api.your-domain.com/*"]. |
Главный сигнал для CWS/AV: чем уже host_permissions, тем меньше подозрений.
<all_urls> оставляйте только если он реально нужен для UX, и будьте готовы
обосновать его в CWS review (поле "Permission justification").
Demo extension'а: build modes
Для self-проверки и e2e-тестов есть demo-extension/ — reference-impleментация.
Билдов два:
pnpm build:demo # production build (= шаблон, который можно копировать клиентам)
pnpm build:demo:e2e # debug build — экспонирует window.__paywall для playwright'аbuild:demo НЕ кладёт window.__paywall в bundle (dead-code elimination через
import.meta.env.MODE !== 'e2e'). Шаблон, который клиент копирует, остаётся
чистым: любой script на странице иначе мог бы дёрнуть paywall.open() /
paywall.track() и злоупотреблять чужим extension'ом.
pnpm dev:demo собирает в e2e-режиме (для удобной отладки из DevTools-консоли).