Skip to main content
Custom tables let you provision your own database tables alongside Sublay’s built-in models. The client.table(name) accessor gives you full row-level access to a custom table from your server. For an overview of the feature — the custom_ naming model, managed columns, and soft-delete — see Custom Tables. To create tables and columns, see Tables — Management.
client.table(name) is a callable accessor, not a flat module namespace — it closes over the table name and returns the row-operation object. You can type the rows by passing a generic: client.table<EventRow>("Events").
interface EventRow {
  id: string;
  name: string;
  capacity: number;
  createdAt: string;
}

const events = sublay.table<EventRow>("Events");
const { data } = await events.find({ limit: 20 });
The name you pass is the logical table name — Sublay applies the custom_ prefix for you.

find

Fetches a filtered, sorted, paginated page of rows. Returns the shared { data, pagination } envelope.
const { data, pagination } = await sublay.table<EventRow>("Events").find({
  page: 1,
  limit: 20,
  sortBy: "createdAt",
  sortDir: "desc",
  filters: [
    { column: "capacity", operator: "gte", value: 100 },
    { column: "name", operator: "contains", value: "summit" },
  ],
});
page
number
Page number (1-indexed).
limit
number
Rows per page.
sortBy
string
Column to sort by. Validated against the table’s real columns. Defaults to createdAt (descending) on a table with timestamps, otherwise id.
sortDir
"asc" | "desc"
Sort direction.
filters
DbFilter[]
An array of { column, operator, value } clauses, AND-combined. Operators: eq, ne, gt, gte, lt, lte, in, contains, like, isNull. Serialized to a JSON query parameter for you.
includeDeleted
boolean
On a paranoid table, set true to include soft-deleted rows. Defaults to false.
ReturnsPromise<PaginatedResponse<T>>

findOne

Fetches a single row by its id. Throws (axios 404) if the row doesn’t exist or has been soft-deleted.
const event = await sublay.table<EventRow>("Events").findOne("a1b2c3d4-...");
rowId
string
required
The row’s id (UUID).
ReturnsPromise<T>

create

Inserts a single row. Managed columns (id, createdAt, updatedAt, deletedAt) are rejected from the body — they are set by the server.
const event = await sublay.table<EventRow>("Events").create({
  name: "Launch Summit",
  capacity: 250,
});
data
Partial<T>
required
The column values for the new row.
ReturnsPromise<T>

bulkCreate

Inserts many rows in one call. Capped at 100 rows per request.
const rows = await sublay.table<EventRow>("Events").bulkCreate([
  { name: "Workshop A", capacity: 40 },
  { name: "Workshop B", capacity: 40 },
]);
rows
Partial<T>[]
required
The rows to insert (max 100).
ReturnsPromise<T[]>

update

Updates a row by id. On a table with timestamps, updatedAt is bumped automatically. Managed columns are rejected from the body.
const event = await sublay.table<EventRow>("Events").update("a1b2c3d4-...", {
  capacity: 300,
});
rowId
string
required
The row’s id.
data
Partial<T>
required
The column values to change.
ReturnsPromise<T>

delete

Deletes a row by id. On a paranoid table this is a soft delete (sets deletedAt); pass force: true to hard-delete. On a non-paranoid table it is always a hard delete.
// Soft delete on a paranoid table
await sublay.table("Events").delete("a1b2c3d4-...");

// Hard delete
await sublay.table("Events").delete("a1b2c3d4-...", { force: true });
rowId
string
required
The row’s id.
opts.force
boolean
When true, hard-deletes a paranoid row instead of soft-deleting it.
ReturnsPromise<{ deleted: boolean; soft: boolean }>soft is true when the row was soft-deleted.

bulkDelete

Deletes many rows by an id list and/or a filters predicate (at least one is required). Paranoid-aware (soft by default, force to hard-delete) and capped at the bulk limit.
// By id list
await sublay.table("Events").bulkDelete({ rowIds: ["id-1", "id-2"] });

// By predicate
await sublay.table("Events").bulkDelete({
  filters: [{ column: "capacity", operator: "lt", value: 10 }],
  force: true,
});
rowIds
string[]
Rows to delete by id.
filters
DbFilter[]
A predicate selecting rows to delete (same shape as find’s filters).
force
boolean
When true, hard-deletes matched paranoid rows.
ReturnsPromise<{ deletedCount: number; soft: boolean }>

restore

Clears deletedAt on a soft-deleted row, bringing it back. Only valid on a paranoid table.
const event = await sublay.table<EventRow>("Events").restore("a1b2c3d4-...");
rowId
string
required
The soft-deleted row’s id.
ReturnsPromise<T>
Row CRUD on the /db surface is currently open — identity is captured but not enforced. See the security note on the overview page before storing access-controlled data in custom tables.