You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Two additions to the in-function runtime documentation:
1. v2.7+ helpers
- getRun402Context(req): zero-dep reader for the x-run402-* request
context (requestId, projectId, releaseId, host, locale,
defaultLocale). Same shape as Astro.locals.run402, accepts Request /
Headers / plain object. Replaces hand-rolled per-field
request.headers.get('x-run402-...') across non-Astro functions.
- assets.fromRef(raw): re-hydrate a stored AssetRef (JSONB column read
from your DB) back into the typed AssetRef shape with camelCase
aliases + variant map. Pure-local, no network. Recommended
persistence pattern stores the full AssetRef as JSONB so variant
SHAs + immutable URLs survive the round-trip.
2. v1.54 AssetRef shape-contract fields (paired with v2.12.0 SDK changes)
- blurhash_data_url: pre-decoded ~600-byte PNG data URL. Embed
directly as background-image - zero render-time decode, no
client-side blurhash library.
- asset_schema: semver shape-contract stamp ("v1.49" | "v1.50" |
"v1.54" | null for partial-shape rows). Strict-mode consumers use
it to skip legacy rows without per-field existence branching.
- Pointer to <Run402Image> in @run402/astro@1.0+ as the consumer
reference impl.
cli/llms-cli.txt + SKILL.md updated. 120/120 SKILL tests + 32/32 sync
tests pass.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
-**`ai.generateImage({ prompt, aspect? })`** — live image generation from deployed functions, billed/rate-limited against the project billing account through `RUN402_SERVICE_KEY`. Aspects: `square`, `landscape`, `portrait`; result: `{ image, content_type, aspect }`. For public routed functions, authenticate/rate-limit app users before calling it.
336
336
-**`assets.put(key, source, opts?)`** — upload runtime bytes through the same CAS-backed apply substrate as deploy-time assets. `source` is a string, `Uint8Array`, or `{ content | bytes }`; returns an SDK-compatible `AssetRef`. v1.50 `opts` accept `metadata` (flat bag, ≤4 KB, leaves `string | number | boolean | string[]`) and `exifPolicy` (`"keep"` | `"strip"`); the returned `AssetRef` includes `image_format`, `image_info`, `image_exif`, and `image_exif_policy` for image MIMEs.
337
337
-**`getUserId(req)` / `getRole(req)`** (v1.51+, `@run402/functions` 2.5+) — typed reads of the `x-run402-user-id` / `x-run402-user-role` headers the gateway injects when a `FunctionSpec.requireAuth` / `requireRole` gate passed. Both return `string | null`. Use these inside a gated function instead of re-decoding the JWT — the gate already verified the caller and resolved the application role. `getRole(req)` is non-null only when `requireRole` ran (the value is guaranteed to be in `requireRole.allowed`). The JWT `role` from `getUser(req)` is the system role (`anon`/`authenticated`/…), NOT the app role — don't conflate them.
338
+
-**`getRun402Context(req)`** (v1.52+, `@run402/functions` 2.7+) — zero-dependency reader for the full per-request context the gateway populates as `x-run402-*` headers. Returns `{ requestId, projectId, releaseId, host, locale, defaultLocale }` (all `string | null`). Use this in non-Astro functions (plain webhook handlers, auth endpoints) instead of hand-rolling `request.headers.get('x-run402-...')` per field — the helper papers over `Request`/`Headers`/plain-object header shapes and any future gateway header renames. Same return shape as `Astro.locals.run402`, so Astro and plain-function code share one mental model. The helper never throws; missing headers come back as `null`.
339
+
-**`assets.fromRef(raw)`** (`@run402/functions` 2.7+) — re-hydrate a stored AssetRef (e.g., a JSONB column read from your DB) back into the typed `AssetRef` shape with camelCase aliases + variant map. Pure-local; no network. The recommended persistence pattern is to store the full `AssetRef` returned by `r.assets.put` as JSONB so the variant SHAs + immutable URLs the gateway computed at upload time survive the round-trip (these can't be re-derived from `(source_sha, key)` alone). Tolerant of partial inputs: pre-v1.49 blobs come back without `variants` / `width_px` rather than synthesizing them. Throws only on null/undefined or non-object input.
338
340
339
341
Fluent surface on both `db(req).from(t)` and `adminDb().from(t)`:
-**`assets_put`** — upload (any size, up to 5 TiB). Returns an `AssetRef` with `cdn_url`, `sri`, `etag`, `cache_kind`. v1.50: accepts `metadata` (flat bag with `string | number | boolean | string[]` leaves, ≤4 KB) and `exif_policy` (`"keep"` | `"strip"`); response includes `image_format`, `image_info`, `image_exif`, and `image_exif_policy` for image MIMEs. Bad shapes throw `INVALID_ASSET_METADATA` / `INVALID_EXIF_POLICY` before the HTTP call.
461
+
- **`assets_put`** — upload (any size, up to 5 TiB). Returns an `AssetRef` with `cdn_url`, `sri`, `etag`, `cache_kind`. v1.50: accepts `metadata` (flat bag with `string | number | boolean | string[]` leaves, ≤4 KB) and `exif_policy` (`"keep"` | `"strip"`); response includes `image_format`, `image_info`, `image_exif`, and `image_exif_policy` for image MIMEs. Bad shapes throw `INVALID_ASSET_METADATA` / `INVALID_EXIF_POLICY` before the HTTP call. v1.54: image uploads also return `blurhash_data_url` (pre-decoded ~600-byte PNG data URL — embed as `background-image` for the placeholder, no client-side decoder) and `asset_schema` (semver shape-contract stamp: `"v1.49"` | `"v1.50"` | `"v1.54"` | `null` for partial-shape rows). When persisting an AssetRef for later render, store the full object as JSONB — the variant SHAs and immutable URLs can't be re-derived from `(source_sha, key)` alone. For Astro consumers, **`<Run402Image>` from `@run402/astro@1.0+`** consumes all of the above directly with zero render-time decode and optional strict-mode schema filtering.
460
462
-**`assets_get`** — download to a local file (no context-window bloat).
461
463
-**`assets_ls`** — keyset-paginated list with prefix filter. v1.50: accepts `sort` (`key:asc` default, `createdAt:asc`, `createdAt:desc`) and `filter` (keys: `uploaded_by`, `tag`, `format`, `is_image`, `min_width`/`max_width`/`min_height`/`max_height`). Cursor is sort-pinned — cross-sort reuse returns `INVALID_CURSOR_FOR_SORT`.
- `email.send(opts)` — send email from the project's mailbox (see email section below)
792
792
- `ai.generateImage({ prompt, aspect? })` — live image generation from deployed functions using project billing authority, not local allowance/x402 signing. Aspects: `square`, `landscape`, `portrait`; result: `{ image, content_type, aspect }`. Add app auth/rate limits before calling it from public routed functions.
793
793
- `assets.put(key, source, opts?)` — upload bytes to the project's blob store from inside a deployed function. Uses the same CAS substrate as deploy-time assets. `source` is a string, `Uint8Array`, or `{ content | bytes }` object. Options: `contentType`, `visibility` (`"public"` | `"private"`, default `"public"`), `immutable` (default `true`). Returns an `AssetRef` with `url`, `immutableUrl`, `cdnUrl`, `sha256`, `size_bytes`, etc. (camelCase aliases included). Use for user-uploaded content, generated images, runtime-produced files.
794
+
- `assets.fromRef(raw)` (v2.7+) — re-hydrate a stored AssetRef (JSONB column read from your DB) into the typed `AssetRef` shape with camelCase aliases + variant map. Pure-local, no network — safe in SSR render paths. The recommended persistence pattern is to store the full `AssetRef` returned by `r.assets.put` as a JSONB column so variant SHAs + immutable URLs survive the round-trip (they can't be re-derived from `(source_sha, key)` alone). Tolerant of partial inputs: pre-v1.49 blobs come back without `variants` / `width_px` rather than synthesizing them. Throws only on null/undefined or non-object input.
795
+
- `getRun402Context(req)` (v2.7+) — zero-dependency reader for the full per-request context the gateway populates as `x-run402-*` headers. Returns `{ requestId, projectId, releaseId, host, locale, defaultLocale }` (all `string | null`). Use in non-Astro functions (plain webhook handlers, auth endpoints) instead of hand-rolling `req.headers.get('x-run402-...')` per field — the helper papers over `Request` / `Headers` / plain-object header shapes and any future gateway header renames. Same return shape as `Astro.locals.run402`. Never throws; missing headers come back as `null`.
794
796
795
-
**TypeScript types**: `npm install @run402/functions` to get full autocomplete for `db(req)`, `adminDb()`, `getUser()`, `email.send()`, `ai.translate()`, `ai.generateImage()`, and `assets.put()`. Works in any Node.js/TypeScript project (Astro, Next.js, plain TS). For static site generation, use `adminDb().from()` at build time with `RUN402_SERVICE_KEY` + `RUN402_PROJECT_ID` in your `.env`.
797
+
**TypeScript types**: `npm install @run402/functions` to get full autocomplete for `db(req)`, `adminDb()`, `getUser()`, `getUserId()`, `getRole()`, `getRun402Context()`, `email.send()`, `ai.translate()`, `ai.generateImage()`, `assets.put()`, and `assets.fromRef()`. Works in any Node.js/TypeScript project (Astro, Next.js, plain TS). For static site generation, use `adminDb().from()` at build time with `RUN402_SERVICE_KEY` + `RUN402_PROJECT_ID` in your `.env`.
- `image_exif_policy` — echo of the EXIF policy actually applied: `"keep"` (default) or `"strip"`. `null` for non-image rows.
1018
1020
- These fields ride alongside the v1.49 `width_px` / `height_px` / `blurhash` / `variants` additions — same FLAT shape, NOT wrapped under `image: {}`.
1019
1021
1022
+
Shape-contract fields (v1.54+ gateway, `@run402/sdk@2.12.0+`, populated atomically with variants at upload time):
1023
+
- `blurhash_data_url` — pre-decoded PNG data URL (~600-1200 bytes typical at 16×16) computed once at upload from the canonical pinned BlurHash decoder. Embed directly as `background-image` for the placeholder — zero render-time decode, no client-side blurhash library needed. `null` only when the decoder failed on otherwise-valid input (rare). Absent for pre-v1.54 uploads.
1024
+
- `asset_schema` — semver shape-contract stamp recording the highest contract this row's fields satisfy (`"v1.49"` | `"v1.50"` | `"v1.54"` | `null`). `null` marks partial-shape rows (e.g., HEIC sources missing `display_jpeg`). Strict-mode consumers read this to skip legacy rows without per-field existence branching. Absent for pre-v1.54 uploads.
1025
+
- The v1.54 substrate enables the **`<Run402Image>` component** in `@run402/astro@1.0+`: pre-decoded placeholder + WebP-ladder responsive `<picture>` + width/height for zero-CLS, with optional `imageDefaults.strict: { onSchema: ">=v1.49" }` to hard-fail on legacy rows during the rollout that follows every schema migration. Astro + React entries; byte-identical HTML output across both.
1026
+
1020
1027
Typed errors a caller can branch on (`catch (e) { if (e.code === "...") }`):
1021
1028
- `INVALID_ASSET_METADATA` (HTTP 400 or `LocalError` pre-network)
1022
1029
- `INVALID_EXIF_POLICY` (HTTP 400 or `LocalError` pre-network)
0 commit comments