Package detail

@pothos/plugin-relay

hayes172.5kISC4.6.2

A Pothos plugin for adding relay style connections, nodes, and cursor based pagination to your GraphQL schema

pothos, graphql, schema, typescript

readme

The Relay plugin adds a number of builder methods and helper functions to simplify building a relay compatible schema.

Usage

Install

npm install --save @pothos/plugin-relay

Setup

import RelayPlugin from '@pothos/plugin-relay';
const builder = new SchemaBuilder({
  plugins: [RelayPlugin],
  relay: {},
});

Options

The relay options object passed to builder can contain the following properties:

  • idFieldName: The name of the field that contains the global id for the node. Defaults to id.
  • idFieldOptions: Options to pass to the id field.
  • clientMutationId: omit (default) | required | optional. Determines if clientMutationId fields are created on relayMutationFields, and if they are required.
  • cursorType: String | ID. Determines type used for cursor fields. Defaults to String
  • nodeQueryOptions: Options for the node field on the query object, set to false to omit the field
  • nodesQueryOptions: Options for the nodes field on the query object, set to false to omit the field
  • nodeTypeOptions: Options for the Node interface type
  • pageInfoTypeOptions: Options for the TypeInfo object type
  • clientMutationIdFieldOptions: Options for the clientMutationId field on connection objects
  • clientMutationIdInputOptions: Options for the clientMutationId input field on connections fields
  • mutationInputArgOptions: Options for the Input object created for each connection field
  • cursorFieldOptions: Options for the cursor field on an edge object.
  • nodeFieldOptions: Options for the node field on an edge object.
  • edgesFieldOptions: Options for the edges field on a connection object.
  • pageInfoFieldOptions: Options for the pageInfo field on a connection object.
  • hasNextPageFieldOptions: Options for the hasNextPage field on the PageInfo object.
  • hasPreviousPageFieldOptions: Options for the hasPreviousPage field on the PageInfo object.
  • startCursorFieldOptions: Options for the startCursor field on the PageInfo object.
  • endCursorFieldOptions: Options for the endCursor field on the PageInfo object.
  • beforeArgOptions: Options for the before arg on a connection field.
  • afterArgOptions: Options for the after arg on a connection field.
  • firstArgOptions: Options for the first arg on a connection field.
  • lastArgOptions: Options for the last arg on a connection field.
  • defaultConnectionTypeOptions: Default options for the Connection Object types.
  • defaultEdgeTypeOptions: Default options for the Edge Object types.
  • defaultPayloadTypeOptions: Default options for the Payload Object types.
  • defaultMutationInputTypeOptions: default options for the mutation Input types.
  • nodesOnConnection: If true, the nodes field will be added to the Connection object types.
  • defaultConnectionFieldOptions: Default options for connection fields defined with t.connection
  • brandLoadedObjects: Defaults to true. This will add a hidden symbol to objects returned from the load methods of Nodes that allows the default resolveType implementation to identify the type of the node. When this is enabled, you will not need to implement an isTypeOf check for most common patterns.

Creating Nodes

To create objects that extend the Node interface, you can use the new builder.node method.

// Using object refs
const User = builder.objectRef<UserType>('User');
// Or using a class
class User {
  id: string;
  name: string;
}

builder.node(User, {
  // define an id field
  id: {
    resolve: (user) => user.id,
    // other options for id field can be added here
  },

  // Define only one of the following methods for loading nodes by id
  loadOne: (id) => loadUserByID(id),
  loadMany: (ids) => loadUsers(ids),
  loadWithoutCache: (id) => loadUserByID(id),
  loadManyWithoutCache: (ids) => loadUsers(ids),

  // if using a class instaed of a ref, you will need to provide a name
  name: 'User',
  fields: (t) => ({
    name: t.exposeString('name'),
  }),
});

builder.node will create an object type that implements the Node interface. It will also create the Node interface the first time it is used. The resolve function for id should return a number or string, which will be converted to a globalID. The relay plugin adds to new query fields node and nodes which can be used to directly fetch nodes using global IDs by calling the provided loadOne or loadMany method. Each node will only be loaded once by id, and cached if the same node is loaded multiple times inn the same request. You can provide loadWithoutCache or loadManyWithoutCache instead if caching is not desired, or you are already using a caching datasource like a dataloader.

Nodes may also implement an isTypeOf method which can be used to resolve the correct type for lists of generic nodes. When using a class as the type parameter, the isTypeOf method defaults to using an instanceof check, and falls back to checking the constructor property on the prototype. The means that for many cases if you are using classes in your type parameters, and all your values are instances of those classes, you won't need to implement an isTypeOf method, but it is usually better to explicitly define that behavior.

By default (unless brandLoadedObjects is set to false) any nodes loaded through one of the load* methods will be branded so that the default resolveType method can identify the GraphQL type for the loaded object. This means isTypeOf is only required for union and interface fields that return node objects that are manually loaded, where the union or interface does not have a custom resolveType method that knows how to resolve the node type.

parsing node ids

By default all node ids are parsed as string. This behavior can be customized by providing a custom parse function for your node's ID field:

const User = builder.objectRef<UserType>('User')
builder.node(User, {
  // define an id field
  id: {
    resolve: (user) => user.id,
    parse: (id) => Number.parseInt(id, 10),
  },
  // the ID is now a number
  loadOne: (id) => loadUserByID(id),
  ...
});

