import { type Table } from 'drizzle-orm'; import '@orpc/openapi/extensions/route'; import * as v from 'valibot'; import type { AnyDb } from '../dialect.js'; import type { IdempotencyConfig } from '../idempotency.js'; import type { RealtimeFacade } from '../realtime/facade.js'; import type { RealtimePublisher } from '../realtime/publisher.js'; import type { CrudApiRouterFor } from './types.js'; import { type ResolvedAccess, type ResolvedTableAccess, type TableAccessInput } from '../access.js'; import { type CrudOperations } from '../crud-operations.js'; import { createApiBuilder } from './builder.js'; export type CrudApiRouterOptions = Record> = { access: ResolvedAccess; idempotency?: boolean | IdempotencyConfig; realtime?: RealtimeFacade; /** * The raw realtime publisher, present when realtime is enabled. The CRUD * router subscribes on behalf of live views (`GET /{table}:live`); * publishing stays behind the facade. */ livePublisher?: RealtimePublisher; }; /** A filter accepts one value (`=`), a list (`IN`), or null (`IS NULL`). */ export type ListFilterValue = T | readonly T[] | null | 'null'; export type ListFilters = { [K in Extract]?: ListFilterValue; }; /** * The `list` input as callers see it. Filter columns and sortable columns come * from the table's `access` entry, so `filters` autocompletes to real columns * and rejects wrong value types at compile time. */ export type ListInputFor = { limit?: number; offset?: number; cursor?: string; sort?: TSortable; order?: 'asc' | 'desc'; q?: string; count?: boolean; filters?: ListFilters; } | undefined; /** * The live-view input as callers see it: the list contract narrowed to what a * stream can honor — no text search, no pagination. */ export type LiveInputFor = { limit?: number; sort?: TSortable; order?: 'asc' | 'desc'; filters?: ListFilters; } | undefined; export type BuildTableCrudProceduresArgs, TTable extends Table> = { table: TTable; operations: CrudOperations; builder: ReturnType>; access: ResolvedTableAccess; /** The schema key events are published under. */ schemaKey: string; /** Present when realtime is enabled; without it no live procedure is built. */ livePublisher?: RealtimePublisher; }; export declare function buildTableCrudProcedures, TTable extends Table, TFilterable extends string = string, TSortable extends string = string>(args: BuildTableCrudProceduresArgs): { list: import("@orpc/server").DecoratedProcedure> & object, object, v.GenericSchema, ListInputFor>, v.StrictObjectSchema<{ readonly items: v.ArraySchema, undefined>; readonly nextCursor: v.OptionalSchema, undefined>; readonly hasMore: v.BooleanSchema; readonly total: v.OptionalSchema, undefined>; readonly limit: v.OptionalSchema, undefined>; readonly offset: v.OptionalSchema, undefined>; readonly cursor: v.OptionalSchema, undefined>; readonly q: v.OptionalSchema, undefined>; readonly sort: v.OptionalSchema, undefined>; readonly order: v.OptionalSchema, undefined>; }, undefined>, { readonly BAD_REQUEST: { readonly data: v.OptionalSchema, "BAD_REQUEST">; readonly details: v.OptionalSchema; }, undefined>, { readonly code: "BAD_REQUEST"; }>; }; readonly UNAUTHORIZED: { readonly data: v.OptionalSchema, "UNAUTHORIZED">; readonly details: v.OptionalSchema; }, undefined>, { readonly code: "UNAUTHORIZED"; }>; }; readonly FORBIDDEN: { readonly data: v.OptionalSchema, "FORBIDDEN">; readonly details: v.OptionalSchema; }, undefined>, { readonly code: "FORBIDDEN"; }>; }; readonly NOT_FOUND: { readonly data: v.OptionalSchema, "NOT_FOUND">; readonly details: v.OptionalSchema; }, undefined>, { readonly code: "NOT_FOUND"; }>; }; readonly CONFLICT: { readonly data: v.OptionalSchema, "CONFLICT">; readonly details: v.OptionalSchema; }, undefined>, { readonly code: "CONFLICT"; }>; }; readonly PAYLOAD_TOO_LARGE: { readonly data: v.OptionalSchema, "PAYLOAD_TOO_LARGE">; readonly details: v.OptionalSchema; }, undefined>, { readonly code: "PAYLOAD_TOO_LARGE"; }>; }; readonly TOO_MANY_REQUESTS: { readonly data: v.OptionalSchema, "TOO_MANY_REQUESTS">; readonly details: v.OptionalSchema; }, undefined>, { readonly code: "TOO_MANY_REQUESTS"; }>; }; }, never>; get: import("@orpc/server").DecoratedProcedure> & object, object, v.StrictObjectSchema<{ readonly id: v.StringSchema; }, undefined>, v.GenericSchema, { readonly BAD_REQUEST: { readonly data: v.OptionalSchema, "BAD_REQUEST">; readonly details: v.OptionalSchema; }, undefined>, { readonly code: "BAD_REQUEST"; }>; }; readonly UNAUTHORIZED: { readonly data: v.OptionalSchema, "UNAUTHORIZED">; readonly details: v.OptionalSchema; }, undefined>, { readonly code: "UNAUTHORIZED"; }>; }; readonly FORBIDDEN: { readonly data: v.OptionalSchema, "FORBIDDEN">; readonly details: v.OptionalSchema; }, undefined>, { readonly code: "FORBIDDEN"; }>; }; readonly NOT_FOUND: { readonly data: v.OptionalSchema, "NOT_FOUND">; readonly details: v.OptionalSchema; }, undefined>, { readonly code: "NOT_FOUND"; }>; }; readonly CONFLICT: { readonly data: v.OptionalSchema, "CONFLICT">; readonly details: v.OptionalSchema; }, undefined>, { readonly code: "CONFLICT"; }>; }; readonly PAYLOAD_TOO_LARGE: { readonly data: v.OptionalSchema, "PAYLOAD_TOO_LARGE">; readonly details: v.OptionalSchema; }, undefined>, { readonly code: "PAYLOAD_TOO_LARGE"; }>; }; readonly TOO_MANY_REQUESTS: { readonly data: v.OptionalSchema, "TOO_MANY_REQUESTS">; readonly details: v.OptionalSchema; }, undefined>, { readonly code: "TOO_MANY_REQUESTS"; }>; }; }, Extract>; create: import("@orpc/server").DecoratedProcedure> & object, object, v.GenericSchema, Partial>, v.GenericSchema, { readonly BAD_REQUEST: { readonly data: v.OptionalSchema, "BAD_REQUEST">; readonly details: v.OptionalSchema; }, undefined>, { readonly code: "BAD_REQUEST"; }>; }; readonly UNAUTHORIZED: { readonly data: v.OptionalSchema, "UNAUTHORIZED">; readonly details: v.OptionalSchema; }, undefined>, { readonly code: "UNAUTHORIZED"; }>; }; readonly FORBIDDEN: { readonly data: v.OptionalSchema, "FORBIDDEN">; readonly details: v.OptionalSchema; }, undefined>, { readonly code: "FORBIDDEN"; }>; }; readonly NOT_FOUND: { readonly data: v.OptionalSchema, "NOT_FOUND">; readonly details: v.OptionalSchema; }, undefined>, { readonly code: "NOT_FOUND"; }>; }; readonly CONFLICT: { readonly data: v.OptionalSchema, "CONFLICT">; readonly details: v.OptionalSchema; }, undefined>, { readonly code: "CONFLICT"; }>; }; readonly PAYLOAD_TOO_LARGE: { readonly data: v.OptionalSchema, "PAYLOAD_TOO_LARGE">; readonly details: v.OptionalSchema; }, undefined>, { readonly code: "PAYLOAD_TOO_LARGE"; }>; }; readonly TOO_MANY_REQUESTS: { readonly data: v.OptionalSchema, "TOO_MANY_REQUESTS">; readonly details: v.OptionalSchema; }, undefined>, { readonly code: "TOO_MANY_REQUESTS"; }>; }; }, Extract>; update: import("@orpc/server").DecoratedProcedure> & object, object, v.GenericSchema<{ id: string; } & Partial>, { id: string; } & Partial>>, v.GenericSchema, { readonly BAD_REQUEST: { readonly data: v.OptionalSchema, "BAD_REQUEST">; readonly details: v.OptionalSchema; }, undefined>, { readonly code: "BAD_REQUEST"; }>; }; readonly UNAUTHORIZED: { readonly data: v.OptionalSchema, "UNAUTHORIZED">; readonly details: v.OptionalSchema; }, undefined>, { readonly code: "UNAUTHORIZED"; }>; }; readonly FORBIDDEN: { readonly data: v.OptionalSchema, "FORBIDDEN">; readonly details: v.OptionalSchema; }, undefined>, { readonly code: "FORBIDDEN"; }>; }; readonly NOT_FOUND: { readonly data: v.OptionalSchema, "NOT_FOUND">; readonly details: v.OptionalSchema; }, undefined>, { readonly code: "NOT_FOUND"; }>; }; readonly CONFLICT: { readonly data: v.OptionalSchema, "CONFLICT">; readonly details: v.OptionalSchema; }, undefined>, { readonly code: "CONFLICT"; }>; }; readonly PAYLOAD_TOO_LARGE: { readonly data: v.OptionalSchema, "PAYLOAD_TOO_LARGE">; readonly details: v.OptionalSchema; }, undefined>, { readonly code: "PAYLOAD_TOO_LARGE"; }>; }; readonly TOO_MANY_REQUESTS: { readonly data: v.OptionalSchema, "TOO_MANY_REQUESTS">; readonly details: v.OptionalSchema; }, undefined>, { readonly code: "TOO_MANY_REQUESTS"; }>; }; }, Extract>; delete: import("@orpc/server").DecoratedProcedure> & object, object, v.StrictObjectSchema<{ readonly id: v.StringSchema; }, undefined>, v.UndefinedSchema, { readonly BAD_REQUEST: { readonly data: v.OptionalSchema, "BAD_REQUEST">; readonly details: v.OptionalSchema; }, undefined>, { readonly code: "BAD_REQUEST"; }>; }; readonly UNAUTHORIZED: { readonly data: v.OptionalSchema, "UNAUTHORIZED">; readonly details: v.OptionalSchema; }, undefined>, { readonly code: "UNAUTHORIZED"; }>; }; readonly FORBIDDEN: { readonly data: v.OptionalSchema, "FORBIDDEN">; readonly details: v.OptionalSchema; }, undefined>, { readonly code: "FORBIDDEN"; }>; }; readonly NOT_FOUND: { readonly data: v.OptionalSchema, "NOT_FOUND">; readonly details: v.OptionalSchema; }, undefined>, { readonly code: "NOT_FOUND"; }>; }; readonly CONFLICT: { readonly data: v.OptionalSchema, "CONFLICT">; readonly details: v.OptionalSchema; }, undefined>, { readonly code: "CONFLICT"; }>; }; readonly PAYLOAD_TOO_LARGE: { readonly data: v.OptionalSchema, "PAYLOAD_TOO_LARGE">; readonly details: v.OptionalSchema; }, undefined>, { readonly code: "PAYLOAD_TOO_LARGE"; }>; }; readonly TOO_MANY_REQUESTS: { readonly data: v.OptionalSchema, "TOO_MANY_REQUESTS">; readonly details: v.OptionalSchema; }, undefined>, { readonly code: "TOO_MANY_REQUESTS"; }>; }; }, never>; live: import("@orpc/server").DecoratedProcedure> & object, object, v.GenericSchema, LiveInputFor>, import("@orpc/contract").Schema, import("@orpc/client").AsyncIteratorClass<{ type: "snapshot"; items: TTable["$inferSelect"][]; sort: string; order: "asc" | "desc"; limit: number; hasMore: boolean; operationId?: string | undefined; } | { type: "upsert"; record: TTable["$inferSelect"]; afterId: string | null; operationId?: string | undefined; } | { type: "remove"; id: string; operationId?: string | undefined; } | { type: "heartbeat"; intervalMs: number; }, unknown, void>>, { readonly BAD_REQUEST: { readonly data: v.OptionalSchema, "BAD_REQUEST">; readonly details: v.OptionalSchema; }, undefined>, { readonly code: "BAD_REQUEST"; }>; }; readonly UNAUTHORIZED: { readonly data: v.OptionalSchema, "UNAUTHORIZED">; readonly details: v.OptionalSchema; }, undefined>, { readonly code: "UNAUTHORIZED"; }>; }; readonly FORBIDDEN: { readonly data: v.OptionalSchema, "FORBIDDEN">; readonly details: v.OptionalSchema; }, undefined>, { readonly code: "FORBIDDEN"; }>; }; readonly NOT_FOUND: { readonly data: v.OptionalSchema, "NOT_FOUND">; readonly details: v.OptionalSchema; }, undefined>, { readonly code: "NOT_FOUND"; }>; }; readonly CONFLICT: { readonly data: v.OptionalSchema, "CONFLICT">; readonly details: v.OptionalSchema; }, undefined>, { readonly code: "CONFLICT"; }>; }; readonly PAYLOAD_TOO_LARGE: { readonly data: v.OptionalSchema, "PAYLOAD_TOO_LARGE">; readonly details: v.OptionalSchema; }, undefined>, { readonly code: "PAYLOAD_TOO_LARGE"; }>; }; readonly TOO_MANY_REQUESTS: { readonly data: v.OptionalSchema, "TOO_MANY_REQUESTS">; readonly details: v.OptionalSchema; }, undefined>, { readonly code: "TOO_MANY_REQUESTS"; }>; }; }, never>; }; export type TableCrudProcedures = Omit, TTable, TFilterable, TSortable>>, 'live'> & (TLive extends true ? { live: ReturnType, TTable, TFilterable, TSortable>>['live']; } : {}); export declare function buildCrudApiRouter, TAccess extends Record | undefined = undefined, TLive extends boolean = false>(schema: TSchema, db: AnyDb, options: CrudApiRouterOptions): CrudApiRouterFor; //# sourceMappingURL=crud-router.d.ts.map