crx-rpc 1.0.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.
@@ -0,0 +1,27 @@
1
+ import type { IMessageAdapter } from './types';
2
+ import type { Identifier } from './id';
3
+ import { Disposable } from './disposable';
4
+ type FunctionArgs<T> = T extends (...args: infer A) => any ? A : never;
5
+ type FunctionReturnType<T> = T extends (...args: any[]) => infer R ? R : never;
6
+ type ServiceProxy<T> = {
7
+ [K in keyof T]: T[K] extends (...args: any[]) => any ? (...args: FunctionArgs<T[K]>) => Promise<Awaited<FunctionReturnType<T[K]>>> : never;
8
+ };
9
+ export declare class RPCClient extends Disposable {
10
+ private messageAdapter;
11
+ private pending;
12
+ constructor(messageAdapter: IMessageAdapter);
13
+ call<T = any>(service: string, method: string, args: any[]): Promise<T>;
14
+ createWebRPCService<T>(serviceIdentifier: Identifier<T>): ServiceProxy<T>;
15
+ }
16
+ export declare class BaseObservable<T> extends Disposable {
17
+ private identifier;
18
+ private key;
19
+ private _callback;
20
+ private _adapter;
21
+ private listeners;
22
+ private completed;
23
+ private get _finalKey();
24
+ constructor(identifier: Identifier<T>, key: string, _callback: (value: T) => void, _adapter: IMessageAdapter);
25
+ unsubscribe(): void;
26
+ }
27
+ export {};
package/dist/client.js ADDED
@@ -0,0 +1,88 @@
1
+ import { OBSERVABLE_EVENT, RPC_EVENT_NAME, RPC_RESPONSE_EVENT_NAME, UNSUBSCRIBE_OBSERVABLE } from './const';
2
+ import { Disposable } from './disposable';
3
+ export class RPCClient extends Disposable {
4
+ messageAdapter;
5
+ pending = new Map();
6
+ constructor(messageAdapter) {
7
+ super();
8
+ this.messageAdapter = messageAdapter;
9
+ this.disposeWithMe(messageAdapter.onMessage(RPC_RESPONSE_EVENT_NAME, (event) => {
10
+ const { id, result, error } = event;
11
+ const promise = this.pending.get(id);
12
+ if (!promise)
13
+ return;
14
+ this.pending.delete(id);
15
+ if (error) {
16
+ const err = new Error(error.message);
17
+ err.name = error.name || 'RPCError';
18
+ err.stack = error.stack;
19
+ promise.reject(err);
20
+ }
21
+ else {
22
+ promise.resolve(result);
23
+ }
24
+ }));
25
+ }
26
+ call(service, method, args) {
27
+ const id = crypto.randomUUID();
28
+ return new Promise((resolve, reject) => {
29
+ this.pending.set(id, { resolve, reject });
30
+ const requestParam = {
31
+ method,
32
+ args,
33
+ id,
34
+ service,
35
+ };
36
+ this.messageAdapter.sendMessage(RPC_EVENT_NAME, requestParam);
37
+ });
38
+ }
39
+ createWebRPCService(serviceIdentifier) {
40
+ const serviceKey = serviceIdentifier.key;
41
+ // 创建代理对象,拦截方法调用
42
+ return new Proxy({}, {
43
+ get: (target, prop) => {
44
+ if (typeof prop === 'string') {
45
+ // 返回一个代理函数
46
+ return (...args) => {
47
+ return this.call(serviceKey, prop, args);
48
+ };
49
+ }
50
+ return target[prop];
51
+ },
52
+ });
53
+ }
54
+ }
55
+ export class BaseObservable extends Disposable {
56
+ identifier;
57
+ key;
58
+ _callback;
59
+ _adapter;
60
+ listeners = new Set();
61
+ completed = false;
62
+ get _finalKey() {
63
+ return `${this.identifier.key}-${this.key}`;
64
+ }
65
+ constructor(identifier, key, _callback, _adapter) {
66
+ super();
67
+ this.identifier = identifier;
68
+ this.key = key;
69
+ this._callback = _callback;
70
+ this._adapter = _adapter;
71
+ this.disposeWithMe(this._adapter.onMessage(OBSERVABLE_EVENT, (event) => {
72
+ const msg = event.detail;
73
+ if (msg.key !== this._finalKey)
74
+ return;
75
+ if (msg.operation === 'next' && !this.completed && msg.value) {
76
+ this._callback(msg.value);
77
+ }
78
+ if (msg.operation === 'complete') {
79
+ this.completed = true;
80
+ this.listeners.clear();
81
+ }
82
+ }));
83
+ this._adapter.sendMessage(OBSERVABLE_EVENT, { key: this._finalKey });
84
+ }
85
+ unsubscribe() {
86
+ this._adapter.sendMessage(UNSUBSCRIBE_OBSERVABLE, { key: this._finalKey });
87
+ }
88
+ }
@@ -0,0 +1,5 @@
1
+ export declare const RPC_EVENT_NAME = "__RPC_CALL_CLIPSHEET_AWESOME__";
2
+ export declare const RPC_RESPONSE_EVENT_NAME = "__RPC_RESPONSE_CLIPSHEET_AWESOME__";
3
+ export declare const SUBSCRIBABLE_OBSERVABLE = "__SUBSCRIBABLE_OBSERVABLE__";
4
+ export declare const UNSUBSCRIBE_OBSERVABLE = "__UNSUBSCRIBE_OBSERVABLE__";
5
+ export declare const OBSERVABLE_EVENT = "__OBSERVABLE_EVENT__";
package/dist/const.js ADDED
@@ -0,0 +1,5 @@
1
+ export const RPC_EVENT_NAME = '__RPC_CALL_CLIPSHEET_AWESOME__';
2
+ export const RPC_RESPONSE_EVENT_NAME = '__RPC_RESPONSE_CLIPSHEET_AWESOME__';
3
+ export const SUBSCRIBABLE_OBSERVABLE = '__SUBSCRIBABLE_OBSERVABLE__';
4
+ export const UNSUBSCRIBE_OBSERVABLE = '__UNSUBSCRIBE_OBSERVABLE__';
5
+ export const OBSERVABLE_EVENT = '__OBSERVABLE_EVENT__';
@@ -0,0 +1,14 @@
1
+ import { BaseObservable, RPCClient } from './client';
2
+ import { Disposable } from './disposable';
3
+ import { Identifier } from './id';
4
+ import type { IMessageAdapter } from './types';
5
+ export declare class ContentRPC extends Disposable {
6
+ constructor();
7
+ }
8
+ export declare const contentMessageAdapter: IMessageAdapter;
9
+ export declare class ContentRPCClient extends RPCClient {
10
+ constructor();
11
+ }
12
+ export declare class ContentObservable<T> extends BaseObservable<T> {
13
+ constructor(identifier: Identifier<T>, key: string, callback: (value: T) => void);
14
+ }
@@ -0,0 +1,55 @@
1
+ import { BaseObservable, RPCClient } from './client';
2
+ import { OBSERVABLE_EVENT, RPC_EVENT_NAME, RPC_RESPONSE_EVENT_NAME, SUBSCRIBABLE_OBSERVABLE, UNSUBSCRIBE_OBSERVABLE } from './const';
3
+ import { Disposable } from './disposable';
4
+ const WEB_TO_BACKGROUND = [RPC_EVENT_NAME, SUBSCRIBABLE_OBSERVABLE, UNSUBSCRIBE_OBSERVABLE];
5
+ const BACKGROUND_TO_WEB = [RPC_RESPONSE_EVENT_NAME, OBSERVABLE_EVENT];
6
+ export class ContentRPC extends Disposable {
7
+ constructor() {
8
+ super();
9
+ WEB_TO_BACKGROUND.forEach(eventName => {
10
+ const handler = (event) => {
11
+ chrome.runtime.sendMessage({ ...event.detail, type: eventName });
12
+ };
13
+ window.addEventListener(eventName, handler);
14
+ this.disposeWithMe(() => {
15
+ window.removeEventListener(eventName, handler);
16
+ });
17
+ });
18
+ const handler = (msg) => {
19
+ if (!BACKGROUND_TO_WEB.includes(msg.type))
20
+ return;
21
+ const { type, ...detail } = msg;
22
+ window.dispatchEvent(new CustomEvent(type, { detail }));
23
+ };
24
+ chrome.runtime.onMessage.addListener(handler);
25
+ this.disposeWithMe(() => {
26
+ chrome.runtime.onMessage.removeListener(handler);
27
+ });
28
+ }
29
+ }
30
+ export const contentMessageAdapter = {
31
+ onMessage(type, callback) {
32
+ const handler = (msg) => {
33
+ if (msg.type === type) {
34
+ callback(msg);
35
+ }
36
+ };
37
+ chrome.runtime.onMessage.addListener(handler);
38
+ return () => {
39
+ chrome.runtime.onMessage.removeListener(handler);
40
+ };
41
+ },
42
+ sendMessage(type, message) {
43
+ chrome.runtime.sendMessage({ ...message, type });
44
+ },
45
+ };
46
+ export class ContentRPCClient extends RPCClient {
47
+ constructor() {
48
+ super(contentMessageAdapter);
49
+ }
50
+ }
51
+ export class ContentObservable extends BaseObservable {
52
+ constructor(identifier, key, callback) {
53
+ super(identifier, key, callback, contentMessageAdapter);
54
+ }
55
+ }
@@ -0,0 +1,7 @@
1
+ export declare class Disposable {
2
+ private _isDisposed;
3
+ private _disposeCallbacks;
4
+ dispose(): void;
5
+ isDisposed(): boolean;
6
+ protected disposeWithMe(disposeLike: () => void): void;
7
+ }
@@ -0,0 +1,16 @@
1
+ export class Disposable {
2
+ _isDisposed = false;
3
+ _disposeCallbacks = new Set();
4
+ dispose() {
5
+ if (this._isDisposed)
6
+ return;
7
+ this._isDisposed = true;
8
+ this._disposeCallbacks.forEach(callback => callback());
9
+ }
10
+ isDisposed() {
11
+ return this._isDisposed;
12
+ }
13
+ disposeWithMe(disposeLike) {
14
+ this._disposeCallbacks.add(disposeLike);
15
+ }
16
+ }
package/dist/id.d.ts ADDED
@@ -0,0 +1,12 @@
1
+ /**
2
+ * Identifier 类型,既携带类型信息,又在运行时能唯一标识。
3
+ */
4
+ export interface Identifier<T> {
5
+ key: string;
6
+ __type?: T;
7
+ }
8
+ /**
9
+ * 创建一个 Identifier。
10
+ * @param key 唯一字符串标识
11
+ */
12
+ export declare function createIdentifier<T>(key: string): Identifier<T>;
package/dist/id.js ADDED
@@ -0,0 +1,8 @@
1
+ // shared/utils/identifier.ts
2
+ /**
3
+ * 创建一个 Identifier。
4
+ * @param key 唯一字符串标识
5
+ */
6
+ export function createIdentifier(key) {
7
+ return { key };
8
+ }
@@ -0,0 +1,6 @@
1
+ export * from './background';
2
+ export * from './content';
3
+ export * from './types';
4
+ export * from './id';
5
+ export * from './web';
6
+ export * from './content';
package/dist/index.js ADDED
@@ -0,0 +1,6 @@
1
+ export * from './background';
2
+ export * from './content';
3
+ export * from './types';
4
+ export * from './id';
5
+ export * from './web';
6
+ export * from './content';
@@ -0,0 +1,43 @@
1
+ export interface RpcRequest {
2
+ id: string;
3
+ method: string;
4
+ service: string;
5
+ args: any[];
6
+ }
7
+ export interface RpcResponse {
8
+ id: string;
9
+ result?: any;
10
+ error?: {
11
+ message: string;
12
+ stack?: string;
13
+ name?: string;
14
+ };
15
+ service: string;
16
+ method: string;
17
+ }
18
+ export type RpcHandler = (...args: any[]) => Promise<any> | any;
19
+ export type RpcService = Record<string, RpcHandler>;
20
+ export interface ObservableLike<T> {
21
+ subscribe(next: (value: T) => void): () => void;
22
+ }
23
+ export interface SubjectLike<T> extends ObservableLike<T> {
24
+ next(value: T): void;
25
+ complete(): void;
26
+ }
27
+ export interface RpcObservableUpdateMessage<T> {
28
+ type: string;
29
+ operation: 'next' | 'complete';
30
+ key: string;
31
+ value?: T;
32
+ }
33
+ export interface RpcObservableSubscribeMessage {
34
+ type: string;
35
+ key: string;
36
+ }
37
+ export interface IMessageAdapter {
38
+ onMessage<T>(type: string, callback: (message: T) => void): () => void;
39
+ sendMessage<T>(type: string, message: T): void;
40
+ }
41
+ export interface IDisposable {
42
+ dispose(): void;
43
+ }
package/dist/types.js ADDED
@@ -0,0 +1 @@
1
+ export {};
package/dist/web.d.ts ADDED
@@ -0,0 +1,10 @@
1
+ import { BaseObservable, RPCClient } from "./client";
2
+ import { Identifier } from "./id";
3
+ import { IMessageAdapter } from "./types";
4
+ export declare const webMessageAdapter: IMessageAdapter;
5
+ export declare class WebRPCClient extends RPCClient {
6
+ constructor();
7
+ }
8
+ export declare class WebObservable<T> extends BaseObservable<T> {
9
+ constructor(identifier: Identifier<T>, key: string, callback: (value: T) => void);
10
+ }
package/dist/web.js ADDED
@@ -0,0 +1,25 @@
1
+ import { BaseObservable, RPCClient } from "./client";
2
+ export const webMessageAdapter = {
3
+ onMessage(type, callback) {
4
+ const handler = (event) => {
5
+ callback(event.detail);
6
+ };
7
+ window.addEventListener(type, handler);
8
+ return () => {
9
+ window.removeEventListener(type, handler);
10
+ };
11
+ },
12
+ sendMessage(type, message) {
13
+ window.dispatchEvent(new CustomEvent(type, { detail: message }));
14
+ },
15
+ };
16
+ export class WebRPCClient extends RPCClient {
17
+ constructor() {
18
+ super(webMessageAdapter);
19
+ }
20
+ }
21
+ export class WebObservable extends BaseObservable {
22
+ constructor(identifier, key, callback) {
23
+ super(identifier, key, callback, webMessageAdapter);
24
+ }
25
+ }
package/package.json ADDED
@@ -0,0 +1,27 @@
1
+ {
2
+ "name": "crx-rpc",
3
+ "version": "1.0.0",
4
+ "description": "A lightweight RPC framework for Chrome Extension (background <-> content <-> web)",
5
+ "author": "YourName",
6
+ "license": "MIT",
7
+ "keywords": [
8
+ "chrome-extension",
9
+ "rpc",
10
+ "content-script",
11
+ "background",
12
+ "typescript"
13
+ ],
14
+ "main": "dist/index.js",
15
+ "types": "dist/index.d.ts",
16
+ "scripts": {
17
+ "build": "tsc",
18
+ "watch": "tsc -w",
19
+ "clean": "rm -rf dist",
20
+ "postinstall": "tsc"
21
+ },
22
+ "devDependencies": {
23
+ "@types/chrome": "^0.0.270",
24
+ "@types/node": "^24.3.0",
25
+ "typescript": "^5.2.2"
26
+ }
27
+ }
@@ -0,0 +1,162 @@
1
+ import type { Identifier } from './id';
2
+ import { OBSERVABLE_EVENT, RPC_EVENT_NAME, RPC_RESPONSE_EVENT_NAME, SUBSCRIBABLE_OBSERVABLE, UNSUBSCRIBE_OBSERVABLE } from './const';
3
+ import type { RpcRequest, RpcResponse, RpcService, SubjectLike, RpcObservableUpdateMessage, RpcObservableSubscribeMessage } from './types';
4
+ import { Disposable } from './disposable';
5
+
6
+ export class BackgroundRPC extends Disposable {
7
+ private services: Record<string, RpcService> = {};
8
+
9
+ constructor() {
10
+ super();
11
+ const handler = ((msg: RpcRequest & { type?: string }, sender: chrome.runtime.MessageSender) => {
12
+ if (msg.type !== RPC_EVENT_NAME) return;
13
+ const senderId = sender.tab!.id!;
14
+ const sendResponse = (response: RpcResponse) => {
15
+ chrome.tabs.sendMessage(senderId, {
16
+ ...response,
17
+ type: RPC_RESPONSE_EVENT_NAME
18
+ });
19
+ };
20
+
21
+ const { id, method, args, service } = msg;
22
+ const serviceInstance = this.services[service];
23
+
24
+ if (!serviceInstance) {
25
+ const resp: RpcResponse = {
26
+ id,
27
+ error: { message: `Unknown service: ${service}` },
28
+ service,
29
+ method,
30
+ };
31
+ sendResponse(resp);
32
+ return true;
33
+ }
34
+
35
+ if (!(method in serviceInstance)) {
36
+ const resp: RpcResponse = {
37
+ id,
38
+ error: { message: `Unknown method: ${method}` },
39
+ service,
40
+ method,
41
+ };
42
+ sendResponse(resp);
43
+ return true;
44
+ }
45
+
46
+ Promise.resolve()
47
+ .then(() => serviceInstance[method](...args))
48
+ .then((result) => sendResponse({
49
+ id,
50
+ result,
51
+ service,
52
+ method
53
+ }))
54
+ .catch((err) => sendResponse({
55
+ id,
56
+ error: {
57
+ message: err.message,
58
+ stack: err.stack,
59
+ name: err.name
60
+ },
61
+ service,
62
+ method
63
+ }));
64
+
65
+ return true; // 异步 sendResponse
66
+ });
67
+
68
+ chrome.runtime.onMessage.addListener(handler);
69
+ this.disposeWithMe(() => {
70
+ chrome.runtime.onMessage.removeListener(handler);
71
+ });
72
+ }
73
+
74
+ register<T>(service: Identifier<T>, serviceInstance: T) {
75
+ this.services[service.key] = serviceInstance as unknown as RpcService;
76
+ }
77
+ }
78
+
79
+ export class RemoteSubject<T> extends Disposable implements SubjectLike<T> {
80
+ private completed = false;
81
+
82
+ private get _finalKey() {
83
+ return `${this.identifier.key}-${this._key}`;
84
+ }
85
+
86
+ private senders = new Set<number>();
87
+
88
+ constructor(
89
+ private identifier: Identifier<T>,
90
+ private _key: string,
91
+ private initialValue: T,
92
+ ) {
93
+ super();
94
+ // 初始化时立即广播一次
95
+ const handleMessage = (msg: RpcObservableSubscribeMessage, sender: chrome.runtime.MessageSender) => {
96
+ const senderId = sender.tab!.id!;
97
+ if (!senderId) return;
98
+
99
+ if (msg.type === SUBSCRIBABLE_OBSERVABLE) {
100
+ const { key } = msg;
101
+ if (key === this._finalKey) {
102
+ this.senders.add(senderId);
103
+ chrome.tabs.sendMessage(senderId, {
104
+ operation: 'next',
105
+ key: this._finalKey,
106
+ value: this.initialValue,
107
+ });
108
+ }
109
+ }
110
+
111
+ if (msg.type === UNSUBSCRIBE_OBSERVABLE) {
112
+ const { key } = msg;
113
+ if (key === this._finalKey) {
114
+ this.senders.delete(senderId);
115
+ }
116
+ }
117
+ }
118
+ chrome.runtime.onMessage.addListener(handleMessage);
119
+ this.disposeWithMe(() => {
120
+ chrome.runtime.onMessage.removeListener(handleMessage);
121
+ });
122
+
123
+ const handleRemove = (tabId: number) => {
124
+ this.senders.delete(tabId);
125
+ };
126
+ chrome.tabs.onRemoved.addListener(handleRemove);
127
+ this.disposeWithMe(() => {
128
+ chrome.tabs.onRemoved.removeListener(handleRemove);
129
+ });
130
+ }
131
+
132
+ private _sendMessage(message: RpcObservableUpdateMessage<any>) {
133
+ chrome.runtime.sendMessage(message);
134
+ this.senders.forEach(senderId => {
135
+ chrome.tabs.sendMessage(senderId, message);
136
+ });
137
+ }
138
+
139
+ next(value: T): void {
140
+ if (this.completed) return;
141
+ this._sendMessage({
142
+ operation: 'next',
143
+ key: this._finalKey,
144
+ value,
145
+ type: OBSERVABLE_EVENT
146
+ });
147
+ }
148
+
149
+ complete(): void {
150
+ if (this.completed) return;
151
+ this.completed = true;
152
+ this._sendMessage({
153
+ operation: 'complete',
154
+ key: this._finalKey,
155
+ type: OBSERVABLE_EVENT
156
+ });
157
+ }
158
+
159
+ subscribe(): () => void {
160
+ throw new Error('RemoteSubject should not be subscribed locally.');
161
+ }
162
+ }
package/src/client.ts ADDED
@@ -0,0 +1,110 @@
1
+ import { OBSERVABLE_EVENT, RPC_EVENT_NAME, RPC_RESPONSE_EVENT_NAME, UNSUBSCRIBE_OBSERVABLE } from './const';
2
+ import type { RpcRequest, RpcResponse, RpcObservableUpdateMessage, IMessageAdapter } from './types';
3
+ import type { Identifier } from './id';
4
+ import { Disposable } from './disposable';
5
+
6
+ // 类型工具:提取函数类型的参数和返回值类型
7
+ type FunctionArgs<T> = T extends (...args: infer A) => any ? A : never;
8
+ type FunctionReturnType<T> = T extends (...args: any[]) => infer R ? R : never;
9
+
10
+ // 类型工具:将服务接口转换为客户端代理类型
11
+ type ServiceProxy<T> = {
12
+ [K in keyof T]: T[K] extends (...args: any[]) => any
13
+ ? (...args: FunctionArgs<T[K]>) => Promise<Awaited<FunctionReturnType<T[K]>>>
14
+ : never;
15
+ };
16
+
17
+ export class RPCClient extends Disposable {
18
+ private pending: Map<string, { resolve: Function; reject: Function }> = new Map();
19
+
20
+ constructor(
21
+ private messageAdapter: IMessageAdapter
22
+ ) {
23
+ super();
24
+ this.disposeWithMe(messageAdapter.onMessage<RpcResponse>(RPC_RESPONSE_EVENT_NAME, (event: RpcResponse) => {
25
+ const { id, result, error } = event as RpcResponse;
26
+ const promise = this.pending.get(id);
27
+ if (!promise) return;
28
+
29
+ this.pending.delete(id);
30
+
31
+ if (error) {
32
+ const err = new Error(error.message);
33
+ err.name = error.name || 'RPCError';
34
+ err.stack = error.stack;
35
+ promise.reject(err);
36
+ } else {
37
+ promise.resolve(result);
38
+ }
39
+ }));
40
+ }
41
+
42
+ call<T = any>(service: string, method: string, args: any[]): Promise<T> {
43
+ const id = crypto.randomUUID();
44
+ return new Promise<T>((resolve, reject) => {
45
+ this.pending.set(id, { resolve, reject });
46
+ const requestParam: RpcRequest = {
47
+ method,
48
+ args,
49
+ id,
50
+ service,
51
+ };
52
+ this.messageAdapter.sendMessage(RPC_EVENT_NAME, requestParam);
53
+ });
54
+ }
55
+
56
+ createWebRPCService<T>(serviceIdentifier: Identifier<T>): ServiceProxy<T> {
57
+ const serviceKey = serviceIdentifier.key;
58
+
59
+ // 创建代理对象,拦截方法调用
60
+ return new Proxy({} as ServiceProxy<T>, {
61
+ get: (target, prop: string | symbol) => {
62
+ if (typeof prop === 'string') {
63
+ // 返回一个代理函数
64
+ return (...args: any[]) => {
65
+ return this.call(serviceKey, prop, args);
66
+ };
67
+ }
68
+ return (target as any)[prop];
69
+ },
70
+ });
71
+ }
72
+ }
73
+
74
+ export class BaseObservable<T> extends Disposable {
75
+ private listeners = new Set<(value: T) => void>();
76
+ private completed = false;
77
+
78
+ private get _finalKey() {
79
+ return `${this.identifier.key}-${this.key}`;
80
+ }
81
+
82
+ constructor(
83
+ private identifier: Identifier<T>,
84
+ private key: string,
85
+ private _callback: (value: T) => void,
86
+ private _adapter: IMessageAdapter
87
+ ) {
88
+ super();
89
+ this.disposeWithMe(this._adapter.onMessage(OBSERVABLE_EVENT, (event: any) => {
90
+ const msg = event.detail as RpcObservableUpdateMessage<T>;
91
+ if (msg.key !== this._finalKey) return;
92
+
93
+ if (msg.operation === 'next' && !this.completed && msg.value) {
94
+ this._callback(msg.value);
95
+ }
96
+
97
+ if (msg.operation === 'complete') {
98
+ this.completed = true;
99
+ this.listeners.clear();
100
+ }
101
+ }));
102
+
103
+ this._adapter.sendMessage(OBSERVABLE_EVENT, { key: this._finalKey });
104
+ }
105
+
106
+ unsubscribe(): void {
107
+ this._adapter.sendMessage(UNSUBSCRIBE_OBSERVABLE, { key: this._finalKey });
108
+ }
109
+ }
110
+
package/src/const.ts ADDED
@@ -0,0 +1,6 @@
1
+ export const RPC_EVENT_NAME = '__RPC_CALL_CLIPSHEET_AWESOME__';
2
+ export const RPC_RESPONSE_EVENT_NAME = '__RPC_RESPONSE_CLIPSHEET_AWESOME__';
3
+
4
+ export const SUBSCRIBABLE_OBSERVABLE = '__SUBSCRIBABLE_OBSERVABLE__';
5
+ export const UNSUBSCRIBE_OBSERVABLE = '__UNSUBSCRIBE_OBSERVABLE__';
6
+ export const OBSERVABLE_EVENT = '__OBSERVABLE_EVENT__';