@livequery/rpc 2.0.100 → 2.0.102
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 +43 -23
- package/dist/ExtensionChannel.d.ts +7 -0
- package/dist/ExtensionChannel.d.ts.map +1 -0
- package/dist/ExtensionChannel.js +32 -0
- package/dist/ExtensionChannel.js.map +1 -0
- package/dist/index.d.ts +1 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1 -0
- package/dist/index.js.map +1 -1
- package/package.json +6 -1
package/README.md
CHANGED
|
@@ -1,6 +1,10 @@
|
|
|
1
1
|
# @livequery/rpc
|
|
2
2
|
|
|
3
|
-
Lightweight RxJS-based RPC utilities for exposing services from a `SharedWorker` and consuming them from the main thread with typed proxies.
|
|
3
|
+
Lightweight RxJS-based RPC utilities for exposing services from a `SharedWorker` or an extension background runtime and consuming them from the main thread with typed proxies.
|
|
4
|
+
|
|
5
|
+
## AI Agent Notes
|
|
6
|
+
|
|
7
|
+
Repository-specific guidance for coding agents lives in `AGENTS.md`.
|
|
4
8
|
|
|
5
9
|
This package is built for a simple model:
|
|
6
10
|
|
|
@@ -25,6 +29,7 @@ bun add @livequery/rpc rxjs
|
|
|
25
29
|
## What It Exports
|
|
26
30
|
|
|
27
31
|
```ts
|
|
32
|
+
export * from "./ExtensionChannel"
|
|
28
33
|
export * from "./RpcChannel"
|
|
29
34
|
export * from "./SharedWorkerChannel"
|
|
30
35
|
export * from "./ServiceLinker"
|
|
@@ -45,6 +50,36 @@ ServiceLinker --(RpcMessage)--> SharedWorkerChannel --> WorkerManager --> your s
|
|
|
45
50
|
|--------------------(response stream)-----------------------|
|
|
46
51
|
```
|
|
47
52
|
|
|
53
|
+
For extension Manifest V3, the same flow can run over `ExtensionChannel` and `chrome.runtime` messaging instead of `SharedWorker`.
|
|
54
|
+
|
|
55
|
+
## Extension MV3 Example
|
|
56
|
+
|
|
57
|
+
### Background service worker
|
|
58
|
+
|
|
59
|
+
```ts
|
|
60
|
+
import { ExtensionChannel, WorkerManager } from "@livequery/rpc"
|
|
61
|
+
import { CounterService } from "./CounterService"
|
|
62
|
+
|
|
63
|
+
const channel = new ExtensionChannel()
|
|
64
|
+
const manager = new WorkerManager(channel)
|
|
65
|
+
|
|
66
|
+
manager.exposeService("counter", new CounterService())
|
|
67
|
+
```
|
|
68
|
+
|
|
69
|
+
### Popup, options page, or content script
|
|
70
|
+
|
|
71
|
+
```ts
|
|
72
|
+
import { ExtensionChannel, ServiceLinker, type WorkerService } from "@livequery/rpc"
|
|
73
|
+
import type { CounterService } from "./CounterService"
|
|
74
|
+
|
|
75
|
+
const channel = new ExtensionChannel()
|
|
76
|
+
const linker = new ServiceLinker(channel)
|
|
77
|
+
|
|
78
|
+
const counter = linker.linkService<WorkerService<CounterService>>("counter")
|
|
79
|
+
```
|
|
80
|
+
|
|
81
|
+
`ExtensionChannel` is a transport for extension contexts such as a background service worker, popup, options page, or content script. Its current implementation listens on `chrome.runtime.onMessage` and sends messages with `chrome.runtime.sendMessage`.
|
|
82
|
+
|
|
48
83
|
## When To Use This Package
|
|
49
84
|
|
|
50
85
|
Use it when you want to:
|
|
@@ -157,7 +192,7 @@ In practice:
|
|
|
157
192
|
|
|
158
193
|
## BehaviorSubject Mirroring
|
|
159
194
|
|
|
160
|
-
If your service exposes a
|
|
195
|
+
If your service exposes a `BehaviorSubject` property, the client can treat it like remote reactive state.
|
|
161
196
|
|
|
162
197
|
This is what allows a worker-side `BehaviorSubject` to feel usable on the client:
|
|
163
198
|
|
|
@@ -177,24 +212,12 @@ settings.theme.subscribe((theme) => {
|
|
|
177
212
|
|
|
178
213
|
Notes:
|
|
179
214
|
|
|
180
|
-
-
|
|
181
|
-
-
|
|
215
|
+
- `ServiceLinker` special-cases only `subscribe()`, `pipe()`, and `getValue()` on remote properties
|
|
216
|
+
- updates are fetched by subscribing to the remote property path, not through a separate initialization API
|
|
217
|
+
- `getValue()` reads the locally cached value, so subscribe first if you need the current worker value to be populated locally
|
|
182
218
|
- this pattern is designed around `BehaviorSubject`-like objects
|
|
183
219
|
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
`ServiceLinker` exposes a helper for waiting until all linked services have loaded their initial state.
|
|
187
|
-
|
|
188
|
-
```ts
|
|
189
|
-
const counter = linker.linkService<WorkerService<CounterService>>("counter")
|
|
190
|
-
const settings = linker.linkService<WorkerService<SettingsService>>("settings")
|
|
191
|
-
|
|
192
|
-
ServiceLinker.ready$({ counter, settings }).subscribe((ready) => {
|
|
193
|
-
if (ready) {
|
|
194
|
-
console.log("all services initialized")
|
|
195
|
-
}
|
|
196
|
-
})
|
|
197
|
-
```
|
|
220
|
+
There is currently no built-in readiness helper in `ServiceLinker`.
|
|
198
221
|
|
|
199
222
|
## Nested Access
|
|
200
223
|
|
|
@@ -310,7 +333,6 @@ Creates and caches client-side proxies.
|
|
|
310
333
|
class ServiceLinker {
|
|
311
334
|
constructor(channel: RpcChannel)
|
|
312
335
|
linkService<T>(name: string): WorkerService<T>
|
|
313
|
-
static ready$(services: Record<string, any>): Observable<boolean>
|
|
314
336
|
}
|
|
315
337
|
```
|
|
316
338
|
|
|
@@ -320,7 +342,7 @@ Behavior:
|
|
|
320
342
|
- assigns incrementing request ids
|
|
321
343
|
- returns an `Observable` that is also `PromiseLike`
|
|
322
344
|
- sends cancellation when a request is unsubscribed early
|
|
323
|
-
-
|
|
345
|
+
- special-cases `subscribe`, `pipe`, and `getValue` for remote observable-like properties
|
|
324
346
|
|
|
325
347
|
### `WorkerService<T>`
|
|
326
348
|
|
|
@@ -330,7 +352,7 @@ Rules:
|
|
|
330
352
|
|
|
331
353
|
- `BehaviorSubject<T>` stays `BehaviorSubject<T>`
|
|
332
354
|
- `Observable<T>` stays `Observable<T>`
|
|
333
|
-
- methods become async call signatures
|
|
355
|
+
- methods become async call signatures unless their awaited return type is already an `Observable`
|
|
334
356
|
|
|
335
357
|
Example:
|
|
336
358
|
|
|
@@ -422,8 +444,6 @@ bun run build
|
|
|
422
444
|
Other scripts:
|
|
423
445
|
|
|
424
446
|
- `bun run clean`
|
|
425
|
-
- `bun run build:js`
|
|
426
|
-
- `bun run build:types`
|
|
427
447
|
- `bun run build:watch`
|
|
428
448
|
|
|
429
449
|
## Package Output
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ExtensionChannel.d.ts","sourceRoot":"","sources":["../src/ExtensionChannel.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,KAAK,UAAU,EAAE,MAAM,iBAAiB,CAAA;AA4B7D,qBAAa,gBAAiB,SAAQ,UAAU;;;IAqB5C,IAAI,CAAC,OAAO,EAAE,UAAU,GAAG,IAAI;CAGlC"}
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
import { RpcChannel } from "./RpcChannel.js";
|
|
2
|
+
const runtime = (() => {
|
|
3
|
+
const runtime = globalThis.chrome?.runtime;
|
|
4
|
+
if (!runtime) {
|
|
5
|
+
throw new Error("chrome.runtime is not available");
|
|
6
|
+
}
|
|
7
|
+
return runtime;
|
|
8
|
+
})();
|
|
9
|
+
function isRpcMessage(value) {
|
|
10
|
+
return !!value && typeof value === "object" && "id" in value;
|
|
11
|
+
}
|
|
12
|
+
export class ExtensionChannel extends RpcChannel {
|
|
13
|
+
constructor() {
|
|
14
|
+
super();
|
|
15
|
+
runtime.onMessage.addListener(this.#onMessage);
|
|
16
|
+
}
|
|
17
|
+
#onMessage = (message) => {
|
|
18
|
+
if (!isRpcMessage(message))
|
|
19
|
+
return;
|
|
20
|
+
const respond = (response) => {
|
|
21
|
+
runtime.sendMessage({
|
|
22
|
+
id: message.id,
|
|
23
|
+
response
|
|
24
|
+
});
|
|
25
|
+
};
|
|
26
|
+
this.next({ ...message, respond });
|
|
27
|
+
};
|
|
28
|
+
send(message) {
|
|
29
|
+
runtime.sendMessage(message);
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
//# sourceMappingURL=ExtensionChannel.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ExtensionChannel.js","sourceRoot":"","sources":["../src/ExtensionChannel.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAmB,MAAM,iBAAiB,CAAA;AAY7D,MAAM,OAAO,GAAG,CAAC,GAAG,EAAE;IAClB,MAAM,OAAO,GAAI,UAEf,CAAC,MAAM,EAAE,OAAO,CAAA;IAElB,IAAI,CAAC,OAAO,EAAE,CAAC;QACX,MAAM,IAAI,KAAK,CAAC,iCAAiC,CAAC,CAAA;IACtD,CAAC;IAED,OAAO,OAAO,CAAA;AAClB,CAAC,CAAC,EAAE,CAAA;AAEJ,SAAS,YAAY,CAAC,KAAc;IAChC,OAAO,CAAC,CAAC,KAAK,IAAI,OAAO,KAAK,KAAK,QAAQ,IAAI,IAAI,IAAI,KAAK,CAAA;AAChE,CAAC;AAED,MAAM,OAAO,gBAAiB,SAAQ,UAAU;IAE5C;QACI,KAAK,EAAE,CAAA;QAEP,OAAO,CAAC,SAAS,CAAC,WAAW,CAAC,IAAI,CAAC,UAAU,CAAC,CAAA;IAClD,CAAC;IAED,UAAU,GAAG,CAAC,OAAgB,EAAE,EAAE;QAC9B,IAAI,CAAC,YAAY,CAAC,OAAO,CAAC;YAAE,OAAM;QAElC,MAAM,OAAO,GAAG,CAAC,QAAgC,EAAE,EAAE;YACjD,OAAO,CAAC,WAAW,CAAC;gBAChB,EAAE,EAAE,OAAO,CAAC,EAAE;gBACd,QAAQ;aACU,CAAC,CAAA;QAC3B,CAAC,CAAA;QAED,IAAI,CAAC,IAAI,CAAC,EAAE,GAAG,OAAO,EAAE,OAAO,EAAE,CAAC,CAAA;IACtC,CAAC,CAAA;IAED,IAAI,CAAC,OAAmB;QACpB,OAAO,CAAC,WAAW,CAAC,OAAO,CAAC,CAAA;IAChC,CAAC;CACJ"}
|
package/dist/index.d.ts
CHANGED
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,iBAAiB,CAAA;AAC/B,cAAc,0BAA0B,CAAA;AACxC,cAAc,oBAAoB,CAAA;AAClC,cAAc,oBAAoB,CAAA;AAClC,cAAc,oBAAoB,CAAA;AAClC,cAAc,uBAAuB,CAAA;AACrC,cAAc,6BAA6B,CAAA;AAC3C,cAAc,gBAAgB,CAAA"}
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,iBAAiB,CAAA;AAC/B,cAAc,uBAAuB,CAAA;AACrC,cAAc,0BAA0B,CAAA;AACxC,cAAc,oBAAoB,CAAA;AAClC,cAAc,oBAAoB,CAAA;AAClC,cAAc,oBAAoB,CAAA;AAClC,cAAc,uBAAuB,CAAA;AACrC,cAAc,6BAA6B,CAAA;AAC3C,cAAc,gBAAgB,CAAA"}
|
package/dist/index.js
CHANGED
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,iBAAiB,CAAA;AAC/B,cAAc,0BAA0B,CAAA;AACxC,cAAc,oBAAoB,CAAA;AAClC,cAAc,oBAAoB,CAAA;AAClC,cAAc,oBAAoB,CAAA;AAClC,cAAc,uBAAuB,CAAA;AACrC,cAAc,6BAA6B,CAAA;AAC3C,cAAc,gBAAgB,CAAA"}
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,iBAAiB,CAAA;AAC/B,cAAc,uBAAuB,CAAA;AACrC,cAAc,0BAA0B,CAAA;AACxC,cAAc,oBAAoB,CAAA;AAClC,cAAc,oBAAoB,CAAA;AAClC,cAAc,oBAAoB,CAAA;AAClC,cAAc,uBAAuB,CAAA;AACrC,cAAc,6BAA6B,CAAA;AAC3C,cAAc,gBAAgB,CAAA"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@livequery/rpc",
|
|
3
|
-
"version": "2.0.
|
|
3
|
+
"version": "2.0.102",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"main": "./dist/index.js",
|
|
6
6
|
"module": "./dist/index.js",
|
|
@@ -21,6 +21,11 @@
|
|
|
21
21
|
"import": "./dist/index.js",
|
|
22
22
|
"default": "./dist/index.js"
|
|
23
23
|
},
|
|
24
|
+
"./ExtensionChannel": {
|
|
25
|
+
"types": "./dist/ExtensionChannel.d.ts",
|
|
26
|
+
"import": "./dist/ExtensionChannel.js",
|
|
27
|
+
"default": "./dist/ExtensionChannel.js"
|
|
28
|
+
},
|
|
24
29
|
"./RpcChannel": {
|
|
25
30
|
"types": "./dist/RpcChannel.d.ts",
|
|
26
31
|
"import": "./dist/RpcChannel.js",
|