@statewalker/webrun-http-browser 0.6.4 → 0.7.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 (93) hide show
  1. package/README.md +319 -65
  2. package/dist/core/data-calls.d.ts +17 -0
  3. package/dist/core/data-calls.d.ts.map +1 -1
  4. package/dist/core/service-worker-control.d.ts +3 -1
  5. package/dist/core/service-worker-control.d.ts.map +1 -1
  6. package/dist/index.d.ts +3 -0
  7. package/dist/index.d.ts.map +1 -1
  8. package/dist/index.js +3907 -266
  9. package/dist/link/errors.d.ts +2 -0
  10. package/dist/link/errors.d.ts.map +1 -0
  11. package/dist/link/http-link.d.ts +58 -0
  12. package/dist/link/http-link.d.ts.map +1 -0
  13. package/dist/link/index.d.ts +4 -0
  14. package/dist/link/index.d.ts.map +1 -0
  15. package/dist/link/locks.d.ts +39 -0
  16. package/dist/link/locks.d.ts.map +1 -0
  17. package/dist/link/rendezvous.d.ts +21 -0
  18. package/dist/link/rendezvous.d.ts.map +1 -0
  19. package/dist/relay/index-sw.d.ts +12 -2
  20. package/dist/relay/index-sw.d.ts.map +1 -1
  21. package/dist/relay/index.d.ts +66 -8
  22. package/dist/relay/index.d.ts.map +1 -1
  23. package/dist/relay-sw.js +1160 -55
  24. package/dist/relay-worker.js +1161 -55
  25. package/dist/sw/handler-endpoint.d.ts +81 -0
  26. package/dist/sw/handler-endpoint.d.ts.map +1 -0
  27. package/dist/sw/handler-table.d.ts +53 -0
  28. package/dist/sw/handler-table.d.ts.map +1 -0
  29. package/dist/sw/http-sw-dispatcher.d.ts +162 -21
  30. package/dist/sw/http-sw-dispatcher.d.ts.map +1 -1
  31. package/dist/sw/index.d.ts +5 -0
  32. package/dist/sw/index.d.ts.map +1 -1
  33. package/dist/sw/protocol.d.ts +115 -0
  34. package/dist/sw/protocol.d.ts.map +1 -0
  35. package/dist/sw/sw-dispatcher.d.ts +2 -1
  36. package/dist/sw/sw-dispatcher.d.ts.map +1 -1
  37. package/dist/sw/sw-http-adapter.d.ts +199 -0
  38. package/dist/sw/sw-http-adapter.d.ts.map +1 -0
  39. package/dist/sw/sw-websocket.d.ts +16 -0
  40. package/dist/sw/sw-websocket.d.ts.map +1 -0
  41. package/dist/sw/worker-service.d.ts +45 -0
  42. package/dist/sw/worker-service.d.ts.map +1 -0
  43. package/dist/sw/worker-url.d.ts +9 -0
  44. package/dist/sw/worker-url.d.ts.map +1 -0
  45. package/dist/sw-worker.js +2075 -210
  46. package/dist/sw.d.ts +2 -0
  47. package/dist/sw.d.ts.map +1 -1
  48. package/dist/sw.js +3853 -480
  49. package/dist/worker.d.ts +10 -0
  50. package/dist/worker.d.ts.map +1 -0
  51. package/dist/worker.js +3507 -0
  52. package/dist/ws/client.d.ts +73 -0
  53. package/dist/ws/client.d.ts.map +1 -0
  54. package/dist/ws/frames.d.ts +68 -0
  55. package/dist/ws/frames.d.ts.map +1 -0
  56. package/dist/ws/index.d.ts +6 -0
  57. package/dist/ws/index.d.ts.map +1 -0
  58. package/dist/ws/server.d.ts +53 -0
  59. package/dist/ws/server.d.ts.map +1 -0
  60. package/dist/ws/socket-core.d.ts +91 -0
  61. package/dist/ws/socket-core.d.ts.map +1 -0
  62. package/dist/ws/upgrade.d.ts +93 -0
  63. package/dist/ws/upgrade.d.ts.map +1 -0
  64. package/package.json +10 -5
  65. package/src/core/data-calls.ts +52 -2
  66. package/src/core/service-worker-control.ts +7 -1
  67. package/src/index.ts +3 -0
  68. package/src/link/errors.ts +3 -0
  69. package/src/link/http-link.ts +222 -0
  70. package/src/link/index.ts +3 -0
  71. package/src/link/locks.ts +97 -0
  72. package/src/link/rendezvous.ts +60 -0
  73. package/src/relay/index-sw.ts +84 -12
  74. package/src/relay/index.ts +205 -29
  75. package/src/sw/handler-endpoint.ts +278 -0
  76. package/src/sw/handler-table.ts +130 -0
  77. package/src/sw/http-sw-dispatcher.ts +649 -90
  78. package/src/sw/index.ts +5 -0
  79. package/src/sw/protocol.ts +103 -0
  80. package/src/sw/sw-dispatcher.ts +12 -30
  81. package/src/sw/sw-http-adapter.ts +613 -0
  82. package/src/sw/sw-websocket.ts +43 -0
  83. package/src/sw/worker-service.ts +133 -0
  84. package/src/sw/worker-url.ts +19 -0
  85. package/src/sw-worker.ts +8 -3
  86. package/src/sw.ts +2 -0
  87. package/src/worker.ts +9 -0
  88. package/src/ws/client.ts +346 -0
  89. package/src/ws/frames.ts +119 -0
  90. package/src/ws/index.ts +11 -0
  91. package/src/ws/server.ts +132 -0
  92. package/src/ws/socket-core.ts +251 -0
  93. package/src/ws/upgrade.ts +200 -0
