/** * Normalise app configuration into the rules the predicate reads. * * `/api/` is always present: it is the prefix the framework's own generated * routes use, and an app that dropped it would find its auto-CRUD endpoints * unreachable with no indication why. Configuring `prefixes` ADDS to it. * * Resolve this once at boot rather than per request. `@stacksjs/config` * populates `overrides` asynchronously, so a per-request read would answer * differently depending on how far boot had progressed. */ export declare function resolveApiProxyRules(input?: ApiProxyConfig): ApiProxyRules; /**` * prefix, or a mutating verb. Callers that have resolved the app's * configuration pass it in. */ export declare function isApiBoundRequest(req: Request, pathname: string, rules?: ApiProxyRules): boolean; /** * A one-line summary of what will be forwarded, for the dev server's boot * output. * * Asked for directly in stacksjs/stacks#2230: a 404 on a route you know you * registered is very hard to diagnose when the rule that swallowed it is * invisible. */ export declare function describeApiProxyRules(rules: ApiProxyRules): string; export declare function proxyToBackend(req: Request, backendBase: string, stripPrefix?: string): Promise; /**` traffic goes, or null when there is no safe answer. * * Returning null is the important part. On a shared box `127.0.0.1:` * is not "my API" — it is whichever tenant bound that port first. Several SSR * sites legitimately share one instance, so falling back to the framework-wide * default silently forwards this app's session cookies, login POSTs and form * bodies into a DIFFERENT tenant's process. A 502 with an actionable log beats * misdelivering a visitor's credentials to a stranger. * * So an explicit target wins, and in a deployed environment there is no * fallback at all. Only a local dev machine, where nothing else is listening, * gets to guess. * * Lives here rather than beside the production server because more than one * server needs it: the public site and the dashboard both proxy to the same * API process, and a second copy of this rule is a second place for it to * drift. */ export declare function resolveApiBase(configuredPort?: number, env?: NodeJS.ProcessEnv): string | null; /**` traffic behaves identically * in both topologies (stacksjs/stacks#1950). */ /** The prefix that is always API-bound, with or without configuration. */ export declare const DEFAULT_API_PREFIX: '/api/'; /** * Verbs that never match a static stx page render, so they always belong to * bun-router. Without this rule, `route.post('/subscribe', ...)` declared at * the root hits stx-serve and 404s. */ export declare const DEFAULT_API_METHODS: readonly string[]; /** * What the views server forwards to the API process. * * ## Why this is configuration and not a route lookup * * The obvious fix for stacksjs/stacks#2230 is to ask the router: * `route.getAllowedMethods(pathname)` already answers exactly the right * question. It is not reachable from here. `isApiBoundRequest` is called from * an `onRequest` hook inside the VIEWS process, and the route table is * registered in the API process — a different process in `buddy dev`, and * potentially a different host in production, where `production-server.ts` * proxies to an `apiBase` URL. Importing the app's route files into the views * process to consult them would execute route registration there, pulling the * models and database in with it, and in a split deployment the views site may * not ship that code at all. * * So the app declares it, the way Next's `rewrites()` does. Empty by default, * so nothing changes for an app that does not set it. * * ## The cost of adding a path here * * stx's `onRequest` runs BEFORE static file serving, so any path this matches * permanently shadows a `public/` file of the same name. Adding `/script.js` * means `public/script.js` stops being reachable. That is a fine trade when * the API really does own the path, and a confusing one otherwise, which is * why `describeApiProxyRules` exists and the dev server prints it at boot. */ export declare interface ApiProxyRules { prefixes: string[] paths: string[] methods: Set } /** The shape an app writes in `config/server.ts` under `proxy`. */ export declare interface ApiProxyConfig { prefixes?: readonly string[] paths?: readonly string[] methods?: readonly string[] }