Updating data

Updating data

Operations

Insert

insert() inserts a new record into a collection. For example:

await client.insert('employee', { id: 'Fry', name: 'Philip Fry' });

The id field in Triplit is a special field that is used to uniquely identify records and is required on entities. If you do not provide an id, one will be generated for you.

The insert method may also be used to upsert an existing record when used in a schemaless database or in conjuction with optional attributes. For example:

const schema = {
  employee: {
    schema: S.Schema({
      id: S.Id(),
      name: S.String(),
      title: S.Optional(S.String()),
      year_hired: S.Optional(S.Number()),
    }),
  },
} satisfies ClientSchema;
await client.insert('employee', { id: 'Fry', name: 'Philip J. Fry' });
await client.insert('employee', {
  id: 'Fry',
  name: 'Philip J. Fry',
  title: 'Pizza Delivery Boy',
});
await client.insert('employee', {
  id: 'Fry',
  name: 'Philip J. Fry',
  title: 'Package Delivery Boy',
  year_hired: 3000,
});
⚠️

When using insert to upsert an existing record, any defaults on the schema will be applied even if the record already exists.

Update

update() updates an existing record in a collection. For example:

await client.update('employee', 'Fry', async (entity) => {
  entity.name = 'Philip J. Fry';
});

If possible, update will look at the schema you have provided to provide proper type hints for interacting with you data. If no schema is provided, all fields are treated as any.

See here for more information on data types.

Delete

delete() deletes a record from a collection. For example:

await client.delete('employee', 'Fry');

Transactions

Transactions are a way to group multiple mutations into a single atomic operation. If any part of the mutations fail, the entire transaction is rolled back.

A transaction can be created by calling client.transact(). For example:

await client.transact((tx) => {
  await tx.insert('employee', { id: 'Fry', name: 'Philip J. Fry' });
  await tx.insert('employee', { id: 'Leela', name: 'Turanga Leela' });
  await tx.insert('employee', {
    id: 'Bender',
    name: 'Bender Bending Rodriguez',
  });
});

If you decide you need to abort a transaction, you can call cancel inside your transaction. For example:

await client.transact((tx) => {
  await tx.insert('employee', { id: 'Hermes', name: 'Hermes Conrad' });
  await tx.cancel();
});

Error and success handling

Mutations are first run on Triplit's local cache "optimistically", returning a promise. If the optimistic mutation is successful, the promise will resolve with the id of the transaction. If the optimistic mutation fails, the promise will reject with an error. So you can handle optimistic updates with standard promise handling. For example:

try {
  const { txId } = await client.insert('employee', {
    id: 'Fry',
    name: 'Philip J. Fry',
  });
  // Optimistic update succeeded
} catch (e) {
  // Optimistic update failed
}

If the sync engine is connected, mutations will then be applied to the server when possible. To react to a transaction successfully running or failing on the server, you can pass a callback to client.syncEngine.onTxCommit(txId, callback) or client.syncEngine.onTxFailure(txId, callback). The client also provides methods for helping you manage what should happen to your data if a transaction fails on the server. client.syncEngine.retry(txId) will retry a transaction with the id txId. client.syncEngine.rollback(txId) will rollback a transaction with the id txId, removing it from the local cache. For example:

const { txId } = await client.insert('employee', {
  id: 'Fry',
  name: 'Philip J. Fry',
});
client.syncEngine.onTxCommit(txId, () => {
  // Transaction succeeded on the server
});
client.syncEngine.onTxFailure(txId, (e) => {
  // Transaction failed on the server
  // shouldRetry is a boolean you define
  if (shouldRetry) {
    client.syncEngine.retry(txId);
  } else {
    client.syncEngine.rollback(txId);
  }
});

Triplit's API attempts to give you the flexibility to handle errors in various ways. For example, you could choose to retry a transaction a certain number of times before rolling it back. Or you could choose to retry a transaction only if it failed due to a network error.