Navigated to /docs/data/field-types.

Field types

API reference for the supported field types in Nokkio

When you use Nokkio's data layer, you provide a schema that describes the different objects in your application, and the fields each object has. The fields are described using types that are provided to your schema function. For more on setting up your schema, refer to the data documentation.

types.string()

string() is for shorter pieces of text, less than or equal to 255 characters.

string() can optionally be supplied a default value for times when the application does not provide a value:

const List = defineModel('List', {
  name: types.string(),
  description: types.string(null),
});

In the above example, name is required but description is not–if one is not provided, the value will be null.

You can also set string() fields to be unique by chaining the unique() modifier. In this example, no two lists will be allowed to have the same name.

const List = defineModel('List', {
  name: types.string().unique(),
});

Scoping uniqueness

In some scenarios, enforcing uniqueness globally is too broad. For example, take this schema for a multitenant application where each user has their own set of lists:

const User = defineModel('User', {
  username: types.string().unique(),
  password: types.password(),
});

const List = defineModel('List', {
  name: types.string().unique(),
});

User.hasMany(List);

Using this schema, only one user in your entire application could have a List with the name Work. If you would instead prefer to scope uniqueness within a relationship, you can use uniqueWithin:

const User = defineModel('User', {
  username: types.string().unique(),
  password: types.password(),
});

const List = defineModel('List', {
  name: types.string().uniqueWithin(User),
});

User.hasMany(List);

Now uniqueness of the List name is scoped by the user the list belongs too.

If you have a set of expected values, you can provide that list via oneOf:

const Post = defineModel('Post', {
  title: types.string(),
  status: types
    .string('draft')
    .oneOf(['draft', 'published']),
});

In this example we've combined a few features for the status field. First, we've provided it with a default value (draft), and then instructed Nokkio to only accept two possible values as input: draft and published.

Finally, string fields are "filterable". When you mark a field as filterable, you can then query and/or sort on that field when using @nokkio/magic hooks. The following will allow us to search for Lists by a particular title.

const List = defineModel('List', {
  name: types.string().filterable(),
});

Limits

To limit the length of the string, three functions are available: min, max, and fixedLength.

const Post = defineModel('Post', {
  title: types.string(),
  // slugs must be between 20 and 100 characters in length
  slug: types.string().min(20).max(100),
  // tokens must be exactly 32 characters
  token: types.string().fixedLength(32),
});

types.text()

text() is for long-form text. text fields do not accept any other modifiers, meaning they are not filterable and cannot be made unique.

const Post = defineModel('Post', {
  title: types.string(),
  body: types.text(),
});

types.markdown()

markdown() is a light wrapper over the text()type. For inputs, it acts the same as text(): it is not filterable and cannot be made unique. The difference is in the returned value. When @nokkio/magic resolves a markdown field, it is an object that has both the source (the original input) and the html of the transformed Markdown.

const Post = defineModel('Post', {
  title: types.string(),
  body: types.markdown(),
});

// resolved fields will look like:
//
// post.title === 'This is my post'
// post.body.source === '# introduction'
// post.body.html === '<h1>introduction</h1>'

Displaying Markdown fields

Nokkio provides a helper component to output your transformed Markdown. Assuming you have a body field on your Post model, you can use it like this:

import MarkdownDisplay from '@nokkio/markdown-display';

<MarkdownDisplay
  as="article"
  className="prose"
  data={post.body} />

Previewing draft Markdown content

Nokkio also provides a component for previewing Markdown content on the client before it is persisted.

import {MarkdownPreview} from '@nokkio/markdown';

<MarkdownPreview
  as="article"
  className="prose"
  markdown="# this is a header" />

types.number()

number() is an umbrella type for any number. Like string(), numbers can take a default value, are filterable, and can accept a limited set of values via oneOf. Here's a mega-example of all three put together:

const User = defineModel('User', {
  username: types.string(),
  level: types.number(1)
    .oneOf([1, 2, 3])
    .filterable(),
});

By default, all numbers in Nokkio are "unsigned", meaning only positive values are allowed. To allow both positive and negative numbers, use signedNumber() instead:

const City = defineModel('City', {
  name: types.string(),
  temperature: types.signedNumber(),
});

Enforcing min and/or max

If you want to enforce that values fall in a specific range, you can use max() and min().

const Student = defineModel('Student', {
  grade: types.number().min(1).max(12),
});

Limits

By default, numbers in Nokkio are valid from 0 to 4294967295. If you use signedNumber(), the default range is -2147483648 to 2147483647. If you need larger numbers than that, use max and min to specify a broader range:

const Prime = defineModel('Prime', {
  n: types.number().max(Number.MAX_SAFE_INTEGER),
});

Numbers in Nokkio can be any JavaScript "safe integer", defined as being between Number.MIN_SAFE_INTEGER and Number.MAX_SAFE_INTEGER .

types.bool()

bool() is for storing true or false values. bool fields are filterable by default, and accept default values. They cannot be made unique.

const Post = defineModel('Post', {
  title: types.string(),
  body: types.text(),
  isPublished: types.bool(false),
});
Caution
bool() fields accept a default value, but unlike other fields that default value cannot be null–it must be true or false.

Dates and Times

Nokkio provides two data types for storing dates and times, and it's important to understand the nuance between the two.

types.date()

types.date() stores a date only. It is a static representation of a day, month, and year, and is not adjusted for time zones. That means if a user enters January 10th, 2022, it is always displayed as that date no matter what time zone other users view it in.

const Person = defineModel('Person', {
  name: types.string(),
  birthday: types.date(),
});

types.date() accepts the filterable() modifier and accepts a default value, including null.

types.datetime()

types.datetime() captures a point in time. These values are always stored in UTC time, then adjusted to the user's local time zone when used inside your application. datetime fields are automatically converted back to JavaScript Date instances by @nokkio/magic.

const Todo = defineModel('Todo', {
  text: types.string(),
  completedOn: types.datetime(null),
});

types.datetime() accepts the filterable() modifier and accepts a default value, including null.

types.image()

image() is a special type that allows you to accept uploads to your models. Combined with @nokkio/image it handles file uploads, automatically resizing images, and more. For a full walkthrough of using images in your models, see the documentation.

const User = defineModel('User', {
  username: types.string().unique(),
  password: types.password(),
  avatar: types.image(),
});

image accepts a few modifiers as well:

  1. minSize(w, h) validates that the uploaded image is at least w x h in size.
  2. maxSize(w, h) validates that the uploaded image is no larger than w x h in size.
  3. maxFilesize(bytes) ensures that the uploaded file is no larger than bytes in filesize.

Here is a full example that guarantees stored images will be from 400 x 400 and 1200 x 1200 and be less than or equal to 5MB. Also, as this illustrates, image accepts a default value, which must be null.

const User = defineModel('User', {
  username: types.string().unique(),
  password: types.password(),
  avatar: types.image(null)
    .minSize(400, 400)
    .maxSize(1200, 1200)
    .maxFilesize(5 * 1024 * 1024),
});

When you use image values in your components, the image is a rich object with several fields inside:

  1. name - the filename of the uploaded image.
  2. type - the type of the original image, e.g. image/jpeg.
  3. width - the width of the original image.
  4. height - the height of the original image.
  5. size - the filesize of the original image.

types.password()

The password type is for use with Nokkio's authentication system. It does not accept any modifiers or a default value. Read more about the password field in the authentication documentation.