@townco/cli 0.1.124 → 0.1.125
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/dist/index.js +0 -0
- package/package.json +9 -9
- package/dist/lib/proxy-server.d.ts +0 -15
- package/dist/lib/proxy-server.js +0 -96
package/dist/index.js
CHANGED
|
File without changes
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@townco/cli",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.125",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"bin": {
|
|
6
6
|
"town": "./dist/index.js"
|
|
@@ -15,7 +15,7 @@
|
|
|
15
15
|
"build": "tsgo"
|
|
16
16
|
},
|
|
17
17
|
"devDependencies": {
|
|
18
|
-
"@townco/tsconfig": "0.1.
|
|
18
|
+
"@townco/tsconfig": "0.1.117",
|
|
19
19
|
"@types/archiver": "^7.0.0",
|
|
20
20
|
"@types/bun": "^1.3.1",
|
|
21
21
|
"@types/ignore-walk": "^4.0.3",
|
|
@@ -24,13 +24,13 @@
|
|
|
24
24
|
"dependencies": {
|
|
25
25
|
"@optique/core": "^0.6.2",
|
|
26
26
|
"@optique/run": "^0.6.2",
|
|
27
|
-
"@townco/agent": "0.1.
|
|
28
|
-
"@townco/apiclient": "0.0.
|
|
29
|
-
"@townco/core": "0.0.
|
|
30
|
-
"@townco/debugger": "0.1.
|
|
31
|
-
"@townco/env": "0.1.
|
|
32
|
-
"@townco/secret": "0.1.
|
|
33
|
-
"@townco/ui": "0.1.
|
|
27
|
+
"@townco/agent": "0.1.128",
|
|
28
|
+
"@townco/apiclient": "0.0.40",
|
|
29
|
+
"@townco/core": "0.0.98",
|
|
30
|
+
"@townco/debugger": "0.1.76",
|
|
31
|
+
"@townco/env": "0.1.70",
|
|
32
|
+
"@townco/secret": "0.1.120",
|
|
33
|
+
"@townco/ui": "0.1.120",
|
|
34
34
|
"@trpc/client": "^11.7.2",
|
|
35
35
|
"archiver": "^7.0.1",
|
|
36
36
|
"eventsource": "^4.1.0",
|
|
@@ -1,15 +0,0 @@
|
|
|
1
|
-
import http from "node:http";
|
|
2
|
-
import type { createLogger } from "@townco/core";
|
|
3
|
-
export interface ProxyServerOptions {
|
|
4
|
-
port: number;
|
|
5
|
-
vitePort: number;
|
|
6
|
-
agentPort: number;
|
|
7
|
-
basicAuthUser: string | undefined;
|
|
8
|
-
basicAuthPass: string | undefined;
|
|
9
|
-
logger: ReturnType<typeof createLogger>;
|
|
10
|
-
}
|
|
11
|
-
export interface ProxyServer {
|
|
12
|
-
server: http.Server;
|
|
13
|
-
stop: () => Promise<void>;
|
|
14
|
-
}
|
|
15
|
-
export declare function createProxyServer(options: ProxyServerOptions): ProxyServer;
|
package/dist/lib/proxy-server.js
DELETED
|
@@ -1,96 +0,0 @@
|
|
|
1
|
-
import crypto from "node:crypto";
|
|
2
|
-
import http from "node:http";
|
|
3
|
-
import httpProxy from "http-proxy";
|
|
4
|
-
// Agent routes that should be proxied to the agent server
|
|
5
|
-
const AGENT_ROUTES = [
|
|
6
|
-
"/rpc",
|
|
7
|
-
"/events",
|
|
8
|
-
"/health",
|
|
9
|
-
"/sessions",
|
|
10
|
-
"/sandbox",
|
|
11
|
-
"/static",
|
|
12
|
-
"/logs",
|
|
13
|
-
];
|
|
14
|
-
function timingSafeEqual(a, b) {
|
|
15
|
-
const aBuf = Buffer.from(a);
|
|
16
|
-
const bBuf = Buffer.from(b);
|
|
17
|
-
// timingSafeEqual requires equal lengths, so pad the shorter buffer
|
|
18
|
-
const maxLen = Math.max(aBuf.length, bBuf.length);
|
|
19
|
-
const paddedA = Buffer.alloc(maxLen);
|
|
20
|
-
const paddedB = Buffer.alloc(maxLen);
|
|
21
|
-
aBuf.copy(paddedA);
|
|
22
|
-
bBuf.copy(paddedB);
|
|
23
|
-
// Always do both comparisons to avoid leaking length information via timing
|
|
24
|
-
const lengthsMatch = aBuf.length === bBuf.length;
|
|
25
|
-
const contentsMatch = crypto.timingSafeEqual(paddedA, paddedB);
|
|
26
|
-
return lengthsMatch && contentsMatch;
|
|
27
|
-
}
|
|
28
|
-
function getTarget(pathname, options) {
|
|
29
|
-
// Check for agent routes
|
|
30
|
-
for (const route of AGENT_ROUTES) {
|
|
31
|
-
if (pathname === route || pathname.startsWith(`${route}/`)) {
|
|
32
|
-
return `http://localhost:${options.agentPort}`;
|
|
33
|
-
}
|
|
34
|
-
}
|
|
35
|
-
// Default: Vite server
|
|
36
|
-
return `http://localhost:${options.vitePort}`;
|
|
37
|
-
}
|
|
38
|
-
export function createProxyServer(options) {
|
|
39
|
-
const { port, basicAuthUser, basicAuthPass, logger } = options;
|
|
40
|
-
const proxy = httpProxy.createProxyServer({
|
|
41
|
-
ws: true,
|
|
42
|
-
changeOrigin: true,
|
|
43
|
-
// Don't add X-Forwarded headers
|
|
44
|
-
xfwd: false,
|
|
45
|
-
});
|
|
46
|
-
// Handle proxy errors
|
|
47
|
-
proxy.on("error", (err, req, res) => {
|
|
48
|
-
logger.error("Proxy error", { error: err.message, url: req.url });
|
|
49
|
-
if (res && "writeHead" in res) {
|
|
50
|
-
res.writeHead(502, {
|
|
51
|
-
"Content-Type": "text/plain",
|
|
52
|
-
});
|
|
53
|
-
res.end("Bad Gateway");
|
|
54
|
-
}
|
|
55
|
-
});
|
|
56
|
-
// Build expected auth header if auth is configured
|
|
57
|
-
const expectedAuth = basicAuthUser && basicAuthPass
|
|
58
|
-
? `Basic ${Buffer.from(`${basicAuthUser}:${basicAuthPass}`).toString("base64")}`
|
|
59
|
-
: null;
|
|
60
|
-
const server = http.createServer((req, res) => {
|
|
61
|
-
// Basic auth check
|
|
62
|
-
if (expectedAuth) {
|
|
63
|
-
const authHeader = req.headers.authorization ?? "";
|
|
64
|
-
if (!timingSafeEqual(authHeader, expectedAuth)) {
|
|
65
|
-
res.statusCode = 401;
|
|
66
|
-
res.setHeader("WWW-Authenticate", "Basic");
|
|
67
|
-
res.end("Unauthorized");
|
|
68
|
-
return;
|
|
69
|
-
}
|
|
70
|
-
}
|
|
71
|
-
const url = new URL(req.url || "/", `http://localhost:${port}`);
|
|
72
|
-
const target = getTarget(url.pathname, options);
|
|
73
|
-
// Proxy the request
|
|
74
|
-
proxy.web(req, res, { target });
|
|
75
|
-
});
|
|
76
|
-
// Handle WebSocket upgrades (for Vite HMR)
|
|
77
|
-
server.on("upgrade", (req, socket, head) => {
|
|
78
|
-
// WebSocket upgrades go to Vite for HMR
|
|
79
|
-
// Note: We don't do auth on WebSocket upgrades since Vite HMR is internal
|
|
80
|
-
const viteTarget = `http://localhost:${options.vitePort}`;
|
|
81
|
-
proxy.ws(req, socket, head, { target: viteTarget });
|
|
82
|
-
});
|
|
83
|
-
server.on("error", (err) => {
|
|
84
|
-
logger.error("Proxy server error", { error: err.message, port });
|
|
85
|
-
});
|
|
86
|
-
server.listen(port, () => {
|
|
87
|
-
logger.info("Proxy server started", { port });
|
|
88
|
-
});
|
|
89
|
-
const stop = () => {
|
|
90
|
-
return new Promise((resolve) => {
|
|
91
|
-
proxy.close();
|
|
92
|
-
server.close(() => resolve());
|
|
93
|
-
});
|
|
94
|
-
};
|
|
95
|
-
return { server, stop };
|
|
96
|
-
}
|