Global IDs

To make it easier to create globally unique ids the relay plugin adds new methods for creating globalID fields.

import { encodeGlobalID } from '@pothos/plugin-relay';

builder.queryFields((t) => ({
  singleID: t.globalID({
    resolve: (parent, args, context) => {
      return { id: 123, type: 'SomeType' };
    },
  }),
  listOfIDs: t.globalIDList({
    resolve: (parent, args, context) => {
      return [{ id: 123, type: 'SomeType' }];
    },
  }),
}));

The returned IDs can either be a string (which is expected to already be a globalID), or an object with the an id and a type, The type can be either the name of a name as a string, or any object that can be used in a type parameter.

There are also new methods for adding globalIDs in arguments or fields of input types:

builder.queryType({
  fields: (t) => ({
    fieldThatAcceptsGlobalID: t.boolean({
      args: {
        id: t.arg.globalID({
          required: true,
        }),
        idList: t.arg.globalIDList(),
      },
      resolve(parent, args) {
        console.log(`Get request for type ${args.id.typename} with id ${args.id.id}`);
        return true;
      },
    }),
  }),
});

globalIDs used in arguments expect the client to send a globalID string, but will automatically be converted to an object with 2 properties (id and typename) before they are passed to your resolver in the arguments object.

Limiting global ID args to specific types

globalID input's can be configured to validate the type of the globalID. This is useful if you only want to accept IDs for specific node types.

builder.queryType({
  fields: (t) => ({
    fieldThatAcceptsGlobalID: t.boolean({
      args: {
        id: t.arg.globalID({
          for: SomeType,
          // or allow multiple types
          for: [TypeOne, TypeTwo],
          required: true,
        }),
      },
    }),
  }),
});

Creating Connections

The t.connection field builder method can be used to define connections. This method will automatically create the Connection and Edge objects used by the connection, and add before, after, first, and last arguments. The first time this method is used, it will also create the PageInfo type.

builder.queryFields((t) => ({
  numbers: t.connection(
    {
      type: NumberThing,
      resolve: (parent, { first, last, before, after }) => {
        return {
          pageInfo: {
            hasNextPage: false,
            hasPreviousPage: false,
            startCursor: 'abc',
            endCursor: 'def',
          },
          edges: [
            {
              cursor: 'abc',
              node: new NumberThing(123),
            },
            {
              cursor: 'def',
              node: new NumberThing(123),
            },
          ],
        };
      },
    },
    {
      name: 'NameOfConnectionType', // optional, will use ParentObject + capitalize(FieldName) + "Connection" as the default
      fields: (tc) => ({
        // define extra fields on Connection
        // We need to use a new variable for the connection field builder (eg tc) to get the correct types
      }),
      edgesField: {}, // optional, allows customizing the edges field on the Connection Object
      // Other options for connection object can be added here
    },
    {
      // Same as above, but for the Edge Object
      name: 'NameOfEdgeType', // optional, will use Connection name + "Edge" as the default
      fields: (te) => ({
        // define extra fields on Edge
        // We need to use a new variable for the connection field builder (eg te) to get the correct types
      }),
      nodeField: {}, // optional, allows customizing the node field on the Edge Object
    },
  ),
}));

Manually implementing connections can be cumbersome, so there are a couple of helper methods that can make resolving connections a little easier.

For limit/offset based apis:

import { resolveOffsetConnection } from '@pothos/plugin-relay';

builder.queryFields((t) => ({
  things: t.connection({
    type: SomeThing,
    resolve: (parent, args) => {
      return resolveOffsetConnection({ args }, ({ limit, offset }) => {
        return getThings(offset, limit);
      });
    },
  }),
}));

resolveOffsetConnection has a few default limits to prevent unintentionally allowing too many records to be fetched at once. These limits can be configure using the following options:

{
  args: ConnectionArguments;
  defaultSize?: number; // defaults to 20
  maxSize?: number; // defaults to 100
  totalCount?: number // required to support using `last` without `before`
}

For APIs where you have the full array available you can use resolveArrayConnection, which works just like resolveOffsetConnection and accepts the same options.

import { resolveArrayConnection } from '@pothos/plugin-relay';

builder.queryFields((t) => ({
  things: t.connection({
    type: SomeThings,
    resolve: (parent, args) => {
      return resolveArrayConnection({ args }, getAllTheThingsAsArray());
    },
  }),
}));

Cursor based pagination can be implemented using the resolveCursorConnection method. The following example uses prisma, but a similar solution should work with any data store that supports limits, ordering, and filtering.

import { resolveCursorConnection, ResolveCursorConnectionArgs } from '@pothos/plugin-relay';

builder.queryField('posts', (t) =>
  t.connection({
    type: Post,
    resolve: (_, args) =>
      resolveCursorConnection(
        {
          args,
          toCursor: (post) => post.createdAt.toISOString(),
        },
        // Manually defining the arg type here is required
        // so that typescript can correctly infer the return value
        ({ before, after, limit, inverted }: ResolveCursorConnectionArgs) =>
          prisma.post.findMany({
            take: limit,
            where: {
              createdAt: {
                lt: before,
                gt: after,
              },
            },
            orderBy: {
              createdAt: inverted ? 'desc' : 'asc',
            },
          }),
      ),
  }),
);

Relay Mutations

