UNPKG

run402-mcp

Version:

MCP server for Run402 — full-stack backend infrastructure for AI agents: Postgres, auth, storage, serverless functions and atomic deploys. Paid with x402/MPP. Includes $0.03 image generation.

80 lines • 3.9 kB
/** * `events` namespace — the cursored project events feed (gateway * `project-events-outbox`). One call answers "what happened to my project * since I last looked": deploy activations, mailbox suspensions, transfers, * lifecycle cliffs, verification outcomes — each with platform-synthesized * `next_actions[]` drill-downs. * * Cursor contract (opaque, store-and-echo): keep the page's `cursor` * wherever you keep state and pass it back as `{ cursor }` next time. An * unusable cursor never errors — the page returns `reset: true` + * `earliest_cursor` and restarts from the earliest retained event. Events * become visible within seconds of commit (a short visibility watermark * orders concurrent transactions) and are never lost after it. * * Exposed both unscoped (`r.events.list(projectId, …)`) and project-scoped * (`r.project(id).events.list(…)`), mirroring `r.grants` / `r.functions`. * The read is never lifecycle-gated: a frozen project's feed stays readable. * * `{ source, eventType }` filter the app-emitted lane from the platform's * own events — see {@link ListEventsOptions}. Consumers should key on * `(source, event_type)` together, since the platform's vocabulary and an * app's own `event_type` names are only disambiguated by the pair. */ import { LocalError } from "../errors.js"; function feedQuery(opts = {}) { const params = new URLSearchParams(); if (opts.cursor !== undefined) params.set("cursor", opts.cursor); if (opts.limit !== undefined) params.set("limit", String(opts.limit)); if (opts.source !== undefined) params.set("source", opts.source); if (opts.eventType !== undefined) { params.set("event_type", Array.isArray(opts.eventType) ? opts.eventType.join(",") : opts.eventType); } const qs = params.toString(); return qs ? `?${qs}` : ""; } export class Events { client; constructor(client) { this.client = client; } /** * Read a page of a project's events feed * (`GET /projects/v1/:project_id/events`). Accepted credentials: the * project's own service_key, a SIWX/control-plane principal with * `project.read`, or a grant key. `opts.source` / `opts.eventType` * filter to the app lane, the platform lane, or one-or-more event types; * both compose with `cursor`/`limit` unchanged. */ async list(projectId, opts = {}) { if (!projectId) { throw new LocalError("events.list requires a projectId", "reading project events feed"); } return this.client.request(`/projects/v1/${encodeURIComponent(projectId)}/events${feedQuery(opts)}`, { method: "GET", context: "reading project events feed" }); } /** * Read the org-wide feed (`GET /orgs/v1/:org_id/events`) — every fact the * organization owns. That is a SUPERSET of its project feeds, not a union * of them: it also carries organization-level facts, which belong to no * project, arrive with `project_id: null`, and are unreachable from any * project feed. * * Principal-only: requires an active org membership; a project service_key * is rejected by the gateway. Same `opts.source` / `opts.eventType` filters * as {@link list}. * * Cursors do NOT interchange with {@link list}, even though an event's `id` * is the same in both — a cursor names a position inside one projection. * Carrying one across returns `reset: true`; see {@link ListEventsOptions.cursor}. */ async listForOrg(orgId, opts = {}) { if (!orgId) { throw new LocalError("events.listForOrg requires an orgId", "reading org events feed"); } return this.client.request(`/orgs/v1/${encodeURIComponent(orgId)}/events${feedQuery(opts)}`, { method: "GET", context: "reading org events feed" }); } } //# sourceMappingURL=events.js.map