@monetize.software/sdk-extension 0.1.0-alpha.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (65) hide show
  1. package/README.md +113 -0
  2. package/dist/chunks/chrome-port-BXHR4SOG.js +2014 -0
  3. package/dist/chunks/chrome-port-BXHR4SOG.js.map +1 -0
  4. package/dist/chunks/chrome-port-EtYqHf3p.js +2 -0
  5. package/dist/chunks/chrome-port-EtYqHf3p.js.map +1 -0
  6. package/dist/chunks/port-name-BPfQKtdb.js +5 -0
  7. package/dist/chunks/port-name-BPfQKtdb.js.map +1 -0
  8. package/dist/chunks/port-name-qwB109u9.js +2 -0
  9. package/dist/chunks/port-name-qwB109u9.js.map +1 -0
  10. package/dist/content/PaywallUI.d.ts +28 -0
  11. package/dist/content/PaywallUI.d.ts.map +1 -0
  12. package/dist/content/RemoteAuthClient.d.ts +91 -0
  13. package/dist/content/RemoteAuthClient.d.ts.map +1 -0
  14. package/dist/content/RemoteBillingClient.d.ts +126 -0
  15. package/dist/content/RemoteBillingClient.d.ts.map +1 -0
  16. package/dist/content/RemoteEventTracker.d.ts +9 -0
  17. package/dist/content/RemoteEventTracker.d.ts.map +1 -0
  18. package/dist/content/RemoteTrialStore.d.ts +13 -0
  19. package/dist/content/RemoteTrialStore.d.ts.map +1 -0
  20. package/dist/content/index.d.ts +11 -0
  21. package/dist/content/index.d.ts.map +1 -0
  22. package/dist/content/transport.d.ts +6 -0
  23. package/dist/content/transport.d.ts.map +1 -0
  24. package/dist/content.cjs +26 -0
  25. package/dist/content.cjs.map +1 -0
  26. package/dist/content.js +2723 -0
  27. package/dist/content.js.map +1 -0
  28. package/dist/offscreen/index.d.ts +21 -0
  29. package/dist/offscreen/index.d.ts.map +1 -0
  30. package/dist/offscreen/server.d.ts +26 -0
  31. package/dist/offscreen/server.d.ts.map +1 -0
  32. package/dist/offscreen.cjs +2 -0
  33. package/dist/offscreen.cjs.map +1 -0
  34. package/dist/offscreen.js +239 -0
  35. package/dist/offscreen.js.map +1 -0
  36. package/dist/shared/channel.d.ts +14 -0
  37. package/dist/shared/channel.d.ts.map +1 -0
  38. package/dist/shared/chrome-port.d.ts +8 -0
  39. package/dist/shared/chrome-port.d.ts.map +1 -0
  40. package/dist/shared/errors.d.ts +4 -0
  41. package/dist/shared/errors.d.ts.map +1 -0
  42. package/dist/shared/messages.d.ts +195 -0
  43. package/dist/shared/messages.d.ts.map +1 -0
  44. package/dist/shared/port-name.d.ts +2 -0
  45. package/dist/shared/port-name.d.ts.map +1 -0
  46. package/dist/shared/protocol.d.ts +59 -0
  47. package/dist/shared/protocol.d.ts.map +1 -0
  48. package/dist/shared/transport-client.d.ts +31 -0
  49. package/dist/shared/transport-client.d.ts.map +1 -0
  50. package/dist/shared/transport-server.d.ts +32 -0
  51. package/dist/shared/transport-server.d.ts.map +1 -0
  52. package/dist/sw/ensure-offscreen.d.ts +8 -0
  53. package/dist/sw/ensure-offscreen.d.ts.map +1 -0
  54. package/dist/sw/forwarder.d.ts +3 -0
  55. package/dist/sw/forwarder.d.ts.map +1 -0
  56. package/dist/sw/index.d.ts +4 -0
  57. package/dist/sw/index.d.ts.map +1 -0
  58. package/dist/sw/types.d.ts +19 -0
  59. package/dist/sw/types.d.ts.map +1 -0
  60. package/dist/sw.cjs +2 -0
  61. package/dist/sw.cjs.map +1 -0
  62. package/dist/sw.js +94 -0
  63. package/dist/sw.js.map +1 -0
  64. package/package.json +63 -0
  65. package/src/offscreen/offscreen.html +24 -0