You can use the relayMutationField method to define relay compliant mutation fields. This method will generate a mutation field, an input object with a clientMutationId field, and an output object with the corresponding clientMutationId.

Example ussage:

builder.relayMutationField(
  'deleteItem',
  {
    inputFields: (t) => ({
      id: t.id({
        required: true,
      }),
    }),
  },
  {
    resolve: async (root, args, ctx) => {
      if (ctx.items.has(args.input.id)) {
        ctx.items.delete(args.input.id);

        return { success: true };
      }

      return { success: false };
    },
  },
  {
    outputFields: (t) => ({
      success: t.boolean({
        resolve: (result) => result.success,
      }),
    }),
  },
);

Which produces the following graphql types:

input DeleteItemInput {
  clientMutationId: ID!
  id: ID!
}

type DeleteItemPayload {
  clientMutationId: ID!
  itWorked: Boolean!
}

type Mutation {
  deleteItem(input: DeleteItemInput!): DeleteItemPayload!
}

The relayMutationField has 4 arguments:

  • name: Name of the mutation field
  • inputOptions: Options for the input object or a ref to an existing input object
  • fieldOptions: Options for the mutation field
  • payloadOptions: Options for the Payload object

The inputOptions has a couple of non-standard options:

  • name which can be used to set the name of the input object
  • argName which can be used to overwrite the default arguments name (input).

The payloadOptions object also accepts a name property for setting the name of the payload object.

You can also access refs for the created input and payload objects so you can re-use them in other fields:

// Using aliases when destructuring lets you name your refs rather than using the generic `inputType` and `payloadType`
const { inputType: DeleteItemInput, payloadType: DeleteItemPayload } = builder.relayMutationField(
  'deleteItem',
  ...
);

Reusing connection objects

In some cases you may want to create a connection object type that is shared by multiple fields. To do this, you will need to create the connection object separately and then create a fields using a ref to your connection object:

import { resolveOffsetConnection } from '@pothos/plugin-relay';

const ThingsConnection = builder.connectionObject(
  {
    // connection options
    type: SomeThing,
    name: 'ThingsConnection',
  },
  {
    // Edge options (optional)
    name: 'ThingsEdge', // defaults to Appending `Edge` to the Connection name
  },
);

// You can use connection object with normal fields
builder.queryFields((t) => ({
  things: t.field({
    type: ThingsConnection,
    args: {
      ...t.arg.connectionArgs(),
    },
    resolve: (parent, args) => {
      return resolveOffsetConnection({ args }, ({ limit, offset }) => {
        return getThings(offset, limit);
      });
    },
  }),
}));

// Or by providing the connection type when creating a connection field
builder.queryFields((t) => ({
  things: t.connection({
    resolve: (parent, args) => {
      return resolveOffsetConnection({ args }, ({ limit, offset }) => {
        return getThings(offset, limit);
      });
    },
  }),
  ThingsConnection,
}));

builder.connectionObject creates the connect object type and the associated Edge type. t.arg.connectionArgs() will create the default connection args.

Reusing edge objects

Similarly you can directly create and re-use edge objects

import { resolveOffsetConnection } from '@pothos/plugin-relay';

const ThingsEdge = builder.edgeObject(
  {
    name: 'ThingsEdge',
    type: SomeThing,
  },
);

// The edge object can be used when creating a connection object
const ThingsConnection = builder.connectionObject(
  {
    type: SomeThing,
    name: 'ThingsConnection',
  },
  ThingsEdge,
);

// Or when creating a connection field
builder.queryFields((t) => ({
  things: t.connection({
    resolve: (parent, args) => {
      return resolveOffsetConnection({ args }, ({ limit, offset }) => {
        return getThings(offset, limit);
      });
    },
  }),
  {
    // connection options
  },
  ThingsEdge,
}));

builder.connectionObject creates the connect object type and the associated Edge type. t.arg.connectionArgs() will create the default connection args.

Expose nodes

The t.node and t.nodes methods can be used to add additional node fields. the expected return values of id and ids fields is the same as the resolve value of t.globalID, and can either be a globalID or an object with and an id and a type.

Loading nodes by id uses a request cache, so the same node will only be loaded once per request, even if it is used multiple times across the schema.

builder.queryFields((t) => ({
  extraNode: t.node({
    id: () => 'TnVtYmVyOjI=',
  }),
  moreNodes: t.nodeList({
    ids: () => ['TnVtYmVyOjI=', { id: 10, type: 'SomeType' }],
  }),
}));

decoding and encoding global ids

The relay plugin exports decodeGlobalID and encodeGlobalID as helper methods for interacting with global IDs directly. If you accept a global ID as an argument you can use the decodeGlobalID function to decode it:

builder.mutationFields((t) => ({
  updateThing: t.field({
    type: Thing,
    args: {
      id: t.args.id({ required: true }),
      update: t.args.string({ required: true }),
    },
    resolve(parent, args) {
      const { type, id } = decodeGlobalID(args.id);

      const thing = Thing.findById(id);

      thing.update(args.update);

      return thing;
    },
  }),
}));

Using custom encoding for global ids

In some cases you may want to encode global ids differently than the build in ID encoding. To do this, you can pass a custom encoding and decoding function into the relay options of the builder:

