@catheadowl/ukp 0.2.3 → 0.2.4
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/bin/ukp.js +31 -11
- package/package.json +1 -1
- package/src/capabilities/propose.ts +1 -1
- package/src/capabilities/read.ts +1 -1
- package/src/capabilities/remote-client.ts +163 -52
- package/src/capabilities/rg.ts +1 -1
- package/src/capabilities/search.ts +2 -2
- package/src/cli.ts +72 -3
- package/src/commands/guide-content/propose.txt +1 -1
- package/src/commands/guide-content/remote.txt +6 -6
- package/src/commands/guide-content/service-qmd.txt +1 -1
- package/src/commands/inventory.ts +182 -36
- package/src/commands/propose.ts +1 -1
- package/src/commands/read.ts +6 -6
- package/src/commands/serve-task.ts +17 -17
- package/src/commands/serve.ts +22 -22
- package/src/registry.ts +2 -2
- package/src/server.ts +4 -4
|
@@ -48,15 +48,15 @@ export function printTaskPreflightError(input: {
|
|
|
48
48
|
allowAnonymous: boolean;
|
|
49
49
|
}): string | undefined {
|
|
50
50
|
if (input.platform !== "win32") {
|
|
51
|
-
return "--print-task is Windows-only; on Linux prefer systemd socket activation (ukp serve --systemd-socket)
|
|
51
|
+
return "--print-task is Windows-only; on Linux prefer systemd socket activation (ukp serve --systemd-socket) - the deployment handbook carries that recipe";
|
|
52
52
|
}
|
|
53
53
|
const loopback =
|
|
54
54
|
input.host === "127.0.0.1" || input.host === "localhost" || input.host === "::1" || input.host === "[::1]";
|
|
55
55
|
if (!loopback && !input.hasTls) {
|
|
56
|
-
return "refusing to print an off-loopback door without TLS: clients refuse to register plain-http urls
|
|
56
|
+
return "refusing to print an off-loopback door without TLS: clients refuse to register plain-http urls - pass --tls (self-signed, pinned at registration) or --tls-cert/--tls-key, or bind loopback behind a TLS-terminating proxy";
|
|
57
57
|
}
|
|
58
58
|
if (input.allowAnonymous && !loopback) {
|
|
59
|
-
return "refusing to print this shape: --allow-anonymous is loopback-only and serve would refuse it at task start
|
|
59
|
+
return "refusing to print this shape: --allow-anonymous is loopback-only and serve would refuse it at task start - set the token in the generated script instead";
|
|
60
60
|
}
|
|
61
61
|
return undefined;
|
|
62
62
|
}
|
|
@@ -86,10 +86,10 @@ function parentDirOf(path: string): string | undefined {
|
|
|
86
86
|
export function renderServeTaskArtifacts(input: ServeTaskInput): string {
|
|
87
87
|
const serveLine = serveCommandLine(input);
|
|
88
88
|
const out: string[] = [
|
|
89
|
-
"ukp serve --print-task
|
|
89
|
+
"ukp serve --print-task - Windows resident-door artifacts",
|
|
90
90
|
"",
|
|
91
91
|
"Print-only: review these, then apply them yourself. UKP installs nothing,",
|
|
92
|
-
"starts nothing, and supervises nothing
|
|
92
|
+
"starts nothing, and supervises nothing - the door's lifecycle belongs to",
|
|
93
93
|
"you and your process manager.",
|
|
94
94
|
"",
|
|
95
95
|
];
|
|
@@ -97,7 +97,7 @@ export function renderServeTaskArtifacts(input: ServeTaskInput): string {
|
|
|
97
97
|
if (input.tls?.mode === "certificates") {
|
|
98
98
|
const certDir = parentDirOf(input.tls.certPath);
|
|
99
99
|
out.push(
|
|
100
|
-
"0) Certificate
|
|
100
|
+
"0) Certificate - generate ONCE (Git for Windows' openssl works; this",
|
|
101
101
|
" avoids any runtime openssl dependency of --tls):",
|
|
102
102
|
"",
|
|
103
103
|
" openssl req -x509 -newkey rsa:2048 -nodes -days 825 -keyout",
|
|
@@ -115,7 +115,7 @@ export function renderServeTaskArtifacts(input: ServeTaskInput): string {
|
|
|
115
115
|
}
|
|
116
116
|
|
|
117
117
|
out.push(
|
|
118
|
-
"1) Start script
|
|
118
|
+
"1) Start script - save as %USERPROFILE%\\.ukp\\start-door.cmd",
|
|
119
119
|
" (write it with a real editor and CRLF line endings; writing cmd",
|
|
120
120
|
" files over ssh echo mangles % escaping)",
|
|
121
121
|
"",
|
|
@@ -125,13 +125,13 @@ export function renderServeTaskArtifacts(input: ServeTaskInput): string {
|
|
|
125
125
|
" rem (e.g. openssl rand -hex 32), paste it in, keep this file private.",
|
|
126
126
|
" set \"UKP_SERVE_TOKEN=<paste-your-token>\"",
|
|
127
127
|
" rem ukp resolves through the logged-on task's per-user PATH; the",
|
|
128
|
-
" rem launcher finds bun itself
|
|
128
|
+
" rem launcher finds bun itself - no PATH export needed.",
|
|
129
129
|
" if not exist \"%USERPROFILE%\\.ukp\" mkdir \"%USERPROFILE%\\.ukp\"",
|
|
130
130
|
` ${serveLine} >> "%USERPROFILE%\\.ukp\\door.log" 2>&1`,
|
|
131
131
|
"",
|
|
132
|
-
"2) Hidden launcher
|
|
132
|
+
"2) Hidden launcher - save as %USERPROFILE%\\.ukp\\start-door-hidden.vbs",
|
|
133
133
|
" (CRLF and a real editor again: the vbs carries literal % signs that",
|
|
134
|
-
" ssh echo would expand
|
|
134
|
+
" ssh echo would expand - copy the file instead)",
|
|
135
135
|
"",
|
|
136
136
|
" ' UKP door hidden launcher: runs start-door.cmd with NO visible",
|
|
137
137
|
" ' window (hidden at process creation - nothing flashes), captures",
|
|
@@ -150,7 +150,7 @@ export function renderServeTaskArtifacts(input: ServeTaskInput): string {
|
|
|
150
150
|
" Next",
|
|
151
151
|
" WScript.Quit rc",
|
|
152
152
|
"",
|
|
153
|
-
"3) Scheduled task
|
|
153
|
+
"3) Scheduled task - starts the door at LOGON, hidden",
|
|
154
154
|
" (create it from an elevated shell: creating an ONLOGON task from a",
|
|
155
155
|
" plain shell fails with Access denied)",
|
|
156
156
|
"",
|
|
@@ -167,29 +167,29 @@ export function renderServeTaskArtifacts(input: ServeTaskInput): string {
|
|
|
167
167
|
"- --tls self-signs at first start using an openssl on PATH (Git",
|
|
168
168
|
" for Windows' openssl qualifies). On a host with no openssl",
|
|
169
169
|
" anywhere, pre-generate the certificate once instead: re-run with",
|
|
170
|
-
" --tls-cert/--tls-key
|
|
170
|
+
" --tls-cert/--tls-key - the handbook's Windows section carries",
|
|
171
171
|
" that recipe.",
|
|
172
172
|
]
|
|
173
173
|
: []),
|
|
174
174
|
"- No visible window, by design: the hidden launcher starts the console",
|
|
175
175
|
" hidden at process creation (nothing ever flashes on the desktop) and",
|
|
176
|
-
" captures everything to door.log
|
|
176
|
+
" captures everything to door.log - that redirect is the paper trail (a",
|
|
177
177
|
" silent EADDRINUSE exit leaves a line).",
|
|
178
178
|
"- Crash self-recovery is the launcher's bounded retry: a non-zero exit",
|
|
179
179
|
" is retried up to 3 times, 30s apart; exhausted retries leave the",
|
|
180
180
|
" failure visible (non-zero task result + door.log). Do not rely on",
|
|
181
|
-
" Task Scheduler's restart-on-failure setting
|
|
181
|
+
" Task Scheduler's restart-on-failure setting - it does not fire on",
|
|
182
182
|
" exit codes.",
|
|
183
183
|
"- To restart the door by hand (new token, ukp upgrade, new cert):",
|
|
184
184
|
" taskkill /PID <door-pid> /T /F, then schtasks /Run /TN ukp-door",
|
|
185
185
|
" (schtasks /End does not reliably kill the process tree).",
|
|
186
|
-
"- LOGON, not boot: the door starts when someone logs on
|
|
186
|
+
"- LOGON, not boot: the door starts when someone logs on - nobody",
|
|
187
187
|
" logged on means no door. Unattended-boot always-on needs a service",
|
|
188
|
-
" wrapper (WinSW-class)
|
|
188
|
+
" wrapper (WinSW-class) - deliberately outside this recipe; prefer the",
|
|
189
189
|
" ssh:// path or a Linux host (systemd socket activation) for that.",
|
|
190
190
|
"- Re-run ukp serve --print-task with different flags to regenerate;",
|
|
191
191
|
" edits land by saving the files and re-running schtasks /Run.",
|
|
192
|
-
"- Full recipes and hardening: the deployment handbook
|
|
192
|
+
"- Full recipes and hardening: the deployment handbook -",
|
|
193
193
|
" docs/remote-deployment.md in this package, or",
|
|
194
194
|
" https://github.com/CatheadOwl/ukp/blob/main/docs/remote-deployment.md",
|
|
195
195
|
"",
|
package/src/commands/serve.ts
CHANGED
|
@@ -34,23 +34,23 @@ function parseServeTokens(raw: string | undefined): string[] {
|
|
|
34
34
|
* over `/e/<name>/` routing. */
|
|
35
35
|
export const SERVE_SPEC: UkpCommandSpec = {
|
|
36
36
|
name: "serve",
|
|
37
|
-
summary: "serve one endpoint
|
|
37
|
+
summary: "serve one endpoint - or the whole registry as a host door, one HTTP server for every endpoint - for remote UKP clients",
|
|
38
38
|
group: "operations",
|
|
39
39
|
description:
|
|
40
|
-
"Expose a registered endpoint over HTTP using the ukp-remote wire, or
|
|
41
|
-
usage: "[--endpoint <name>] [--host <addr>] [--port <n>] [--tls [--tls-san <ip|dns>]
|
|
40
|
+
"Expose a registered endpoint over HTTP using the ukp-remote wire, or - without --endpoint - serve every local endpoint as one host door routed by name.",
|
|
41
|
+
usage: "[--endpoint <name>] [--host <addr>] [--port <n>] [--tls [--tls-san <ip|dns>]... | --tls-cert <pem> --tls-key <pem>] [--max-idle <seconds>] [--systemd-socket] [--print-task]",
|
|
42
42
|
options: [
|
|
43
43
|
{ flags: "--endpoint <name>", help: "the registered endpoint to expose; omit it to serve the whole registry as a host door (/e/<name>/ routing, all endpoints, one port)" },
|
|
44
44
|
{ flags: "--host <addr>", help: "listen address (default 127.0.0.1, loopback only without a token)" },
|
|
45
45
|
{ flags: "--port <n>", help: "listen port (default 8570)" },
|
|
46
46
|
{ flags: "--tls", help: "serve HTTPS with a self-signed identity (auto-generated under .ukp/tls/, SAN covers this host's addresses; clients pin it at registration)" },
|
|
47
47
|
{ flags: "--tls-san <ip|dns>", help: "extra SAN entry for the --tls self-signed identity (repeatable): a public/NAT IP or hostname no NIC of this host carries; a persisted certificate missing an entry is re-signed over the same key (pin unchanged, pinned clients re-anchor)", multi: true },
|
|
48
|
-
{ flags: "--tls-cert <pem>", help: "TLS certificate (chain) PEM path
|
|
48
|
+
{ flags: "--tls-cert <pem>", help: "TLS certificate (chain) PEM path - Let's Encrypt, mkcert, or a private CA; pair with --tls-key" },
|
|
49
49
|
{ flags: "--tls-key <pem>", help: "TLS private key PEM path; pair with --tls-cert" },
|
|
50
50
|
{ flags: "--allow-anonymous", help: "permit tokenless access on loopback (local testing, or an ssh-forwarded host door where SSH carries encryption and auth; reverse-proxy deployments still require UKP_SERVE_TOKEN)" },
|
|
51
|
-
{ flags: "--max-idle <seconds>", help: "exit after <seconds> without requests (self-reap; the orphan backstop for on-demand-woken doors
|
|
52
|
-
{ flags: "--systemd-socket", help: "serve on the systemd socket-activation listener (LISTEN_FDS fd 3) instead of binding a port
|
|
53
|
-
{ flags: "--print-task", help: "Windows: print this door's process-manager artifacts (start script, hidden launcher, Task Scheduler command, firewall rule) instead of serving
|
|
51
|
+
{ flags: "--max-idle <seconds>", help: "exit after <seconds> without requests (self-reap; the orphan backstop for on-demand-woken doors - fractional values accepted for tests)" },
|
|
52
|
+
{ flags: "--systemd-socket", help: "serve on the systemd socket-activation listener (LISTEN_FDS fd 3) instead of binding a port - the port belongs to your .socket unit; Linux-only" },
|
|
53
|
+
{ flags: "--print-task", help: "Windows: print this door's process-manager artifacts (start script, hidden launcher, Task Scheduler command, firewall rule) instead of serving - review and apply them yourself; nothing is installed or started for you, and the token is yours to paste (never printed)" },
|
|
54
54
|
],
|
|
55
55
|
helpSuffix: [
|
|
56
56
|
"",
|
|
@@ -58,9 +58,9 @@ export const SERVE_SPEC: UkpCommandSpec = {
|
|
|
58
58
|
` GET ${DISCOVERY_PATH} discovery document (manifest projection,`,
|
|
59
59
|
" protocol version, instance identity)",
|
|
60
60
|
" POST /v1/search {query, limit} -> ukp.search.v1 envelope",
|
|
61
|
-
" GET /v1/read?ref
|
|
61
|
+
" GET /v1/read?ref=...|uri=... endpoint-relative ref or ukp:// URI",
|
|
62
62
|
" GET /v1/nav?path=&depth= markdown route view (ukp.nav.v1)",
|
|
63
|
-
" GET /v1/rg?query
|
|
63
|
+
" GET /v1/rg?query=... lexical search (ukp.rg.v1, ukp_uri handoff)",
|
|
64
64
|
"",
|
|
65
65
|
"Wire (ukp-remote v1), host door (no --endpoint):",
|
|
66
66
|
` GET ${DISCOVERY_PATH} door document (scope:"host", endpoint roster)`,
|
|
@@ -75,26 +75,26 @@ export const SERVE_SPEC: UkpCommandSpec = {
|
|
|
75
75
|
" --allow-anonymous, loopback binds only. The discovery document stays",
|
|
76
76
|
" public. A reverse proxy on the same host forwards from the public side",
|
|
77
77
|
" to the loopback bind, so proxy deployments treat the token as",
|
|
78
|
-
" mandatory
|
|
78
|
+
" mandatory - serve cannot see past its own bind address.",
|
|
79
79
|
"",
|
|
80
80
|
" Loopback-without-token covers testing/dogfood AND the ssh door",
|
|
81
81
|
" deployment: bind the door on the remote host's loopback and let ssh",
|
|
82
82
|
" forwarding carry encryption and authentication (clients register",
|
|
83
|
-
" 'ukp register --url ssh://<host>'
|
|
83
|
+
" 'ukp register --url ssh://<host>' - zero tokens, docker",
|
|
84
84
|
" DOCKER_HOST=ssh:// posture). It is not the way to consume a",
|
|
85
|
-
" same-machine endpoint
|
|
85
|
+
" same-machine endpoint - register its local path instead.",
|
|
86
86
|
" TLS: pass --tls to serve HTTPS with a self-signed identity",
|
|
87
|
-
" (generated under .ukp/tls/
|
|
88
|
-
" mode
|
|
87
|
+
" (generated under .ukp/tls/ - under the registry directory in door",
|
|
88
|
+
" mode -, SAN covers this host's addresses; remote clients TOFU-pin it",
|
|
89
89
|
" at registration and refresh by re-registering), or --tls-cert/--tls-key",
|
|
90
|
-
" for your own certificate (Let's Encrypt
|
|
91
|
-
" 2026-01
|
|
90
|
+
" for your own certificate (Let's Encrypt - IP certs available since",
|
|
91
|
+
" 2026-01 -, mkcert, a private CA). Plain HTTP remains loopback-only by",
|
|
92
92
|
" admission; public exposure needs TLS or the ssh:// transport.",
|
|
93
93
|
"",
|
|
94
94
|
" A cloud NAT/EIP host's public IP is on no NIC (--tls alone cannot",
|
|
95
95
|
" cover it): add --tls-san <public-ip> next to --tls. Repeatable; DNS",
|
|
96
96
|
" names accepted. The persisted certificate re-signs over the same key",
|
|
97
|
-
" when a new entry appears
|
|
97
|
+
" when a new entry appears - the pin is unchanged and pinned clients",
|
|
98
98
|
" re-anchor transparently; dropping entries never re-signs.",
|
|
99
99
|
"",
|
|
100
100
|
].join("\n"),
|
|
@@ -136,7 +136,7 @@ function toParsedServe(parsed: KitParsed): ParsedServe {
|
|
|
136
136
|
}
|
|
137
137
|
const printTask = options.printTask === true;
|
|
138
138
|
if (printTask && systemdSocket) {
|
|
139
|
-
throw new KitUsageError("--print-task is the Windows resident form; --systemd-socket is the Linux one (systemd holds the port
|
|
139
|
+
throw new KitUsageError("--print-task is the Windows resident form; --systemd-socket is the Linux one (systemd holds the port - see the deployment handbook)");
|
|
140
140
|
}
|
|
141
141
|
let maxIdleSeconds: number | undefined;
|
|
142
142
|
if (options.maxIdle !== undefined) {
|
|
@@ -183,10 +183,10 @@ export function renderServeBanner(info: ServeInfo): string {
|
|
|
183
183
|
`serving host door (ukp-remote v1)`,
|
|
184
184
|
` listening: ${info.url}`,
|
|
185
185
|
` discovery: ${info.url.startsWith("http") ? `${info.url}${DISCOVERY_PATH}` : info.url} (host door)`,
|
|
186
|
-
` endpoints: ${info.door!.endpoints.length > 0 ? info.door!.endpoints.join(", ") : "(none
|
|
186
|
+
` endpoints: ${info.door!.endpoints.length > 0 ? info.door!.endpoints.join(", ") : "(none - register endpoints on this host)"}`,
|
|
187
187
|
` write: ${info.door!.write.length > 0 ? info.door!.write.join(", ") + " (propose via PUT /e/<name>/v1/propose/<id>)" : "(no endpoint declares propose)"}`,
|
|
188
188
|
` auth: ${info.authRequired ? "bearer token required" : "no token (loopback bind; ssh-forwarded clients authenticate by SSH key)"}`,
|
|
189
|
-
` rg: ${info.rg === "ok" ? "ok" : "missing (rg calls skip with a warning
|
|
189
|
+
` rg: ${info.rg === "ok" ? "ok" : "missing (rg calls skip with a warning - install ripgrep on this door's PATH)"}`,
|
|
190
190
|
...(info.maxIdleSeconds !== undefined
|
|
191
191
|
? [` idle: exits after ${info.maxIdleSeconds}s without requests (--max-idle)`]
|
|
192
192
|
: []),
|
|
@@ -201,7 +201,7 @@ export function renderServeBanner(info: ServeInfo): string {
|
|
|
201
201
|
` listening: ${info.url}`,
|
|
202
202
|
` discovery: ${info.url.startsWith("http") ? `${info.url}${DISCOVERY_PATH}` : info.url}`,
|
|
203
203
|
` auth: ${info.authRequired ? "bearer token required" : "no token (loopback only)"}`,
|
|
204
|
-
` rg: ${info.rg === "ok" ? "ok" : "missing (rg calls skip with a warning
|
|
204
|
+
` rg: ${info.rg === "ok" ? "ok" : "missing (rg calls skip with a warning - install ripgrep on this door's PATH)"}`,
|
|
205
205
|
...(info.maxIdleSeconds !== undefined
|
|
206
206
|
? [` idle: exits after ${info.maxIdleSeconds}s without requests (--max-idle)`]
|
|
207
207
|
: []),
|
|
@@ -295,7 +295,7 @@ export function executeServeCommand(
|
|
|
295
295
|
// premise of --allow-anonymous is unverifiable here (RQ-18 review P1).
|
|
296
296
|
if (systemdSocket && tokens.length === 0) {
|
|
297
297
|
throw new Error(
|
|
298
|
-
"refusing to serve on --systemd-socket without a token: the listener's bind address belongs to the socket unit and may be public
|
|
298
|
+
"refusing to serve on --systemd-socket without a token: the listener's bind address belongs to the socket unit and may be public - tokenless loopback serving cannot be verified here; set UKP_SERVE_TOKEN",
|
|
299
299
|
);
|
|
300
300
|
}
|
|
301
301
|
const decision = serveAuthDecision(host, tokens, allowAnonymous);
|
package/src/registry.ts
CHANGED
|
@@ -230,7 +230,7 @@ export function assertRegistrableRemoteUrl(raw: string): void {
|
|
|
230
230
|
+ `${parts.endpointName !== undefined ? `/${parts.endpointName}` : ""}`;
|
|
231
231
|
throw new RegistryError(
|
|
232
232
|
`ssh:// urls take no port: the woken door listens on a client-chosen loopback port and the url port selects nothing`
|
|
233
|
-
+ `
|
|
233
|
+
+ ` - register '${portless}' instead`
|
|
234
234
|
+ ` (for a non-standard sshd port, use an ssh config Host alias)`,
|
|
235
235
|
);
|
|
236
236
|
}
|
|
@@ -240,7 +240,7 @@ export class RegistryBusyError extends RegistryError {
|
|
|
240
240
|
constructor(path: string) {
|
|
241
241
|
super(
|
|
242
242
|
`registry_busy: ${path} (another ukp process holds the registry lock; ` +
|
|
243
|
-
`stale locks are reclaimed automatically
|
|
243
|
+
`stale locks are reclaimed automatically - close other ukp commands or retry shortly)`,
|
|
244
244
|
);
|
|
245
245
|
this.name = "RegistryBusyError";
|
|
246
246
|
}
|
package/src/server.ts
CHANGED
|
@@ -407,7 +407,7 @@ function parseReadParams(
|
|
|
407
407
|
pin: string | null,
|
|
408
408
|
): { request: ReadRequest } | { error: string; class?: string } {
|
|
409
409
|
if ((ref === null) === (uri === null)) {
|
|
410
|
-
return { error: "exactly one of 'ref' (endpoint-relative) or 'uri' (ukp
|
|
410
|
+
return { error: "exactly one of 'ref' (endpoint-relative) or 'uri' (ukp://...) is required" };
|
|
411
411
|
}
|
|
412
412
|
const args = uri !== null
|
|
413
413
|
? [
|
|
@@ -546,14 +546,14 @@ export function parseListenFds(env: NodeJS.ProcessEnv): { fd: number } | { error
|
|
|
546
546
|
};
|
|
547
547
|
}
|
|
548
548
|
if (Number(env.LISTEN_PID) !== process.pid) {
|
|
549
|
-
return { error: `LISTEN_PID ${env.LISTEN_PID} does not match this process (${process.pid})
|
|
549
|
+
return { error: `LISTEN_PID ${env.LISTEN_PID} does not match this process (${process.pid}) - inherited activation variables belong to another process` };
|
|
550
550
|
}
|
|
551
551
|
const count = Number(env.LISTEN_FDS);
|
|
552
552
|
if (!Number.isSafeInteger(count) || count < 1) {
|
|
553
553
|
return { error: `LISTEN_FDS=${String(env.LISTEN_FDS)} is not a positive integer` };
|
|
554
554
|
}
|
|
555
555
|
if (count !== 1) {
|
|
556
|
-
return { error: `expected exactly one listening fd (LISTEN_FDS=1), got ${count}
|
|
556
|
+
return { error: `expected exactly one listening fd (LISTEN_FDS=1), got ${count} - run one socket unit per serve instance` };
|
|
557
557
|
}
|
|
558
558
|
delete env.LISTEN_FDS;
|
|
559
559
|
delete env.LISTEN_PID;
|
|
@@ -645,7 +645,7 @@ function startServeListener(
|
|
|
645
645
|
isSocket = false;
|
|
646
646
|
}
|
|
647
647
|
if (!isSocket) {
|
|
648
|
-
throw new ServeSetupError(`fd ${parsed.fd} is not an open socket
|
|
648
|
+
throw new ServeSetupError(`fd ${parsed.fd} is not an open socket - socket activation must pass a bound listening socket`);
|
|
649
649
|
}
|
|
650
650
|
const server = Bun.serve({ hostname: "127.0.0.1", port: 0, ...tls, fetch });
|
|
651
651
|
const acceptor = netCreateServer();
|