import type { ClientConfig } from "@beignet/core/client"; import { type ErrorReporterPort } from "@beignet/core/error-reporting"; import { type DrainOutboxOptions, type OutboxRegistry } from "@beignet/core/outbox"; import type { PaymentsPort, PaymentWebhookEvent } from "@beignet/core/payments"; import type { AnyPorts, BestEffortWorkPort, StorageObject, StoragePort } from "@beignet/core/ports"; import type { InferProviderPorts, ProviderInstrumentationPort, ServiceProvider } from "@beignet/core/providers"; import { type ScheduleDef, type StandardSchema } from "@beignet/core/schedules"; import type { AddedCtxFromHooks, AppEnvironment, ContractLike, CreateServerOptions, Handler, HealthConfig, HttpContractConfig, HttpRequestLike, RawRouteInit, ResolveContract, RouteDef, RouteHook, ServerInstance, StandardSchemaV1 } from "@beignet/core/server"; import type { TracingPort } from "@beignet/core/tracing"; import type { UploadRouter } from "@beignet/core/uploads"; import { type InferWebhookEvent, type VerifyWebhookInput, type WebhookDef, type WebhookEvent, type WebhookEventSchemas } from "@beignet/core/webhooks"; export { type BroadcastRouteOptions, createBroadcastRoute } from "@beignet/web"; type AnyProvider = ServiceProvider, AnyPorts, any, any>; type MaybePromise = T | Promise; type ServerSource = TServer | (() => MaybePromise); /** * Beignet client config with Next.js base URL defaults. */ export type NextClientConfig = Omit, "baseUrl"> & { /** * Explicit base URL for both browser and server calls. * * In browser code, omit this to use same-origin relative requests. */ baseUrl?: string | (() => string | undefined); /** * Server-only fallback base URL for SSR, prefetching, tests, and server actions. * Browser calls ignore this value unless `baseUrl` is also provided. */ serverBaseUrl?: string | (() => string | undefined); }; /** * OpenAPI server object accepted by `createOpenAPIHandler(...)`. */ export type OpenAPIServer = { /** * Server URL. */ url: string; /** * Server description. */ description?: string; /** * Server URL variables. */ variables?: Record; }; /** * Options for the Next.js OpenAPI route handler. */ export type CreateOpenAPIHandlerOptions = { /** * API title. */ title: string; /** * API version. */ version: string; /** * API description. */ description?: string; /** * Static servers or a request-aware server factory. */ servers?: OpenAPIServer[] | ((req: Request) => OpenAPIServer[]); /** * JSON media type used for generated content. */ jsonMediaType?: string; /** * OpenAPI security schemes. */ securitySchemes?: Record; /** * Global security requirements. */ security?: Array>; /** * Custom schema introspector for non-Zod schema libraries. */ schemaIntrospector?: unknown; /** * Additional response headers. */ headers?: HeadersInit | ((req: Request) => HeadersInit | undefined); /** * Add the current request origin as the OpenAPI server when `servers` is omitted. * * @default false */ inferServersFromRequest?: boolean; }; /** * Options for the Next.js Swagger UI route handler. */ export type CreateSwaggerUIHandlerOptions = { /** * HTML page title. */ title?: string; /** * URL of the OpenAPI JSON route. */ specUrl?: string | ((req: Request) => string); /** * Additional response headers. */ headers?: HeadersInit | ((req: Request) => HeadersInit | undefined); }; /** * Options for serving public storage objects through a Next.js route. */ export type CreateStorageRouteOptions = { /** * Public path prefix that maps to storage keys. * * @default "/storage" */ basePath?: string; /** * Additional response headers for served objects. */ headers?: HeadersInit | ((req: Request) => HeadersInit | undefined); /** * Content-Disposition policy for public objects. * * `"auto"` serves active content types such as HTML, SVG, XML, and * JavaScript as downloads while leaving other objects inline. * * @default "auto" */ contentDisposition?: "auto" | "inline" | "attachment" | ((args: { req: Request; object: StorageObject; }) => string | undefined); }; /** * Options for creating a Next.js upload route. */ export type CreateUploadRouteOptions = { /** * Static upload name. Omit when using a dynamic `[uploadName]` segment. */ uploadName?: string; /** * Static upload action. Omit when using a dynamic `[action]` segment. */ action?: "prepare" | "complete" | "upload"; }; type OutboxDrainLogger = { error(message: string, metadata?: Record): void; }; type OutboxDrainInstrumentation = { record(event: { type: "custom"; watcher: string; name: string; label: string; summary: string; requestId?: string; traceId?: string; details: unknown; }): unknown; }; type OutboxDrainPorts = { outbox: DrainOutboxOptions["outbox"]; eventBus?: DrainOutboxOptions["eventBus"]; jobs?: DrainOutboxOptions["jobs"]; logger?: OutboxDrainLogger; devtools?: OutboxDrainInstrumentation; instrumentation?: OutboxDrainInstrumentation; tracing?: TracingPort; errorReporter?: ErrorReporterPort; }; type OutboxDrainContext = { requestId?: string; traceId?: string; ports: OutboxDrainPorts; }; /** * Scheduler compatible with Next.js 15.1+ `after(...)` and equivalent * request-bound deferred-work primitives. */ export type NextDeferredWorkScheduler = (work: () => MaybePromise) => MaybePromise; /** * Options for adapting Next.js 15.1+ `after(...)` to `BestEffortWorkPort`. */ export type CreateNextBestEffortWorkPortOptions = { /** Schedule work after the response, usually with `next/server`'s `after`. */ defer: NextDeferredWorkScheduler; /** * Best-effort observer for scheduler or deferred callback failures. * Observer failures are isolated too. */ onError?: (error: unknown) => MaybePromise; }; /** * Options for scheduling a bounded outbox drain after a successful request * transaction. */ export type CreateNextOutboxDrainTriggerOptions = { /** Schedule work after the response, usually with `next/server`'s `after`. */ defer: NextDeferredWorkScheduler; /** Build the service context used by the deferred drain. */ createContext: () => MaybePromise; /** Static registry or lazy loader used to avoid server/provider cycles. */ registry: OutboxRegistry | (() => MaybePromise); /** Maximum eligible messages to handle in the deferred drain pass. */ batchSize?: number; /** Maximum messages delivered concurrently. Values above one are unordered. */ concurrency?: number; /** Claim lease duration in milliseconds. */ leaseMs?: number; /** Serialized claim-renewal interval. Must remain shorter than `leaseMs`. */ heartbeatMs?: number; /** Maximum time Beignet renews a claim for one delivery. */ maxActiveMs?: number; /** Retry delay override passed through to `drainOutbox(...)`. */ retryDelayMs?: DrainOutboxOptions["retryDelayMs"]; /** * Best-effort observer for scheduler, context, registry, or drain failures. * Observer failures are ignored. */ onError?: (error: unknown) => MaybePromise; }; /** * Minimal server surface required by the Next.js route factories. * * Both a `NextServer` and a core `ServerInstance` satisfy this shape * structurally, so route modules built on these factories are executable * under a standard test runner: construct the route with a fake server exposing * `createRequestContext` and invoke the exported handlers with a plain * `Request`. No Next.js runtime (`next/headers`) is involved. * * When the server also exposes `rawRoute(...)` — real Beignet servers do — * the factories run their handler through the full hooks pipeline (rate * limiting, CORS, logging, error reporting, instrumentation). Minimal fakes * without it keep the direct `createRequestContext` flow. */ export type NextRouteServer = { createRequestContext: (req: HttpRequestLike) => Promise; }; /** * Options for creating a serverless-safe outbox drain route. */ export type CreateOutboxDrainRouteOptions = { /** * Beignet server that owns app context and ports. * * Any object exposing `createRequestContext` works: a `NextServer`, a core * `ServerInstance`, or a test fake driven from a standard test runner. */ server: ServerSource>; /** * Registry of events and jobs that may be delivered from the outbox. */ registry: OutboxRegistry; /** * Shared secret expected in the `Authorization: Bearer ` header. * * Missing secrets fail closed with a 500 response so deployments do not * accidentally expose an unauthenticated drain route. */ secret?: string; /** * Maximum eligible messages to handle in one drain pass. */ batchSize?: number; /** Maximum messages delivered concurrently. Values above one are unordered. */ concurrency?: number; /** * Claim lease duration in milliseconds. */ leaseMs?: number; /** Serialized claim-renewal interval. Must remain shorter than `leaseMs`. */ heartbeatMs?: number; /** Maximum time Beignet renews a claim for one delivery. */ maxActiveMs?: number; /** * Retry delay override passed through to `drainOutbox(...)`. */ retryDelayMs?: DrainOutboxOptions["retryDelayMs"]; /** * Identity and metadata for the hooks pipeline when the server exposes * `rawRoute(...)`. `metadata` feeds metadata-driven hooks such as rate * limiting and idempotency; `name` and `path` identify the route to * hooks, instrumentation, and devtools. */ pipeline?: { name?: string; path?: string; metadata?: RawRouteInit["metadata"]; }; /** * Additional response headers. */ headers?: HeadersInit | ((req: Request) => HeadersInit | undefined); }; type ScheduleRouteLogger = { error(message: string, metadata?: Record): void; }; type ScheduleRoutePorts = { logger?: ScheduleRouteLogger; devtools?: ProviderInstrumentationPort; instrumentation?: ProviderInstrumentationPort; errorReporter?: ErrorReporterPort; }; type ScheduleRouteContext = { requestId?: string; traceId?: string; ports: ScheduleRoutePorts; }; type PaymentWebhookLogger = { error(message: string, metadata?: Record): void; }; type PaymentWebhookRoutePorts = { payments: PaymentsPort; logger?: PaymentWebhookLogger; }; type PaymentWebhookRouteContext = { requestId?: string; traceId?: string; ports: PaymentWebhookRoutePorts; }; export type PaymentWebhookRouteHandlerResult = Response | { status?: number; headers?: HeadersInit; body?: unknown; } | undefined; export type PaymentWebhookRouteHandlerArgs = { req: Request; ctx: Ctx; rawBody: string; signature: string; event: PaymentWebhookEvent; }; type WebhookRouteLogger = { error(message: string, metadata?: Record): void; }; type WebhookRouteContext = { requestId?: string; traceId?: string; ports: { logger?: WebhookRouteLogger; }; }; export type WebhookRouteHandlerResult = Response | { status?: number; headers?: HeadersInit; body?: unknown; } | undefined; export type WebhookRouteVerifyArgs = { req: Request; ctx: Ctx; rawBody: string; headers: Record; input: VerifyWebhookInput; }; export type WebhookRouteHandlerArgs, AllowUnknownEvents extends boolean> = { req: Request; ctx: Ctx; rawBody: string; event: AllowUnknownEvents extends false ? InferWebhookEvent : InferWebhookEvent | WebhookEvent; }; /** * Options for creating a generic inbound webhook route. */ export type CreateWebhookRouteOptions, AllowUnknownEvents extends boolean = false> = { /** * Beignet server that owns app context and ports. * * Any object exposing `createRequestContext` works: a `NextServer`, a core * `ServerInstance`, or a test fake driven from a standard test runner. */ server: ServerSource>; /** * Inbound webhook definition. */ webhook: Webhook; /** * Optional context-aware verifier. Use this when verification depends on app * ports, such as `ctx.ports.payments.verifyWebhook(...)`. */ verify?: (args: WebhookRouteVerifyArgs) => Promise | WebhookEvent; /** * Whether unknown event types should pass through without payload parsing. * * @default false */ allowUnknownEvents?: AllowUnknownEvents; /** * Maximum raw webhook body size in bytes. * * Bodies above this limit are rejected before server resolution, hooks, * context creation, verification, or fulfillment. * * @default 1048576 */ maxBodyBytes?: number; /** * App-owned fulfillment handler. The webhook is verified before this runs. * * Omit to acknowledge verified events with `{ ok: true }`. */ handle?: (args: WebhookRouteHandlerArgs) => Promise | WebhookRouteHandlerResult; /** * Identity and metadata for the hooks pipeline when the server exposes * `rawRoute(...)`. `metadata` feeds metadata-driven hooks such as rate * limiting and idempotency; `name` and `path` identify the route to * hooks, instrumentation, and devtools. */ pipeline?: { name?: string; path?: string; metadata?: RawRouteInit["metadata"]; }; /** * Additional response headers. */ headers?: HeadersInit | ((req: Request) => HeadersInit | undefined); }; /** * Options for creating a serverless-safe schedule trigger route. */ export type CreateScheduleRouteOptions = { /** * Beignet server that owns app context and ports. * * Any object exposing `createRequestContext` works: a `NextServer`, a core * `ServerInstance`, or a test fake driven from a standard test runner. */ server: ServerSource>; /** * Registered schedules, usually the `schedules` array from * `server/schedules.ts`. */ schedules: readonly ScheduleDef[]; /** * Name of the schedule this route triggers. Unknown names throw when the * route module loads so misconfigured routes fail at build or boot time. */ schedule: string; /** * Shared secret expected in the `Authorization: Bearer ` header. * * Missing secrets fail closed with a 500 response so deployments do not * accidentally expose an unauthenticated trigger route. */ secret?: string; /** * Run source label recorded on run metadata and devtools events. * * @default "next-cron-route" */ source?: string; /** * Identity and metadata for the hooks pipeline when the server exposes * `rawRoute(...)`. `metadata` feeds metadata-driven hooks such as rate * limiting and idempotency; `name` and `path` identify the route to * hooks, instrumentation, and devtools. */ pipeline?: { name?: string; path?: string; metadata?: RawRouteInit["metadata"]; }; /** * Additional response headers. */ headers?: HeadersInit | ((req: Request) => HeadersInit | undefined); }; /** * Options for creating a payment webhook route. */ export type CreatePaymentWebhookRouteOptions = { /** * Beignet server that owns app context and ports. * * Any object exposing `createRequestContext` works: a `NextServer`, a core * `ServerInstance`, or a test fake driven from a standard test runner. */ server: ServerSource>; /** * Provider signature header. Stripe uses `stripe-signature`. * * @default "stripe-signature" */ signatureHeader?: string; /** * Maximum raw webhook body size in bytes. * * Signed bodies above this limit are rejected before provider verification * or fulfillment, and before server resolution, hooks, or context creation. * A missing signature takes precedence and cancels the unread body. * * @default 1048576 */ maxBodyBytes?: number; /** * App-owned fulfillment handler. The webhook is verified before this runs. * * Omit to acknowledge verified events with `{ ok: true }`. */ handle?: (args: PaymentWebhookRouteHandlerArgs) => Promise | PaymentWebhookRouteHandlerResult; /** * Identity and metadata for the hooks pipeline when the server exposes * `rawRoute(...)`. `metadata` feeds metadata-driven hooks such as rate * limiting and idempotency; `name` and `path` identify the route to * hooks, instrumentation, and devtools. */ pipeline?: { name?: string; path?: string; metadata?: RawRouteInit["metadata"]; }; /** * Additional response headers. */ headers?: HeadersInit | ((req: Request) => HeadersInit | undefined); }; type UploadRouteContext = { params?: Promise> | Record; }; /** * Beignet server adapted for Next.js route handlers and server components. */ export interface NextServer { /** * Catch-all Next.js route handler. */ api: (req: Request) => Promise; /** * Register and build a single Next.js route handler imperatively. */ route: (contractLike: CLike) => { handle: (fn: Handler>) => (req: Request) => Promise; }; /** * Build a Next.js route handler for a route that cannot be a contract — * webhooks, third-party auth callbacks, streaming endpoints — that still * runs the whole server pipeline: hooks (rate limiting, idempotency, CORS, * logging, error reporting), context creation, instrumentation, and * framework error mapping. * * Request parsing and validation are skipped and the request body is left * unconsumed, so the handler owns body reading — for example webhook * signature verification over the exact raw bytes. Metadata-driven hooks * read `init.metadata`. Raw routes are not added to the route registry; * export the returned handler from the route file that owns the path. */ rawRoute: [] = readonly []>(init: RawRouteInit & { hooks?: Hooks; }) => { handle: (fn: Handler, HttpContractConfig>) => (req: Request) => Promise; }; /** * Create app context from `next/headers` for Server Components. */ createContextFromNext: () => Promise; /** * Build a fully assembled request context from a framework-neutral request. */ createRequestContext: ServerInstance["createRequestContext"]; /** * Build a fully assembled service context for schedules, outbox drains, * commands, and background work. * * Requires `context.service` to be declared in `createNextServer(...)`. */ createServiceContext: ServerInstance["createServiceContext"]; /** * Build a service context and run `fn` inside a scoped ambient correlation * frame, returning its result. * * This is the script-safe counterpart to `createServiceContext(...)`. * Requires `context.service` to be declared in `createNextServer(...)`. */ runServiceContext: ServerInstance["runServiceContext"]; /** * Registered contract inputs. */ contracts: readonly ContractLike[]; /** * Stop installed providers. */ stop: () => Promise; /** * Final app ports after provider setup. */ ports: Ports; } /** * Lazy, memoized loader for a Beignet Next server. */ export type NextServerLoader = () => Promise; /** * HTTP method handlers for a central Beignet API catch-all route. */ export type NextApiRouteHandlers = { DELETE: (req: Request) => Promise; GET: (req: Request) => Promise; HEAD: (req: Request) => Promise; OPTIONS: (req: Request) => Promise; PATCH: (req: Request) => Promise; POST: (req: Request) => Promise; PUT: (req: Request) => Promise; }; /** * Create a memoized Next server loader for route modules. * * Next.js imports route modules during production builds. Exporting a lazy * loader lets those modules stay cheap to import while still booting providers * before the first real request in each runtime process. */ export declare function createNextServerLoader(createServer: () => MaybePromise): NextServerLoader; /** * Create HTTP method exports for a catch-all API route. */ export declare function createApiRoute, "api">>(loadServer: NextServerLoader): NextApiRouteHandlers; /** * Create a readiness route whose server is loaded only when the route handles * a request. */ export declare function createHealthRoute(loadServer: NextServerLoader, "ports">>, healthConfig: HealthConfig | undefined, environment?: AppEnvironment): { GET: (req: Request) => Promise; }; /** * Resolve the right Beignet client base URL for Next.js. * * Browser calls default to same-origin relative URLs. Server calls need an * absolute URL, so this helper checks `NEXT_PUBLIC_API_URL`, then Vercel's * deployment URL, then localhost. */ export declare function resolveNextBaseUrl(options?: NextClientConfig): string; /** * Create a Beignet client with Next.js-friendly base URL defaults. */ export declare function createNextClient(config?: NextClientConfig): import("@beignet/core/client").Client; /** * Create a Next.js route handler that returns an OpenAPI document. * * Requires `@beignet/core/openapi` and the `zod` peer dependency. */ export declare function createOpenAPIHandler(contracts: readonly ContractLike[], options: CreateOpenAPIHandlerOptions): (req: Request) => Promise; /** * Create a Next.js route handler that serves Swagger UI for an OpenAPI route. */ export declare function createSwaggerUIHandler(options?: CreateSwaggerUIHandlerOptions): (req: Request) => Response; /** * Create Next.js route handlers that serve public storage objects. * * Missing objects, private objects, invalid keys, and paths outside `basePath` * all return 404 so storage routes do not leak object existence. */ export declare function createStorageRoute(storage: ServerSource, options?: CreateStorageRouteOptions): { GET: (req: Request) => Promise; HEAD: (req: Request) => Promise; }; /** * Create a Next.js POST handler for Beignet upload routes. * * Use this in a dynamic route such as * `app/api/uploads/[uploadName]/[action]/route.ts`, where `action` is * `prepare`, `complete`, or `upload`. */ export declare function createUploadRoute(router: ServerSource, options?: CreateUploadRouteOptions): { POST: (req: Request, ctx?: UploadRouteContext) => Promise; }; /** * Adapt Next.js 15.1+ `after(...)` to Beignet's non-durable best-effort-work * port. * * Scheduling failures and deferred callback failures are isolated from the * originating operation. Use jobs or an outbox when work must be retried or * survive process termination. This adapter is request-bound: scheduling * outside a Next.js context supported by `after(...)` is passed to `onError` * when configured. */ export declare function createNextBestEffortWorkPort(options: CreateNextBestEffortWorkPortOptions): BestEffortWorkPort; /** * Create a best-effort trigger for one bounded outbox drain. * * Pass Next.js `after` as `defer`. The trigger is an immediate-delivery * optimization only; keep a cron or worker drain for recovery, delayed * messages, and retries. Calls coalesce while a drain is scheduled or running * so transactions started by delivery handlers cannot fan out recursively. */ export declare function createNextOutboxDrainTrigger(options: CreateNextOutboxDrainTriggerOptions): () => void; /** * Create Next.js route handlers that drain one durable outbox batch. * * This helper is intended for serverless cron routes. It performs bounded work * and exits; do not start long-running outbox polling loops from provider * lifecycle hooks in serverless apps. */ export declare function createOutboxDrainRoute(options: CreateOutboxDrainRouteOptions): { GET: (req: Request) => Promise; POST: (req: Request) => Promise; }; /** * Create a Next.js POST handler for generic verified inbound webhooks. * * The route bounds and reads the raw request body before resolving the server, * then normalizes request headers and builds app context from a rehydrated * request through * `server.createRequestContext(...)`, verifies the event through the webhook * definition or a context-aware verifier, validates the matching event * payload schema, and delegates fulfillment to app code. */ export declare function createWebhookRoute, AllowUnknownEvents extends boolean = false>(options: CreateWebhookRouteOptions): { POST: (req: Request) => Promise; }; /** * Create a Next.js POST handler for provider-verified payment webhooks. * * The route checks the provider signature header and bounds the raw request * body before resolving the server, then builds app context from a rehydrated * request through * `server.createRequestContext(...)`, verifies the event through * `ctx.ports.payments`, and then delegates fulfillment to app code. This is the canonical helper for Beignet * billing flows backed by `PaymentsPort`. Keep this route on the Node.js * runtime when your provider SDK requires Node APIs. */ export declare function createPaymentWebhookRoute(options: CreatePaymentWebhookRouteOptions): { POST: (req: Request) => Promise; }; /** * Create Next.js route handlers that trigger one registered schedule. * * This helper is intended for serverless cron routes. It authenticates the * caller with a timing-safe bearer comparison, builds app context from the * real request through `server.createRequestContext(...)`, runs the schedule * inline, and records `schedule` events through the resolved * provider instrumentation port (`ports.instrumentation`, then * `ports.devtools`) when one is installed. */ export declare function createScheduleRoute(options: CreateScheduleRouteOptions): { GET: (req: Request) => Promise; POST: (req: Request) => Promise; }; /** * Create a Beignet server adapted for Next.js. * * The returned `api` handler is intended for a catch-all route. Focused routes * such as OpenAPI, Swagger UI, devtools, and public storage can use their own * route helpers. */ export declare function createNextServer[] = readonly RouteDef[], Providers extends readonly AnyProvider[] = readonly AnyProvider[]>(options: CreateServerOptions): Promise, ServiceInput>>; //# sourceMappingURL=index.d.ts.map