Skip to content
Permalink
Branch: master
Find file Copy path
Find file Copy path
9 contributors

Users who have contributed to this file

@nikolasburk @timsuchanek @Tyguy160 @schickling @janpio @johannesschobel @infoverload @jjangga0214 @fivechjr
557 lines (404 sloc) 22.8 KB

Generated Photon API (JavaScript/TypeScript)

Photon is a type-safe database client auto-generated based on your data model definition (which is a declarative representation of your database schema). This page explains the generated API operations you have available when using Photon.

Overview

Using Photon typically follows this high-level workflow:

  1. Add Photon.js to your project using: npm install @prisma/photon
  2. Define/update your data model definition (e.g. by manually adding a new model or by (re)introspecting your database)
  3. Generate your Photon database client based on the changes in the data model definition

Note that steps 2. and 3. might happen repeatedly as you evolve your application.

The Photon constructor can then be imported from node_modules/@prisma/photon.

Assume you have the following data model definition:

model User {
  id    Int    @id
  name  String
  role  Role
  posts Post[]
}

model Post {
  id     Int    @id
  title  String
  author User
}

enum Role {
  USER
  ADMIN
}

CRUD

Your generated Photon API will expose the following CRUD operations for the User and Post models:

You can access each function via the respective model property on your generated Photon instance, e.g. users for the User model:

import { Photon } from '@prisma/photon'

const photon = new Photon()

async function main() {
  await photon.connect()
  const result = await photon.users.findOne({
    where: { id: 1 },
  })
  // result = { id: 1, name: "Alice", role: "USER" }
  await photon.disconnect()
}

Note that the name of the users property is auto-generated using the pluralize package.

Aggregations

In addition to CRUD operations, Photon.js also allows for aggregation queries.

count

To return the number of elements in a list, you can the count() method on any model property on your Photon instance, for example:

const userCount = await photon.users.count()
// userCount = 42

Field selection

This section explains how to predict and control which fields of a model are returned in a Photon API call.

Selection sets

To understand which fields are being returned by a certain API call, you need to be aware of its selection set.

The selection set defines the set of fields on a model instance that is returned in a Photon API call.

For example, in the findOne API call from above, the selection set includes the id, name and role fields of the model User. In that example, the selection set has not been manipulated and the API call therefore returns the default selection set (read below).

The default selection set

If the selection set is not manipulated (via select or include), a Photon API call returns the default selection set for a model. It includes all scalar fields (including enums) fields of the model.

Considering the sample datamodel from above:

  • The default selection set for the User model includes id, name, role. It does not include posts because that's a relation and not a scalar field.
  • The default selection set for the Post model includes id, title. It does not include author because that's a relation and not a scalar field.

Manipulating the selection set

There are two ways how the default selection set can be manipulated to specify which fields should be returned by a Photon API call:

  • Select exclusively (via select): When using select, the selection set only contains the fields that are explicitly provided as arguments to select.
  • Include additionally (via include): When using include, the default selection set gets extended with additional fields that are provided as arguments to include.

Select exclusively via select

In this example, we're using select to exclusively select the name field of the returned User object:

const result = await photon.users.findOne({
  where: { id: 1 },
  select: { name: true },
})
// result = { name: "Alice" }

Include additionally via include

Sometimes you want to directly include a relation when retrieving data from a database. To eagerly load and include the relations of a model in an API call right away, you can use include:

const result = await photon.users.findOne({
  where: { id: 1 },
  include: { posts: true },
})
// result = {
//   id: 1,
//   name: "Alice",
//   role: "USER",
//   posts: [
//     { id: 1, title: "Hello World"},
//   ]
// }

Lazy loading

Coming soon.

Relations

Learn more about relations in the generated Photon API here.

Bring your own ID

With Photon.js, you can set your own values for fields that are annotated with the @id attribute. This attribute express that the respective field is considered a primary key. Consider the following model:

model User {
  id    Int    @id
  name  String
}

You can provide the id as input value in create and update operations, for example:

const user = await photon.users.create({
  data: {
    id: 1
  }
})

Note that Photon.js will throw an error if you're trying to create/update a record with an id value that already belongs to another record since the @id attribute always implies uniqueness.

Raw database access

Coming soon.

Scalar lists

Photon.js provides a dedicated API for (re)setting scalar lists using a set field inside the data argument when creating or updating a Prisma model, for example:

