@run402/functions 1.62.1 → 1.64.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.
Files changed (2) hide show
  1. package/README.md +34 -51
  2. package/package.json +1 -1
package/README.md CHANGED
@@ -147,72 +147,55 @@ Use `adminDb()` (not `db(req)`) here — there's no incoming request to forward.
147
147
 
148
148
  ## Routed HTTP functions
149
149
 
150
- Deploy-v2 web routes can map public same-origin browser paths to functions, for example `routes: { "replace": [{ "pattern": "/api/*", "target": { "type": "function", "name": "api" } }] }`. A browser request to a routed path does **not** need a Run402 API key at the public edge. Direct `/functions/v1/:name` invocation is unchanged: it remains API-key protected and API-shaped.
150
+ Deploy-v2 web routes can map public same-origin browser paths to functions, for example `routes.replace` / `"routes": { "replace": [{ "pattern": "/api/*", "target": { "type": "function", "name": "api" } }] }`. Use exact `/admin` plus final-wildcard `/admin/*` when a dynamic section root and its children should route to the same function. A browser request to a routed path does **not** need a Run402 API key at the public edge. Direct `/functions/v1/:name` invocation is unchanged: it remains API-key protected and API-shaped.
151
151
 
152
- Routed browser traffic invokes your function with the `run402.routed_http.v1` envelope. The gateway preserves the public URL, path, raw query, duplicate-safe lower-case headers, raw cookie header, optional base64 body, and route context. The matched prefix is not stripped from `path`.
153
-
154
- Request fields:
155
- - `version`, `method`, `url`, `path`, `rawPath`, `rawQuery`
156
- - `headers: Array<[string, string]>`
157
- - `cookies.raw`
158
- - `body: null | { encoding: "base64"; data; size }`
159
- - `context.source`, `projectId`, `releaseId`, `deploymentId`, `host`, `proto`, `routePattern`, `routeKind`, `routeTarget`, `requestId`, plus optional `clientIp` and `userAgent`
160
-
161
- Response fields:
162
- - `status` from 200 through 599
163
- - optional duplicate-safe `headers`
164
- - optional `cookies: string[]`, preserved as separate `Set-Cookie` headers
165
- - optional base64 `body`
166
-
167
- Helpers:
152
+ Routed browser traffic invokes the same Node 22 Fetch Request -> Response handler used by direct functions:
168
153
 
169
154
  ```ts
170
- import {
171
- routedHttp,
172
- type RoutedHttpRequestV1,
173
- type RoutedHttpResponseV1,
174
- } from "@run402/functions";
175
-
176
- export default async function handler(
177
- event: RoutedHttpRequestV1,
178
- ): Promise<RoutedHttpResponseV1> {
179
- if (!routedHttp.isRequest(event)) {
180
- return routedHttp.json({ error: "unsupported_event" }, { status: 400 });
181
- }
155
+ export default async function handler(req: Request): Promise<Response> {
156
+ const url = new URL(req.url);
182
157
 
183
- if (event.method === "OPTIONS") {
184
- return routedHttp.text("", {
158
+ if (req.method === "OPTIONS") {
159
+ return new Response(null, {
185
160
  status: 204,
186
- headers: [
187
- ["access-control-allow-origin", "https://app.example.com"],
188
- ["access-control-allow-methods", "GET, POST, OPTIONS"],
189
- ["access-control-allow-headers", "content-type, authorization"],
190
- ],
161
+ headers: {
162
+ "access-control-allow-origin": "https://app.example.com",
163
+ "access-control-allow-methods": "GET, POST, OPTIONS",
164
+ "access-control-allow-headers": "content-type, authorization",
165
+ },
191
166
  });
192
167
  }
193
168
 
194
- if (event.method === "POST" && !event.headers.some(([k]) => k === "x-csrf-token")) {
195
- return routedHttp.json({ error: "csrf_required" }, { status: 403 });
169
+ if (req.method === "POST" && !req.headers.has("x-csrf-token")) {
170
+ return Response.json({ error: "csrf_required" }, { status: 403 });
196
171
  }
197
172
 
198
- return routedHttp.json(
199
- { ok: true, path: event.path, query: event.rawQuery },
200
- {
201
- headers: [["cache-control", "private, no-store"]],
202
- cookies: [
203
- "sid=abc; HttpOnly; Secure; SameSite=Lax; Path=/",
204
- "theme=dark; Secure; SameSite=Lax; Path=/",
205
- ],
206
- },
207
- );
173
+ const headers = new Headers({ "cache-control": "private, no-store" });
174
+ headers.append("Set-Cookie", "sid=abc; HttpOnly; Secure; SameSite=Lax; Path=/");
175
+ headers.append("Set-Cookie", "theme=dark; Secure; SameSite=Lax; Path=/");
176
+ return Response.json({ ok: true, path: url.pathname, query: url.search }, { headers });
208
177
  }
209
178
  ```
