The Model API

The @teamkeel/sdk package is generated based on your schema and contains type-safe APIs for interacting with your models. These APIs are all available on the exported models object.

import { models } from "@teamkeel/sdk";

Given the following Keel schema:

model Post {
	fields {
     title Text
  }
 
  actions {
    write createPost()
  }
}
 
model Author {
  fields {
     name Text
  }
}

models.post and models.author will be available.

Creating a record

.create() receives a single parameter:

  • params - object representing all of the data you would like to insert. This must include all required fields on the model.

Fields that have a @default value in the schema will have their default values populated if no value is provided.

For @unique fields, inserted data will be checked for uniqueness.

import { models } from "@teamkeel/sdk";
 
const post = await models.post.create({
  title: "a post about star wars",
});
 
console.log(post.title); // => a post about star wars

The return type is Promise<Model>

Updating a record

.update() receives two parameters:

  • where - the query conditions to lookup records by.
  • values - the set of changes you want to update the record(s) with.

For @unique fields, updated data will be checked for uniqueness.

import { models } from "@teamkeel/sdk";
 
const where = {
  id: "123",
};
 
const values = {
  title: "a post about star wars",
};
 
const post = await models.post.update(where, values);
 
console.log(`Updated ${post.id}'s title`);

The return type is Promise<Model>

Deleting a record

.delete() receives a single parameter:

  • where - the conditions applied to the database query that will determine which records will be deleted
import { models } from "@teamkeel/sdk";
 
const deletedId = models.post.delete({
  id: "123",
});

Reading a single record

.findOne() receives a single parameter:

  • where - an object where the keys are any unique field on a model and the values are the unique values you want to look up by
import { models } from "@teamkeel/sdk";
 
const post = await models.post.findOne({
  id: "abc",
});

The return type is Promise<Model | null>

Reading multiple records

.findMany receives a single parameter:

  • params - Object of type FindManyParams

FindManyParams

Consists of four top level properties:

  • limit (number) - the number of rows to limit the result set by
    import { models } from "@teamkeel/sdk";
     
    const results = await models.post.findMany({
      limit: 5,
    });
  • offset (number) - the number of rows to offset by. Usually combined with limit and orderBy to return individual pages of data.
    import { models } from "@teamkeel/sdk";
     
    const results = await models.post.findMany({
      limit: 10,
      offset: 2,
      orderBy: {
        title: "asc",
      },
    });
  • where (Where) - an object where the keys are one of the fields on the model and the values are objects conforming to the WhereConditions type. See the WhereConditions reference for a full table of the available options for different field types below.
    import { models } from "@teamkeel/sdk";
     
    const postsBeginningWithA = await models.post.findMany({
      {
        where: {
          title: {
            startsWith: 'a'
          }
        }
      }
    });
  • orderBy (OrderBy) - an object used to define the sort order of the results returned from the database. The object must contain one property where the key is a known field name on the model, and the value must either be asc, desc.
    import { models } from "@teamkeel/sdk";
     
    const orderedByTitle = await models.post.findMany(
      orderBy: {
        title: 'asc'
      }
    );

WhereConditions

The WhereConditions type can be used with the findMany method to filter by a range of different operators:

Operator NameField TypesDescriptionUsage
startsWithTextMatch values beginning with the search value{ title: { startsWith: 'abc' }}
endsWithTextMatch values ending with the search value{ title: { endsWith: 'xyz' }}
oneOfTextMatch values against an array of possible values{ title: { oneOf: ['apple', 'orange'] }}
containsTextMatch values against a partial match within a string{ title: { contains: 'apple' } }
notEqualsText, Number, BooleanFind values where not matching search value{ title: { notEquals: 'apple' }}
equalsText, Number, Date, ID, BooleanFind values matching the search value{ title: { equals: 'orange' }}
greaterThanNumberFind values where the value is greater than the search value{ rating: { greaterThan: 5 }}
greaterThanOrEqualsNumberFind values where the value is greater than or equal to the search value{ rating: { greaterThanOrEquals: 5 }}
lessThanNumberFind values where the value is less than the search value{ rating: { lessThan: 5 }}
lessThanOrEqualsNumberFind values where the value is less than or equal to the search value{ rating: { lessThanOrEquals: 5 }}
beforeDateFind values where the date is before the search date{ createdAt: { before: new Date(2020, 1, 1) }}
onOrBeforeDateFind values where the date is equal to or before the search date{ createdAt: { onOrBefore: new Date(2020, 1, 1) }}
afterDateFind values where the date is after the search date{ createdAt: { after: new Date(2020, 1, 1) }}
onOrAfterDateFind values where the date is equal to or after the search date{ createdAt: { onOrAfter: new Date(2020, 1, 1) }}

Nested Create / Update

⚠️

The Model API doesn't currently support creating or updating nested relations, but will in the near future.

Until then, you can create related models yourself using the Model API:

functions/createPost.ts
import { CreatePost, models } from '@teamkeel/sdk';
 
export default CreatePost({
  beforeWrite: async (ctx, inputs) => {
    const {
      author: { name }
    } = inputs;
 
    // create the new author prior to creating the post
    const author = await models.author.create({ name });
 
    return {
      ...inputs,
      authorId: author.id
    }
  }
});