model User {
  id        Int       @id
  coinFlips Boolean[]
}

When creating or updating a User record, you can create a new list or replace the current one with a new list like so:

await photon.users.create({
  data: {
    coinFlips: {
      set: [true, false]
    }
  }
})

await photon.users.update({
  where: { id: 42 ,}
  data: {
    coinFlips: {
      set: [true, false]
    }
  }
})

API reference

For simplicity, we're assuming the User model from above as foundation for the generated code.

Constructor

Creates a new Photon instance.

Options

Name Type Required Description
debug boolean No When set to true, the Photon instance prints additional logging output to the console when sending requests to Prisma's query engine. Default: false.
log `boolean LogOption[]` No

Examples

const photon = new Photon({ debug: true })

findOne

Returns a single object identified by a unique value (e.g. id or email). You can use the select and include arguments to determine which fields should be included on the returned object.

Options

Name Type Required Description
where UserWhereUniqueInput Yes Wraps all unique fields of a model so that individual records can be selected.
select UserSelect No Specifies which fields to include in the selection set.

Examples

const user = await photon.users.findOne({
  where: { id: 1 },
})

findMany

Returns a list of objects. The list can be altered using pagination, filtering and ordering arguments. You can use the select and include arguments to determine which fields should be included on each object in the returned list.

For more filtering examples, look here.

Options

Name Type Required Description
where UserWhereInput No Wraps all fields of a model so that the list can be filtered by any model property.
orderBy UserOrderByInput No Lets you order the returned list by any model property.
skip string No Specifies how many of the returned objects in the list should be skipped.
after string No Specifies the starting object for the list (the value typically specifies an id or another unique value).
before string No Specifies the last object for the list (the value typically specifies an id or another unique value).
first number No Specifies how many elements should be returned in the list (as seen from the beginning of the list).
last number No Specifies how many elements should be returned in the list (as seen from the end of the list).
select UserSelect No Specifies which fields to include in the selection set.

Examples

const user = await photon.users.findMany({
  where: { name: 'Alice' },
})

create

Creates a new record and returns the corresponding object. You can use the select and include arguments to determine which fields should be included on the returned object. create also lets you perform transactional nested inserts (e.g. create a new User and Post in the same API call).

Options

Name Type Required Description
data UserCreateInput Yes Wraps all the fields of the model so that they can be provided when creating new records. It also includes relation fields which lets you perform (transactional) nested inserts. Fields that are marked as optional or have default values in the datamodel are optional on data.
select UserSelect No Specifies which fields to include in the selection set.

Examples

const user = await photon.users.create({
  data: { name: 'Alice' },
})

update

Updates an existing record and returns the corresponding object. You can use the select and include arguments to determine which fields should be included on the returned object.

Options

Name Type Required Description
data UserUpdateInput Yes Wraps all the fields of the model so that they can be provided when updating an existing record. Fields that are marked as optional or have default values in the datamodel are optional on data.
where UserWhereUniqueInput Yes Wraps all unique fields of a model so that individual records can be selected.
select UserSelect No Specifies which fields to include in the selection set.

Examples

const user = await photon.users.update({
  where: { id: 1 },
  data: { name: 'ALICE' },
})

updateMany

Updates a batch of existing records in bulk and returns the number of updated records.

Options

Name Type Required Description
data UserUpdateManyMutationInput Yes Wraps all the fields of the model so that they can be provided when updating an existing record. Fields that are marked as optional or have default values in the datamodel are optional on data.
where UserWhereInput No Wraps all fields of a model so that the list can be filtered by any model property.

Examples

const updatedUserCount = await photon.users.updateMany({
  where: { name: 'Alice' },
  data: { name: 'ALICE' },
})

upsert

Updates an existing or creates a new record and returns the corresponding object. You can use the select and include arguments to determine which fields should be included on the returned object.

Options

Name Type Required Description
create UserCreateInput Yes Wraps all the fields of the model so that they can be provided when creating new records. It also includes relation fields which lets you perform (transactional) nested inserts. Fields that are marked as optional or have default values in the datamodel are optional on data.
update UserUpdateInput Yes Wraps all the fields of the model so that they can be provided when updating an existing record. Fields that are marked as optional or have default values in the datamodel are optional on data.
where UserWhereUniqueInput Yes Wraps all unique fields of a model so that individual records can be selected.
select UserSelect No Specifies which fields to include in the selection set.

