Querying Data

There are a few different ways to retrieve data from a Paper instance.

Note: It is important to remember that a document retrieved from the store is considered stale-on-arrival and cannot be modified. It does not represent an instance but instead a stale copy, or snapshot, of the document at the time of retrieval. For an updated version of the document it needs to be exchanged for an updated copy (see below)

Querying Documents via the data Property

A frozen read-only copy of the store is available via the data property on the Paper instance.

The shape of a store is:

{
[typeName]: Document[]
}

A GraphQL Schema with these two types:

type Actor {
name: String!
}
type Film {
title: String!
}

Could have a store like:

{
Film: [
{ title: 'Jurassic Park' },
{ title: 'Godzilla' }
],
Actor: [
{ name: 'Jeff Goldblum' },
{ name: 'Elizabeth Olsen' }
]
}

Since the data is accessed by type as a regular array the usual array methods can be used for accessing the data, and Documents in the array can be treated as POJOs.

// returns the document { title: 'Jurassic Park' }
paper.data.Film[0];
// returns the document { title: 'Godzilla' }
paper.data.Film.find(({title}) => title === 'Godzilla');

Exchange Documents for a Newer Copy

Since documents are immutable snapshots they need to be exchanged for updated copies. This can be done by using the find method on a Paper instance which will take the existing document to be exchanged for the latest copy.

// with a reference to an existing document exists from previously being fetched
film;
// return the latest copy of that document
const latestFilm = paper.find(film);

Returning Documents from Mutation Transactions

It's often useful to be able to have immediate access to a Document that has just been created/updated in a mutation transaction. This can be done by returning the Document, an array of Documents or an object of documents.

const macAndMe = await paper.mutate(({ create }) => {
const film = create('Film', { title: 'Mac and Me' });
return film;
});

The film variable representing the newly created document is returned and available outside via the macAndMe.

Similar with returning an object that can be destructured:

const { macAndme, spaceJam } = await paper.mutate(({ create }) => {
const macAndMe = create('Film', { title: 'Mac and Me' });
const spaceJam = create('Film', { title: 'Space Jam' });
return { macAndMe, spaceJam };
});

Or from an Array:

const [macAndme, spaceJam] = await paper.mutate(({ create }) => {
const filmOne = create('Film', { title: 'Mac and Me' });
const filmTwo = create('Film', { title: 'Space Jam' });
return [filmOne, filmTwo];
});

Traversing Connections Between Documents

GraphQL Paper has support for connections between types as defined by the GraphQL Schema. If it's a list of types or a singular type it can be handled by GraphQL Paper. Accessing connections on a document do not have any special API and are accessible like any other field, as a property on the document.

With a schema where a Film can have multiple actors:

type Actor {
name: String!
}
type Film {
title: String!
actors: [Actor!]!
}

A film's actors could be accessed directly:

const film = paper.data.Film[0];
// returns any actors connected to the Film document
film.actors;

Connections between documents are created during a mutation and are covered in Mutating Data.