User-defined functions

User-defined functions (UDF) can be exposed through the GraphQL API by using the @resolver directive at fields in the Query and Mutation types. This directive has no effect if placed elsewhere.

The UDF must have the same arguments, in the same order, as its associated field in the GraphQL schema. There is no association between the arguments' names in the GraphQL schema and the arguments' names in the UDF definition. When a UDF field is queried, the GraphQL API simply calls the underlying UDF with the given arguments.

The UDF result type must be a GraphQL-compatible type. If an object is returned, an equivalent type must exist in the GraphQL schema to allow users to select which fields to return. Embedded types can be used to map return types that are not associated with any existing type.

UDFs with pagination support must return a database page. In addition to the function arguments, the API calls the UDF with three additional arguments appended the query’s arguments:

  • size: the requested page size

  • after: the database forward cursor

  • before: the database backwards cursor

A UDF’s implementation must account for these additional arguments and call the appropriate form of the FQL Paginate function to return a database page to the GraphQL API.

Examples

A UDF that returns a scalar type:

The following is a UDF, using Fauna Shell syntax, that returns a scalar type:

CreateFunction({
  name: "say_hello",
  body: Query(Lambda(["name"],
    Concat(["Hello ", Var("name")])
  ))
})

A GraphQL schema that uses the UDF:

type Query {
  sayHello(name: String!): String! @resolver(name: "say_hello")
}

With these in place, when you run the following query:

{
  sayHello(name: "Jane")
}

The result should be:

{
  "data": {
    "sayHello": "Hello Jane"
  }
}

A UDF that returns an embedded object

The following is a UDF, in Fauna Shell syntax, that returns an embedded object:

CreateFunction({
  name: "sample_obj",
  body: Query(Lambda([], {
    time: Time("now"),
    sample: true
  }))
})

A GraphQL schema that uses the UDF:

type SampleObj @embedded {
  time: Time!
  sample: Boolean!
}

type Query {
  sampleObj: SampleObj! @resolver(name: "sample_obj")
}

With these in place, when you run the following query:

{
  sampleObj {
    time
    sample
  }
}

The result should be:

{
  "data": {
    "sampleObj": {
      "time": "2019-06-14T17:42:54.001987Z",
      "sample": true
    }
  }
}

A UDF that returns a database page

The following is a UDF (along with a Collection and Index), in Fauna Shell syntax, that returns a database page, so that repeated querying can retrieve all of the paginated results.

CreateCollection({
  name: "users"
})
CreateIndex({
  name: "vip_users",
  source: Collection("users"),
  terms: [{ field: [ "data", "vip" ] }]
})
CreateFunction({
  name: "vip_users",
  body: Query(Lambda(["size", "after", "before"],
    Let(
      {
        match: Match(Index("vip_users"), true),
        page: If(
          Equals(Var("before"), null),
          If(
            Equals(Var("after"), null),
              Paginate(Var("match"), { size: Var("size") }),
              Paginate(Var("match"), { size: Var("size"), after: Var("after") })
          ),
          Paginate(Var("match"), { size: Var("size"), before: Var("before") }),
        )
      },
      Map(Var("page"), Lambda("ref", Get(Var("ref"))))
    )
  ))
})

A GraphQL schema that uses the UDF:

type User @collection(name: "users") {
  username: String!
  vip: Boolean!
}

type Query {
  vips: [User!] @resolver(name: "vip_users", paginated: true)
}

With these in place, when you run the following query:

{
  vips(
    _size: 2
    _cursor: "2DOB2DRyMjM1MTcwOTY5MDA0NTQwNDIzgWV1c2Vyc4FnY2xhc3Nlc4CAgIA="
  ) {
    data {
      username
    }
    after
    before
  }
}

The result should be:

{
  "data": {
    "vips": {
      "data": [
        { "username": "Mary" },
        { "username": "Ted" }
      ],
      "after": null,
      "before": "2DKB2DRyMjM1MTcwOTY5MDA0NTQwNDIzgWV1c2Vyc4FnY2xhc3Nlc4CAgIA="
    }
  }
}

Was this article helpful?

We're sorry to hear that.
Tell us how we can improve! documentation@fauna.com

Thank you for your feedback!