import RelayPlugin from '@pothos/plugin-relay';
const builder = new SchemaBuilder({
  plugins: [RelayPlugin],
  relayOptions: {
    encodeGlobalID: (typename: string, id: string | number | bigint) => `${typename}:${id}`,
    decodeGlobalID: (globalID: string) => {
      const [typename, id] = globalID.split(':');

      return { typename, id };
    },
  },
});

Using custom resolve for node and or nodes field

If you need to customize how nodes are loaded for the node and or nodes fields you can provide custom resolve functions in the builder options for these fields:

import RelayPlugin from '@pothos/plugin-relay';

function customUserLoader({ id, typename }: { id: string; typename: string }) {
  // load user
}

const builder = new SchemaBuilder({
  plugins: [RelayPlugin],
  relayOptions: {
    nodeQueryOptions: {
      resolve: (root, { id }, context, info, resolveNode) => {
        // use custom loading for User nodes
        if (id.typename === 'User') {
          return customUserLoader(id);
        }

        // fallback to normal loading for everything else
        return resolveNode(id);
      },
    },
    nodesQueryOptions: {
      resolve: (root, { ids }, context, info, resolveNodes) => {
        return ids.map((id) => {
          if (id.typename === 'User') {
            return customNodeLoader(id);
          }

          // it would be more efficient to load all the nodes at once
          // but it is important to ensure the resolver returns nodes in the right order
          // we are resolving nodes one at a time here for simplicity
          return resolveNodes([id]);
        });
      },
    },
  },
});

Extending all connections

There are 2 builder methods for adding fields to all connection objects: t.globalConnectionField and t.globalConnectionFields. These methods work like many of the other methods on the builder for adding fields to objects or interfaces.

builder.globalConnectionField('totalCount', (t) =>
  t.int({
    nullable: false,
    resolve: (parent) => 123,
  }),
);
// Or
builder.globalConnectionFields((t) => ({
  totalCount: t.int({
    nullable: false,
    resolve: (parent) => 123,
  }),
}));

In the above example, we are just returning a static number for our totalCount field. To make this more useful, we need to have our resolvers for each connection actually return an object that contains a totalCount for us. To guarantee that resolvers correctly implement this behavior, we can define custom properties that must be returned from connection resolvers when we set up our builder:

import RelayPlugin from '@pothos/plugin-relay';
const builder = new SchemaBuilder<{
  Connection: {
    totalCount: number;
  };
}>({
  plugins: [RelayPlugin],
  relayOptions: {},
});

Now typescript will ensure that objects returned from each connection resolver include a totalCount property, which we can use in our connection fields:

builder.globalConnectionField('totalCount', (t) =>
  t.int({
    nullable: false,
    resolve: (parent) => parent.totalCount,
  }),
);

Note that adding additional required properties will make it harder to use the provided connection helpers since they will not automatically return your custom properties. You will need to manually add in any custom props after getting the result from the helpers:

builder.queryFields((t) => ({
  posts: t.connection({
    type: Post,
    resolve: (parent, args, context) => {
      const postsArray = context.Posts.getAll();
      const result = resolveArrayConnection({ args }, postsArray);

      return result && { totalCount: postsArray.length, ...result };
    },
  }),
}));

Changing nullability of edges and nodes

If you want to change the nullability of the edges field on a Connection or the node field on an Edge you can configure this in 2 ways:

Globally

import RelayPlugin from '@pothos/plugin-relay';
const builder = new SchemaBuilder<{
  DefaultEdgesNullability: false;
  DefaultNodeNullability: true;
}>({
  plugins: [RelayPlugin],
  relayOptions: {
    edgesFieldOptions: {
      nullable: false,
    },
    nodeFieldOptions: {
      nullable: true,
    },
  },
});

The types provided for DefaultEdgesNullability and DefaultNodeNullability must match the values provided in the nullable option of edgesFieldOptions and nodeFieldOptions respectively. This will set the default nullability for all connections created by your builder.

nullability for edges fields defaults to { list: options.defaultFieldNullability, items: true } and the nullability of node fields is the same as options.defaultFieldNullability (which defaults to true).

Per connection

builder.queryFields((t) => ({
  things: t.connection({
    type: SomeThings,
    edgesNullable: {
      items: true,
      list: false,
    },
    nodeNullable: false,
    resolve: (parent, args) => {
      return resolveOffsetConnection({ args }, ({ limit, offset }) => {
        return getThings(offset, limit);
      });
    },
  }),
}));
// Or

const ThingsConnection = builder.connectionObject({
  type: SomeThing,
  name: 'ThingsConnection',
  edgesNullable: {
    items: true,
    list: false,
  },
  nodeNullable: false,
});

Extending the Node interface

Use the nodeInterfaceRef method of your Builder.

For example, to add a new derived field on the interface:

builder.interfaceField(builder.nodeInterfaceRef(), 'extra', (t) =>
  t.string({
    resolve: () => 'it works',
  }),
);

changelog

Change Log

4.6.2

Patch Changes

  • 517b559: Improve types when replace resolve definitions

4.6.1

Patch Changes

  • 86e1ee2: remove extra await

4.6.0

Minor Changes

  • 12713e5: improve handling of iterable connections

4.5.0

Minor Changes

  • fd7121c: Add relayMutationFieldOptions to builder options

4.4.3

Patch Changes

  • 1622740: update dependencies

4.4.2

Patch Changes

  • cd7f309: Update dependencies

4.4.1

