@nervur-org/dock 0.3.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.
- package/GETTING_STARTED.md +128 -0
- package/LICENSE +202 -0
- package/NOTICE +6 -0
- package/README.md +37 -0
- package/api/quo-api.md +196 -0
- package/api/route.ts +227 -0
- package/beings/GLOSSARY.md +118 -0
- package/beings/WORLDS.md +567 -0
- package/beings/avatar.ts +101 -0
- package/beings/carry.ts +159 -0
- package/beings/clock.ts +552 -0
- package/beings/courier.ts +107 -0
- package/beings/desk.ts +128 -0
- package/beings/doorbell.ts +129 -0
- package/beings/envoy.ts +218 -0
- package/beings/index.ts +16 -0
- package/beings/join.ts +51 -0
- package/beings/link.ts +104 -0
- package/beings/look.ts +139 -0
- package/beings/porter.ts +43 -0
- package/beings/presence.ts +39 -0
- package/beings/quo-app-bells.md +280 -0
- package/beings/quo-dock.md +1942 -0
- package/beings/setup.ts +45 -0
- package/beings/side.ts +60 -0
- package/beings/user.ts +459 -0
- package/beings/way.ts +65 -0
- package/cli/bundles.ts +20 -0
- package/cli/client.ts +73 -0
- package/cli/daemon.ts +581 -0
- package/cli/estate/Caddyfile +33 -0
- package/cli/estate/quo.service +35 -0
- package/cli/estate/systems.quo.plist +44 -0
- package/cli/estate.ts +48 -0
- package/cli/folder.ts +27 -0
- package/cli/oauth.ts +32 -0
- package/cli/pilot.ts +38 -0
- package/cli/quo-dock.md +1942 -0
- package/cli/quo.ts +203 -0
- package/cli/stand.ts +160 -0
- package/dist/api/route.d.ts +21 -0
- package/dist/api/route.js +193 -0
- package/dist/beings/avatar.d.ts +32 -0
- package/dist/beings/avatar.js +100 -0
- package/dist/beings/carry.d.ts +12 -0
- package/dist/beings/carry.js +174 -0
- package/dist/beings/clock.d.ts +161 -0
- package/dist/beings/clock.js +528 -0
- package/dist/beings/courier.d.ts +50 -0
- package/dist/beings/courier.js +96 -0
- package/dist/beings/desk.d.ts +53 -0
- package/dist/beings/desk.js +135 -0
- package/dist/beings/doorbell.d.ts +78 -0
- package/dist/beings/doorbell.js +133 -0
- package/dist/beings/envoy.d.ts +54 -0
- package/dist/beings/envoy.js +211 -0
- package/dist/beings/index.d.ts +14 -0
- package/dist/beings/index.js +16 -0
- package/dist/beings/join.d.ts +15 -0
- package/dist/beings/join.js +42 -0
- package/dist/beings/link.d.ts +14 -0
- package/dist/beings/link.js +91 -0
- package/dist/beings/look.d.ts +30 -0
- package/dist/beings/look.js +104 -0
- package/dist/beings/porter.d.ts +14 -0
- package/dist/beings/porter.js +41 -0
- package/dist/beings/presence.d.ts +8 -0
- package/dist/beings/presence.js +21 -0
- package/dist/beings/setup.d.ts +3 -0
- package/dist/beings/setup.js +39 -0
- package/dist/beings/side.d.ts +32 -0
- package/dist/beings/side.js +37 -0
- package/dist/beings/user.d.ts +315 -0
- package/dist/beings/user.js +462 -0
- package/dist/beings/way.d.ts +19 -0
- package/dist/beings/way.js +28 -0
- package/dist/cli/bundles.d.ts +5 -0
- package/dist/cli/bundles.js +17 -0
- package/dist/cli/client.d.ts +15 -0
- package/dist/cli/client.js +58 -0
- package/dist/cli/daemon.d.ts +50 -0
- package/dist/cli/daemon.js +584 -0
- package/dist/cli/estate/Caddyfile +33 -0
- package/dist/cli/estate/quo.service +35 -0
- package/dist/cli/estate/systems.quo.plist +44 -0
- package/dist/cli/estate.d.ts +5 -0
- package/dist/cli/estate.js +50 -0
- package/dist/cli/folder.d.ts +2 -0
- package/dist/cli/folder.js +25 -0
- package/dist/cli/oauth.d.ts +2 -0
- package/dist/cli/oauth.js +32 -0
- package/dist/cli/pilot.d.ts +5 -0
- package/dist/cli/pilot.js +22 -0
- package/dist/cli/quo.d.ts +2 -0
- package/dist/cli/quo.js +201 -0
- package/dist/cli/stand.d.ts +37 -0
- package/dist/cli/stand.js +110 -0
- package/dist/dock/agents.d.ts +102 -0
- package/dist/dock/agents.js +105 -0
- package/dist/dock/apns.d.ts +27 -0
- package/dist/dock/apns.js +98 -0
- package/dist/dock/console.d.ts +6 -0
- package/dist/dock/console.js +20 -0
- package/dist/dock/dialers.d.ts +56 -0
- package/dist/dock/dialers.js +75 -0
- package/dist/dock/faculty.d.ts +24 -0
- package/dist/dock/faculty.js +142 -0
- package/dist/dock/fcm.d.ts +13 -0
- package/dist/dock/fcm.js +77 -0
- package/dist/dock/grants.d.ts +41 -0
- package/dist/dock/grants.js +99 -0
- package/dist/dock/http2.d.ts +4 -0
- package/dist/dock/http2.js +68 -0
- package/dist/dock/index.d.ts +41 -0
- package/dist/dock/index.js +113 -0
- package/dist/dock/local.d.ts +13 -0
- package/dist/dock/local.js +44 -0
- package/dist/dock/location.d.ts +19 -0
- package/dist/dock/location.js +11 -0
- package/dist/dock/notifications.d.ts +38 -0
- package/dist/dock/notifications.js +60 -0
- package/dist/dock/push.d.ts +79 -0
- package/dist/dock/push.js +132 -0
- package/dist/dock/service.d.ts +4 -0
- package/dist/dock/service.js +107 -0
- package/dist/dock/timer.d.ts +52 -0
- package/dist/dock/timer.js +149 -0
- package/dist/dock/webpush.d.ts +12 -0
- package/dist/dock/webpush.js +144 -0
- package/dist/harbor/browser.d.ts +15 -0
- package/dist/harbor/browser.js +82 -0
- package/dist/harbor/capacitor.d.ts +28 -0
- package/dist/harbor/capacitor.js +218 -0
- package/dist/harbor/disk.d.ts +27 -0
- package/dist/harbor/disk.js +249 -0
- package/dist/harbor/edge/alarm.d.ts +10 -0
- package/dist/harbor/edge/alarm.js +38 -0
- package/dist/harbor/edge/edge.d.ts +54 -0
- package/dist/harbor/edge/edge.js +370 -0
- package/dist/harbor/edge/exercise.d.ts +7 -0
- package/dist/harbor/edge/exercise.js +232 -0
- package/dist/harbor/edge/given.d.ts +26 -0
- package/dist/harbor/edge/given.js +42 -0
- package/dist/harbor/edge/platform.d.ts +39 -0
- package/dist/harbor/edge/storage.d.ts +30 -0
- package/dist/harbor/edge/storage.js +180 -0
- package/dist/harbor/edge/worker.d.ts +17 -0
- package/dist/harbor/edge/worker.js +67 -0
- package/dist/harbor/files.d.ts +15 -0
- package/dist/harbor/files.js +220 -0
- package/dist/harbor/http.d.ts +19 -0
- package/dist/harbor/http.js +177 -0
- package/dist/harbor/idb.d.ts +15 -0
- package/dist/harbor/idb.js +0 -0
- package/dist/harbor/quo.d.ts +10 -0
- package/dist/harbor/quo.js +42 -0
- package/dist/harbor/resolve.d.ts +16 -0
- package/dist/harbor/resolve.js +17 -0
- package/dist/harbor/seal.d.ts +3 -0
- package/dist/harbor/seal.js +25 -0
- package/dist/harbor/sealed.d.ts +35 -0
- package/dist/harbor/sealed.js +162 -0
- package/dist/harbor/tauri.d.ts +16 -0
- package/dist/harbor/tauri.js +59 -0
- package/dist/harbor/ward.d.ts +9 -0
- package/dist/harbor/ward.js +15 -0
- package/dist/human/app.d.ts +32 -0
- package/dist/human/app.js +527 -0
- package/dist/human/apps.d.ts +10 -0
- package/dist/human/apps.js +29 -0
- package/dist/human/dom.d.ts +2 -0
- package/dist/human/dom.js +15 -0
- package/dist/human/door.d.ts +19 -0
- package/dist/human/door.js +92 -0
- package/dist/human/guest.d.ts +3 -0
- package/dist/human/guest.js +33 -0
- package/dist/human/html.d.ts +55 -0
- package/dist/human/html.js +451 -0
- package/dist/human/local.d.ts +7 -0
- package/dist/human/local.js +10 -0
- package/dist/human/mark.d.ts +8 -0
- package/dist/human/mark.js +47 -0
- package/dist/human/move.d.ts +17 -0
- package/dist/human/move.js +90 -0
- package/dist/human/screen.d.ts +19 -0
- package/dist/human/screen.js +119 -0
- package/dist/human/style.d.ts +2 -0
- package/dist/human/style.js +60 -0
- package/dist/human/tab.bundle.txt +4775 -0
- package/dist/human/tab.d.ts +15 -0
- package/dist/human/tab.js +409 -0
- package/dist/human/tree.d.ts +50 -0
- package/dist/human/tree.js +157 -0
- package/dist/human/wake.d.ts +34 -0
- package/dist/human/wake.js +179 -0
- package/dist/human/web.d.ts +33 -0
- package/dist/human/web.js +184 -0
- package/dist/human/worker.bundle.txt +3868 -0
- package/dist/human/worker.d.ts +1 -0
- package/dist/human/worker.js +81 -0
- package/dist/human/worlds.d.ts +24 -0
- package/dist/human/worlds.js +99 -0
- package/dist/mcp/agent.d.ts +10 -0
- package/dist/mcp/agent.js +78 -0
- package/dist/mcp/allow.d.ts +20 -0
- package/dist/mcp/allow.js +88 -0
- package/dist/mcp/http.d.ts +27 -0
- package/dist/mcp/http.js +92 -0
- package/dist/mcp/oauth.d.ts +91 -0
- package/dist/mcp/oauth.js +241 -0
- package/dist/mcp/route.d.ts +15 -0
- package/dist/mcp/route.js +42 -0
- package/dist/mcp/runner.d.ts +45 -0
- package/dist/mcp/runner.js +99 -0
- package/dist/mcp/server.d.ts +11 -0
- package/dist/mcp/server.js +102 -0
- package/dock/agents.ts +121 -0
- package/dock/apns.ts +138 -0
- package/dock/console.ts +23 -0
- package/dock/dialers.ts +85 -0
- package/dock/faculty.ts +148 -0
- package/dock/fcm.ts +103 -0
- package/dock/grants.ts +111 -0
- package/dock/http2.ts +70 -0
- package/dock/index.ts +133 -0
- package/dock/local.ts +48 -0
- package/dock/location.ts +22 -0
- package/dock/notifications.ts +67 -0
- package/dock/push.ts +161 -0
- package/dock/quo-app-bells.md +280 -0
- package/dock/quo-dock.md +1942 -0
- package/dock/service.ts +100 -0
- package/dock/timer.ts +174 -0
- package/dock/webpush.ts +182 -0
- package/harbor/browser.ts +97 -0
- package/harbor/capacitor.ts +223 -0
- package/harbor/disk.ts +237 -0
- package/harbor/edge/alarm.ts +48 -0
- package/harbor/edge/edge.ts +407 -0
- package/harbor/edge/exercise.ts +241 -0
- package/harbor/edge/given.ts +106 -0
- package/harbor/edge/platform.d.ts +39 -0
- package/harbor/edge/storage.ts +179 -0
- package/harbor/edge/text.d.ts +15 -0
- package/harbor/edge/worker.ts +70 -0
- package/harbor/edge/wrangler.toml +30 -0
- package/harbor/files.ts +221 -0
- package/harbor/http.ts +188 -0
- package/harbor/idb.ts +0 -0
- package/harbor/quo-harbor.md +850 -0
- package/harbor/quo.ts +44 -0
- package/harbor/resolve.ts +31 -0
- package/harbor/seal.ts +26 -0
- package/harbor/sealed.ts +183 -0
- package/harbor/tauri.ts +79 -0
- package/harbor/ward.ts +28 -0
- package/human/app.ts +580 -0
- package/human/apps.ts +47 -0
- package/human/dom.ts +21 -0
- package/human/door.ts +113 -0
- package/human/guest.ts +34 -0
- package/human/html.ts +490 -0
- package/human/local.ts +30 -0
- package/human/mark.ts +53 -0
- package/human/move.ts +122 -0
- package/human/quo-human.md +1042 -0
- package/human/screen.ts +136 -0
- package/human/style.ts +63 -0
- package/human/tab.bundle.txt +4775 -0
- package/human/tab.ts +446 -0
- package/human/tree.ts +217 -0
- package/human/wake.ts +191 -0
- package/human/web.ts +259 -0
- package/human/worker.bundle.txt +3868 -0
- package/human/worker.ts +124 -0
- package/human/worlds.ts +127 -0
- package/mcp/agent.ts +94 -0
- package/mcp/allow.ts +131 -0
- package/mcp/http.ts +92 -0
- package/mcp/oauth.ts +270 -0
- package/mcp/quo-mcp.md +343 -0
- package/mcp/route.ts +45 -0
- package/mcp/runner.ts +136 -0
- package/mcp/server.ts +101 -0
- package/package.json +121 -0
package/harbor/http.ts
ADDED
|
@@ -0,0 +1,188 @@
|
|
|
1
|
+
// SPDX-License-Identifier: Apache-2.0
|
|
2
|
+
// The HTTP door: one listener on loopback that a reverse proxy fronts, and
|
|
3
|
+
// the routes mount on it by path prefix. `/health` is the harbor's own: the
|
|
4
|
+
// wards it hosts, by name and pk, and nothing a stranger can use. Each route
|
|
5
|
+
// lives in its own folder, `human/web.ts`, `harbor/quo.ts`, `mcp/route.ts`,
|
|
6
|
+
// and this file knows none of them: a route is a handler under a prefix.
|
|
7
|
+
//
|
|
8
|
+
// This is the route contract every side is written against, and it stands
|
|
9
|
+
// beside the disk harbor whose door it is. A route is `Request` in and
|
|
10
|
+
// `Response` out, the shapes every runtime speaks, so a side runs on this
|
|
11
|
+
// daemon, on a worker at the edge, in a browser's own service worker, on
|
|
12
|
+
// Deno or on Bun without a line of it changing. A handler answering nothing
|
|
13
|
+
// declines, and the mount tries what comes after it. A folder writing a
|
|
14
|
+
// route takes `Handler`, `readAll` and `Quo` from here and nothing of the
|
|
15
|
+
// daemon that mounts them.
|
|
16
|
+
//
|
|
17
|
+
// `listenHttp` is the one place Node's own objects appear: its door turns an
|
|
18
|
+
// `IncomingMessage` into a `Request` and writes a `Response` back onto a
|
|
19
|
+
// `ServerResponse`, and nothing downstream of it names either. The
|
|
20
|
+
// translation runs that one way only: a `Request` is never dressed up as an
|
|
21
|
+
// `IncomingMessage`, because a route writes headers and there would be
|
|
22
|
+
// nothing to write them onto.
|
|
23
|
+
//
|
|
24
|
+
// The listener half of the socket reach is here too, and for the same reason:
|
|
25
|
+
// holding a socket is the one thing no two runtimes do alike, so it stands
|
|
26
|
+
// with the terrain's own door and never in a route. `ws` is that half on
|
|
27
|
+
// Node; at the edge it is a `WebSocketPair` in the harbor there.
|
|
28
|
+
import { createServer as createHttp, type Server as HttpServer } from 'node:http';
|
|
29
|
+
import { Readable } from 'node:stream';
|
|
30
|
+
import { WebSocketServer } from 'ws';
|
|
31
|
+
import type { IncomingMessage } from 'node:http';
|
|
32
|
+
import { Socket as Held } from '@nervur-org/nervur/harbor';
|
|
33
|
+
import type { Dialer } from '@nervur-org/nervur/harbor';
|
|
34
|
+
import type { DiskHarbor } from './disk.ts';
|
|
35
|
+
|
|
36
|
+
export type Handler = (req: Request, rest: string) => Response | undefined | Promise<Response | undefined>;
|
|
37
|
+
export type Http = { port: number; host: string; mount(prefix: string, handler: Handler): void };
|
|
38
|
+
// What the quo. route holds: the sockets held here and the dialers this
|
|
39
|
+
// daemon runs. `/health` reports them.
|
|
40
|
+
export type Quo = { sockets: Set<Held>; dialers: Dialer[] };
|
|
41
|
+
|
|
42
|
+
// What a request may carry, on the doors that read a body: enough for any ask
|
|
43
|
+
// a ward seals, and not a body chosen by whoever is on the other end.
|
|
44
|
+
// The bytes are a `Uint8Array` and not a `Buffer`: a route runs on every
|
|
45
|
+
// runtime, and node's own type is not one of the shapes they all speak.
|
|
46
|
+
const BODY = 1 << 20;
|
|
47
|
+
export async function readAll(req: Request): Promise<Uint8Array | undefined> {
|
|
48
|
+
if (!req.body) return new Uint8Array(0);
|
|
49
|
+
const chunks: Uint8Array[] = [];
|
|
50
|
+
let size = 0;
|
|
51
|
+
const reader = req.body.getReader();
|
|
52
|
+
for (;;) {
|
|
53
|
+
const { done, value } = await reader.read();
|
|
54
|
+
if (done) break;
|
|
55
|
+
size += value.length;
|
|
56
|
+
if (size > BODY) {
|
|
57
|
+
await reader.cancel().catch(() => {});
|
|
58
|
+
return undefined;
|
|
59
|
+
}
|
|
60
|
+
chunks.push(value);
|
|
61
|
+
}
|
|
62
|
+
const all = new Uint8Array(size);
|
|
63
|
+
let at = 0;
|
|
64
|
+
for (const c of chunks) {
|
|
65
|
+
all.set(c, at);
|
|
66
|
+
at += c.length;
|
|
67
|
+
}
|
|
68
|
+
return all;
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
// The same body as text, for the doors that read one: JSON, a form, or a
|
|
72
|
+
// vendor's signed bytes a being reads as a string.
|
|
73
|
+
export async function readText(req: Request): Promise<string | undefined> {
|
|
74
|
+
const raw = await readAll(req);
|
|
75
|
+
return raw === undefined ? undefined : new TextDecoder().decode(raw);
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
export async function listenHttp(harbor: DiskHarbor, host: string, port: number, quo: Quo): Promise<Http & { server: HttpServer }> {
|
|
79
|
+
const mounts = new Map<string, Handler>();
|
|
80
|
+
const server = createHttp((req, res) => {
|
|
81
|
+
const url = new URL(req.url ?? '/', `http://${req.headers.host ?? 'localhost'}`);
|
|
82
|
+
const answer = async (): Promise<Response> => {
|
|
83
|
+
if (url.pathname === '/health') {
|
|
84
|
+
// the wards it hosts, and the directory: pks and whether each is a
|
|
85
|
+
// socket held here, which is what an operator needs to see a dialer.
|
|
86
|
+
// Open to any origin: a tab reads it, and it holds nothing a stranger can use.
|
|
87
|
+
return Response.json(
|
|
88
|
+
{
|
|
89
|
+
ok: true,
|
|
90
|
+
wards: Object.fromEntries([...harbor.wards].map(([n, h]) => [n, h.pk])),
|
|
91
|
+
reaches: Object.fromEntries([...harbor.reaches].map(([pk, b]) => [pk, b.held ? 'held' : 'reach'])),
|
|
92
|
+
sockets: quo.sockets.size,
|
|
93
|
+
dialers: quo.dialers.map((d) => ({ url: d.url, open: d.socket !== null })),
|
|
94
|
+
// How many saves the disk refused, per ward. The asker whose
|
|
95
|
+
// write was refused was told at the door; this is the operator's
|
|
96
|
+
// half, and a box that says nothing about it looks healthy while
|
|
97
|
+
// one world stops keeping anything.
|
|
98
|
+
faults: Object.fromEntries([...harbor.faults]),
|
|
99
|
+
},
|
|
100
|
+
{ headers: { 'access-control-allow-origin': '*' } },
|
|
101
|
+
);
|
|
102
|
+
}
|
|
103
|
+
for (const [prefix, handler] of mounts) {
|
|
104
|
+
if (url.pathname === prefix || url.pathname.startsWith(prefix + '/')) {
|
|
105
|
+
const out = await handler(asRequest(req, url), url.pathname.slice(prefix.length));
|
|
106
|
+
if (out) return out;
|
|
107
|
+
break;
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
return Response.json({ error: 'no such route' }, { status: 404 });
|
|
111
|
+
};
|
|
112
|
+
void answer()
|
|
113
|
+
.then((out) => writeResponse(out, res))
|
|
114
|
+
.catch(() => {
|
|
115
|
+
if (!res.headersSent) res.writeHead(500);
|
|
116
|
+
res.end();
|
|
117
|
+
});
|
|
118
|
+
});
|
|
119
|
+
await new Promise<void>((ok, no) => {
|
|
120
|
+
server.once('error', no);
|
|
121
|
+
server.listen(port, host, () => ok());
|
|
122
|
+
});
|
|
123
|
+
hold(server, harbor, quo);
|
|
124
|
+
const address = server.address();
|
|
125
|
+
const bound = typeof address === 'object' && address !== null ? address.port : port;
|
|
126
|
+
return { server, host, port: bound, mount: (prefix, handler) => mounts.set(prefix.replace(/\/$/, ''), handler) };
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
// A dialer's held socket, this terrain's way: an upgrade at the quo route on
|
|
130
|
+
// the daemon's own listener, held as the library's `Socket`. Its pks are bound
|
|
131
|
+
// at announce, each proven at its door, and unbound when the line drops. The
|
|
132
|
+
// route itself reads no socket, and every runtime holds one differently.
|
|
133
|
+
function hold(server: HttpServer, harbor: DiskHarbor, quo: Quo): void {
|
|
134
|
+
const wss = new WebSocketServer({ noServer: true });
|
|
135
|
+
server.on('upgrade', (req: IncomingMessage, socket, head) => {
|
|
136
|
+
const url = new URL(req.url ?? '/', 'http://localhost');
|
|
137
|
+
if (url.pathname.replace(/\/$/, '') !== '/quo') return void socket.destroy(); // the proxy rewrites the route root to /quo/
|
|
138
|
+
wss.handleUpgrade(req, socket, head, (ws) => {
|
|
139
|
+
const s: Held = new Held(
|
|
140
|
+
ws,
|
|
141
|
+
(pk, bytes) => harbor.deliver(pk, bytes),
|
|
142
|
+
(far) => void harbor.bind(far, s, true), // a dialer's claims, each proven at its door: held here, reachable through this socket
|
|
143
|
+
() => {
|
|
144
|
+
harbor.unbind(s);
|
|
145
|
+
quo.sockets.delete(s);
|
|
146
|
+
},
|
|
147
|
+
);
|
|
148
|
+
quo.sockets.add(s);
|
|
149
|
+
s.announce([...harbor.doors.keys()]);
|
|
150
|
+
});
|
|
151
|
+
});
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
// Node's request as a `Request`: the one translation in, at the daemon's own
|
|
155
|
+
// door. A method that carries no body carries none here either, since the
|
|
156
|
+
// web shape refuses one.
|
|
157
|
+
function asRequest(req: import('node:http').IncomingMessage, url: URL): Request {
|
|
158
|
+
const headers = new Headers();
|
|
159
|
+
for (const [k, v] of Object.entries(req.headers)) {
|
|
160
|
+
if (v === undefined) continue;
|
|
161
|
+
if (Array.isArray(v)) for (const one of v) headers.append(k, one);
|
|
162
|
+
else headers.set(k, v);
|
|
163
|
+
}
|
|
164
|
+
const method = req.method ?? 'GET';
|
|
165
|
+
const bodied = method !== 'GET' && method !== 'HEAD';
|
|
166
|
+
return new Request(url, {
|
|
167
|
+
method,
|
|
168
|
+
headers,
|
|
169
|
+
...(bodied ? { body: Readable.toWeb(req) as ReadableStream<Uint8Array>, duplex: 'half' } : {}),
|
|
170
|
+
} as RequestInit);
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
// And the one translation out.
|
|
174
|
+
async function writeResponse(out: Response, res: import('node:http').ServerResponse): Promise<void> {
|
|
175
|
+
const headers: Record<string, string | string[]> = {};
|
|
176
|
+
out.headers.forEach((v, k) => {
|
|
177
|
+
headers[k] = k === 'set-cookie' ? [...(Array.isArray(headers[k]) ? (headers[k] as string[]) : []), v] : v;
|
|
178
|
+
});
|
|
179
|
+
res.writeHead(out.status, headers);
|
|
180
|
+
if (!out.body) return void res.end();
|
|
181
|
+
const reader = out.body.getReader();
|
|
182
|
+
for (;;) {
|
|
183
|
+
const { done, value } = await reader.read();
|
|
184
|
+
if (done) break;
|
|
185
|
+
res.write(Buffer.from(value));
|
|
186
|
+
}
|
|
187
|
+
res.end();
|
|
188
|
+
}
|
package/harbor/idb.ts
ADDED
|
Binary file
|