@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
@@ -0,0 +1,130 @@
1
+ /**
2
+ * The ServiceWorker's table of handler links, per key. Pure bookkeeping, no
3
+ * ports, so routing can be tested without a browser.
4
+ */
5
+
6
+ /** What a `route` function sees of a handler. */
7
+ export interface HandlerInfo {
8
+ /** The handler slot, unique within its key. */
9
+ readonly id: string;
10
+ readonly key: string;
11
+ /** Token of the current attachment; `drain` and `detach` must name it. */
12
+ readonly owner: string;
13
+ /** Requests sent to it whose responses have not finished. */
14
+ readonly inflight: number;
15
+ /** Whatever the attaching page sent. */
16
+ readonly meta: unknown;
17
+ /** When it attached (`Date.now()`); ties go to the oldest. */
18
+ readonly attachedAt: number;
19
+ /** Draining: it finishes what it has and gets nothing new. */
20
+ readonly draining: boolean;
21
+ }
22
+
23
+ /**
24
+ * Picks the handler for one request among the live (not draining) handlers of
25
+ * its key. `undefined` means none of them: the request waits for another, as
26
+ * when there is none at all.
27
+ */
28
+ export type RouteFunction = <H extends HandlerInfo>(
29
+ request: Request,
30
+ key: string,
31
+ handlers: H[],
32
+ ) => H | undefined;
33
+
34
+ /**
35
+ * The default route: the handler with the fewest requests in flight, the
36
+ * oldest on a tie. With one handler per key — one tab — that is the first
37
+ * live handler of the key, as before routing was pluggable.
38
+ */
39
+ export const leastInflightRoute: RouteFunction = (_request, _key, handlers) => {
40
+ let best: (typeof handlers)[number] | undefined;
41
+ for (const handler of handlers) {
42
+ if (
43
+ best === undefined ||
44
+ handler.inflight < best.inflight ||
45
+ (handler.inflight === best.inflight && handler.attachedAt < best.attachedAt)
46
+ ) {
47
+ best = handler;
48
+ }
49
+ }
50
+ return best;
51
+ };
52
+
53
+ export class HandlerTable<E extends HandlerInfo> {
54
+ private readonly _entries = new Map<string, Map<string, E>>();
55
+ private _waiters: Array<{ key: string; resolve: (found: boolean) => void }> = [];
56
+
57
+ /** Adds `entry`. Returns the entry it replaces (same key and id), if any. */
58
+ add(entry: E): E | undefined {
59
+ let slots = this._entries.get(entry.key);
60
+ if (!slots) {
61
+ slots = new Map();
62
+ this._entries.set(entry.key, slots);
63
+ }
64
+ const replaced = slots.get(entry.id);
65
+ slots.set(entry.id, entry);
66
+ if (!entry.draining) {
67
+ this._waiters = this._waiters.filter(({ key, resolve }) => {
68
+ if (key !== entry.key) return true;
69
+ resolve(true);
70
+ return false;
71
+ });
72
+ }
73
+ return replaced;
74
+ }
75
+
76
+ /** Removes `entry` if it is still the one in its slot. */
77
+ remove(entry: E): boolean {
78
+ const slots = this._entries.get(entry.key);
79
+ if (slots?.get(entry.id) !== entry) return false;
80
+ slots.delete(entry.id);
81
+ if (slots.size === 0) this._entries.delete(entry.key);
82
+ return true;
83
+ }
84
+
85
+ get(key: string, id: string): E | undefined {
86
+ return this._entries.get(key)?.get(id);
87
+ }
88
+
89
+ /** Every entry of `key`, draining or not. */
90
+ all(key: string): E[] {
91
+ return [...(this._entries.get(key)?.values() ?? [])];
92
+ }
93
+
94
+ /** The entries of `key` that take new requests. */
95
+ live(key: string): E[] {
96
+ return this.all(key).filter((entry) => !entry.draining);
97
+ }
98
+
99
+ entries(): E[] {
100
+ return [...this._entries.values()].flatMap((slots) => [...slots.values()]);
101
+ }
102
+
103
+ get size(): number {
104
+ let size = 0;
105
+ for (const slots of this._entries.values()) size += slots.size;
106
+ return size;
107
+ }
108
+
109
+ /**
110
+ * Resolves `true` once a live entry for `key` is added (at once if there is
111
+ * one, unless `next`), `false` after `ms`.
112
+ */
113
+ waitFor(key: string, ms: number, next = false): Promise<boolean> {
114
+ if (!next && this.live(key).length > 0) return Promise.resolve(true);
115
+ return new Promise((resolve) => {
116
+ const waiter = {
117
+ key,
118
+ resolve: (found: boolean) => {
119
+ clearTimeout(timer);
120
+ resolve(found);
121
+ },
122
+ };
123
+ const timer = setTimeout(() => {
124
+ this._waiters = this._waiters.filter((w) => w !== waiter);
125
+ resolve(false);
126
+ }, ms);
127
+ this._waiters.push(waiter);
128
+ });
129
+ }
130
+ }