Patch Changes

  • d874bce: Improve inference of multiple interfaces

4.4.0

Minor Changes

  • 9cfb6a7: cache input mappings accross resolvers to reduce memory ussage in large schemas

4.3.0

Minor Changes

  • 6a80a7c: Add builder.nodeRef method

4.2.1

Patch Changes

  • 3085a2c: Export parseCurserConnectionArgs function

4.2.0

Minor Changes

  • f3e8940: Add totalCount option to resolveOffsetConnection, which enables using last on offset and array connections without before

4.1.0

Minor Changes

  • 27af377: replace eslint and prettier with biome

4.0.2

Patch Changes

  • Updated dependencies [777f6de]
    • @pothos/core@4.0.2

4.0.1

Patch Changes

  • 9bd203e: Fix graphql peer dependency version to match documented minumum version
  • Updated dependencies [9bd203e]
    • @pothos/core@4.0.1

4.0.0

Major Changes

Patch Changes

  • c1e6dcb: update readmes
  • Updated dependencies [c1e6dcb]
  • Updated dependencies [29841a8]
    • @pothos/core@4.0.0

4.0.0-next.1

Patch Changes

  • update readmes
  • Updated dependencies
    • @pothos/core@4.0.0-next.1

4.0.0-next.0

Major Changes

Patch Changes

  • Updated dependencies [29841a8]
    • @pothos/core@4.0.0-next.0

3.46.1

Patch Changes

  • 1ecea46: revert accidental pinning of graphql peer dependency

3.46.0

Minor Changes

  • 2a1843d: Allow inputOptions on relayMutationField to be set to null to remove input argument

3.45.1

Patch Changes

  • 0f5cfa9: Fix bug when decoding lists of global IDs with null items

3.45.0

Minor Changes

  • 7d1459b: Improve typing of globalID args in node(s)QueryFieldOptions

3.44.0

Minor Changes

  • 96ba1822: Improve validation for global IDs

3.43.1

Patch Changes

  • b7954d40: Fix hasPreviousPage in resolveCursorConnection

3.43.0

Minor Changes

  • 0c042150: Allow globalConnectionFields to be overwritten on specific connections

3.42.0

Minor Changes

  • b3259d3e: Make parent and args available in connection and edge fields of prisma connections

3.41.1

Patch Changes

  • 4c6bc638: Add provinance to npm releases

3.41.0

Minor Changes

  • cd1558a3: Included idFieldOptions when creating the Node interface’s ID field.

3.40.0

Minor Changes

  • cd98256e: Add nodeQueryOptions.args and nodesQueryOptions.args to allow setting arg options on the node and nodes queries

3.39.0

Minor Changes

  • 1878d5d9: Allow readonly arrays in more places

3.38.0

Minor Changes

  • e8d75349: - allow connection fields (edges / pageInfo) to be promises
    • add completeValue helper to core for unwrapping MaybePromise values
    • set nodes as null if edges is null and the field permits a null return

3.37.0

Minor Changes

  • 68c94e4f: Support parsing globalIDs for loadableNode

Patch Changes

  • d2b02b79: Fix a few issues with globalID parsing

3.36.0

Minor Changes

  • d60cb49e: handle string contining ':' in global ID

3.35.0

Minor Changes

  • 1c73b585: Add new parse option for id field on nodes, and a for option on globalID args
  • bf0385ae: Add new PothosError classes

3.34.0

Minor Changes

  • 252ba5fb: Add nodeField and edgesField options to edge/connection builders

3.33.1

Patch Changes

  • be5bff07: Update resolveArrayConnection return type to reflect that it always returns a non-null ConnectionShape

3.33.0

Minor Changes

  • 5c6e0abb: Add option for disabling node and nodes fields

3.32.0

Minor Changes

  • 75d13217: Export utils for formatting prisma cursors

3.31.0

Minor Changes

  • c3db3bcd: Enable adding interfaces to connections and edges

Patch Changes

  • fd08a9d9: allow readonly lists to be exposed and improve inference of t.expose fields

3.30.2

Patch Changes

  • 92ccae6d: Fix a bug where the t.connection helper wasn't correctly inferring the shape of the returned connection object when used on interfaces.

3.30.1

Patch Changes

  • dbc32872: Fix a bug where builder.node crashed when the interfaces was provided as a function

3.30.0

Minor Changes

  • daa2bf9a: Add support for custom node/nodes resolving

3.29.1

Patch Changes

  • 15d19a38: Fix hasNextPage when paginating backwards with resolveOffsetConnection

3.29.0

Minor Changes

  • cd1c0502: Add support for nested lists
  • 99bc6574: Add initial support for reusable prisma connections

3.28.7

Patch Changes

  • d4d41796: Update dev dependencies

3.28.6

Patch Changes

  • 6f00194c: Fix an issue with esm import transform

3.28.5

Patch Changes

  • b12f9122: Fix issue with esm build script

3.28.4

Patch Changes

  • 9fa27cf7: Transform dynamic type imports in d.ts files

3.28.3

Patch Changes

  • 3a82d645: Apply esm transform to esm d.ts definitions

3.28.2

Patch Changes

  • 218fc68b: Fix script for copying ems d.ts definitions

3.28.1

Patch Changes

  • 67531f1e: Create separate typescript definitions for esm files

3.28.0