210
179
 
211
- `routedHttp.text`, `routedHttp.json`, and `routedHttp.bytes` return `RoutedHttpResponseV1`. Named `text`, `json`, `bytes`, and `isRequest` exports are also available. Redirects are ordinary 3xx responses with a `Location` header. `HEAD` responses send headers without body bytes. WebSockets, `101 Switching Protocols`, streaming, and SSE are not supported in Phase 1.
180
+ Request fields:
181
+ - `req.method` is the original browser method. `GET` routes also match `HEAD`; `HEAD` reaches the handler as `HEAD`.
182
+ - `req.url` is the full public URL, including scheme, host, path, and query, on managed subdomains, deployment hosts, and verified custom domains. Derive OAuth callback URLs from `new URL(req.url).origin`.
183
+ - `req.headers` is a Fetch `Headers` object. Cookie data is available through the `cookie` header.
184
+ - `await req.text()`, `await req.json()`, and `await req.arrayBuffer()` read the buffered request body, capped at 6 MiB.
185
+
186
+ Response behavior:
187
+ - Return a Web `Response` with status 200 through 599 except `101 Switching Protocols`.
188
+ - Append each cookie with `headers.append("Set-Cookie", value)`; Run402 preserves multiple `Set-Cookie` values as separate browser headers.
189
+ - Redirects are ordinary 3xx responses with a `Location` header. `HEAD` responses send headers without body bytes.
190
+ - Request and response bodies are capped at 6 MiB. WebSockets, `101 Switching Protocols`, streaming, and SSE are not supported in Phase 1.
191
+
192
+ Limits and defaults: Run402 does not add wildcard CORS. Run402 does not store routed dynamic responses in a shared cache; if your function sets no `Cache-Control`, the gateway adds `Cache-Control: private, no-store` and `x-run402-cache: dynamic-bypass`.
193
+
194
+ Security notes: application auth, authorization, sessions, OAuth callbacks, CORS, and CSRF belong in your function code. For cookie-authenticated `POST`, `PUT`, `PATCH`, or `DELETE`, validate a CSRF token or an equivalent same-site defense. Do not trust spoofable forwarding headers for authorization.
212
195
 
213
- Limits and defaults: request and response bodies are capped at 6 MiB. Run402 does not add wildcard CORS. Run402 does not store routed dynamic responses in a shared cache; if your function sets no `Cache-Control`, the gateway adds `Cache-Control: private, no-store` and `x-run402-cache: dynamic-bypass`.
196
+ The raw `run402.routed_http.v1` envelope is an internal gateway transport. Low-level `routedHttp` helpers and `RoutedHttpRequestV1` / `RoutedHttpResponseV1` types remain exported for tests and gateway-adjacent utilities, but browser route handlers should use Fetch `Request` and `Response`.
214
197
 
215
- Security notes: application auth, authorization, sessions, OAuth callbacks, CORS, and CSRF belong in your function code. For cookie-authenticated `POST`, `PUT`, `PATCH`, or `DELETE`, validate a CSRF token or an equivalent same-site defense. Do not trust spoofable forwarding headers for authorization; prefer the typed `event.context` metadata when it is present.
198
+ Runtime route failure codes to branch on: `ROUTE_MANIFEST_LOAD_FAILED` (manifest/propagation), `ROUTED_INVOKE_WORKER_SECRET_MISSING` (custom-domain Worker secret), `ROUTED_INVOKE_AUTH_FAILED` (internal invoke signature), `ROUTED_ROUTE_STALE` (selected route failed release revalidation), `ROUTE_METHOD_NOT_ALLOWED` (method mismatch), and `ROUTED_RESPONSE_TOO_LARGE` (body over 6 MiB).
216
199
 
217
200
  ## Imports auto-resolved
218
201
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@run402/functions",
3
- "version": "1.62.1",
3
+ "version": "1.64.0",
4
4
  "description": "In-function helper library for Run402 serverless functions — db, adminDb, getUser, email, ai. Auto-bundled into deployed functions; also installable for local TypeScript autocomplete.",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",