package/src/sw/index.ts CHANGED
@@ -1,2 +1,7 @@
1
+ export * from "./handler-endpoint.js";
2
+ export * from "./handler-table.js";
1
3
  export * from "./http-sw-dispatcher.js";
2
4
  export * from "./sw-dispatcher.js";
5
+ export * from "./sw-http-adapter.js";
6
+ export * from "./sw-websocket.js";
7
+ export * from "./worker-service.js";
@@ -0,0 +1,103 @@
1
+ /**
2
+ * The messages between pages, Dedicated Workers and the same-origin
3
+ * ServiceWorker. Internal: the shapes may change between versions, which is
4
+ * why every hand-shake carries `HTTP_LINK_PROTOCOL`.
5
+ *
6
+ * THREE PORTS PER HANDLER LINK. A page makes the channels and hands one end of
7
+ * each to the handler (itself, or a worker) and the other to the
8
+ * ServiceWorker; after that it carries nothing:
9
+ *
10
+ * - `down`: ServiceWorker → handler, the requests the handler serves;
11
+ * - `ctl`: a raw port next to them, for what HTTP over a stream cannot carry,
12
+ * transferred `MessagePort`s (WebSocket hand-over);
13
+ * - `up` (workers only): handler → ServiceWorker, the requests the handler
14
+ * sends through the router (to other handlers).
15
+ */
16
+
17
+ /** Page → ServiceWorker: attach a handler link. The name is the one version 1 used. */
18
+ export const ATTACH_CALL = "UPDATE_COMMUNICATION_PORT";
19
+ /** Page → ServiceWorker: remove a handler link now. */
20
+ export const DETACH_CALL = "webrun-http:detach";
21
+ /** Page → ServiceWorker: stop routing to a link, let its requests finish, then remove it. */
22
+ export const DRAIN_CALL = "webrun-http:drain";
23
+ /** Page → ServiceWorker: open a WebSocket to a handler. */
24
+ export const WS_CONNECT_CALL = "webrun-http:ws-connect";
25
+ /** ServiceWorker → pages: attach your links again (the ServiceWorker restarted). */
26
+ export const NEED_LINKS_CALL = "webrun-http:need-links";
27
+ /**
28
+ * Page → ServiceWorker, plain messages (no reply). A message to the
29
+ * ServiceWorker object is an event: it starts a stopped worker and resets its
30
+ * idle timer. Port messages do neither.
31
+ */
32
+ export const WAKE_MESSAGE = "webrun-http:wake";
33
+ export const KEEPALIVE_MESSAGE = "webrun-http:keepalive";
34
+
35
+ export interface AttachParams {
36
+ /** `HTTP_LINK_PROTOCOL`; absent from version 1 pages. */
37
+ wire?: string;
38
+ key: string;
39
+ /** The handler slot. Attaching an id that is attached already replaces it. */
40
+ id?: string;
41
+ /** Token of this attachment, named by `drain` / `detach`. */
42
+ owner?: string;
43
+ /** A Web Lock the handler holds while it lives. */
44
+ ownerLock?: string;
45
+ /** Whatever the host wants a `route` function to see. */
46
+ meta?: unknown;
47
+ /** Which ports follow `down` in the transfer list, in this order. */
48
+ ctl?: boolean;
49
+ up?: boolean;
50
+ }
51
+
52
+ export interface AttachReply {
53
+ /** `HTTP_LINK_PROTOCOL`: proves the worker speaks it. */
54
+ accepted: string;
55
+ /** The Web Lock the ServiceWorker holds while it lives; absent without Web Locks. */
56
+ routerLock?: string;
57
+ }
58
+
59
+ export interface DrainParams {
60
+ key: string;
61
+ id: string;
62
+ owner: string;
63
+ /** How long requests in flight may run before the link is closed anyway. */
64
+ ms?: number;
65
+ }
66
+
67
+ export interface NeedLinksParams {
68
+ /** Links made for this router are alive; only the others need attaching again. */
69
+ routerLock?: string;
70
+ }
71
+
72
+ /** The `ctl` port's messages. */
73
+ export type ControlMessage =
74
+ // ServiceWorker → handler: a caller asks for a socket.
75
+ | {
76
+ t: "ws-connect";
77
+ id: string;
78
+ url: string;
79
+ protocols: string[];
80
+ headers?: [string, string][];
81
+ }
82
+ // handler → ServiceWorker: the answer (`port` is transferred).
83
+ | { t: "ws-accept"; id: string; protocol: string; port: MessagePort }
84
+ | { t: "ws-refuse"; id: string; status: number; message: string }
85
+ // handler → ServiceWorker: the handler itself asks for a socket to another handler.
86
+ | { t: "ws-open"; id: string; url: string; protocols: string[] }
87
+ | { t: "ws-opened"; id: string; protocol: string; port: MessagePort }
88
+ | { t: "ws-failed"; id: string; message: string };
89
+
90
+ /** Page ↔ worker: what `attachWorker` and `serveHttpInWorker` exchange. */
91
+ export const WORKER_HELLO = "webrun-http:worker-hello";
92
+
93
+ export type WorkerControlMessage =
94
+ // worker → page, once: the worker serves, and holds this owner lock.
95
+ | { type: "ready"; ownerLock?: string }
96
+ // page → worker: a fresh link (ports: down, ctl, up).
97
+ | { type: "link"; key: string; routerLock?: string }
98
+ // page → worker: drop the links of this key.
99
+ | { type: "unlink"; key: string }
100
+ // worker → page: my links are dead and a call waits; attach me again.
101
+ | { type: "relink" }
102
+ // worker → page: a call is in flight; keep the ServiceWorker awake.
103
+ | { type: "keepalive" };
@@ -8,6 +8,7 @@ import {
8
8
  handleClaimRequests,
9
9
  ServiceWorkerControlError,
10
10
  } from "../core/service-worker-control.js";