Minor Changes

  • 11929311: Update type definitions to work with module: "nodeNext"

3.27.1

Patch Changes

  • aa18acb7: update dev dependencies

3.27.0

Minor Changes

  • cf93c7c9: Fix some edge cases with how option objects become optional when no arguments are required

3.26.0

Minor Changes

  • 631dea27: Move some checks from isTypeOf to resovleType to improve performance and allow nodes without isTypeOf checks

3.25.0

Minor Changes

  • d67764b5: Make options objecst on toSchema, queryType, and mutationType optional

3.24.0

Minor Changes

  • 69be1873: Add defaultConnectionFieldOptions to relayOptions

3.23.0

Minor Changes

  • c9b02338: Support context when using custom gloablID encoding or decoding

3.22.0

Minor Changes

  • 390e74a7: Add idFieldOptions to relay plugin options

3.21.0

Minor Changes

  • 33789284: Update cursor encoding to work in deno

3.20.0

Minor Changes

  • 2bb5db96: Added new nodesOnConnections option for adding a nodes field on connections

3.19.0

Minor Changes

  • 09572175: Add options for default payload and mutation type options

3.18.1

Patch Changes

  • 84a77af5: Fix incorrect types for relayOptions.default(Connection|Edge)ObjectOptions

3.18.0

Minor Changes

  • f7f74585: Add option for configuring name of id field for relay nodes

3.17.0

Minor Changes

  • 3a7ff291: Refactor internal imports to remove import cycles

Patch Changes

  • 3a7ff291: Update dev dependencies

3.16.0

Minor Changes

  • ad928594: Add defaultConnectionTypeOptions and defaultEdgeTypeOptions

Patch Changes

  • 04ed2b0c: Fix args in plugin methods on connection fields sometimes not being typed correctly

3.15.0

Minor Changes

  • 7311904e: Add ability to accept an inputTypeRef for builder.mutationField

Patch Changes

  • 7311904e: Update dev deps
  • 7311904e: Fix nodeType option, which was incorrectly acceptiong options for an object type rather than an interface

3.14.0

Minor Changes

  • e79b3ce5: Pass node list to toCursor option of resolveCursorConnection

3.13.0

Minor Changes

  • 79e69c2b: Add resolveCursorConnection helper for relay plugin

3.12.1

Patch Changes

  • 4e5756ca: Update dev dependencies

3.12.0

Minor Changes

  • 1735eb40: Add edgeObject method to relay plugin

3.11.0

Minor Changes

  • ecb2714c: Add types entry to export map in package.json and update dev dependencies

    This should fix compatibility with typescripts new "moduleResolution": "node12"

3.10.2

Patch Changes

  • 89f09498: Fix issue with argument mapping utils that caused nested lists of input objects to be transformed incorrectly in the relay plugin

3.10.1

Patch Changes

  • 205a8c73: Recactor internal imports to reduce imports from index files

3.10.0

Minor Changes

  • a8e31a70: Improve user experience when srtict mode is disabled

3.9.0

Minor Changes

  • 241a385f: Add peer dependency on @pothos/core

3.8.0

Minor Changes

  • 6279235f: Update build process to use swc and move type definitions to dts directory

Patch Changes

  • 21a2454e: update dev dependencies

3.7.0

Minor Changes

  • c0bdbc1b: Fix type for InputFieldRef.kind

3.6.0

Minor Changes

  • 8add0378: Allow relay.*.FieldOptions objects to set nullable to change nullability of default relay fields
  • 5294a17f: Explicitly make pageInfo non nullable. Previously pageInfo was nullable for defaultFieldNullability: true, which is against the Relay spec. You can revert back to previous behavior by updating your builder relay options:

    relay: {
      pageInfoFieldOptions: {
        nullable: true,
      },
    },
    
  • 8add0378: Explicitly make id field on Node interface nullable

  • 8add0378: Explicitly make cursor non nullable. Previously cursor was nullable for defaultFieldNullability: true, which is against the Relay spec. You can revert back to previous behavior by updating your builder relay options:

    relay: {
      cursorFieldOptions: {
        nullable: true,
      },
    },
    

3.5.2

Patch Changes

  • 31f9e8be: Fix isTypeOf check not handling __typename correctly

3.5.1

Patch Changes

  • 03aecf76: update .npmignore

3.5.0

Minor Changes

  • 80b24ec1: Add ability to branded objects loaded by relay plugin with typename to reduce need to isTypeOf checks

Patch Changes

  • 80b24ec1: Fix issue with connection arg types

3.4.0

Minor Changes

  • 4ad5f4ff: Normalize resolveType and isTypeOf behavior to match graphql spec behavior and allow both to be optional

Patch Changes

  • 43ca3031: Update dev dependencies

3.3.1

Patch Changes

  • ab4a9ae4: Fix some type compatibility issues when skipLibCheck is false

3.3.0

Minor Changes

  • eb9c33b8: Add loadManyWithoutCache option to dataloader to avoid double caching in loadableNode

3.2.0

Minor Changes

  • 2d9b21cd: Make edge nullability configurable at both the builder and field level
  • 695c9b2d: Make relay node nullability configurable

Patch Changes

  • 2d9b21cd: Use workspace:* for dev dependencies on pothos packages

3.1.0

Minor Changes

  • 11b02e73: Fix some issues with type inference on nullable connections

3.0.0

