📣July 19th release is out!Read the release notes

    Triplit Release Notes 2/23/2024

    • Added support for optional attributes in a schema. Optional attributes will not be required by the schema and will be undefined at runtime if not provided. Optional attributes may also be deleted or set to undefined in updater functions.
    export const schema = {
      foo: {
        schema: S.Schema({
          id: S.Id(),
          bar: S.Optional(S.String()),
          baz: S.Optional(S.Number({ nullable: true })),
        }),
      },
    };
    
    /* would be equivalent to the following TypeScript type:
      { 
        id: string
        bar?: string 
        baz?: number | null
      }
     */
    
    • With optional attribute support, Triplit now supports upsert behavior. 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 Fry',
      year_hired: 3000,
    });
    
    await client.insert('employee', {
      id: 'Fry',
      name: 'Philip J. Fry',
      title: 'Delivery Boy',
    });
    
    const { result } = await client.fetchById('employee', 'Fry');
    
    /* result will be
      { 
        id: 'Fry', 
        name: 'Philip J. Fry', 
        title: 'Delivery Boy,
        year_hired: 3000
      }
    */
    
    • Added new schema debugging commands in CLI. You can run triplit schema print to print out the local and remote schemas. You can also run triplit schema diff to see the differences between the local and remote schemas.

    • Improved support and simplified API for defining paginated queries. Triplit supports cursor-based pagination in conjunction with the order query parameter. We've simplified the API for defining paginated queries, such that you need only provide a valid entity from your results to indicate where the next page should start.

    const query = client.query('users').order('created_at', 'DESC').limit(10);
    
    const { results: firstPage } = client.fetch(query);
    const lastEntity = Array.from(firstPage.values()).pop();
    
    const secondPageQuery = query.after(lastEntity);
    
    // will return at most 5 entities created before the last entity in the first page
    const { results: secondPage } = client.fetch(secondPageQuery);