@statewalker/webrun-http-browser 0.5.0 → 0.6.2
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 +127 -5
- package/dist/index.js +92 -20
- package/dist/relay/index-sw.d.ts +86 -1
- package/dist/relay/index-sw.d.ts.map +1 -1
- package/dist/relay/index.d.ts +9 -2
- package/dist/relay/index.d.ts.map +1 -1
- package/dist/relay/mount-table.d.ts +48 -0
- package/dist/relay/mount-table.d.ts.map +1 -0
- package/dist/relay/split-service-url.d.ts.map +1 -1
- package/dist/relay-sw.js +275 -49
- package/dist/relay-worker.d.ts +20 -0
- package/dist/relay-worker.d.ts.map +1 -0
- package/dist/relay-worker.js +1899 -0
- package/dist/sw/sw-dispatcher.d.ts +8 -0
- package/dist/sw/sw-dispatcher.d.ts.map +1 -1
- package/dist/sw.js +10 -1
- package/package.json +19 -10
- package/src/relay/index-sw.ts +288 -37
- package/src/relay/index.ts +60 -4
- package/src/relay/mount-table.ts +115 -0
- package/src/relay/split-service-url.ts +73 -13
- package/src/relay-sw.ts +11 -3
- package/src/relay-worker.ts +20 -0
- package/src/sw/sw-dispatcher.ts +10 -1
- package/public-relay/heartbeat.js +0 -31
package/README.md
CHANGED
|
@@ -49,7 +49,8 @@ npm install @statewalker/webrun-http-browser
|
|
|
49
49
|
| --- | --- |
|
|
50
50
|
| `@statewalker/webrun-http-browser` | Page-side relay API: `newRemoteRelayChannel`, `initHttpService`, `callHttpService`, `splitServiceUrl`, `initServiceWorker`, `newServiceWorkerPort`, `getRelayWindowMessageHandler`; the MessagePort call primitives (`callChannel`, `handleChannelCalls`, `newInvokationChannel`, `sendStream`, `handleStreams`, `newRegistry`); plus everything re-exported from `@statewalker/webrun-http-streams` (`HttpError`, the client/server stubs), `@statewalker/webrun-streams` (stream and error helpers) and the `MessageTarget` family from `@statewalker/webrun-rpc` |
|
|
51
51
|
| `@statewalker/webrun-http-browser/sw` | Same-origin adapter classes: `SwHttpAdapter` (page), `SwHttpDispatcher` (SW), `startHttpDispatcher` bootstrap; `start()` options `timeout` and `reloadIfUncontrolled` |
|
|
52
|
-
| `@statewalker/webrun-http-browser/relay-sw` | IIFE bundle of the relay SW runtime — load via `importScripts` from a loader script in your relay origin |
|
|
52
|
+
| `@statewalker/webrun-http-browser/relay-sw` | IIFE bundle of the relay SW runtime — load via `importScripts` from a loader script in your relay origin. No declarations: it takes its options from `self.RELAY_OPTIONS` |
|
|
53
|
+
| `@statewalker/webrun-http-browser/relay-worker` | The same runtime as a typed ES module, for a host that bundles its own relay worker: `startRelayServiceWorker(self, options)`, plus `RelayServiceWorkerOptions` and `MountSpec` to type them (including a hand-written `self.RELAY_OPTIONS`) |
|
|
53
54
|
| `@statewalker/webrun-http-browser/sw-worker` | IIFE bundle of the same-origin SW runtime — ditto, for same-origin apps |
|
|
54
55
|
|
|
55
56
|
## Examples
|
|
@@ -101,6 +102,125 @@ const res = await callHttpService(
|
|
|
101
102
|
serving a mini site; [`demo/demo-2.html`](./demo/demo-2.html) pipes a
|
|
102
103
|
local-disk folder (File System Access API) through it.
|
|
103
104
|
|
|
105
|
+
### Mounting a service at a path
|
|
106
|
+
|
|
107
|
+
A service can claim a path prefix instead of living at `/~<key>/`. Both the
|
|
108
|
+
key and the path are the caller's, and several services can share **one**
|
|
109
|
+
relay connection — the shape mounts exist for is an app at the origin root
|
|
110
|
+
and, say, a gateway one level down, both reachable through the same iframe:
|
|
111
|
+
|
|
112
|
+
```ts
|
|
113
|
+
const connection = await newRemoteRelayChannel(/* … */);
|
|
114
|
+
|
|
115
|
+
await initHttpService(appHandler, { key: "app", path: "/", port: connection.port });
|
|
116
|
+
await initHttpService(meshHandler, { key: "mesh", path: "/peers/", port: connection.port });
|
|
117
|
+
```
|
|
118
|
+
|
|
119
|
+
A `CONNECT` is routed to the service named in its `key`, so the two never see
|
|
120
|
+
each other's calls even though they share one port. (Earlier builds routed
|
|
121
|
+
every `CONNECT` on a connection to every registered service, which collided
|
|
122
|
+
whenever more than one service shared a port — fixed before this shipped.)
|
|
123
|
+
|
|
124
|
+
The worker routes by the longest matching path prefix, so a catch-all at `/`
|
|
125
|
+
does not shadow `/peers/`, and registration order does not matter. A service
|
|
126
|
+
registered with no `path` is reachable at `/~<key>/`, exactly as before —
|
|
127
|
+
unless the host declared that key in `mounts`, in which case the host's mount
|
|
128
|
+
stands and the page need not repeat it.
|
|
129
|
+
|
|
130
|
+
**A request that matches no mount is not the relay's** — the worker does not
|
|
131
|
+
answer it at all, so the browser performs it exactly as it would with no
|
|
132
|
+
worker installed. That is what lets a host serve its own files from the same
|
|
133
|
+
origin, and it is why a root mount needs `exclude`.
|
|
134
|
+
|
|
135
|
+
**The matched prefix is NOT stripped.** A handler mounted at `/peers/`
|
|
136
|
+
receives `/peers/12D3Koo/llm`, not `/12D3Koo/llm` — the request reaches it
|
|
137
|
+
with the path the browser asked for, whichever mount matched. A handler that
|
|
138
|
+
wants to route relative to its mount keeps its own `basePath` and strips the
|
|
139
|
+
prefix itself.
|
|
140
|
+
|
|
141
|
+
These options are read by `startRelayServiceWorker`, which a host that
|
|
142
|
+
bundles its own relay worker imports from
|
|
143
|
+
`@statewalker/webrun-http-browser/relay-worker` and calls directly (see the
|
|
144
|
+
options table below for the prebuilt-bundle equivalent):
|
|
145
|
+
|
|
146
|
+
```ts
|
|
147
|
+
import { startRelayServiceWorker } from "@statewalker/webrun-http-browser/relay-worker";
|
|
148
|
+
|
|
149
|
+
startRelayServiceWorker(self, {
|
|
150
|
+
exclude: (url) =>
|
|
151
|
+
url.pathname === "/index.html" ||
|
|
152
|
+
url.pathname === "/relay.html" ||
|
|
153
|
+
url.pathname === "/relay-sw.js",
|
|
154
|
+
takeover: "first-wins",
|
|
155
|
+
canRegister: (client, _key) => new URL(client.url).pathname === "/relay.html",
|
|
156
|
+
decorateResponse: (response) => withMyHeaders(response),
|
|
157
|
+
});
|
|
158
|
+
```
|
|
159
|
+
|
|
160
|
+
> **Mounting at `/` — set `takeover: "first-wins"` and `canRegister`.**
|
|
161
|
+
> The default is `takeover: "last-wins"` with no `canRegister`, which is what
|
|
162
|
+
> the relay has always done: the last page to REGISTER a key gets it. Before
|
|
163
|
+
> mounts the worst that bought a rogue or buggy same-origin page was
|
|
164
|
+
> `/~<key>/`; with mounts it can claim the **origin root**, and the mount is
|
|
165
|
+
> persisted in IndexedDB, so it outlives the page and every worker restart.
|
|
166
|
+
> On an origin where more than the host's own page can reach the relay,
|
|
167
|
+
> `takeover: "first-wins"` keeps a live holder's key and `canRegister` says
|
|
168
|
+
> which client may ask for it — set both, together, for any mount at `/`.
|
|
169
|
+
|
|
170
|
+
A root mount claims *every* path under the worker's scope, including the
|
|
171
|
+
host's own navigation. If `exclude` only covers the relay page and its
|
|
172
|
+
worker script, a reload requests the host's own entry page — say
|
|
173
|
+
`/index.html` — through the mount too, the mount has no handler for it, and
|
|
174
|
+
the origin cannot come back. `exclude` needs three things, always: the relay
|
|
175
|
+
page, the worker script, and the host's own entry page. That third one is
|
|
176
|
+
easy to miss because nothing fails until the first reload.
|
|
177
|
+
|
|
178
|
+
An excluded page is one the worker does not answer, and in Firefox such a
|
|
179
|
+
page can load **uncontrolled** even while the worker is running — then its
|
|
180
|
+
own `fetch()` never reaches the worker and its mounts look dead. The remedy
|
|
181
|
+
is the one this package already ships for that case: call
|
|
182
|
+
`awaitServiceWorkerControl(registration)` (exported from the package root)
|
|
183
|
+
before relying on `fetch()` from an excluded page. A page *served by* a mount
|
|
184
|
+
is a navigation the worker answers, so it is controlled from its first byte
|
|
185
|
+
and needs nothing.
|
|
186
|
+
|
|
187
|
+
#### `self.RELAY_OPTIONS` — options for the prebuilt worker
|
|
188
|
+
|
|
189
|
+
`dist/relay-sw.js` is an IIFE loaded via classic `importScripts`, so a host
|
|
190
|
+
that uses the shipped worker (rather than building its own from
|
|
191
|
+
`startRelayServiceWorker`) cannot pass options as arguments. It reads them
|
|
192
|
+
instead from `self.RELAY_OPTIONS`, which the host's own tiny worker script
|
|
193
|
+
sets *before* importing the bundle:
|
|
194
|
+
|
|
195
|
+
```js
|
|
196
|
+
// relay-sw.js — served next to your relay page.
|
|
197
|
+
self.RELAY_OPTIONS = {
|
|
198
|
+
exclude: (url) => url.pathname === "/index.html" || url.pathname === "/relay.html" || url.pathname === "/relay-sw.js",
|
|
199
|
+
takeover: "first-wins",
|
|
200
|
+
};
|
|
201
|
+
importScripts("/path/to/node_modules/@statewalker/webrun-http-browser/dist/relay-sw.js");
|
|
202
|
+
```
|
|
203
|
+
|
|
204
|
+
This is the only way a prebuilt-worker host reaches `exclude`, `takeover`,
|
|
205
|
+
`canRegister` or `decorateResponse` — omit it and the worker boots with `{}`,
|
|
206
|
+
exactly as it did before mounts. The bundle ships no declarations, so to type
|
|
207
|
+
that object (in a TypeScript loader script, or to check it before shipping)
|
|
208
|
+
import the type from the runtime entry:
|
|
209
|
+
|
|
210
|
+
```ts
|
|
211
|
+
import type { RelayServiceWorkerOptions } from "@statewalker/webrun-http-browser/relay-worker";
|
|
212
|
+
|
|
213
|
+
declare const self: ServiceWorkerGlobalScope & { RELAY_OPTIONS?: RelayServiceWorkerOptions };
|
|
214
|
+
```
|
|
215
|
+
|
|
216
|
+
| Option | Default | What it does |
|
|
217
|
+
| --- | --- | --- |
|
|
218
|
+
| `mounts` | none | A fixed table, for a host that knows its services at build time. Each entry is `{ key, path? , match? }`. A key declared here is the host's: a page's REGISTER or UNREGISTER for the same key never replaces or removes it, so the page can register with no `path` of its own. |
|
|
219
|
+
| `exclude` | none | Paths the relay never claims — neither through the table nor through the `/~<key>/` spelling. Checked first. |
|
|
220
|
+
| `canRegister` | everyone | Refuse a registration from the wrong page. |
|
|
221
|
+
| `takeover` | `"last-wins"` | `"first-wins"` keeps a live holder's key. |
|
|
222
|
+
| `decorateResponse` | none | Stamp headers on responses the relay makes; not applied to network fetches. |
|
|
223
|
+
|
|
104
224
|
### Same-origin mode
|
|
105
225
|
|
|
106
226
|
Your page registers its own SW, handlers are local to the page:
|
|
@@ -277,13 +397,15 @@ imports keep working after those extractions. Its own surface is below.
|
|
|
277
397
|
| `newRemoteRelayChannel(opts?)` | function | Embeds the hidden relay iframe, handshakes a `MessageChannel`, resolves a `RemoteRelayChannel`. |
|
|
278
398
|
| `RemoteRelayChannelOptions` | interface | `baseUrl`, `url`, `container` — where the relay lives and what to append the iframe to. |
|
|
279
399
|
| `RemoteRelayChannel` | interface | `{ baseUrl, port, close() }`. |
|
|
280
|
-
| `initHttpService(handler, opts)` | function | Registers `handler` as the server for a service `key` on the relay
|
|
400
|
+
| `initHttpService(handler, opts)` | function | Registers `handler` as the server for a service `key` on the relay, optionally mounted at `path`. Several services may share one `port`. Returns a cleanup. |
|
|
281
401
|
| `callHttpService(request, opts)` | function | Sends a `Request` to the service under `key`; resolves its `Response`. |
|
|
282
|
-
| `ServiceOptions` | interface | `{ key: string; port: MessageTarget }` — shared by the two above. |
|
|
402
|
+
| `ServiceOptions` | interface | `{ key: string; path?: string; port: MessageTarget }` — shared by the two above. `path` mounts the service (see [Mounting a service at a path](#mounting-a-service-at-a-path)); omitted, it stays at `/~<key>/`. |
|
|
283
403
|
| `getRelayWindowMessageHandler(opts?)` | function | The `window.onmessage` handler that runs *inside* the relay iframe. |
|
|
284
404
|
| `RelayWindowHandlerOptions` | interface | `swUrl`, `scopeUrl` for that handler. |
|
|
285
|
-
| `splitServiceUrl(url, separator?)` | function | Splits a relay URL into service key + remaining path (default separator `~`). |
|
|
405
|
+
| `splitServiceUrl(url, separator?)` | function | Splits a relay URL into service key + remaining path (default separator `~`); anchored to the pathname, so a query string like `?q=~foo` is never read as a service. |
|
|
286
406
|
| `SplitServiceUrl` | interface | Its result shape. |
|
|
407
|
+
| `startRelayServiceWorker(self, opts?)` | function | The SW side of the relay: routes `fetch` to the client that registered a mount, and answers `REGISTER`/`UNREGISTER`/`CONNECT`. Not re-exported from the package root — it is what the prebuilt `dist/relay-sw.js` calls internally; see [`self.RELAY_OPTIONS`](#selfrelay_options--options-for-the-prebuilt-worker). |
|
|
408
|
+
| `RelayServiceWorkerOptions` | interface | `{ mounts?, exclude?, canRegister?, takeover?, decorateResponse? }` — see the options table in [Mounting a service at a path](#mounting-a-service-at-a-path). |
|
|
287
409
|
|
|
288
410
|
### ServiceWorker lifecycle
|
|
289
411
|
|
|
@@ -341,7 +463,7 @@ imports keep working after those extractions. Its own surface is below.
|
|
|
341
463
|
| Entry | Purpose |
|
|
342
464
|
| --- | --- |
|
|
343
465
|
| `@statewalker/webrun-http-browser/sw` | `SwHttpAdapter` — the same-origin ServiceWorker adapter. |
|
|
344
|
-
| `@statewalker/webrun-http-browser/relay-sw` | IIFE relay SW runtime, loadable via `importScripts(...)`. |
|
|
466
|
+
| `@statewalker/webrun-http-browser/relay-sw` | IIFE relay SW runtime, loadable via `importScripts(...)`. Reads its options from `self.RELAY_OPTIONS`, set before the `importScripts` call. |
|
|
345
467
|
| `@statewalker/webrun-http-browser/sw-worker` | IIFE same-origin SW runtime, loadable via `importScripts(...)`. |
|
|
346
468
|
|
|
347
469
|
## Internals
|
package/dist/index.js
CHANGED
|
@@ -2660,25 +2660,54 @@ async function sendHttpRequest(communicationPort, request) {
|
|
|
2660
2660
|
*/
|
|
2661
2661
|
function splitServiceUrl(url, separator = "~") {
|
|
2662
2662
|
const str = `${url}`;
|
|
2663
|
-
const
|
|
2664
|
-
|
|
2665
|
-
|
|
2666
|
-
|
|
2667
|
-
|
|
2668
|
-
|
|
2669
|
-
|
|
2670
|
-
|
|
2671
|
-
|
|
2672
|
-
|
|
2673
|
-
|
|
2674
|
-
|
|
2675
|
-
|
|
2676
|
-
|
|
2663
|
+
const empty = {
|
|
2664
|
+
url: str,
|
|
2665
|
+
key: "",
|
|
2666
|
+
baseUrl: "",
|
|
2667
|
+
path: ""
|
|
2668
|
+
};
|
|
2669
|
+
const hashIdx = str.indexOf("#");
|
|
2670
|
+
const queryIdx = str.indexOf("?");
|
|
2671
|
+
let strippedEnd = str.length;
|
|
2672
|
+
if (hashIdx >= 0) strippedEnd = Math.min(strippedEnd, hashIdx);
|
|
2673
|
+
if (queryIdx >= 0) strippedEnd = Math.min(strippedEnd, queryIdx);
|
|
2674
|
+
const stripped = str.slice(0, strippedEnd);
|
|
2675
|
+
let prefixEnd = 0;
|
|
2676
|
+
const schemeMatch = stripped.match(/^[a-zA-Z][a-zA-Z0-9+\-.]*:\/\//);
|
|
2677
|
+
if (schemeMatch) {
|
|
2678
|
+
prefixEnd = schemeMatch[0].length;
|
|
2679
|
+
const slashIdx = stripped.indexOf("/", prefixEnd);
|
|
2680
|
+
if (slashIdx >= 0) prefixEnd = slashIdx;
|
|
2681
|
+
else return empty;
|
|
2682
|
+
} else if (stripped.startsWith("//")) {
|
|
2683
|
+
prefixEnd = 2;
|
|
2684
|
+
const slashIdx = stripped.indexOf("/", prefixEnd);
|
|
2685
|
+
if (slashIdx >= 0) prefixEnd = slashIdx;
|
|
2686
|
+
else return empty;
|
|
2687
|
+
}
|
|
2688
|
+
const prefix = stripped.slice(0, prefixEnd);
|
|
2689
|
+
const pathPart = stripped.slice(prefixEnd);
|
|
2690
|
+
let keyStart;
|
|
2691
|
+
let rooted = false;
|
|
2692
|
+
if (prefix === "") {
|
|
2693
|
+
if (pathPart.startsWith(`/${separator}`)) {
|
|
2694
|
+
rooted = true;
|
|
2695
|
+
keyStart = separator.length + 1;
|
|
2696
|
+
} else if (pathPart.startsWith(separator)) keyStart = separator.length;
|
|
2697
|
+
else return empty;
|
|
2698
|
+
} else {
|
|
2699
|
+
if (!pathPart.startsWith(`/${separator}`)) return empty;
|
|
2700
|
+
keyStart = separator.length + 1;
|
|
2701
|
+
}
|
|
2702
|
+
const rest = pathPart.slice(keyStart);
|
|
2703
|
+
const slash = rest.indexOf("/");
|
|
2704
|
+
const key = slash < 0 ? rest : rest.slice(0, slash);
|
|
2705
|
+
if (key === "") return empty;
|
|
2677
2706
|
return {
|
|
2678
2707
|
url: str,
|
|
2679
2708
|
key,
|
|
2680
|
-
baseUrl
|
|
2681
|
-
path
|
|
2709
|
+
baseUrl: `${prefix === "" ? rooted ? "/" : "" : `${prefix}/`}${separator}${key}${slash < 0 ? "" : "/"}`,
|
|
2710
|
+
path: slash < 0 ? "" : rest.slice(slash + 1)
|
|
2682
2711
|
};
|
|
2683
2712
|
}
|
|
2684
2713
|
//#endregion
|
|
@@ -2735,9 +2764,10 @@ async function registerServiceWorker({ swUrl, scopeUrl, type, timeout = DEFAULT_
|
|
|
2735
2764
|
* Registers `handler` as the server for the given service `key` on the relay.
|
|
2736
2765
|
* Returns a cleanup function that unregisters the service.
|
|
2737
2766
|
*/
|
|
2738
|
-
async function initHttpService(handler, { key, port }) {
|
|
2767
|
+
async function initHttpService(handler, { key, path, port }) {
|
|
2739
2768
|
return await registerConnectionsHandler({
|
|
2740
2769
|
key,
|
|
2770
|
+
path,
|
|
2741
2771
|
communicationPort: port,
|
|
2742
2772
|
handler: async (_event, _data, callPort) => {
|
|
2743
2773
|
handleHttpRequests(callPort, handler);
|
|
@@ -2859,14 +2889,56 @@ async function initializeConnection({ key, communicationPort, ...options }) {
|
|
|
2859
2889
|
}
|
|
2860
2890
|
return channel.port1;
|
|
2861
2891
|
}
|
|
2862
|
-
async function registerConnectionsHandler({ key, handler, communicationPort }) {
|
|
2892
|
+
async function registerConnectionsHandler({ key, path, handler, communicationPort }) {
|
|
2863
2893
|
const [register, cleanup] = newRegistry();
|
|
2864
|
-
await callChannel(communicationPort, "REGISTER", { key }
|
|
2894
|
+
await callChannel(communicationPort, "REGISTER", path == null ? { key } : {
|
|
2895
|
+
key,
|
|
2896
|
+
path
|
|
2897
|
+
});
|
|
2865
2898
|
register(() => callChannel(communicationPort, "UNREGISTER", { key }));
|
|
2866
|
-
register(
|
|
2899
|
+
register(handleKeyedChannelCalls(communicationPort, "CONNECT", key, async (event, data, port) => {
|
|
2867
2900
|
return await handler(event, data, port);
|
|
2868
2901
|
}));
|
|
2869
2902
|
return cleanup;
|
|
2870
2903
|
}
|
|
2904
|
+
/**
|
|
2905
|
+
* `handleChannelCalls`, but only for calls whose `params.key` is `key`.
|
|
2906
|
+
*
|
|
2907
|
+
* ONE CONNECTION CARRIES SEVERAL SERVICES — an app at `/` and a mesh gateway
|
|
2908
|
+
* at `/peers/` over one relay iframe is the shape mounts exist for. Plain
|
|
2909
|
+
* `handleChannelCalls` cannot do that: every listener it has for a call type
|
|
2910
|
+
* runs on every message, and each is handed the SAME reply port and the SAME
|
|
2911
|
+
* transferred stream port. Two services then both serve the one channel the
|
|
2912
|
+
* worker is reading, and its response comes back with both bodies in it.
|
|
2913
|
+
*
|
|
2914
|
+
* WHY NOT A FILTER INSIDE THE HANDLER. Returning `false` for a foreign key
|
|
2915
|
+
* does not help: `handleChannelCalls` still replies, `callChannel` resolves on
|
|
2916
|
+
* the FIRST reply it receives, and the loser's `false` reaches the worker as
|
|
2917
|
+
* "the client refused" — a 403, non-deterministically. A service that is not
|
|
2918
|
+
* the addressee must stay SILENT and leave the transferred port untouched.
|
|
2919
|
+
*
|
|
2920
|
+
* Local to this module on purpose. `handleChannelCalls` is also used where a
|
|
2921
|
+
* call carries no key (REGISTER/UNREGISTER, and the worker's own CONNECT in
|
|
2922
|
+
* `index-sw.ts`, which is the other direction), so its semantics must not
|
|
2923
|
+
* change.
|
|
2924
|
+
*/
|
|
2925
|
+
function handleKeyedChannelCalls(target, callType, key, handler) {
|
|
2926
|
+
const listener = async (event) => {
|
|
2927
|
+
const data = event.data;
|
|
2928
|
+
if (!data || data.type !== callType) return;
|
|
2929
|
+
if (data.params?.key !== key) return;
|
|
2930
|
+
const [port, ...transfers] = event.ports ?? [];
|
|
2931
|
+
const response = {};
|
|
2932
|
+
try {
|
|
2933
|
+
response.result = await handler(event, data.params, ...transfers);
|
|
2934
|
+
} catch (error) {
|
|
2935
|
+
response.error = serializeError(error);
|
|
2936
|
+
}
|
|
2937
|
+
port?.postMessage(response);
|
|
2938
|
+
};
|
|
2939
|
+
target.addEventListener("message", listener);
|
|
2940
|
+
target.start?.();
|
|
2941
|
+
return () => target.removeEventListener("message", listener);
|
|
2942
|
+
}
|
|
2871
2943
|
//#endregion
|
|
2872
2944
|
export { CLAIM_CALL, DEFAULT_SERVICE_WORKER_TIMEOUT, DuplexSiteBuilder, HttpError, HttpParseError, PEER_ERROR_HEADER, ServiceWorkerControlError, TransportClosedError, awaitActiveServiceWorker, awaitServiceWorkerControl, callChannel, callHttpService, collect, collectBytes, collectString, decodeJsonl, decodeMessage, decodeText, defaultCodec, deserializeError, emulateMux, encodeJsonl, encodeMessage, encodeText, fetchOverDuplex, fromReadableStream, getRelayWindowMessageHandler, handleChannelCalls, handleClaimRequests, handleHttpRequests, handleStreams, httpCodec, httpFetch, httpServe, initHttpService, initServiceWorker, initializeConnection, joinLines, jsonEnvelopeCodec, map, newAsyncGenerator, newCreditGrantor, newCreditLedger, newHttpClientStub, newHttpCodec, newHttpServerStub, newInvokationChannel, newRegistry, newRemoteRelayChannel, newServiceWorkerPort, newSniffingCodec, normalizeToUint8Array, recieveIterator, registerConnectionsHandler, sendHttpRequest, sendIterator, sendStream, serializeError, serveFetchOverDuplex, splitLines, splitServiceUrl, toChunks, toReadableStream };
|
package/dist/relay/index-sw.d.ts
CHANGED
|
@@ -1,7 +1,92 @@
|
|
|
1
|
+
import { type MountSpec, type MountTable } from "./mount-table.js";
|
|
2
|
+
/** What the registry keeps per service key. */
|
|
3
|
+
export interface RegisteredClient {
|
|
4
|
+
clientId: string;
|
|
5
|
+
/** Where the service is mounted. Absent means `/~<key>/`, as before mounts. */
|
|
6
|
+
path?: string;
|
|
7
|
+
}
|
|
8
|
+
/**
|
|
9
|
+
* One stored registry entry, whatever shape it is on disk.
|
|
10
|
+
*
|
|
11
|
+
* BEFORE MOUNTS THE VALUE WAS A BARE CLIENT ID. A browser that ran the earlier
|
|
12
|
+
* worker still holds that shape, and reading it as an object would drop the id
|
|
13
|
+
* and quietly unregister every service the visitor had.
|
|
14
|
+
*/
|
|
15
|
+
export declare function readStoredEntry(value: unknown): RegisteredClient | undefined;
|
|
16
|
+
/**
|
|
17
|
+
* Which service, if any, should answer `url`.
|
|
18
|
+
*
|
|
19
|
+
* `undefined` means NOT THE RELAY'S, and the caller must not call
|
|
20
|
+
* `respondWith`: the request then goes to the network, which is how a host
|
|
21
|
+
* keeps serving its own files from its own origin. Answering 404 here instead
|
|
22
|
+
* would make a root mount fatal.
|
|
23
|
+
*/
|
|
24
|
+
export declare function resolveServiceKey(url: URL, table: MountTable, selfOrigin: string): string | undefined;
|
|
25
|
+
/**
|
|
26
|
+
* Waits for the mount table to be restored from the registry before routing
|
|
27
|
+
* `url` — but a restore failure must never wedge every fetch. `restored`
|
|
28
|
+
* rejecting (blocked storage, quota, private-mode edge cases) would otherwise
|
|
29
|
+
* propagate straight to `respondWith` on every request, including ones that
|
|
30
|
+
* should reach the network, which breaks the one rule this file exists to
|
|
31
|
+
* uphold. So: log the failure and route with whatever the in-memory table
|
|
32
|
+
* already holds — possibly empty, never fatal.
|
|
33
|
+
*/
|
|
34
|
+
export declare function resolveAfterRestore(restored: Promise<void>, url: URL, table: MountTable, selfOrigin: string): Promise<string | undefined>;
|
|
35
|
+
/**
|
|
36
|
+
* What REGISTER does to the mount table: set it when `path` is given, or
|
|
37
|
+
* remove any earlier mount when it is not. A path-less re-registration
|
|
38
|
+
* reverts a service to `/~<key>/` addressing, and a stale prefix left behind
|
|
39
|
+
* would keep routing requests to a mount that no longer exists.
|
|
40
|
+
*
|
|
41
|
+
* A REGISTRATION ONLY TOUCHES WHAT A REGISTRATION MADE. `hostKeys` names the
|
|
42
|
+
* mounts the host declared itself, in `options.mounts`. Those are the host's
|
|
43
|
+
* build-time decision and a page may not undo it: the documented static flow
|
|
44
|
+
* -- host declares `{ key: "app", path: "/" }`, page calls `initHttpService(h,
|
|
45
|
+
* { key: "app", port })` with no path -- would otherwise have its very first
|
|
46
|
+
* registration delete the host's own mount and leave the origin unmounted. A
|
|
47
|
+
* path-ful REGISTER naming a host key is ignored for the same reason (it would
|
|
48
|
+
* replace a `match` predicate with a prefix of the page's choosing).
|
|
49
|
+
*/
|
|
50
|
+
export declare function applyRegisteredMount(table: MountTable, key: string, path: string | undefined, hostKeys?: ReadonlySet<string>): void;
|
|
51
|
+
/**
|
|
52
|
+
* What UNREGISTER does to the mount table: drop the mount a registration
|
|
53
|
+
* made. A host-declared mount stays, for the reason `applyRegisteredMount`
|
|
54
|
+
* gives -- a page tearing down its service must not take the host's table
|
|
55
|
+
* with it.
|
|
56
|
+
*/
|
|
57
|
+
export declare function removeRegisteredMount(table: MountTable, key: string, hostKeys?: ReadonlySet<string>): void;
|
|
58
|
+
export interface RelayServiceWorkerOptions {
|
|
59
|
+
/** A fixed table, for a host that knows its services at build time. */
|
|
60
|
+
mounts?: Array<{
|
|
61
|
+
key: string;
|
|
62
|
+
} & MountSpec>;
|
|
63
|
+
/** Paths the relay never claims. Checked before the table. */
|
|
64
|
+
exclude?: (url: URL) => boolean;
|
|
65
|
+
/** Refuse a registration from the wrong client. Default: everyone may. */
|
|
66
|
+
canRegister?: (client: Client, key: string) => boolean | Promise<boolean>;
|
|
67
|
+
/** Default `"last-wins"`, the behaviour before this option existed. */
|
|
68
|
+
takeover?: "first-wins" | "last-wins";
|
|
69
|
+
/** Stamp headers on responses the relay makes. Not applied to network fetches. */
|
|
70
|
+
decorateResponse?: (response: Response, request: Request) => Response;
|
|
71
|
+
}
|
|
72
|
+
/**
|
|
73
|
+
* May `candidateId` take the key?
|
|
74
|
+
*
|
|
75
|
+
* `last-wins` is what the relay has always done and stays the default. With
|
|
76
|
+
* `first-wins`, a LIVE holder keeps its key: on an origin whose name is
|
|
77
|
+
* guessable, a second page proves nothing by existing. A holder that reloaded
|
|
78
|
+
* is no longer live, so a host's own re-registration is never blocked.
|
|
79
|
+
*/
|
|
80
|
+
export declare function mayRegister(args: {
|
|
81
|
+
current?: RegisteredClient;
|
|
82
|
+
candidateId: string;
|
|
83
|
+
isCurrentLive: boolean;
|
|
84
|
+
takeover: "first-wins" | "last-wins";
|
|
85
|
+
}): boolean;
|
|
1
86
|
/**
|
|
2
87
|
* Boots the relay ServiceWorker: routes fetches shaped `<origin>/~<key>/…` to
|
|
3
88
|
* the client that registered `key`, and exposes REGISTER/UNREGISTER/CONNECT
|
|
4
89
|
* channel calls used by the page-side relay client.
|
|
5
90
|
*/
|
|
6
|
-
export declare function startRelayServiceWorker(self: ServiceWorkerGlobalScope): () => void;
|
|
91
|
+
export declare function startRelayServiceWorker(self: ServiceWorkerGlobalScope, options?: RelayServiceWorkerOptions): () => void;
|
|
7
92
|
//# sourceMappingURL=index-sw.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index-sw.d.ts","sourceRoot":"","sources":["../../src/relay/index-sw.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"index-sw.d.ts","sourceRoot":"","sources":["../../src/relay/index-sw.ts"],"names":[],"mappings":"AAMA,OAAO,EAAE,KAAK,SAAS,EAAE,KAAK,UAAU,EAAiB,MAAM,kBAAkB,CAAC;AAGlF,+CAA+C;AAC/C,MAAM,WAAW,gBAAgB;IAC/B,QAAQ,EAAE,MAAM,CAAC;IACjB,+EAA+E;IAC/E,IAAI,CAAC,EAAE,MAAM,CAAC;CACf;AAED;;;;;;GAMG;AACH,wBAAgB,eAAe,CAAC,KAAK,EAAE,OAAO,GAAG,gBAAgB,GAAG,SAAS,CAM5E;AAED;;;;;;;GAOG;AACH,wBAAgB,iBAAiB,CAC/B,GAAG,EAAE,GAAG,EACR,KAAK,EAAE,UAAU,EACjB,UAAU,EAAE,MAAM,GACjB,MAAM,GAAG,SAAS,CAUpB;AAED;;;;;;;;GAQG;AACH,wBAAsB,mBAAmB,CACvC,QAAQ,EAAE,OAAO,CAAC,IAAI,CAAC,EACvB,GAAG,EAAE,GAAG,EACR,KAAK,EAAE,UAAU,EACjB,UAAU,EAAE,MAAM,GACjB,OAAO,CAAC,MAAM,GAAG,SAAS,CAAC,CAO7B;AAED;;;;;;;;;;;;;;GAcG;AACH,wBAAgB,oBAAoB,CAClC,KAAK,EAAE,UAAU,EACjB,GAAG,EAAE,MAAM,EACX,IAAI,EAAE,MAAM,GAAG,SAAS,EACxB,QAAQ,GAAE,WAAW,CAAC,MAAM,CAAa,GACxC,IAAI,CAON;AAED;;;;;GAKG;AACH,wBAAgB,qBAAqB,CACnC,KAAK,EAAE,UAAU,EACjB,GAAG,EAAE,MAAM,EACX,QAAQ,GAAE,WAAW,CAAC,MAAM,CAAa,GACxC,IAAI,CAGN;AAED,MAAM,WAAW,yBAAyB;IACxC,uEAAuE;IACvE,MAAM,CAAC,EAAE,KAAK,CAAC;QAAE,GAAG,EAAE,MAAM,CAAA;KAAE,GAAG,SAAS,CAAC,CAAC;IAC5C,8DAA8D;IAC9D,OAAO,CAAC,EAAE,CAAC,GAAG,EAAE,GAAG,KAAK,OAAO,CAAC;IAChC,0EAA0E;IAC1E,WAAW,CAAC,EAAE,CAAC,MAAM,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,KAAK,OAAO,GAAG,OAAO,CAAC,OAAO,CAAC,CAAC;IAC1E,uEAAuE;IACvE,QAAQ,CAAC,EAAE,YAAY,GAAG,WAAW,CAAC;IACtC,kFAAkF;IAClF,gBAAgB,CAAC,EAAE,CAAC,QAAQ,EAAE,QAAQ,EAAE,OAAO,EAAE,OAAO,KAAK,QAAQ,CAAC;CACvE;AAED;;;;;;;GAOG;AACH,wBAAgB,WAAW,CAAC,IAAI,EAAE;IAChC,OAAO,CAAC,EAAE,gBAAgB,CAAC;IAC3B,WAAW,EAAE,MAAM,CAAC;IACpB,aAAa,EAAE,OAAO,CAAC;IACvB,QAAQ,EAAE,YAAY,GAAG,WAAW,CAAC;CACtC,GAAG,OAAO,CAIV;AAED;;;;GAIG;AACH,wBAAgB,uBAAuB,CACrC,IAAI,EAAE,wBAAwB,EAC9B,OAAO,GAAE,yBAA8B,GACtC,MAAM,IAAI,CAwJZ"}
|
package/dist/relay/index.d.ts
CHANGED
|
@@ -30,13 +30,18 @@ export interface InitServiceWorkerOptions {
|
|
|
30
30
|
export declare function initServiceWorker(options: InitServiceWorkerOptions): Promise<ServiceWorker>;
|
|
31
31
|
export interface ServiceOptions {
|
|
32
32
|
key: string;
|
|
33
|
+
/**
|
|
34
|
+
* Where this service is mounted on the relay origin, e.g. `/` or `/peers/`.
|
|
35
|
+
* Omitted, the service stays reachable at `/~<key>/`, as before mounts.
|
|
36
|
+
*/
|
|
37
|
+
path?: string;
|
|
33
38
|
port: MessageTarget;
|
|
34
39
|
}
|
|
35
40
|
/**
|
|
36
41
|
* Registers `handler` as the server for the given service `key` on the relay.
|
|
37
42
|
* Returns a cleanup function that unregisters the service.
|
|
38
43
|
*/
|
|
39
|
-
export declare function initHttpService(handler: HttpHandler, { key, port }: ServiceOptions): Promise<() => void>;
|
|
44
|
+
export declare function initHttpService(handler: HttpHandler, { key, path, port }: ServiceOptions): Promise<() => void>;
|
|
40
45
|
/**
|
|
41
46
|
* Sends a `Request` to the service registered under `key` on the relay and
|
|
42
47
|
* resolves with the corresponding `Response`.
|
|
@@ -79,8 +84,10 @@ export interface InitializeConnectionOptions {
|
|
|
79
84
|
export declare function initializeConnection({ key, communicationPort, ...options }: InitializeConnectionOptions): Promise<MessagePort | null>;
|
|
80
85
|
export interface RegisterConnectionsHandlerOptions {
|
|
81
86
|
key: string;
|
|
87
|
+
/** Where this service is mounted; see `ServiceOptions.path`. */
|
|
88
|
+
path?: string;
|
|
82
89
|
handler: (event: MessageEvent, data: unknown, port: MessagePort) => boolean | Promise<boolean>;
|
|
83
90
|
communicationPort: MessageTarget;
|
|
84
91
|
}
|
|
85
|
-
export declare function registerConnectionsHandler({ key, handler, communicationPort, }: RegisterConnectionsHandlerOptions): Promise<() => void>;
|
|
92
|
+
export declare function registerConnectionsHandler({ key, path, handler, communicationPort, }: RegisterConnectionsHandlerOptions): Promise<() => void>;
|
|
86
93
|
//# sourceMappingURL=index.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/relay/index.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,kCAAkC,CAAC;AAGpE,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,2BAA2B,CAAC;AAQ/D,cAAc,wBAAwB,CAAC;AAavC;;;;;GAKG;AACH,wBAAgB,oBAAoB,CAAC,YAAY,CAAC,EAAE,yBAAyB,GAAG,WAAW,CAU1F;AAED,MAAM,WAAW,wBAAwB;IACvC,KAAK,EAAE,MAAM,CAAC;IACd,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,IAAI,CAAC,EAAE,UAAU,CAAC;IAClB;;;;OAIG;IACH,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB;AAED;;;;;;;GAOG;AACH,wBAAsB,iBAAiB,CAAC,OAAO,EAAE,wBAAwB,GAAG,OAAO,CAAC,aAAa,CAAC,CAEjG;AAgBD,MAAM,WAAW,cAAc;IAC7B,GAAG,EAAE,MAAM,CAAC;IACZ,IAAI,EAAE,aAAa,CAAC;CACrB;AAED;;;GAGG;AACH,wBAAsB,eAAe,CACnC,OAAO,EAAE,WAAW,EACpB,EAAE,GAAG,EAAE,IAAI,EAAE,EAAE,cAAc,
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/relay/index.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Which registered service owns a URL.
|
|
3
|
+
*
|
|
4
|
+
* A pure lookup: no ServiceWorker, no storage, no I/O, so the routing rules
|
|
5
|
+
* can be tested as arithmetic rather than through a browser.
|
|
6
|
+
*
|
|
7
|
+
* TWO KINDS OF MOUNT, AND WHY BOTH. A `path` is a prefix, which is all most
|
|
8
|
+
* hosts need and costs nothing to match. A `match` predicate is the escape
|
|
9
|
+
* hatch for anything richer -- a host that wants URLPattern brings it and pays
|
|
10
|
+
* for it; this file must stay dependency-free, because it runs in a
|
|
11
|
+
* ServiceWorker that has to start fast.
|
|
12
|
+
*
|
|
13
|
+
* SPECIFICITY, NOT REGISTRATION ORDER. Prefixes are tried longest-first, so a
|
|
14
|
+
* catch-all at "/" cannot swallow "/peers/" and a host need not register in a
|
|
15
|
+
* careful order. Predicates are opaque -- nothing can be said about how
|
|
16
|
+
* specific they are -- so they are tried after every prefix, in the order they
|
|
17
|
+
* were registered.
|
|
18
|
+
*/
|
|
19
|
+
export interface MountSpec {
|
|
20
|
+
/** A path prefix, e.g. `/peers/`. `/` is the whole origin. */
|
|
21
|
+
path?: string;
|
|
22
|
+
/** Anything richer. Consulted only when no prefix matches. */
|
|
23
|
+
match?: (url: URL) => boolean;
|
|
24
|
+
}
|
|
25
|
+
export interface MountTable {
|
|
26
|
+
/** Add or replace the mount for `key`. */
|
|
27
|
+
set(key: string, spec: MountSpec): void;
|
|
28
|
+
remove(key: string): void;
|
|
29
|
+
/** The key that owns `url`, or `undefined` — meaning "not the relay's". */
|
|
30
|
+
find(url: URL): string | undefined;
|
|
31
|
+
/**
|
|
32
|
+
* Is `url` reserved by `exclude`? `find` already applies it, but the relay
|
|
33
|
+
* has a SECOND route — the `/~<key>/` spelling, which does not go through
|
|
34
|
+
* the table at all — and "an excluded path is never claimed" has to hold
|
|
35
|
+
* for both. The predicate lives here so there is one copy of it.
|
|
36
|
+
*/
|
|
37
|
+
excludes(url: URL): boolean;
|
|
38
|
+
}
|
|
39
|
+
export interface MountTableOptions {
|
|
40
|
+
/**
|
|
41
|
+
* Paths the relay never claims, checked BEFORE the table. A root mount
|
|
42
|
+
* matches every path, so a host with files of its own (a relay page, a
|
|
43
|
+
* worker, hashed assets) is unusable without this.
|
|
44
|
+
*/
|
|
45
|
+
exclude?: (url: URL) => boolean;
|
|
46
|
+
}
|
|
47
|
+
export declare function newMountTable(options?: MountTableOptions): MountTable;
|
|
48
|
+
//# sourceMappingURL=mount-table.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"mount-table.d.ts","sourceRoot":"","sources":["../../src/relay/mount-table.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;GAiBG;AAEH,MAAM,WAAW,SAAS;IACxB,8DAA8D;IAC9D,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,8DAA8D;IAC9D,KAAK,CAAC,EAAE,CAAC,GAAG,EAAE,GAAG,KAAK,OAAO,CAAC;CAC/B;AAED,MAAM,WAAW,UAAU;IACzB,0CAA0C;IAC1C,GAAG,CAAC,GAAG,EAAE,MAAM,EAAE,IAAI,EAAE,SAAS,GAAG,IAAI,CAAC;IACxC,MAAM,CAAC,GAAG,EAAE,MAAM,GAAG,IAAI,CAAC;IAC1B,2EAA2E;IAC3E,IAAI,CAAC,GAAG,EAAE,GAAG,GAAG,MAAM,GAAG,SAAS,CAAC;IACnC;;;;;OAKG;IACH,QAAQ,CAAC,GAAG,EAAE,GAAG,GAAG,OAAO,CAAC;CAC7B;AAED,MAAM,WAAW,iBAAiB;IAChC;;;;OAIG;IACH,OAAO,CAAC,EAAE,CAAC,GAAG,EAAE,GAAG,KAAK,OAAO,CAAC;CACjC;AAyBD,wBAAgB,aAAa,CAAC,OAAO,GAAE,iBAAsB,GAAG,UAAU,CAyCzE"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"split-service-url.d.ts","sourceRoot":"","sources":["../../src/relay/split-service-url.ts"],"names":[],"mappings":"AAAA,MAAM,WAAW,eAAe;IAC9B,GAAG,EAAE,MAAM,CAAC;IACZ,GAAG,EAAE,MAAM,CAAC;IACZ,OAAO,EAAE,MAAM,CAAC;IAChB,IAAI,EAAE,MAAM,CAAC;IACb,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC;CAC1B;AAED;;;GAGG;AACH,wBAAgB,eAAe,CAAC,GAAG,EAAE,GAAG,GAAG,MAAM,EAAE,SAAS,SAAM,GAAG,eAAe,
|
|
1
|
+
{"version":3,"file":"split-service-url.d.ts","sourceRoot":"","sources":["../../src/relay/split-service-url.ts"],"names":[],"mappings":"AAAA,MAAM,WAAW,eAAe;IAC9B,GAAG,EAAE,MAAM,CAAC;IACZ,GAAG,EAAE,MAAM,CAAC;IACZ,OAAO,EAAE,MAAM,CAAC;IAChB,IAAI,EAAE,MAAM,CAAC;IACb,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC;CAC1B;AAED;;;GAGG;AACH,wBAAgB,eAAe,CAAC,GAAG,EAAE,GAAG,GAAG,MAAM,EAAE,SAAS,SAAM,GAAG,eAAe,CA6EnF"}
|