Major Changes

  • 4caad5e4: Rename GiraphQL to Pothos

2.19.0

Minor Changes

  • 9307635a: Migrate build process to use turborepo

2.18.4

Patch Changes

  • 2b08f852: Fix syntax highlighting in docs and update npm README.md files"

2.18.3

Patch Changes

  • c6aa732: graphql@15 type compatibility fix

2.18.2

Patch Changes

  • 5619aca: Standardize context caches across all plugins to correctly take advantage of initContextCache

2.18.1

Patch Changes

  • c85dc33: Add types entry in package.json

2.18.0

Minor Changes

  • aeef5e5: Update dependencies

2.17.0

Minor Changes

  • 9107f29: Update dependencies (includes graphql 16)

2.16.0

Minor Changes

  • 17db3bd: Make type refs extendable by plugins

2.15.2

Patch Changes

  • c976bfe: Update dependencies

2.15.1

Patch Changes

  • 4150f92: Fixed esm transformer for path-imports from dependencies

2.15.0

Minor Changes

  • dc87e68: update esm build process so extensions are added during build rather than in source

2.14.1

Patch Changes

  • b4b8381: Updrade deps (typescript 4.4)

2.14.0

Minor Changes

  • a4c87cf: Use ".js" extensions everywhere and add module and exports to package.json to better support ems in node

2.13.2

Patch Changes

  • f13208c: bump to fix latest tag

2.13.1

Patch Changes

  • 9ab8fbc: re-release previous version due to build-process issue

2.13.0

Minor Changes

  • 3dd3ff14: Updated dev dependencies, switched to pnpm, and added changesets for releases

All notable changes to this project will be documented in this file. See Conventional Commits for commit guidelines.

2.12.1 - 2021-08-05

🐞 Fixes

  • make nodes non-nullable in resolveConnection helpers (83449b8)

Note: Version bump only for package @giraphql/plugin-relay

2.12.0 - 2021-08-03

🚀 Updates

  • add relay integration for prisma plugin (e714e54)

Note: Version bump only for package @giraphql/plugin-relay

2.12.0-alpha.0 - 2021-08-02

🚀 Updates

  • add relay integration for prisma plugin (0b1d378)

Note: Version bump only for package @giraphql/plugin-relay

2.11.0 - 2021-07-30

🚀 Updates

Note: Version bump only for package @giraphql/plugin-relay

2.10.0 - 2021-07-29

🐞 Fixes

  • create start and end cursors even if edges are null (64b9d2f)

📘 Docs

  • update relay docs with info on re-using types created for relayMutationField (2000f90)

Note: Version bump only for package @giraphql/plugin-relay

2.10.0-alpha.0 - 2021-07-28

🚀 Updates

  • expose input and object ref from relayMutationField (af5a061)

🐞 Fixes

  • improve handling of null edges in resolveConnection helpers (6577a00)

Note: Version bump only for package @giraphql/plugin-relay

2.9.2 - 2021-07-23

Note: Version bump only for package @giraphql/plugin-relay

2.9.2-alpha.0 - 2021-07-17

Note: Version bump only for package @giraphql/plugin-relay

2.9.1 - 2021-07-10

Note: Version bump only for package @giraphql/plugin-relay

2.9.0 - 2021-07-04

Note: Version bump only for package @giraphql/plugin-relay

2.9.0-alpha.1 - 2021-07-04

🚀 Updates

  • add early warning for undefined refs to simplify debugging of circular import issues (095b68b)

📦 Dependencies

Note: Version bump only for package @giraphql/plugin-relay

2.9.0-alpha.0 - 2021-07-03

🚀 Updates

  • [relay] add connectionObject helper, cursorType option, and more field options (466b61f)

Note: Version bump only for package @giraphql/plugin-relay

2.8.1 - 2021-07-02

Note: Version bump only for package @giraphql/plugin-relay

2.8.0 - 2021-07-02

🚀 Updates

  • add option to make clientMutationField optional, or omit it entirly (95a74bb)
  • update deno (382775e)

🛠 Internals

  • update relay tests to account for new options (ea363b9)

Note: Version bump only for package @giraphql/plugin-relay

2.7.0 - 2021-06-28

Note: Version bump only for package @giraphql/plugin-relay

2.7.0-alpha.1 - 2021-06-28

Note: Version bump only for package @giraphql/plugin-relay

2.7.0-alpha.0 - 2021-06-28

🚀 Updates

Note: Version bump only for package @giraphql/plugin-relay

2.6.0 - 2021-06-11

🚀 Updates

  • make field options args optional when empty (ae71648)

🐞 Fixes

  • fix a couple type errors (453bf7b)

📦 Dependencies

Note: Version bump only for package @giraphql/plugin-relay

2.5.0 - 2021-06-10

🚀 Updates

Note: Version bump only for package @giraphql/plugin-relay

2.5.0-alpha.0 - 2021-06-09

🚀 Updates

  • plum parentShape through all ussage of output refs (2dac2ca)

📘 Docs

  • fix a couple typos (e2d41f7)
  • update docs on edge and connection fields (63b4b52)
  • update relay readme and add troubleshooting guide (56350e8)

🛠 Internals

Note: Version bump only for package @giraphql/plugin-relay

2.4.0 - 2021-05-31

🚀 Updates

  • add relayMutation method (a058430)

