@flowup/contentful-client
v3.0.0
Published
Wrapper client for Contentful delivery API
Downloads
3
Readme
@flowup/contentful-client
This package provides a type-safe wrapper for Typescript around the Contentful client from the
contentful
package.
It is recommended to use this with the @flowup/contentful-types-generator
, which enables generating Contentful types automatically instead of writing them manually.
For more information on querying Contentful, see documentation on the Content Delivery API.
Installation
npm install @flowup/contentful-client
Usage
Setup
Create a ContentfulClient
instance, supplying necessary configuration for your Contentful space.
To make use of type-checking and IDE intelisense, create types for your Contentful space and the content types contained therein, and supply it as a generic type.
For example:
import { ContentfulClient, ContentfulConfig } from '@flowup/contentful-client';
import { Entry } from 'contentful';
// map Contentful content type ID to content model
interface SpaceModel {
author: AuthorModel;
book: BookModel;
}
// map Contentful field ID to type
interface AuthorModel {
name: string;
age: number;
rating?: number;
}
interface BookModel {
title: string;
author: Entry<AuthorModel>; // link to another content type
}
// configure Contentful environment
const config: ContentfulConfig = {
spaceId: '...',
accessToken: '...',
environment: '...',
// ...
};
// create connection to Contentful
const client = new ContentfulClient<SpaceModel>(config);
Setup with types generator
Since creating and maintaining the Contentful types can be cumbersome and error-prone, it is recommended to automate this process.
See @flowup/contentful-types-generator
package for instructions on how to generate the types via CLI.
Once the types are generated, all that is needed is to supply the Contentful space type, e.g.:
import { ContentfulClient } from '@flowup/contentful-client';
import { AppSpace } from './app-space.ts';
const client = new ContentfulClient<AppSpace>({
// ...
});
Querying
Single-line comments show inferred types.
Ordering
Example of ordering:
/* fetch top 10 highest rated authors */
client
.getFields({
contentType: 'author', // keyof SpaceModel
ordering: {
field: 'rating', // keyof AuthorModel
desc: true,
},
limit: 10,
})
// Promise<AuthorModel[]>
.then(authors => {
console.log(authors);
});
Example of ordering by metadata field:
/* fetch 5 most recent books */
client
.getFields({
contentType: 'book', // keyof SpaceModel
ordering: {
metadata: 'createdAt',
desc: true,
},
limit: 5,
})
// Promise<BookModel[]>
.then(books => {
console.log(books);
});
Example of ordering by multiple fields:
/* fetch top 10 authors - if they have the same rating, order from youngest */
client
.getFields({
contentType: 'author', // keyof SpaceModel
ordering: [
{
field: 'rating', // keyof AuthorModel
desc: true,
},
{
field: 'age', // keyof AuthorModel
desc: false /* ascending is default */,
},
],
limit: 10,
})
// Promise<AuthorModel[]>
.then(authors => {
console.log(authors);
});
Filtering
Example of filtering by fields:
/* filter books for exact title match */
client
.getFields({
contentType: 'book', // keyof SpaceModel
filters: {
fields: {
// keyof BookModel
title: {
value: 'The Shining', // string
},
},
},
limit: 1,
})
// Promise<BookModel[]>
.then(books => {
if (books.length === 0) {
console.log('Book not found');
} else {
console.log(
`${books[0].title} is written by ${books[0].author.fields.name}`,
);
}
});
Example of filtering by metadata:
/* filter books created since a certain date */
client
.getItems({
contentType: 'book', // keyof SpaceModel
filters: {
metadata: {
createdAt: {
operator: 'gte',
value: '2020-01-01',
},
},
},
})
// Promise<Entry<BookModel[]>>
.then(bookEntries => {
bookEntries.forEach(bookEntry => {
console.log(
`${bookEntry.fields.title} was created at ${bookEntry.sys.createdAt}`,
);
});
});
Example of filtering by sub-fields:
/* filter books whose author is younger than 21 */
client
.getFields({
contentType: 'book', // keyof SpaceModel
filters: {
subfields: {
// keyof BookModel
author: {
contentType: 'author', // 'author'
fields: {
// keyof AuthorModel
age: {
operator: 'lt',
value: 21, // number
},
},
},
},
},
})
// Promise<BookModel[]>
.then(books => {
books.forEach(book => {
console.log(
`Author of ${book.title} is ${book.author.fields.age} years old`,
);
});
});
Selection
Example of selecting specific fields and metadata:
/* fetch names of authors */
client
.getFields({
contentType: 'author', // keyof SpaceModel
select: {
fields: ['name', 'age'], // (keyof AuthorModel)[]
metadata: ['id'], // (keyof Sys)[]
},
})
// Promise<AuthorModel[]>
.then(authors => {
console.log(authors);
});
Example of selecting only content fields (without sys
metadata):
/* fetch names of authors */
client
.getFields({
contentType: 'author', // keyof SpaceModel
select: 'fields',
})
// Promise<AuthorModel[]>
.then(authors => {
console.log(authors);
});