11
+ import { resolveWorkerUrl } from "./worker-url.js";
11
12
 
12
13
  export interface SwPortHandlerOptions {
13
14
  key: string;
@@ -44,6 +45,7 @@ export class SwPortHandler {
44
45
  private _serviceWorkerUrl?: string;
45
46
  private _serviceWorker?: ServiceWorker;
46
47
  private _registrationPromise?: Promise<void>;
48
+ private _registration?: ServiceWorkerRegistration;
47
49
  private _cleanupRegistrations?: () => void;
48
50
 
49
51
  constructor(options: SwPortHandlerOptions) {
@@ -65,7 +67,7 @@ export class SwPortHandler {
65
67
  * own url when one is given, not against this module's: a bundle that is
66
68
  * not an ES module (an IIFE, Theia's frontend) has no `import.meta.url`, and
67
69
  * `new URL(scope, undefined)` threw `Invalid URL` there. Only without a
68
- * worker url does the module's location decide (its default `index-sw.js`
70
+ * worker url does the module's location decide (its default `sw-worker.js`
69
71
  * sits next to it).
70
72
  */
71
73
  get rootUrl(): URL {
@@ -82,7 +84,7 @@ export class SwPortHandler {
82
84
  // use — `"/sw-worker.js"` — threw a bare `Invalid URL` naming
83
85
  // neither the option nor the value.
84
86
  resolveWorkerUrl(this.options.serviceWorkerUrl)
85
- : new URL("./index-sw.js", this.rootUrl);
87
+ : new URL("./sw-worker.js", this.rootUrl);
86
88
  this._serviceWorkerUrl = `${url}`;
87
89
  }
88
90
  return this._serviceWorkerUrl;
@@ -133,7 +135,7 @@ export class SwPortHandler {
133
135
  const registration = await navigator.serviceWorker.register(this.serviceWorkerUrl, {
134
136
  scope: this.scope,
135
137
  });
136
- register(() => registration.unregister());
138
+ this._registration = registration;
137
139
 
138
140
  const stopListening = handleChannelCalls(
139
141
  navigator.serviceWorker,
@@ -170,6 +172,7 @@ export class SwPortHandler {
170
172
  // that is not controlled, and other pages may be using the worker.
171
173
  stopListening();
172
174
  this._cleanupRegistrations = undefined;
175
+ this._registration = undefined;
173
176
  this._registrationPromise = undefined;
174
177
  throw error;
175
178
  }
@@ -180,13 +183,12 @@ export class SwPortHandler {
180
183
 
181
184
  async stop(): Promise<void> {
182
185
  this._cleanupRegistrations?.();
183
- const registrations = await navigator.serviceWorker.getRegistrations();
184
- for (const registration of registrations) {
185
- try {
186
- await registration.unregister();
187
- } catch (error) {
188
- console.log("Service Worker registration failed: ", error);
189
- }
186
+ const registration = this._registration;
187
+ this._registration = undefined;
188
+ try {
189
+ await registration?.unregister();
190
+ } catch (error) {
191
+ console.log("Service Worker unregistration failed: ", error);
190
192
  }
191
193
  }
192
194
  }
@@ -346,23 +348,3 @@ export class SwPortDispatcher {
346
348
  return index;
347
349
  }
348
350
  }
349
-
350
- /**
351
- * Resolve a `serviceWorkerUrl` option the way a page would: relative to the
352
- * current document. Absolute urls pass through untouched. A url that cannot
353
- * be resolved is reported with the option name and the offending value,
354
- * because the raw `TypeError: Failed to construct 'URL': Invalid URL` says
355
- * neither.
356
- */
357
- function resolveWorkerUrl(serviceWorkerUrl: string): URL {
358
- const base = globalThis.location?.href;
359
- try {
360
- return new URL(serviceWorkerUrl, base);
361
- } catch (error) {
362
- throw new Error(
363
- `Invalid serviceWorkerUrl: ${JSON.stringify(serviceWorkerUrl)}` +
364
- (base ? ` (relative to ${base})` : " (no document to resolve it against)"),
365
- { cause: error },
366
- );
367
- }
368
- }