🐞 Fixes

  • add builder options for generated fields and args (b3edb2c)
  • rename resultFuelds to outputFields (b5e101d)

🛠 Internals

  • add tests for relayMutation options (1295347)

Note: Version bump only for package @giraphql/plugin-relay

2.4.0-alpha.2 - 2021-05-29

🐞 Fixes

  • add builder options for generated fields and args (52a218a)

🛠 Internals

  • add tests for relayMutation options (656b1c0)

Note: Version bump only for package @giraphql/plugin-relay

2.4.0-alpha.1 - 2021-05-29

🐞 Fixes

  • rename resultFuelds to outputFields (e00be1b)

Note: Version bump only for package @giraphql/plugin-relay

2.4.0-alpha.0 - 2021-05-29

🚀 Updates

  • add relayMutation method (57e3d7a)

Note: Version bump only for package @giraphql/plugin-relay

2.3.0 - 2021-05-28

🚀 Updates

  • add globalConnectionField methods for extending connection objects (a22e7e3)

Note: Version bump only for package @giraphql/plugin-relay

2.2.6 - 2021-05-26

🐞 Fixes

  • Make relay connection args optional explicitly (5eb1390)

Note: Version bump only for package @giraphql/plugin-relay

2.2.5 - 2021-05-18

Note: Version bump only for package @giraphql/plugin-relay

2.2.4 - 2021-05-13

📘 Docs

  • add docs for loadableNode (1ae01e8)

🛠 Internals

  • add tests for loadableNode (c1b49a0)

Note: Version bump only for package @giraphql/plugin-relay

2.2.3 - 2021-05-12

🛠 Internals

Note: Version bump only for package @giraphql/plugin-relay

2.2.2 - 2021-05-10

🐞 Fixes

  • update ci build command (7e1d1d2)

Note: Version bump only for package @giraphql/plugin-relay

2.2.1 - 2021-05-10

🐞 Fixes

  • force new version to fix esm build issue (25f1fd2)

Note: Version bump only for package @giraphql/plugin-relay

2.2.0 - 2021-05-10

🚀 Updates

  • add esm build for all packages (d8bbdc9)

Note: Version bump only for package @giraphql/plugin-relay

2.1.5 - 2021-05-09

📘 Docs

Note: Version bump only for package @giraphql/plugin-relay

2.1.5-alpha.0 - 2021-05-08

🛠 Internals

  • fix up a couple issues in internal types of relay field builder methods (1131f42)

Note: Version bump only for package @giraphql/plugin-relay

2.1.4 - 2021-05-05

Note: Version bump only for package @giraphql/plugin-relay

2.1.3 - 2021-05-05

Note: Version bump only for package @giraphql/plugin-relay

2.1.3-alpha.0 - 2021-05-05

Note: Version bump only for package @giraphql/plugin-relay

2.1.2 - 2021-05-02

🛠 Internals

  • force version bumps and update validation to 2.0 range (07730b3)

Note: Version bump only for package @giraphql/plugin-relay

2.1.1 - 2021-05-02

🛠 Internals

  • migrate to @beemo/dev for dev tool configs (1da1283)

Note: Version bump only for package @giraphql/plugin-relay

2.1.0 - 2021-04-16

📘 Docs

  • add docs for validation plugin (f7d83bf)

Note: Version bump only for package @giraphql/plugin-relay

2.1.0-alpha.0 - 2021-04-12

🚀 Updates

  • add globalID and globalIDList methods to InputFieldBuilder (1048354)

📦 Dependencies

Note: Version bump only for package @giraphql/plugin-relay

2.0.4 - 2021-03-28

🐞 Fixes

  • [relay] include extra fields defined for connections and edges (2b29e3a)

Note: Version bump only for package @giraphql/plugin-relay

2.0.3 - 2021-03-16

Note: Version bump only for package @giraphql/plugin-relay

2.0.2 - 2021-02-21

🐞 Fixes

  • restore missing exports in relay plugin (2630250)

Note: Version bump only for package @giraphql/plugin-relay

2.0.1 - 2021-02-19

Note: Version bump only for package @giraphql/plugin-relay

2.0.0 - 2021-02-16

💥 Breaking

  • update plugin exports and names to be more consistent (ee07b35)

🐞 Fixes

  • restore globalId helper function exports in relay plugin (16d8a0c)

📦 Dependencies

  • update dependencies and add license files (cb0d102)

📘 Docs

  • add more docs o writing plugins (b996fc6)
  • wip - plugin guide (cf9c6ec)

Note: Version bump only for package @giraphql/plugin-relay

2.0.0-alpha.1 - 2021-02-10

🛠 Internals

Note: Version bump only for package @giraphql/plugin-relay

2.0.0-alpha.0 - 2021-02-10

💥 Breaking

  • bump peer deps to 2.0 range (2a0fae8)

Note: Version bump only for package @giraphql/plugin-relay

1.4.1 - 2021-02-07

🐞 Fixes

  • specify @giraphql/core as peer and dev dep so it is updated correctly (f096393)

Note: Version bump only for package @giraphql/plugin-relay

1.3.0 (2020-10-21)

Note: Version bump only for package @giraphql/plugin-relay

Changelog

1.2.0

Add options objects for auto generated node and nodes queries, as well as the Node and PageInfo types.

1.1.0

Fixed issues with isTypeOf and ids on nodes.

1.0.0

Initial release