Examples

const user = await photon.users.upsert({
  where: { id: 1 },
  update: { name: "ALICE" },
  create: { name: "ALICE" }
})

delete

Deletes an existing record and returns the corresponding object. You can use the select and include arguments to determine which fields should be included on the returned object.

Options

Name Type Required Description
where UserWhereUniqueInput Yes Wraps all unique fields of a model so that individual records can be selected.
select UserSelect No Specifies which fields to include in the selection set.

Examples

const user = await photon.users.delete({
  where: { id: 1 },
})

deleteMany

Deletes a batch of existing records in bulk and returns the number of deleted records.

Options

Name Type Required Description
where UserWhereInput No Wraps all fields of a model so that the list can be filtered by any model property.

Examples

const deletedUserCount = await photon.users.deleteMany({
  where: { name: 'Alice' },
})

count

Returns the number of elements in a list as a value of type number.

Options

The count() method doesn't take any input arguments.

Examples

const userCount = await photon.users.count()
// userCount = 42

Filtering

The Photon.js API offers filtering options for constraining the items that are returned from API calls that return lists via the where argument.

The following examples are based on this data model:

model User {
  id     Int    @id
  name   String
  email  String
  role   String
  active Boolean
}

enum Role {
  USER
  ADMIN
}

Filtering can be applied to this data model. It is not the same as manipulating the selection set. Based on the User model, Photon generates the UserWhereInput type, which holds the filtering properties.

export declare type UserWhereInput = {
  id?: number | IntFilter | null
  name?: string | StringFilter | null
  email?: string | StringFilter | null
  role?: Role | RoleFilter | null
  active?: boolean | BooleanFilter | null
  AND?: Enumerable<UserWhereInput>
  OR?: Enumerable<UserWhereInput>
  NOT?: Enumerable<UserWhereInput>
}

For example, to get the record for the user with the id 1, where is used in combination with the id IntFilter:

const result = await photon.users.findMany({
  where: { id: 1 },
})
// result = [{
//   id: 1,
//   name: "Alice",
//   email: "alice@prisma.io",
//   role: "USER",
//   active: true
// }]

Note: As a recap, the findMany API returns a list of objects which can be filtered by any model property.

To get the record for the user with the name Alice with a USER role, where is used in combination with the name StringFilter and the role RoleFilter:

const result = await photon.users.findMany({
  where: {
    name: 'Alice',
    role: 'USER',
  },
})
// result = [{
//   id: 1,
//   name: "Alice",
//   email: "alice@prisma.io",
//   role: "USER",
//   active: true
// }]

To apply one of the operator filters (AND, OR, NOT), filter for the record where the user with the name Alice has a non-active status. Here, where is used in combination with the name StringFilter, the active BooleanFilter, and the NOT operator:

const result = await photon.users.findMany({
  where: {
    name: 'Alice',
    NOT: {
      active: true,
    },
  },
})
// result = {
//
// }

Debugging

You can view the generated database queries that Photon.js sends to your database by setting the debug option to true when instantiating Photon:

const photon = new Photon({ debug: true })

You can also configure log levels via the log option:

const photon = new Photon({ 
  debug: true,
  log: true
})

This logs all log levels:

  • INFO: Logs general information
  • WARN: Logs warnings
  • QUERY: Logs the queries that generated by a Photon.js API call

To specify more fine-grained log-levels, you can pass an array of log options to log:

const photon = new Photon({
  debug: true,
  log: [{
    level: 'QUERY'
  }]
})

Managing connections

Photon connects and disconnects from your data sources using the following two methods:

  • connect(): Promise<void>
  • disconnect(): Promise<void>

Unless you want to employ a specific optimization, calling photon.connect() is not necessary thanks to the lazy connect behavior: The Photon instance connects lazily when the first request is made to the API (connect() is called for you under the hood).

If you need the first request to respond instantly and can't wait for the lazy connection to be established, you can explicitly call photon.connect() to establish a connection to the data source.

IMPORTANT: It is recommended to always explicitly call photon.disconnect() in your code. Generally the Photon instance disconnects automatically. However, if your program terminates but still has an unhandled promise rejection, the port will keep the connection to the data source open beyond the lifetime of your program!

You can’t perform that action at this time.