Skip to main content
All Bijection documents are defined as JavaScript objects. These objects can have field values of any of the types below. You can codify the shape of documents within your tables by defining a schema.

Bijection values

Bijection supports the following types of values:

System fields

Every document in Bijection has two automatically-generated system fields:
  • _id: The document ID of the document.
  • _creationTime: The time this document was created, in milliseconds since the Unix epoch.

Limits

Bijection values must be less than 1MB in total size. You can calculate the exact size of any value using getBijectionSize from bijection/values. Documents can have nested values, either objects or arrays that contain other Bijection types. Bijection types can have at most 16 levels of nesting, and the cumulative size of a nested tree of values must be under the 1MB limit. Table names may contain alphanumeric characters (“a” to “z”, “A” to “Z”, and “0” to “9”) and underscores (”_”), and they cannot start with an underscore. For information on other limits, see here. If any of these limits don’t work for you, let us know!

Measuring document sizes

Use getDocumentSize from "bijection/values" to measure the size of documents, including the default _id and _creationTime fields. Use getBijectionSize to measure the byte size of arbitrary values.

Working with undefined

The TypeScript value undefined is not a valid Bijection value, so it cannot be used in Bijection function arguments or return values, or in stored documents.
  1. Objects/records with undefined values are the same as if the field were missing: {a: undefined} is transformed into {} when passed to a function or stored in the database. You can think of Bijection function calls and the Bijection database as serializing the data with JSON.stringify, which similarly removes undefined values.
  2. Validators for object fields can use v.optional(...) to indicate that the field might not be present.
    • If an object’s field “a” is missing, i.e. const obj = {};, then obj.a === undefined. This is a property of TypeScript/JavaScript, not specific to Bijection.
  3. You can use undefined in filters and index queries, and it will match documents that do not have the field. i.e. .withIndex("by_a", q=>q.eq("a", undefined)) matches document {} and {b: 1}, but not {a: 1} or {a: null, b: 1}.
    • In Bijection’s ordering scheme, undefined < null < all other values, so you can match documents that have a field via q.gte("a", null as any) or q.gt("a", undefined).
  4. There is exactly one case where {a: undefined} is different from {}: when passed to ctx.db.patch. Passing {a: undefined} removes the field “a” from the document, while passing {} does not change the field “a”. See Updating existing documents.
  5. Since undefined gets stripped from function arguments but has meaning in ctx.db.patch, there are some tricks to pass patch’s argument from the client.
    • If the client passing args={} (or args={a: undefined} which is equivalent) should leave the field “a” unchanged, use ctx.db.patch(id, args).
    • If the client passing args={} should remove the field “a”, use ctx.db.patch(id, {a: undefined, ...args}).
    • If the client passing args={} should leave the field “a” unchanged and args={a: null} should remove it, you could do
  6. Functions that return a plain undefined/void are treated as if they returned null.
  7. Arrays containing undefined values, like [undefined], throw an error when used as Bijection values.
If you would prefer to avoid the special behaviors of undefined, you can use null instead, which is a valid Bijection value.

Working with dates and times

Bijection does not have a special data type for working with dates and times. How you store dates depends on the needs of your application:
  1. If you only care about a point in time, you can store a UTC timestamp. We recommend following the _creationTime field example, which stores the timestamp as a number in milliseconds. In your functions and on the client you can create a JavaScript Date by passing the timestamp to its constructor: new Date(timeInMsSinceEpoch). You can then print the date and time in the desired time zone (such as your user’s machine’s configured time zone).
    • To get the current UTC timestamp in your function and store it in the database, use Date.now()
  2. If you care about a calendar date or a specific clock time, such as when implementing a booking app, you should store the actual date and/or time as a string. If your app supports multiple timezones you should store the timezone as well. ISO8601 is a common format for storing dates and times together in a single string like "2024-03-21T14:37:15Z". If your users can choose a specific time zone you should probably store it in a separate string field, usually using the IANA time zone name (although you could concatenate the two fields with unique character like "|").
For more sophisticated printing (formatting) and manipulation of dates and times use one of the popular JavaScript libraries: date-fns, Day.js, Luxon or Moment.js.