packages/dev-proxy/README.md
Generic Hono-based development proxy for frontend projects. The package does not ship any product-specific routes, cookie names, or environment variable conventions. Every proxied path and upstream target is declared in a local config file.
pnpm add -D @langgenius/dev-proxy
Add a script in your frontend project:
{
"scripts": {
"dev:proxy": "dev-proxy --config ./dev-proxy.config.ts --env-file ./.env.local"
}
}
Run it with:
pnpm dev:proxy
dev-proxy --config ./dev-proxy.config.ts
Supported options:
--config, -c: config file path. Defaults to dev-proxy.config.ts.--env-file: load environment variables before evaluating the config file.--host: override server.host from config.--port: override server.port from config.--watch: reload config and env file changes. Enabled by default.--no-watch: disable config and env file reloads.--help, -h: print help.--target is not supported. Put targets in the config file so routes and upstreams stay explicit.
The CLI watches the config file and the explicit --env-file by default. Route, CORS, target, and cookie rewrite changes are applied in the running process. If the resolved host or port changes, the proxy closes the old server and starts a new one.
import { defineDevProxyConfig } from '@langgenius/dev-proxy'
export default defineDevProxyConfig({
server: {
host: '127.0.0.1',
port: 5001,
},
routes: [
{
paths: '/api',
target: 'https://example.com',
},
],
cors: {
allowedOrigins: 'local',
},
})
Config files can be .ts, .mts, .js, or .mjs.
routes are matched in declaration order. The first matching route wins. Each configured path matches both the exact path and all child paths, so paths: '/api' matches /api, /api/apps, and /api/apps/123.
By default, credentialed CORS is allowed for local development origins such as localhost, 127.0.0.1, and ::1. To restrict it to specific origins:
cors: {
allowedOrigins: ['http://localhost:3000'],
}
Use this when a local frontend should call an online backend through one proxy server. For example, the frontend calls http://127.0.0.1:5001/api/apps, and the proxy forwards it to https://cloud.example.com/api/apps.
import { defineDevProxyConfig } from '@langgenius/dev-proxy'
const target = process.env.DEV_PROXY_TARGET || 'https://cloud.example.com'
export default defineDevProxyConfig({
server: {
host: process.env.DEV_PROXY_HOST || '127.0.0.1',
port: Number(process.env.DEV_PROXY_PORT || 5001),
},
routes: [
{
paths: '/api',
target,
},
],
})
Optional .env:
DEV_PROXY_TARGET=https://cloud.example.com
DEV_PROXY_HOST=127.0.0.1
DEV_PROXY_PORT=5001
Command:
dev-proxy --config ./dev-proxy.config.ts --env-file ./.env.local
Edits to ./.env.local reload the proxy automatically.
Use this when one frontend needs to talk to two different local services. For example:
/console/api/* goes to a local console backend at http://127.0.0.1:5001/api/* goes to a local public API backend at http://127.0.0.1:5002import { defineDevProxyConfig } from '@langgenius/dev-proxy'
const consoleApiTarget = process.env.DEV_PROXY_CONSOLE_API_TARGET || 'http://127.0.0.1:5001'
const publicApiTarget = process.env.DEV_PROXY_PUBLIC_API_TARGET || 'http://127.0.0.1:5002'
export default defineDevProxyConfig({
server: {
host: process.env.DEV_PROXY_HOST || '127.0.0.1',
port: Number(process.env.DEV_PROXY_PORT || 8082),
},
routes: [
{
paths: '/console/api',
target: consoleApiTarget,
},
{
paths: '/api',
target: publicApiTarget,
},
],
})
Optional .env:
DEV_PROXY_CONSOLE_API_TARGET=http://127.0.0.1:5001
DEV_PROXY_PUBLIC_API_TARGET=http://127.0.0.1:5002
DEV_PROXY_HOST=127.0.0.1
DEV_PROXY_PORT=8082
When two route groups overlap, put the more specific one first:
routes: [
{ paths: '/api/enterprise', target: 'http://127.0.0.1:5003' },
{ paths: '/api', target: 'http://127.0.0.1:5002' },
]
Cookie rewriting is opt-in and config-driven. The package does not know any application cookie names.
Use cookieRewrite when an upstream uses secure cookie prefixes such as __Host- or __Secure-, but local development needs cookies to work over http://localhost.
import type { CookieRewriteOptions } from '@langgenius/dev-proxy'
import { defineDevProxyConfig } from '@langgenius/dev-proxy'
const cookieRewrite: CookieRewriteOptions = {
hostPrefixCookies: ['access_token', 'refresh_token', /^passport-/],
}
export default defineDevProxyConfig({
routes: [
{
paths: '/api',
target: 'https://cloud.example.com',
cookieRewrite,
},
],
})
Set cookieRewrite: false to disable cookie rewriting for a route.
When one local proxy can point to multiple online targets, use localCookieScope: 'target-origin'
for auth cookies. The proxy stores configured cookies under target-specific local names,
forwards only the active target's cookies upstream, and can override a stale frontend CSRF
header from the active scoped cookie:
const cookieRewrite: CookieRewriteOptions = {
hostPrefixCookies: ['access_token', 'csrf_token', 'refresh_token'],
localCookieScope: 'target-origin',
csrfHeader: {
cookieName: 'csrf_token',
headerName: 'X-CSRF-Token',
},
}