@@ -0,0 +1,195 @@
1
+ import { Balance, CheckoutResult, Identity, PaywallBootstrap, PaywallPrice, PaywallPurchaseDetailed, PaywallUser, TrialConfig, TrialStatus } from '../../../sdk/src/core/types';
2
+ import { AuthSession, OAuthProvider, OtpVerifyType, SignUpResult } from '../../../sdk/src/core/auth';
3
+ declare module './protocol' {
4
+ interface RequestParamsMap {
5
+ handshake: {
6
+ protocolVersion: number;
7
+ clientId: string;
8
+ };
9
+ subscribe: {
10
+ events: ReadonlyArray<'userChange' | 'authChange' | 'balancesChange'>;
11
+ };
12
+ unsubscribe: {
13
+ events: ReadonlyArray<'userChange' | 'authChange' | 'balancesChange'>;
14
+ };
15
+ 'billing.bootstrap': {
16
+ force?: boolean;
17
+ };
18
+ 'billing.getCachedBootstrap': void;
19
+ 'billing.getUser': {
20
+ force?: boolean;
21
+ };
22
+ 'billing.getCachedUser': void;
23
+ 'billing.getBalances': {
24
+ force?: boolean;
25
+ };
26
+ 'billing.getCachedBalances': void;
27
+ 'billing.createCheckout': {
28
+ priceId: string;
29
+ successUrl?: string;
30
+ errorUrl?: string;
31
+ shopUrl?: string;
32
+ trialDays?: number;
33
+ idempotencyKey?: string;
34
+ ignoreActivePurchase?: boolean;
35
+ };
36
+ 'billing.listPurchases': void;
37
+ 'billing.cancelSubscription': {
38
+ subscriptionId: string;
39
+ reason: string;
40
+ };
41
+ 'billing.getIdentity': void;
42
+ 'billing.setIdentity': {
43
+ identity: Identity | null;
44
+ };
45
+ 'billing.getVisitorId': void;
46
+ 'auth.signInWithEmail': {
47
+ email: string;
48
+ password: string;
49
+ };
50
+ 'auth.signUp': {
51
+ email: string;
52
+ password: string;
53
+ userMeta?: Record<string, string>;
54
+ };
55
+ 'auth.signOut': void;
56
+ 'auth.getCachedSession': void;
57
+ 'auth.refresh': void;
58
+ 'auth.requestPasswordReset': {
59
+ email: string;
60
+ };
61
+ 'auth.updatePassword': {
62
+ password: string;
63
+ };
64
+ 'auth.sendOtp': {
65
+ email: string;
66
+ createUser?: boolean;
67
+ userMeta?: Record<string, unknown>;
68
+ };
69
+ 'auth.verifyOtp': {
70
+ email: string;
71
+ token: string;
72
+ type: OtpVerifyType;
73
+ };
74
+ 'auth.resendConfirmation': {
75
+ email: string;
76
+ };
77
+ 'auth.revokeAllSessions': void;
78
+ /** OAuth split: content делает /init через offscreen, получает
79
+ * authorize_url и state. State (вместе с PKCE verifier'ом) живёт в
80
+ * offscreen'е до второго запроса. */
81
+ 'auth.oauthStart': {
82
+ provider: OAuthProvider;
83
+ scopes?: string;
84
+ userMeta?: Record<string, string>;
85
+ };
86
+ /** Обмен code'а на session. State из oauthStart resolution идёт сюда —
87
+ * offscreen lookup'ит сохранённый verifier по state. */
88
+ 'auth.oauthExchange': {
89
+ state: string;
90
+ code: string;
91
+ };
92
+ /** Текущий access token (lazy-refreshable). content/popup вызывает для
93
+ * передачи Bearer'а в внешние fetch'и (например, ApiGatewayClient в
94
+ * content-script). Возвращает null если разлогинен или refresh упал. */
95
+ 'auth.getAccessToken': void;
96
+ /** Анонимный sign-in через offscreen AuthClient. `captchaToken`
97
+ * опциональный — bootloaded на будущее (когда сервер вернёт
98
+ * challenge_required и потребует proof-of-something). Сейчас сервер
99
+ * его не проверяет, поле резерв на forward-compat. `forceCaptcha`
100
+ * обходит idempotent + resume шаги и сразу делает /signin (создаёт
101
+ * нового anon-user'а — нужно при switch-account flow'е). */
102
+ 'auth.signInAnonymously': {
103
+ captchaToken?: string;
104
+ userMeta?: Record<string, string>;
105
+ forceCaptcha?: boolean;
106
+ };
107
+ 'tracker.track': {
108
+ name: string;
109
+ props?: Record<string, unknown>;
110
+ };
111
+ 'storage.get': {
112
+ key: string;
113
+ };
114
+ 'storage.set': {
115
+ key: string;
116
+ value: string;
117
+ };
118
+ 'storage.remove': {
119
+ key: string;
120
+ };
121
+ 'trial.check': {
122
+ paywallId: string;
123
+ config: TrialConfig;
124
+ };
125
+ 'trial.recordBlock': {
126
+ paywallId: string;
127
+ config: TrialConfig;
128
+ };
129
+ 'trial.reset': {
130
+ paywallId: string;
131
+ config: TrialConfig;
132
+ };
133
+ }
134
+ interface RequestResultMap {
135
+ handshake: {
136
+ protocolVersion: number;
137
+ offscreenReady: boolean;
138
+ };
139
+ subscribe: void;
140
+ unsubscribe: void;
141
+ 'billing.bootstrap': PaywallBootstrap;
142
+ 'billing.getCachedBootstrap': PaywallBootstrap | null;
143
+ 'billing.getUser': PaywallUser;
144
+ 'billing.getCachedUser': PaywallUser | null;
145
+ 'billing.getBalances': ReadonlyArray<Balance>;
146
+ 'billing.getCachedBalances': ReadonlyArray<Balance> | null;
147
+ 'billing.createCheckout': CheckoutResult;
148
+ 'billing.listPurchases': ReadonlyArray<PaywallPurchaseDetailed>;
149
+ 'billing.cancelSubscription': {
150
+ subscription: {
151
+ status: string | null;
152
+ canceled_at: string | null;
153
+ cancel_at: string | null;
154
+ cancel_at_period_end: boolean | null;
155
+ };
156
+ };
157
+ 'billing.getIdentity': Identity | null;
158
+ 'billing.setIdentity': void;
159
+ 'billing.getVisitorId': string;
160
+ 'auth.signInWithEmail': AuthSession;
161
+ 'auth.signUp': SignUpResult;
162
+ 'auth.signOut': void;
163
+ 'auth.getCachedSession': AuthSession | null;
164
+ 'auth.refresh': AuthSession | null;
165
+ 'auth.requestPasswordReset': void;
166
+ 'auth.updatePassword': void;
167
+ 'auth.sendOtp': void;
168
+ 'auth.verifyOtp': AuthSession;
169
+ 'auth.resendConfirmation': void;
170
+ 'auth.revokeAllSessions': void;
171
+ 'auth.oauthStart': {
172
+ authorizeUrl: string;
173
+ state: string;
174
+ };
175
+ 'auth.oauthExchange': AuthSession;
176
+ 'auth.getAccessToken': string | null;
177
+ 'auth.signInAnonymously': AuthSession;
178
+ 'tracker.track': void;
179
+ 'storage.get': string | null;
180
+ 'storage.set': void;
181
+ 'storage.remove': void;
182
+ 'trial.check': TrialStatus;
183
+ 'trial.recordBlock': TrialStatus;
184
+ 'trial.reset': void;
185
+ }
186
+ }
187
+ declare module './protocol' {
188
+ interface EventPayloadMap {
189
+ userChange: PaywallUser;
190
+ authChange: AuthSession | null;
191
+ balancesChange: ReadonlyArray<Balance>;
192
+ }
193
+ }
194
+ export type _PriceUnused = PaywallPrice;
195
+ //# sourceMappingURL=messages.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"messages.d.ts","sourceRoot":"","sources":["../../src/shared/messages.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ export declare const PORT_NAME = "@monetize.software/sdk-extension";
2
+ //# sourceMappingURL=port-name.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"port-name.d.ts","sourceRoot":"","sources":["../../src/shared/port-name.ts"],"names":[],"mappings":"AAGA,eAAO,MAAM,SAAS,qCAAqC,CAAC"}
@@ -0,0 +1,59 @@
1
+ /** Версия протокола — bump'аем при breaking changes wire-формата. SW сравнивает
2
+ * версии при handshake'е и отказывается маршрутить, если версии разъехались
3
+ * (extension и SDK обновлены не одновременно). */
4
+ export declare const PROTOCOL_VERSION: 1;
5
+ /** Сообщение отмены: клиент послал cancel(id), сервер ищет соответствующий
6
+ * AbortController в активных запросах и abort'ит его. Не имеет ответа —
7
+ * fire-and-forget. */
8
+ export interface CancelEnvelope {
9
+ type: 'cancel';
10
+ id: string;
11
+ }
12
+ export type RequestKind = 'billing.bootstrap' | 'billing.getCachedBootstrap' | 'billing.getUser' | 'billing.getCachedUser' | 'billing.getBalances' | 'billing.getCachedBalances' | 'billing.createCheckout' | 'billing.listPurchases' | 'billing.cancelSubscription' | 'billing.getIdentity' | 'billing.setIdentity' | 'billing.getVisitorId' | 'auth.signInWithEmail' | 'auth.signUp' | 'auth.signOut' | 'auth.getCachedSession' | 'auth.refresh' | 'auth.requestPasswordReset' | 'auth.updatePassword' | 'auth.sendOtp' | 'auth.verifyOtp' | 'auth.resendConfirmation' | 'auth.revokeAllSessions' | 'auth.oauthStart' | 'auth.oauthExchange' | 'auth.getAccessToken' | 'auth.signInAnonymously' | 'tracker.track' | 'storage.get' | 'storage.set' | 'storage.remove' | 'trial.check' | 'trial.recordBlock' | 'trial.reset' | 'handshake' | 'subscribe' | 'unsubscribe';
13
+ export interface RequestEnvelope<P = unknown> {
14
+ type: 'request';
15
+ id: string;
16
+ kind: RequestKind;
17
+ params: P;
18
+ }
19
+ export interface ResponseOk<R = unknown> {
20
+ type: 'response';
21
+ id: string;
22
+ ok: true;
23
+ result: R;
24
+ }
25
+ export interface ResponseErr {
26
+ type: 'response';
27
+ id: string;
28
+ ok: false;
29
+ error: SerializedError;
30
+ }
31
+ export type ResponseEnvelope<R = unknown> = ResponseOk<R> | ResponseErr;
32
+ export type EventKind = 'userChange' | 'authChange' | 'balancesChange';
33
+ export interface EventEnvelope<P = unknown> {
34
+ type: 'event';
35
+ kind: EventKind;
36
+ payload: P;
37
+ }
38
+ /** Плоский снепшот PaywallError, который переживает structured cloning.
39
+ * Reconstruct происходит в RemoteBillingClient'е через `new PaywallError(...)` —
40
+ * чтобы у host'а `error instanceof PaywallError` работал как обычно. */
41
+ export interface SerializedError {
42
+ name: string;
43
+ code: string;
44
+ message: string;
45
+ status?: number;
46
+ /** Stack из offscreen'а — для отладки в DevTools content-script'а. */
47
+ stack?: string;
48
+ }
49
+ export type Envelope = RequestEnvelope | ResponseEnvelope | EventEnvelope | CancelEnvelope;
50
+ export type RequestParams<K extends RequestKind> = K extends keyof RequestParamsMap ? RequestParamsMap[K] : unknown;
51
+ export type RequestResult<K extends RequestKind> = K extends keyof RequestResultMap ? RequestResultMap[K] : unknown;
52
+ export type EventPayload<K extends EventKind> = K extends keyof EventPayloadMap ? EventPayloadMap[K] : unknown;
53
+ export interface RequestParamsMap {
54
+ }
55
+ export interface RequestResultMap {
56
+ }
57
+ export interface EventPayloadMap {
58
+ }
59
+ //# sourceMappingURL=protocol.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"protocol.d.ts","sourceRoot":"","sources":["../../src/shared/protocol.ts"],"names":[],"mappings":"AAgBA;;mDAEmD;AACnD,eAAO,MAAM,gBAAgB,EAAG,CAAU,CAAC;AAI3C;;uBAEuB;AACvB,MAAM,WAAW,cAAc;IAC7B,IAAI,EAAE,QAAQ,CAAC;IACf,EAAE,EAAE,MAAM,CAAC;CACZ;AAED,MAAM,MAAM,WAAW,GAEnB,mBAAmB,GACnB,4BAA4B,GAC5B,iBAAiB,GACjB,uBAAuB,GACvB,qBAAqB,GACrB,2BAA2B,GAC3B,wBAAwB,GACxB,uBAAuB,GACvB,4BAA4B,GAC5B,qBAAqB,GACrB,qBAAqB,GACrB,sBAAsB,GAEtB,sBAAsB,GACtB,aAAa,GACb,cAAc,GACd,uBAAuB,GACvB,cAAc,GACd,2BAA2B,GAC3B,qBAAqB,GACrB,cAAc,GACd,gBAAgB,GAChB,yBAAyB,GACzB,wBAAwB,GACxB,iBAAiB,GACjB,oBAAoB,GACpB,qBAAqB,GACrB,wBAAwB,GAExB,eAAe,GAIf,aAAa,GACb,aAAa,GACb,gBAAgB,GAIhB,aAAa,GACb,mBAAmB,GACnB,aAAa,GAEb,WAAW,GACX,WAAW,GACX,aAAa,CAAC;AAElB,MAAM,WAAW,eAAe,CAAC,CAAC,GAAG,OAAO;IAC1C,IAAI,EAAE,SAAS,CAAC;IAChB,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,EAAE,WAAW,CAAC;IAClB,MAAM,EAAE,CAAC,CAAC;CACX;AAED,MAAM,WAAW,UAAU,CAAC,CAAC,GAAG,OAAO;IACrC,IAAI,EAAE,UAAU,CAAC;IACjB,EAAE,EAAE,MAAM,CAAC;IACX,EAAE,EAAE,IAAI,CAAC;IACT,MAAM,EAAE,CAAC,CAAC;CACX;AAED,MAAM,WAAW,WAAW;IAC1B,IAAI,EAAE,UAAU,CAAC;IACjB,EAAE,EAAE,MAAM,CAAC;IACX,EAAE,EAAE,KAAK,CAAC;IACV,KAAK,EAAE,eAAe,CAAC;CACxB;AAED,MAAM,MAAM,gBAAgB,CAAC,CAAC,GAAG,OAAO,IAAI,UAAU,CAAC,CAAC,CAAC,GAAG,WAAW,CAAC;AAIxE,MAAM,MAAM,SAAS,GACjB,YAAY,GACZ,YAAY,GACZ,gBAAgB,CAAC;AAErB,MAAM,WAAW,aAAa,CAAC,CAAC,GAAG,OAAO;IACxC,IAAI,EAAE,OAAO,CAAC;IACd,IAAI,EAAE,SAAS,CAAC;IAChB,OAAO,EAAE,CAAC,CAAC;CACZ;AAID;;yEAEyE;AACzE,MAAM,WAAW,eAAe;IAC9B,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,MAAM,CAAC;IAChB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,sEAAsE;IACtE,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAID,MAAM,MAAM,QAAQ,GAChB,eAAe,GACf,gBAAgB,GAChB,aAAa,GACb,cAAc,CAAC;AAInB,MAAM,MAAM,aAAa,CAAC,CAAC,SAAS,WAAW,IAC7C,CAAC,SAAS,MAAM,gBAAgB,GAAG,gBAAgB,CAAC,CAAC,CAAC,GAAG,OAAO,CAAC;AAEnE,MAAM,MAAM,aAAa,CAAC,CAAC,SAAS,WAAW,IAC7C,CAAC,SAAS,MAAM,gBAAgB,GAAG,gBAAgB,CAAC,CAAC,CAAC,GAAG,OAAO,CAAC;AAEnE,MAAM,MAAM,YAAY,CAAC,CAAC,SAAS,SAAS,IAC1C,CAAC,SAAS,MAAM,eAAe,GAAG,eAAe,CAAC,CAAC,CAAC,GAAG,OAAO,CAAC;AAMjE,MAAM,WAAW,gBAAgB;CAAG;AACpC,MAAM,WAAW,gBAAgB;CAAG;AACpC,MAAM,WAAW,eAAe;CAAG"}
@@ -0,0 +1,31 @@
1
+ import { EventKind, EventPayload, RequestKind, RequestParams, RequestResult } from './protocol';
2
+ import { ChannelFactory } from './channel';
3
+ export declare class TransportClient {
4
+ private readonly factory;
5
+ private channel;
6
+ private channelDisposers;
7
+ private pending;
8
+ private listeners;
9
+ private destroyed;
10
+ private nextId;
11
+ /** Уникальный ID клиента — отправляется в handshake'е, server может логировать
12
+ * для отладки connection-flap'а. */
13
+ private readonly clientId;
14
+ constructor(factory: ChannelFactory);
15
+ /** Гарантирует наличие живого канала. Lazy — поднимается при первом request.
16
+ * Сразу после connect'а fire-and-forget шлёт handshake — на mismatch
17
+ * логируем warning, но не блокируем дальнейшие запросы. */
18
+ private ensureChannel;
19
+ private handleMessage;
20
+ private handleDisconnect;
21
+ request<K extends RequestKind>(kind: K, params: RequestParams<K>, opts?: {
22
+ signal?: AbortSignal;
23
+ }): Promise<RequestResult<K>>;
24
+ on<K extends EventKind>(kind: K, handler: (payload: EventPayload<K>) => void): () => void;
25
+ destroy(): void;
26
+ }
27
+ export declare class TransportDisconnectedError extends Error {
28
+ readonly code = "transport_disconnected";
29
+ constructor();
30
+ }
31
+ //# sourceMappingURL=transport-client.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"transport-client.d.ts","sourceRoot":"","sources":["../../src/shared/transport-client.ts"],"names":[],"mappings":"AAiBA,OAAO,KAAK,EAEV,SAAS,EACT,YAAY,EAEZ,WAAW,EACX,aAAa,EACb,aAAa,EAGd,MAAM,YAAY,CAAC;AAGpB,OAAO,KAAK,EAAE,cAAc,EAAkB,MAAM,WAAW,CAAC;AAShE,qBAAa,eAAe;IAWd,OAAO,CAAC,QAAQ,CAAC,OAAO;IAVpC,OAAO,CAAC,OAAO,CAA+B;IAC9C,OAAO,CAAC,gBAAgB,CAAyB;IACjD,OAAO,CAAC,OAAO,CAAqC;IACpD,OAAO,CAAC,SAAS,CAAyD;IAC1E,OAAO,CAAC,SAAS,CAAS;IAC1B,OAAO,CAAC,MAAM,CAAK;IACnB;yCACqC;IACrC,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAAkD;gBAE9C,OAAO,EAAE,cAAc;IAEpD;;gEAE4D;IAC5D,OAAO,CAAC,aAAa;IAiCrB,OAAO,CAAC,aAAa;IA8BrB,OAAO,CAAC,gBAAgB;IAaxB,OAAO,CAAC,CAAC,SAAS,WAAW,EAC3B,IAAI,EAAE,CAAC,EACP,MAAM,EAAE,aAAa,CAAC,CAAC,CAAC,EACxB,IAAI,GAAE;QAAE,MAAM,CAAC,EAAE,WAAW,CAAA;KAAO,GAClC,OAAO,CAAC,aAAa,CAAC,CAAC,CAAC,CAAC;IAqD5B,EAAE,CAAC,CAAC,SAAS,SAAS,EACpB,IAAI,EAAE,CAAC,EACP,OAAO,EAAE,CAAC,OAAO,EAAE,YAAY,CAAC,CAAC,CAAC,KAAK,IAAI,GAC1C,MAAM,IAAI;IAkBb,OAAO,IAAI,IAAI;CAehB;AAED,qBAAa,0BAA2B,SAAQ,KAAK;IACnD,QAAQ,CAAC,IAAI,4BAA4B;;CAK1C"}
@@ -0,0 +1,32 @@
1
+ import { EventKind, EventPayload, RequestKind, RequestParams, RequestResult } from './protocol';
2
+ import { MessageChannel } from './channel';
3
+ export interface RequestContext {
4
+ /** AbortSignal, который тригернётся при получении cancel-envelope от клиента.
5
+ * Handler может пробросить его в underlying fetch для отмены сетевой
6
+ * операции. Игнорировать тоже OK — старые handler'ы продолжат работать. */
7
+ signal: AbortSignal;
8
+ }
9
+ export type RequestHandler<K extends RequestKind> = (params: RequestParams<K>, ctx: RequestContext) => Promise<RequestResult<K>> | RequestResult<K>;
10
+ export declare class TransportServer {
11
+ private handlers;
12
+ private channels;
13
+ /** Активные запросы по каналам: channel → id → AbortController. На cancel
14
+ * envelope ищем controller и abort'им его. На disconnect — abort всех. */
15
+ private active;
16
+ constructor();
17
+ on<K extends RequestKind>(kind: K, handler: RequestHandler<K>): void;
18
+ off<K extends RequestKind>(kind: K): void;
19
+ /** Подключить канал. Сервер начинает обрабатывать запросы из него и
20
+ * включает его в broadcast'ы. На disconnect автоматически удаляет +
21
+ * abort'ит все in-flight handlers для этого канала. */
22
+ accept(channel: MessageChannel): void;
23
+ /** Fan-out события всем подключённым каналам. */
24
+ broadcast<K extends EventKind>(kind: K, payload: EventPayload<K>): void;
25
+ /** Размер активного пула — для health-check / cleanup'а offscreen'а
26
+ * (если 0, host может закрыть offscreen-документ). */
27
+ get connectionCount(): number;
28
+ private dispatch;
29
+ private respondOk;
30
+ private respondErr;
31
+ }
32
+ //# sourceMappingURL=transport-server.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"transport-server.d.ts","sourceRoot":"","sources":["../../src/shared/transport-server.ts"],"names":[],"mappings":"AAcA,OAAO,KAAK,EAGV,SAAS,EACT,YAAY,EAEZ,WAAW,EACX,aAAa,EACb,aAAa,EACd,MAAM,YAAY,CAAC;AAGpB,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,WAAW,CAAC;AAEhD,MAAM,WAAW,cAAc;IAC7B;;gFAE4E;IAC5E,MAAM,EAAE,WAAW,CAAC;CACrB;AAED,MAAM,MAAM,cAAc,CAAC,CAAC,SAAS,WAAW,IAAI,CAClD,MAAM,EAAE,aAAa,CAAC,CAAC,CAAC,EACxB,GAAG,EAAE,cAAc,KAChB,OAAO,CAAC,aAAa,CAAC,CAAC,CAAC,CAAC,GAAG,aAAa,CAAC,CAAC,CAAC,CAAC;AAElD,qBAAa,eAAe;IAC1B,OAAO,CAAC,QAAQ,CAAuD;IACvE,OAAO,CAAC,QAAQ,CAA6B;IAC7C;+EAC2E;IAC3E,OAAO,CAAC,MAAM,CAA+D;;IAY7E,EAAE,CAAC,CAAC,SAAS,WAAW,EAAE,IAAI,EAAE,CAAC,EAAE,OAAO,EAAE,cAAc,CAAC,CAAC,CAAC,GAAG,IAAI;IAIpE,GAAG,CAAC,CAAC,SAAS,WAAW,EAAE,IAAI,EAAE,CAAC,GAAG,IAAI;IAIzC;;4DAEwD;IACxD,MAAM,CAAC,OAAO,EAAE,cAAc,GAAG,IAAI;IAcrC,iDAAiD;IACjD,SAAS,CAAC,CAAC,SAAS,SAAS,EAAE,IAAI,EAAE,CAAC,EAAE,OAAO,EAAE,YAAY,CAAC,CAAC,CAAC,GAAG,IAAI;IAWvE;2DACuD;IACvD,IAAI,eAAe,IAAI,MAAM,CAE5B;YAEa,QAAQ;IAkCtB,OAAO,CAAC,SAAS;IAQjB,OAAO,CAAC,UAAU;CAOnB"}
@@ -0,0 +1,8 @@
1
+ interface EnsureOffscreenOptions {
2
+ url: string;
3
+ reasons: chrome.offscreen.Reason[];
4
+ justification: string;
5
+ }
6
+ export declare function ensureOffscreen(opts: EnsureOffscreenOptions): Promise<void>;
7
+ export {};
8
+ //# sourceMappingURL=ensure-offscreen.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ensure-offscreen.d.ts","sourceRoot":"","sources":["../../src/sw/ensure-offscreen.ts"],"names":[],"mappings":"AAMA,UAAU,sBAAsB;IAC9B,GAAG,EAAE,MAAM,CAAC;IACZ,OAAO,EAAE,MAAM,CAAC,SAAS,CAAC,MAAM,EAAE,CAAC;IACnC,aAAa,EAAE,MAAM,CAAC;CACvB;AAID,wBAAsB,eAAe,CAAC,IAAI,EAAE,sBAAsB,GAAG,OAAO,CAAC,IAAI,CAAC,CAMjF"}
@@ -0,0 +1,3 @@
1
+ import { RouterOptions } from './types';
2
+ export declare function installForwarder(opts: RouterOptions): void;
3
+ //# sourceMappingURL=forwarder.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"forwarder.d.ts","sourceRoot":"","sources":["../../src/sw/forwarder.ts"],"names":[],"mappings":"AAMA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,SAAS,CAAC;AAS7C,wBAAgB,gBAAgB,CAAC,IAAI,EAAE,aAAa,GAAG,IAAI,CAa1D"}
@@ -0,0 +1,4 @@
1
+ import { RouterOptions } from './types';
2
+ export type { RouterOptions };
3
+ export declare function installRouter(opts: RouterOptions): void;
4
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/sw/index.ts"],"names":[],"mappings":"AAgBA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,SAAS,CAAC;AAE7C,YAAY,EAAE,aAAa,EAAE,CAAC;AAE9B,wBAAgB,aAAa,CAAC,IAAI,EAAE,aAAa,GAAG,IAAI,CAKvD"}
@@ -0,0 +1,19 @@
1
+ export interface RouterOptions {
2
+ /** URL offscreen-страницы. Может быть статической строкой ИЛИ функцией —
3
+ * функция позволяет resolve'ить URL на каждом connect'е, что нужно когда
4
+ * параметры (apiOrigin, paywallId, etc.) приходят из chrome.storage и
5
+ * могут поменяться без перезагрузки SW. Каждый ленивый resolve может
6
+ * быть async — функция async читает storage и возвращает URL.
7
+ *
8
+ * Простой случай: `chrome.runtime.getURL('offscreen.html')`.
9
+ * С параметрами:
10
+ * `() => chrome.storage.local.get(['k']).then(({ k }) =>
11
+ * chrome.runtime.getURL('offscreen.html') + '?k=' + k)`
12
+ */
13
+ offscreenUrl: string | (() => string | Promise<string>);
14
+ /** Reasons для chrome.offscreen.createDocument. Дефолт — `['LOCAL_STORAGE']`. */
15
+ offscreenReasons?: chrome.offscreen.Reason[];
16
+ /** Justification для CWS ревью. */
17
+ offscreenJustification?: string;
18
+ }
19
+ //# sourceMappingURL=types.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/sw/types.ts"],"names":[],"mappings":"AAGA,MAAM,WAAW,aAAa;IAC5B;;;;;;;;;;OAUG;IACH,YAAY,EAAE,MAAM,GAAG,CAAC,MAAM,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CAAC,CAAC;IACxD,iFAAiF;IACjF,gBAAgB,CAAC,EAAE,MAAM,CAAC,SAAS,CAAC,MAAM,EAAE,CAAC;IAC7C,mCAAmC;IACnC,sBAAsB,CAAC,EAAE,MAAM,CAAC;CACjC"}
package/dist/sw.cjs ADDED
@@ -0,0 +1,2 @@
1
+ "use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const f=require("./chunks/port-name-qwB109u9.js");let r=null;async function d(e){return r||(r=l(e).finally(()=>{r=null}),r)}async function l(e){if(!await m(e.url))try{await chrome.offscreen.createDocument({url:e.url,reasons:e.reasons,justification:e.justification})}catch(s){if(s instanceof Error&&/single offscreen document/i.test(s.message))return;throw s}}async function m(e){return typeof chrome.runtime.getContexts=="function"?(await chrome.runtime.getContexts({contextTypes:[chrome.runtime.ContextType.OFFSCREEN_DOCUMENT],documentUrls:[e]})).length>0:!1}const h=[chrome.offscreen.Reason.LOCAL_STORAGE],y="Persist auth session and bootstrap cache across all extension surfaces via localStorage, which is unavailable in service workers.";function g(e){const s=e.offscreenReasons??h,o=e.offscreenJustification??y;chrome.runtime.onConnect.addListener(c=>{c.name===f.PORT_NAME&&w(c,e.offscreenUrl,s,o)})}async function w(e,s,o,c){const i=[],a=n=>{i.push(n)};e.onMessage.addListener(a);let u=!1;e.onDisconnect.addListener(()=>{u=!0});try{const n=typeof s=="function"?await s():s;await d({url:n,reasons:o,justification:c})}catch(n){console.error("[sdk-extension/sw] ensureOffscreen failed",n),e.disconnect();return}if(u)return;let t;try{t=chrome.runtime.connect({name:f.PORT_NAME})}catch(n){console.error("[sdk-extension/sw] connect to offscreen failed",n),e.disconnect();return}e.onMessage.removeListener(a),e.onMessage.addListener(n=>{try{t.postMessage(n)}catch{}}),t.onMessage.addListener(n=>{try{e.postMessage(n)}catch{}}),e.onDisconnect.addListener(()=>{try{t.disconnect()}catch{}}),t.onDisconnect.addListener(()=>{try{e.disconnect()}catch{}});for(const n of i)try{t.postMessage(n)}catch{break}}function E(e){if(typeof chrome>"u"||!chrome.runtime)throw new Error("@monetize.software/sdk-extension/sw requires chrome.runtime");g(e)}exports.installRouter=E;
2
+ //# sourceMappingURL=sw.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"sw.cjs","sources":["../src/sw/ensure-offscreen.ts","../src/sw/forwarder.ts","../src/sw/index.ts"],"sourcesContent":["// Singleton-страж offscreen-документа. Chrome 116+ имеет\n// chrome.runtime.getContexts (Promise-overload в MV3); используем его как\n// основной путь. Race: несколько параллельных onConnect'ов в одном tick'е\n// могут вызвать ensureOffscreen одновременно — запоминаем in-flight promise,\n// чтобы каждый следующий ждал общий create.\n\ninterface EnsureOffscreenOptions {\n url: string;\n reasons: chrome.offscreen.Reason[];\n justification: string;\n}\n\nlet inflight: Promise<void> | null = null;\n\nexport async function ensureOffscreen(opts: EnsureOffscreenOptions): Promise<void> {\n if (inflight) return inflight;\n inflight = doEnsure(opts).finally(() => {\n inflight = null;\n });\n return inflight;\n}\n\nasync function doEnsure(opts: EnsureOffscreenOptions): Promise<void> {\n if (await offscreenExists(opts.url)) return;\n try {\n await chrome.offscreen.createDocument({\n url: opts.url,\n reasons: opts.reasons,\n justification: opts.justification\n });\n } catch (e) {\n // Гонка: между нашим check'ом и create'ом другой onConnect успел создать.\n // Chrome бросает 'Only a single offscreen document may be created' — это\n // OK, документ есть. Любая другая ошибка — пробрасываем.\n if (e instanceof Error && /single offscreen document/i.test(e.message)) return;\n throw e;\n }\n}\n\nasync function offscreenExists(url: string): Promise<boolean> {\n if (typeof chrome.runtime.getContexts === 'function') {\n const contexts = await chrome.runtime.getContexts({\n contextTypes: [chrome.runtime.ContextType.OFFSCREEN_DOCUMENT],\n documentUrls: [url]\n });\n return contexts.length > 0;\n }\n return false;\n}\n","// Service worker forwarder. Stateless по дизайну — единственная задача\n// маршрутизировать port'ы content↔offscreen. SW можеть умирать в любой момент\n// (после 30с idle); reconnect происходит органически: следующий content\n// runtime.connect разбудит SW, тот пересоздаст offscreen (если умер — а он\n// обычно нет) и поднимет свежий pipe.\n\nimport type { RouterOptions } from './types';\nimport { ensureOffscreen } from './ensure-offscreen';\nimport { PORT_NAME } from '../shared/port-name';\n\nconst DEFAULT_REASONS: chrome.offscreen.Reason[] = [chrome.offscreen.Reason.LOCAL_STORAGE];\nconst DEFAULT_JUSTIFICATION =\n 'Persist auth session and bootstrap cache across all extension surfaces ' +\n 'via localStorage, which is unavailable in service workers.';\n\nexport function installForwarder(opts: RouterOptions): void {\n const reasons = opts.offscreenReasons ?? DEFAULT_REASONS;\n const justification = opts.offscreenJustification ?? DEFAULT_JUSTIFICATION;\n\n chrome.runtime.onConnect.addListener((contentPort) => {\n if (contentPort.name !== PORT_NAME) return;\n\n // Поднимаем offscreen и проксируем. ensureOffscreen async — content успел\n // отправить request'ы до её резолва: буферим в queue до создания offscreen\n // port'а. Это лучше чем потерять — content всё равно тащит абсолютно всё\n // через нас.\n void connectAndPipe(contentPort, opts.offscreenUrl, reasons, justification);\n });\n}\n\nasync function connectAndPipe(\n contentPort: chrome.runtime.Port,\n offscreenUrlOrResolver: string | (() => string | Promise<string>),\n reasons: chrome.offscreen.Reason[],\n justification: string\n): Promise<void> {\n const queue: unknown[] = [];\n const queueListener = (msg: unknown): void => {\n queue.push(msg);\n };\n contentPort.onMessage.addListener(queueListener);\n\n let disconnected = false;\n contentPort.onDisconnect.addListener(() => {\n disconnected = true;\n });\n\n try {\n const offscreenUrl =\n typeof offscreenUrlOrResolver === 'function'\n ? await offscreenUrlOrResolver()\n : offscreenUrlOrResolver;\n await ensureOffscreen({ url: offscreenUrl, reasons, justification });\n } catch (e) {\n console.error('[sdk-extension/sw] ensureOffscreen failed', e);\n contentPort.disconnect();\n return;\n }\n\n if (disconnected) return;\n\n let offscreenPort: chrome.runtime.Port;\n try {\n offscreenPort = chrome.runtime.connect({ name: PORT_NAME });\n } catch (e) {\n console.error('[sdk-extension/sw] connect to offscreen failed', e);\n contentPort.disconnect();\n return;\n }\n\n // Снимаем буфер-listener, ставим прямой forwarder.\n contentPort.onMessage.removeListener(queueListener);\n contentPort.onMessage.addListener((msg) => {\n try {\n offscreenPort.postMessage(msg);\n } catch {\n /* offscreen уже отвалился — disconnect-каскад поднимет content */\n }\n });\n offscreenPort.onMessage.addListener((msg) => {\n try {\n contentPort.postMessage(msg);\n } catch {\n /* content уже отвалился */\n }\n });\n\n contentPort.onDisconnect.addListener(() => {\n try {\n offscreenPort.disconnect();\n } catch {\n /* ignore */\n }\n });\n offscreenPort.onDisconnect.addListener(() => {\n try {\n contentPort.disconnect();\n } catch {\n /* ignore */\n }\n });\n\n // Сливаем накопившийся буфер.\n for (const msg of queue) {\n try {\n offscreenPort.postMessage(msg);\n } catch {\n break;\n }\n }\n}\n","// Service worker entry. Тонкий forwarder между content-script'ами и offscreen.\n// State не держит — вся правда в offscreen, SW только маршрут. SW может\n// умирать в любой момент; следующий content runtime.connect разбудит его и\n// pipe пересоздастся.\n//\n// OAuth не проксируем — auth-flow на extension'е использует тот же\n// web-вариант, что и на сайтах: window.open на наш домен → callback в новой\n// вкладке передаёт code в offscreen через chrome.runtime сообщение.\n// chrome.identity намеренно не используется (требует chrome-extension://\n// redirect URL у провайдеров, ломает совместимость с web).\n//\n// Использование в host'е:\n// import { installRouter } from '@monetize.software/sdk-extension/sw';\n// installRouter({ offscreenUrl: chrome.runtime.getURL('offscreen.html') });\n\nimport { installForwarder } from './forwarder';\nimport type { RouterOptions } from './types';\n\nexport type { RouterOptions };\n\nexport function installRouter(opts: RouterOptions): void {\n if (typeof chrome === 'undefined' || !chrome.runtime) {\n throw new Error('@monetize.software/sdk-extension/sw requires chrome.runtime');\n }\n installForwarder(opts);\n}\n"],"names":["inflight","ensureOffscreen","opts","doEnsure","offscreenExists","e","url","DEFAULT_REASONS","DEFAULT_JUSTIFICATION","installForwarder","reasons","justification","contentPort","PORT_NAME","connectAndPipe","offscreenUrlOrResolver","queue","queueListener","msg","disconnected","offscreenUrl","offscreenPort","installRouter"],"mappings":"kIAYA,IAAIA,EAAiC,KAErC,eAAsBC,EAAgBC,EAA6C,CACjF,OAAIF,IACJA,EAAWG,EAASD,CAAI,EAAE,QAAQ,IAAM,CACtCF,EAAW,IACb,CAAC,EACMA,EACT,CAEA,eAAeG,EAASD,EAA6C,CACnE,GAAI,OAAME,EAAgBF,EAAK,GAAG,EAClC,GAAI,CACF,MAAM,OAAO,UAAU,eAAe,CACpC,IAAKA,EAAK,IACV,QAASA,EAAK,QACd,cAAeA,EAAK,aAAA,CACrB,CACH,OAASG,EAAG,CAIV,GAAIA,aAAa,OAAS,6BAA6B,KAAKA,EAAE,OAAO,EAAG,OACxE,MAAMA,CACR,CACF,CAEA,eAAeD,EAAgBE,EAA+B,CAC5D,OAAI,OAAO,OAAO,QAAQ,aAAgB,YACvB,MAAM,OAAO,QAAQ,YAAY,CAChD,aAAc,CAAC,OAAO,QAAQ,YAAY,kBAAkB,EAC5D,aAAc,CAACA,CAAG,CAAA,CACnB,GACe,OAAS,EAEpB,EACT,CCtCA,MAAMC,EAA6C,CAAC,OAAO,UAAU,OAAO,aAAa,EACnFC,EACJ,oIAGK,SAASC,EAAiBP,EAA2B,CAC1D,MAAMQ,EAAUR,EAAK,kBAAoBK,EACnCI,EAAgBT,EAAK,wBAA0BM,EAErD,OAAO,QAAQ,UAAU,YAAaI,GAAgB,CAChDA,EAAY,OAASC,aAMpBC,EAAeF,EAAaV,EAAK,aAAcQ,EAASC,CAAa,CAC5E,CAAC,CACH,CAEA,eAAeG,EACbF,EACAG,EACAL,EACAC,EACe,CACf,MAAMK,EAAmB,CAAA,EACnBC,EAAiBC,GAAuB,CAC5CF,EAAM,KAAKE,CAAG,CAChB,EACAN,EAAY,UAAU,YAAYK,CAAa,EAE/C,IAAIE,EAAe,GACnBP,EAAY,aAAa,YAAY,IAAM,CACzCO,EAAe,EACjB,CAAC,EAED,GAAI,CACF,MAAMC,EACJ,OAAOL,GAA2B,WAC9B,MAAMA,IACNA,EACN,MAAMd,EAAgB,CAAE,IAAKmB,EAAc,QAAAV,EAAS,cAAAC,EAAe,CACrE,OAASN,EAAG,CACV,QAAQ,MAAM,4CAA6CA,CAAC,EAC5DO,EAAY,WAAA,EACZ,MACF,CAEA,GAAIO,EAAc,OAElB,IAAIE,EACJ,GAAI,CACFA,EAAgB,OAAO,QAAQ,QAAQ,CAAE,KAAMR,EAAAA,UAAW,CAC5D,OAASR,EAAG,CACV,QAAQ,MAAM,iDAAkDA,CAAC,EACjEO,EAAY,WAAA,EACZ,MACF,CAGAA,EAAY,UAAU,eAAeK,CAAa,EAClDL,EAAY,UAAU,YAAaM,GAAQ,CACzC,GAAI,CACFG,EAAc,YAAYH,CAAG,CAC/B,MAAQ,CAER,CACF,CAAC,EACDG,EAAc,UAAU,YAAaH,GAAQ,CAC3C,GAAI,CACFN,EAAY,YAAYM,CAAG,CAC7B,MAAQ,CAER,CACF,CAAC,EAEDN,EAAY,aAAa,YAAY,IAAM,CACzC,GAAI,CACFS,EAAc,WAAA,CAChB,MAAQ,CAER,CACF,CAAC,EACDA,EAAc,aAAa,YAAY,IAAM,CAC3C,GAAI,CACFT,EAAY,WAAA,CACd,MAAQ,CAER,CACF,CAAC,EAGD,UAAWM,KAAOF,EAChB,GAAI,CACFK,EAAc,YAAYH,CAAG,CAC/B,MAAQ,CACN,KACF,CAEJ,CC1FO,SAASI,EAAcpB,EAA2B,CACvD,GAAI,OAAO,OAAW,KAAe,CAAC,OAAO,QAC3C,MAAM,IAAI,MAAM,6DAA6D,EAE/EO,EAAiBP,CAAI,CACvB"}
package/dist/sw.js ADDED
@@ -0,0 +1,94 @@
1
+ import { P as u } from "./chunks/port-name-BPfQKtdb.js";
2
+ let r = null;
3
+ async function d(e) {
4
+ return r || (r = l(e).finally(() => {
5
+ r = null;
6
+ }), r);
7
+ }
8
+ async function l(e) {
9
+ if (!await m(e.url))
10
+ try {
11
+ await chrome.offscreen.createDocument({
12
+ url: e.url,
13
+ reasons: e.reasons,
14
+ justification: e.justification
15
+ });
16
+ } catch (s) {
17
+ if (s instanceof Error && /single offscreen document/i.test(s.message)) return;
18
+ throw s;
19
+ }
20
+ }
21
+ async function m(e) {
22
+ return typeof chrome.runtime.getContexts == "function" ? (await chrome.runtime.getContexts({
23
+ contextTypes: [chrome.runtime.ContextType.OFFSCREEN_DOCUMENT],
24
+ documentUrls: [e]
25
+ })).length > 0 : !1;
26
+ }
27
+ const h = [chrome.offscreen.Reason.LOCAL_STORAGE], y = "Persist auth session and bootstrap cache across all extension surfaces via localStorage, which is unavailable in service workers.";
28
+ function g(e) {
29
+ const s = e.offscreenReasons ?? h, o = e.offscreenJustification ?? y;
30
+ chrome.runtime.onConnect.addListener((c) => {
31
+ c.name === u && w(c, e.offscreenUrl, s, o);
32
+ });
33
+ }
34
+ async function w(e, s, o, c) {
35
+ const i = [], a = (n) => {
36
+ i.push(n);
37
+ };
38
+ e.onMessage.addListener(a);
39
+ let f = !1;
40
+ e.onDisconnect.addListener(() => {
41
+ f = !0;
42
+ });
43
+ try {
44
+ const n = typeof s == "function" ? await s() : s;
45
+ await d({ url: n, reasons: o, justification: c });
46
+ } catch (n) {
47
+ console.error("[sdk-extension/sw] ensureOffscreen failed", n), e.disconnect();
48
+ return;
49
+ }
50
+ if (f) return;
51
+ let t;
52
+ try {
53
+ t = chrome.runtime.connect({ name: u });
54
+ } catch (n) {
55
+ console.error("[sdk-extension/sw] connect to offscreen failed", n), e.disconnect();
56
+ return;
57
+ }
58
+ e.onMessage.removeListener(a), e.onMessage.addListener((n) => {
59
+ try {
60
+ t.postMessage(n);
61
+ } catch {
62
+ }
63
+ }), t.onMessage.addListener((n) => {
64
+ try {
65
+ e.postMessage(n);
66
+ } catch {
67
+ }
68
+ }), e.onDisconnect.addListener(() => {
69
+ try {
70
+ t.disconnect();
71
+ } catch {
72
+ }
73
+ }), t.onDisconnect.addListener(() => {
74
+ try {
75
+ e.disconnect();
76
+ } catch {
77
+ }
78
+ });
79
+ for (const n of i)
80
+ try {
81
+ t.postMessage(n);
82
+ } catch {
83
+ break;
84
+ }
85
+ }
86
+ function x(e) {
87
+ if (typeof chrome > "u" || !chrome.runtime)
88
+ throw new Error("@monetize.software/sdk-extension/sw requires chrome.runtime");
89
+ g(e);
90
+ }
91
+ export {
92
+ x as installRouter
93
+ };
94
+ //# sourceMappingURL=sw.js.map
package/dist/sw.js.map ADDED
@@ -0,0 +1 @@
1
+ {"version":3,"file":"sw.js","sources":["../src/sw/ensure-offscreen.ts","../src/sw/forwarder.ts","../src/sw/index.ts"],"sourcesContent":["// Singleton-страж offscreen-документа. Chrome 116+ имеет\n// chrome.runtime.getContexts (Promise-overload в MV3); используем его как\n// основной путь. Race: несколько параллельных onConnect'ов в одном tick'е\n// могут вызвать ensureOffscreen одновременно — запоминаем in-flight promise,\n// чтобы каждый следующий ждал общий create.\n\ninterface EnsureOffscreenOptions {\n url: string;\n reasons: chrome.offscreen.Reason[];\n justification: string;\n}\n\nlet inflight: Promise<void> | null = null;\n\nexport async function ensureOffscreen(opts: EnsureOffscreenOptions): Promise<void> {\n if (inflight) return inflight;\n inflight = doEnsure(opts).finally(() => {\n inflight = null;\n });\n return inflight;\n}\n\nasync function doEnsure(opts: EnsureOffscreenOptions): Promise<void> {\n if (await offscreenExists(opts.url)) return;\n try {\n await chrome.offscreen.createDocument({\n url: opts.url,\n reasons: opts.reasons,\n justification: opts.justification\n });\n } catch (e) {\n // Гонка: между нашим check'ом и create'ом другой onConnect успел создать.\n // Chrome бросает 'Only a single offscreen document may be created' — это\n // OK, документ есть. Любая другая ошибка — пробрасываем.\n if (e instanceof Error && /single offscreen document/i.test(e.message)) return;\n throw e;\n }\n}\n\nasync function offscreenExists(url: string): Promise<boolean> {\n if (typeof chrome.runtime.getContexts === 'function') {\n const contexts = await chrome.runtime.getContexts({\n contextTypes: [chrome.runtime.ContextType.OFFSCREEN_DOCUMENT],\n documentUrls: [url]\n });\n return contexts.length > 0;\n }\n return false;\n}\n","// Service worker forwarder. Stateless по дизайну — единственная задача\n// маршрутизировать port'ы content↔offscreen. SW можеть умирать в любой момент\n// (после 30с idle); reconnect происходит органически: следующий content\n// runtime.connect разбудит SW, тот пересоздаст offscreen (если умер — а он\n// обычно нет) и поднимет свежий pipe.\n\nimport type { RouterOptions } from './types';\nimport { ensureOffscreen } from './ensure-offscreen';\nimport { PORT_NAME } from '../shared/port-name';\n\nconst DEFAULT_REASONS: chrome.offscreen.Reason[] = [chrome.offscreen.Reason.LOCAL_STORAGE];\nconst DEFAULT_JUSTIFICATION =\n 'Persist auth session and bootstrap cache across all extension surfaces ' +\n 'via localStorage, which is unavailable in service workers.';\n\nexport function installForwarder(opts: RouterOptions): void {\n const reasons = opts.offscreenReasons ?? DEFAULT_REASONS;\n const justification = opts.offscreenJustification ?? DEFAULT_JUSTIFICATION;\n\n chrome.runtime.onConnect.addListener((contentPort) => {\n if (contentPort.name !== PORT_NAME) return;\n\n // Поднимаем offscreen и проксируем. ensureOffscreen async — content успел\n // отправить request'ы до её резолва: буферим в queue до создания offscreen\n // port'а. Это лучше чем потерять — content всё равно тащит абсолютно всё\n // через нас.\n void connectAndPipe(contentPort, opts.offscreenUrl, reasons, justification);\n });\n}\n\nasync function connectAndPipe(\n contentPort: chrome.runtime.Port,\n offscreenUrlOrResolver: string | (() => string | Promise<string>),\n reasons: chrome.offscreen.Reason[],\n justification: string\n): Promise<void> {\n const queue: unknown[] = [];\n const queueListener = (msg: unknown): void => {\n queue.push(msg);\n };\n contentPort.onMessage.addListener(queueListener);\n\n let disconnected = false;\n contentPort.onDisconnect.addListener(() => {\n disconnected = true;\n });\n\n try {\n const offscreenUrl =\n typeof offscreenUrlOrResolver === 'function'\n ? await offscreenUrlOrResolver()\n : offscreenUrlOrResolver;\n await ensureOffscreen({ url: offscreenUrl, reasons, justification });\n } catch (e) {\n console.error('[sdk-extension/sw] ensureOffscreen failed', e);\n contentPort.disconnect();\n return;\n }\n\n if (disconnected) return;\n\n let offscreenPort: chrome.runtime.Port;\n try {\n offscreenPort = chrome.runtime.connect({ name: PORT_NAME });\n } catch (e) {\n console.error('[sdk-extension/sw] connect to offscreen failed', e);\n contentPort.disconnect();\n return;\n }\n\n // Снимаем буфер-listener, ставим прямой forwarder.\n contentPort.onMessage.removeListener(queueListener);\n contentPort.onMessage.addListener((msg) => {\n try {\n offscreenPort.postMessage(msg);\n } catch {\n /* offscreen уже отвалился — disconnect-каскад поднимет content */\n }\n });\n offscreenPort.onMessage.addListener((msg) => {\n try {\n contentPort.postMessage(msg);\n } catch {\n /* content уже отвалился */\n }\n });\n\n contentPort.onDisconnect.addListener(() => {\n try {\n offscreenPort.disconnect();\n } catch {\n /* ignore */\n }\n });\n offscreenPort.onDisconnect.addListener(() => {\n try {\n contentPort.disconnect();\n } catch {\n /* ignore */\n }\n });\n\n // Сливаем накопившийся буфер.\n for (const msg of queue) {\n try {\n offscreenPort.postMessage(msg);\n } catch {\n break;\n }\n }\n}\n","// Service worker entry. Тонкий forwarder между content-script'ами и offscreen.\n// State не держит — вся правда в offscreen, SW только маршрут. SW может\n// умирать в любой момент; следующий content runtime.connect разбудит его и\n// pipe пересоздастся.\n//\n// OAuth не проксируем — auth-flow на extension'е использует тот же\n// web-вариант, что и на сайтах: window.open на наш домен → callback в новой\n// вкладке передаёт code в offscreen через chrome.runtime сообщение.\n// chrome.identity намеренно не используется (требует chrome-extension://\n// redirect URL у провайдеров, ломает совместимость с web).\n//\n// Использование в host'е:\n// import { installRouter } from '@monetize.software/sdk-extension/sw';\n// installRouter({ offscreenUrl: chrome.runtime.getURL('offscreen.html') });\n\nimport { installForwarder } from './forwarder';\nimport type { RouterOptions } from './types';\n\nexport type { RouterOptions };\n\nexport function installRouter(opts: RouterOptions): void {\n if (typeof chrome === 'undefined' || !chrome.runtime) {\n throw new Error('@monetize.software/sdk-extension/sw requires chrome.runtime');\n }\n installForwarder(opts);\n}\n"],"names":["inflight","ensureOffscreen","opts","doEnsure","offscreenExists","e","url","DEFAULT_REASONS","DEFAULT_JUSTIFICATION","installForwarder","reasons","justification","contentPort","PORT_NAME","connectAndPipe","offscreenUrlOrResolver","queue","queueListener","msg","disconnected","offscreenUrl","offscreenPort","installRouter"],"mappings":"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"}
package/package.json ADDED
@@ -0,0 +1,63 @@
1
+ {
2
+ "name": "@monetize.software/sdk-extension",
3
+ "version": "0.1.0-alpha.0",
4
+ "description": "Monetize SDK for Chrome extensions — single source of truth via offscreen document, drop-in compatible with @monetize.software/sdk public API",
5
+ "type": "module",
6
+ "sideEffects": false,
7
+ "license": "MIT",
8
+ "files": [
9
+ "dist",
10
+ "src/offscreen/offscreen.html"
11
+ ],
12
+ "exports": {
13
+ ".": {
14
+ "types": "./dist/content/index.d.ts",
15
+ "import": "./dist/content.js",
16
+ "require": "./dist/content.cjs"
17
+ },
18
+ "./offscreen": {
19
+ "types": "./dist/offscreen/index.d.ts",
20
+ "import": "./dist/offscreen.js",
21
+ "require": "./dist/offscreen.cjs"
22
+ },
23
+ "./sw": {
24
+ "types": "./dist/sw/index.d.ts",
25
+ "import": "./dist/sw.js",
26
+ "require": "./dist/sw.cjs"
27
+ },
28
+ "./offscreen.html": "./src/offscreen/offscreen.html"
29
+ },
30
+ "scripts": {
31
+ "dev": "vite",
32
+ "build": "vite build",
33
+ "dev:demo": "vite build --watch --mode e2e --config demo-extension/vite.config.ts & vite build --watch --mode e2e --config demo-extension/vite.content.config.ts & wait",
34
+ "typecheck": "tsc --noEmit",
35
+ "test": "vitest run",
36
+ "test:watch": "vitest",
37
+ "test:e2e": "pnpm build:demo:e2e && playwright test",
38
+ "build:demo": "vite build --config demo-extension/vite.config.ts && vite build --config demo-extension/vite.content.config.ts",
39
+ "build:demo:e2e": "vite build --mode e2e --config demo-extension/vite.config.ts && vite build --mode e2e --config demo-extension/vite.content.config.ts",
40
+ "prepublishOnly": "pnpm typecheck && pnpm build",
41
+ "version:alpha": "npm version prerelease --preid=alpha --no-git-tag-version",
42
+ "version:patch": "npm version patch --no-git-tag-version",
43
+ "version:minor": "npm version minor --no-git-tag-version",
44
+ "version:major": "npm version major --no-git-tag-version",
45
+ "release:alpha": "npm publish --access public --tag alpha",
46
+ "release:latest": "npm publish --access public"
47
+ },
48
+ "dependencies": {
49
+ "preact": "^10.24.0"
50
+ },
51
+ "devDependencies": {
52
+ "@playwright/test": "^1.59.1",
53
+ "@tailwindcss/vite": "^4.0.0",
54
+ "@types/chrome": "^0.0.287",
55
+ "@types/node": "^20.17.28",
56
+ "jsdom": "^25.0.1",
57
+ "tailwindcss": "^4.0.0",
58
+ "typescript": "^5.8.2",
59
+ "vite": "^6.0.5",
60
+ "vite-plugin-dts": "^4.3.0",
61
+ "vitest": "^2.1.8"
62
+ }
63
+ }