Ecosyste.ms: Awesome

An open API service indexing awesome lists of open source software.

Awesome Lists | Featured Topics | Projects

https://github.com/luchiniatwork/contentql

Access Contentful data using Om Next Queries
https://github.com/luchiniatwork/contentql

clojure clojurescript cms content contentful omnext query-language

Last synced: 2 months ago
JSON representation

Access Contentful data using Om Next Queries

Awesome Lists containing this project

README

        

# ContentQL

ContentQL allows one to access Contentful data using Om Next Queries.

[Contentful](https://www.contentful.com/) is a popular headless, cloud-based CMS system. Beyond
being purely an API-first CMS system it also supports somewhat complex data schemas, responsive
images and webhooks making it a very compelling content platform.

Despite the great features provided by Contentful, one thing remains somewhat challenging:
its API is not the most straightforward to use.

Instead of porting Contentful's API on a one-on-one basis to Clojure and ClojureScript, this
library takes an abstraction route to querying: it uses Om Next's Query language as its main
interface.

## Table of Contents

* [Getting Started](#getting-started)
* [Motivation](#motivation)
* [Features](#features)
* [Query Syntax](#query-syntax)
* [Usage](#usage)
* [Pagination](#pagination)
* [Bugs](#bugs)
* [Help!](#help)

## Getting Started

Add the following dependency to your `project.clj` file:

[![Clojars Project](http://clojars.org/luchiniatwork/contentql/latest-version.svg)](http://clojars.org/luchiniatwork/contentql)

## Motivation

By using Om Next queries one can:

* easily describe deep nested joins
* clearly parameterize root (as well as other) queries
* easily express field selections
* easily dispatch queries to Contentful from Om Next remotes
* easy-to-use responsive images as part of the query
* describe your queries using macro syntax

## Features

ContentQL's key features are:

1. Support for both Clojure and ClojureScript
2. Seamless `clojure.core.async` and `cljs.core.async` support
3. Use with or without Om Next - it's your call
4. Access to deep field selectors
5. Access to filters, ordering, and pagination
6. Dead simple, cached, responsive images

## Query Syntax

The Om Next query syntax is beautifuly described by António Monteiro [here](https://anmonteiro.com/2016/01/om-next-query-syntax/) but if you need a quick primer, here it is:

### Simple properties

If you have a content type called `blogs`, you can query its entries with:

```clojure
'[:blogs]
```

You can always combine several content types in one go:

```clojure
'[:blogs :articles]
```

### Joins

If you want just the `title` and the `body` of your `blogs`, you can use a join such as:

```clojure
'[{:blogs [:title :body]}]
```

### Nested joins

Assuming your `blogs` content type has an `author` embedded whose `name` you want to fetch
as well, simply nest your joins:

```clojure
'[{:blogs [:title :body
{:author [:name]}]}]
```

This will continue to give you the `title` and the `body` of each blog entry but now also
the name of each blog's author.

### Parametrized queries

Queries can be parametrized by using a list where the second element is a map of parameters.
If you want the blog identified by `id` `"3x1YMtJ1CoOWk0ycYsOw4I"` you can fetch it with:

```clojure
'[(:blogs {:id "3x1YMtJ1CoOWk0ycYsOw4I"})]
```

This can be combined with joins, ie:

```clojure
'[({:blogs [:title :body]} {:id "3x1YMtJ1CoOWk0ycYsOw4I"})]
```

Or even nested joins:

```clojure
'[({:blogs [:title :body
{:author [:name]}]}
{:id "3x1YMtJ1CoOWk0ycYsOw4I"})]
```
### Supported parameters for Query roots

All your content types can be queries as part of a query root.

You've already seen above how to query a specific entry by its `id`:

```clojure
'[(:blogs {:id "3x1YMtJ1CoOWk0ycYsOw4I"})]
```

In addition to `:id` the other supported query root parameters are:

* `:limit` - limits the page size to its value (i.e. `:limit 10`)
* `:skip` - skips the specified number of entries (i.e. `:skip 5` skips 5 entries)
* `:order` - allows ordering of the entries (i.e. `:order "fields.name"` ordres the dataset by `name`). Reverse ordering is supported with the addition of `-` (i.e. `:order "-fields.name"`)

### Supported parameters for Images

Any image asset is immidetally wrapped in an image entity containing three fields `:width`, `:height` and `:url`. The asset can be scaled up or down by sending the intended `:width` or `:height` parameter.

In order to see it in action, suppose your `author` has an `avatar` image and you want it constrained within a `width` of 150 pixels:

```clojure
'[{:authors [({:avatar [:width
:height
:url]}
{:width 150})]}]
```

## Usage

Async channels are slightly different between Clojure and ClojureScript due to underlying characteristics of how the JVM and the JavaScript environment deal with multi-threading. ContentQL supports both platforms seamlessly.

For Clojure, require `contentql.core` and `clojure.core.async`:

```clojure
(ns my-project
(:require [contentql.core :as contentql]
[clojure.core.async :refer [go