// A record: the entity's fields plus the system fields below (no others).
type RecordData = Record<string, unknown> & {
id: string;
created_at: string;
updated_at: string;
};
type ListResponse<T> = {
data: T[];
meta: { has_more: boolean; next_cursor: string | null };
};
type SingleResponse<T> = { data: T };
type FilterOperator =
| 'eq' | 'neq' | 'gt' | 'gte' | 'lt' | 'lte'
| 'in' | 'contains' | 'starts_with' | 'is_null';
type FilterScalar = string | number | boolean;
// Only `in` takes a list; `is_null` takes a boolean.
type FilterOperatorMap = {
eq?: FilterScalar; neq?: FilterScalar;
gt?: string | number; gte?: string | number;
lt?: string | number; lte?: string | number;
in?: (string | number)[];
contains?: string; starts_with?: string;
is_null?: boolean;
};
type FieldFilter =
| FilterScalar // equals
| null // unset
| FilterOperatorMap // every operator must hold
| { op: FilterOperator; value: unknown }; // one operator, spelled out
type Filter = Record<string, FieldFilter>;
type ListOptions = {
filter?: Filter;
sort?: string;
pageSize?: number;
cursor?: string;
};
type PaginateOptions = Omit<ListOptions, 'cursor'> & {
maxPages?: number;
maxRecords?: number;
signal?: AbortSignal;
};
type SchemaEntity = {
slug: string; // the entityKey every record method takes
name: string;
description: string | null;
version: number;
fields: SchemaField[]; // ordered by position
};
type SchemaFieldType =
| 'text' | 'multiline' | 'number' | 'boolean' | 'date' | 'enum'
| 'reference' | 'currency' | 'phone' | 'email' | 'json';
type SchemaField = {
key: string;
name: string;
type: SchemaFieldType;
phi_flag: boolean;
constraints: Record<string, unknown> | null;
position: number;
};
type BootstrapData = {
user: { id: string; name: string; email: string } | null;
org: { id: string; role: string };
role: string; // 'viewer' | 'org_admin_viewer' | 'editor' | 'admin'
app: { id: string; name: string; type: string };
limits: Record<string, number>;
};
// Returned by uploadFile()
type UploadedFile = {
id: string;
originalFilename: string | null;
mimeType: string;
byteSize: number;
created_at: string;
};
// Returned by getFileUrl()
type FileDownloadResponse = {
id: string;
url: string; // valid for one hour
originalFilename: string | null;
mimeType: string;
byteSize: number;
expiresAt: string;
};