Skip to main content

.insert() method

The .insert() method in Supastash lets you add new rows to your local SQLite table. It follows the Supabase pattern, but with offline-first logic built in โ€” handling inserts locally first, then syncing to Supabase when possible.


๐Ÿง  How It Worksโ€‹

Calling .insert() performs the following steps internally:

  1. Validates the payload and target table.
  2. Ensures every record has a valid id. If missing, Supastash generates a UUID.
  3. Adds created_at, updated_at, and synced_at fields if not already included.
  4. Writes the data into the local database.
  5. Triggers background sync (based on the chosen sync mode).

๐Ÿ” Supastash always returns the inserted payload as data, either as a single object or an array โ€” depending on how it was inserted.

โšก All non-select operations (insert, update, delete, upsert) use a debounced version tracker to group rapid updates and trigger a single UI refresh per table. This prevents unnecessary re-renders in high-frequency update scenarios.


๐Ÿงพ Supported Payloadsโ€‹

There are two accepted payload types for .insert():

1. Single Objectโ€‹

Used when you want to insert a single row:

await supastash
.from("orders")
.insert<T>({ id: "abc", amount: 500 })
.single() // Optional: to enforce one-row expectation
.run();
  • You can optionally chain .single() to indicate only one row is expected.
  • If you mistakenly pass an array with .single(), Supastash will throw:
.single() cannot be used with array payloads on INSERT to orders. Use a single object instead.

2. Array of Objectsโ€‹

Used for batch inserts:

await supastash
.from("orders")
.insert<T>([
{ id: "o1", amount: 100 },
{ id: "o2", amount: 200 },
])
.run();

You shouldnโ€™t use .single() when inserting an array. Supastash will catch this at runtime and throw a clear error to let you know.


๐Ÿ” ID Handlingโ€‹

Supastash guarantees every inserted row has an id by default. If any record lacks one, it auto-generates a UUID. This removes the burden of generating IDs manually while ensuring consistency in syncing and querying later.


๐Ÿ” Sync Modesโ€‹

Sync behavior depends on the mode selected:

ModeBehavior
localOnlyInserts only into SQLite
remoteOnlySends directly to Supabase, skips local DB
localFirst(Default) Inserts locally, queues remote sync
remoteFirstSends to Supabase first, mirrors to local on success

You can control this with .syncMode("mode"):

await supastash
.from("orders")
.insert({ amount: 500 })
.syncMode("remoteFirst")
.run();

โœ… Return Shapeโ€‹

All .insert() calls always return the inserted payload:

{
data: [...insertedRecords],
error: null,
success: true
}

If .single() was used, data is a single object instead of an array.

You can also opt to get Supabase response by passing { viewRemoteResult: true } to .run():

{
local: {...},
remote: {...},
success: true
}

โœ… When to Use .insert()โ€‹

Use .insert() when:

  • Creating a new row or batch of rows

Next: .select()