{"id":13517844,"url":"https://github.com/contentful/cf-graphql","last_synced_at":"2025-10-08T08:32:21.371Z","repository":{"id":57108307,"uuid":"84376551","full_name":"contentful/cf-graphql","owner":"contentful","description":"Generate a GraphQL schema out of your Contentful space","archived":true,"fork":false,"pushed_at":"2018-10-16T07:14:52.000Z","size":1011,"stargazers_count":186,"open_issues_count":17,"forks_count":32,"subscribers_count":59,"default_branch":"master","last_synced_at":"2024-10-29T09:09:20.438Z","etag":null,"topics":["contentful","graphql"],"latest_commit_sha":null,"homepage":"","language":"JavaScript","has_issues":false,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/contentful.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2017-03-08T23:32:14.000Z","updated_at":"2024-06-11T21:10:27.000Z","dependencies_parsed_at":"2022-08-20T17:10:44.379Z","dependency_job_id":null,"html_url":"https://github.com/contentful/cf-graphql","commit_stats":null,"previous_names":["contentful-labs/cf-graphql"],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/contentful%2Fcf-graphql","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/contentful%2Fcf-graphql/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/contentful%2Fcf-graphql/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/contentful%2Fcf-graphql/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/contentful","download_url":"https://codeload.github.com/contentful/cf-graphql/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":235700110,"owners_count":19031668,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["contentful","graphql"],"created_at":"2024-08-01T05:01:37.994Z","updated_at":"2025-10-08T08:32:16.045Z","avatar_url":"https://github.com/contentful.png","language":"JavaScript","funding_links":[],"categories":["JavaScript"],"sub_categories":[],"readme":"# cf-graphql\n\n[![travis build status](https://img.shields.io/travis/contentful-labs/cf-graphql.svg)](https://travis-ci.org/contentful-labs/cf-graphql)\n[![npm version](https://img.shields.io/npm/v/cf-graphql.svg)](https://www.npmjs.com/package/cf-graphql)\n[![npm downloads](https://img.shields.io/npm/dt/cf-graphql.svg)](https://www.npmjs.com/package/cf-graphql)\n[![deps status](https://img.shields.io/david/contentful-labs/cf-graphql.svg)](https://david-dm.org/contentful-labs/cf-graphql)\n[![dev deps status](https://img.shields.io/david/dev/contentful-labs/cf-graphql.svg)](https://david-dm.org/contentful-labs/cf-graphql?type=dev)\n[![codecov coverage](https://img.shields.io/codecov/c/github/contentful-labs/cf-graphql.svg)](https://codecov.io/gh/contentful-labs/cf-graphql)\n\n`cf-graphql` is a library that allows you to query your data stored in [Contentful](https://www.contentful.com/) with [GraphQL](http://graphql.org/). A schema and value resolvers are automatically generated out of an existing space.\n\nGenerated artifacts can be used with any node-based GraphQL server. The outcome of the project's main function call is an instance of the [`GraphQLSchema`](http://graphql.org/graphql-js/type/#graphqlschema) class.\n\n\n## Table of contents\n\n- [Disclaimers](#disclaimers)\n- [First steps](#first-steps)\n- [Demo](#demo)\n  - [Run it locally](#run-it-locally)\n  - [Deploy to Zeit's now](#deploy-to-zeits-now)\n- [Programmatic usage](#programmatic-usage)\n- [Querying](#querying)\n- [Helpers](#helpers)\n- [Contributing](#contributing)\n\n\n## Disclaimers\n\nPlease note that `cf-graphql` library is released as an experiment:\n\n- we might introduce breaking changes into programmatic interfaces and space querying approach before v1.0 is released\n- there’s no magic bullet: complex GraphQL queries can result in a large number of CDA calls, which will be counted against your quota\n- we might discontinue development of the library and stop maintaining it\n\n\n## First steps\n\nIf you just want to see how it works, please follow the [Demo](#demo) section. You can deploy the demo with your own credentials so it queries your own data.\n\nIn general `cf-graphql` is a library and it can be used as a part of your project. If you want to get your hands dirty coding, follow the [Programmatic usage](#programmatic-usage) section.\n\n\n## Demo\n\nWe host an [online demo](https://cf-graphql-demo.now.sh/) for you. You can query Contentful's \"Blog\" space template there. This how its graph looks like:\n\n![Demo space graph](./demo/demo-space-graph.png)\n\n\n### Run it locally\n\nThis repository contains a demo project. The demo comes with a web server (with [CORS](https://developer.mozilla.org/en-US/docs/Web/HTTP/Access_control_CORS) enabled) providing the GraphQL, [an in-browser IDE (GraphiQL)](https://github.com/graphql/graphiql) and a React Frontend application using this endpoint.\n\nTo run it, clone the repository, install dependencies and start a server:\n\n```\ngit clone git@github.com:contentful-labs/cf-graphql.git\ncd cf-graphql/demo\n# optionally change your node version with nvm, anything 6+ should work just fine\n# we prefer node v6 matching the current AWS Lambda environment\nnvm use\nnpm install\nnpm start\n```\n\nUse \u003chttp://localhost:4000/graphql/\u003e to query the data from within your application and navigate to \u003chttp://localhost:4000\u003e to use the IDE (GraphiQL) for test-querying. Please refer to the [Querying](#querying) section for more details.\n\nIf you also want to see how to integrate GraphQL in a React technology stack the demo project also contains an application based on the [Apollo framework](https://www.apollodata.com/). To check it out use \u003chttp://localhost:4000/client/\u003e.\n\nTo use your own Contentful space with the demo, you have to provide:\n\n- space ID\n- CDA token\n- CMA token\n\nPlease refer the [\"Authentication\" section](https://www.contentful.com/developers/docs/references/authentication/) of Contentful's documentation.\n\nYou can provide listed values with env variables:\n\n```\nSPACE_ID=some-space-id CDA_TOKEN=its-cda-token CMA_TOKEN=your-cma-token npm start\n```\n\n\n### Deploy to [Zeit's `now`](https://zeit.co/now)\n\nTo be able to deploy to [Zeit's `now`](https://zeit.co/now) you need to have an activated account. There is a free open source option available.\n\nYou can also deploy the demo with `now`. In your terminal, navigate to the `demo/` directory and run:\n\n```\nnpm run deploy-demo-now\n```\n\nAs soon as the deployment is done you'll have a URL of your GraphQL server copied.\n\nYou can also create a deployment for your own space:\n\n```\nSPACE_ID=some-space-id CDA_TOKEN=its-cda-token CMA_TOKEN=your-cma-token npm run deploy-now\n```\n\nPlease note:\n\n- when deploying a server to consume Contentful's \"Blog\" space template, the command to use is `npm run deploy-demo-now`; when the demo should be configured to use your own space, the command is `npm run deploy-now`\n- if you've never used `now` before, you'll be asked to provide your e-mail; just follow on-screen instructions\n- if you use `now`'s OSS plan (the default one), the source code will be public; it's completely fine: all credentials are passed as env variables and are not available publicly\n\n\n## Programmatic usage\n\nThe library can be installed with `npm`:\n\n```\nnpm install --save cf-graphql\n```\n\nLet's assume we've required this module with `const cfGraphql = require('cf-graphql')`. To create a schema out of your space you need to call `cfGraphgl.createSchema(spaceGraph)`.\n\nWhat is `spaceGraph`? It is a graph-like data structure containing descriptions of content types of your space which additionally provide some extra pieces of information allowing the library to create a GraphQL schema.\n\nTo prepare this data structure you need to fetch raw content types data from the [CMA](https://www.contentful.com/developers/docs/references/content-management-api/). Let's create a Contentful client first:\n\n```js\nconst client = cfGraphql.createClient({\n  spaceId: 'some-space-id',\n  cdaToken: 'its-cda-token',\n  cmaToken: 'your-cma-token'\n});\n```\n\n`spaceId`, `cdaToken` and `cmaToken` options are required. You can also pass the following options:\n\n- `locale` - a locale code to use when fetching content. If not provided, the default locale of a space is used\n- `preview` - if `true`, CPA will be used instead of CDA for fetching content\n- `cpaToken` - if `preview` is `true` then this option has to hold a CPA token\n\nFetch content types with your `client` and then pass them to `cfGraphql.prepareSpaceGraph(rawCts)`:\n\n```js\nclient.getContentTypes()\n.then(cfGraphql.prepareSpaceGraph)\n.then(spaceGraph =\u003e {\n  // `spaceGraph` can be passed to `cfGraphql.createSchema`!\n});\n```\n\nThe last step is to use the schema with a server. A popular choice is [express-graphql](https://github.com/graphql/express-graphql). The only caveat is how the context is constructed. The library expects the `entryLoader` key of the context to be set to an instance created with `client.createEntryLoader()`:\n\n```js\n// Skipped in snippet: `require` calls, Express app setup, `client` creation.\n// `spaceGraph` was fetched and prepared in the previous snippet. In most cases\n// you shouldn't be doing it per request, once is fine.\nconst schema = cfGraphql.createSchema(spaceGraph);\n\n// IMPORTANT: we're passing a function to `graphqlHTTP`: this function will be\n// called every time a GraphQL query arrives to create a fresh entry loader.\n// You can also use `expressGraphqlExtension` described below.\napp.use('/graphql', graphqlHTTP(function () {\n  return {\n    schema,\n    context: {entryLoader: client.createEntryLoader()}\n  };\n}));\n```\n\n[You can see a fully-fledged example in the `demo/` directory](./demo/server.js).\n\n\n## Querying\n\nFor each Contentful content type three root-level fields are created:\n\n- a singular field accepts a required `id` argument and resolves to a single entity\n- a collection field accepts an optional `q`, `skip` and `limit` arguments and resolves to a list of entities\n- a collection metadata field accepts an optional `q` argument and resolves to a metadata object (currently comprising only `count`)\n\n\nPlease note that:\n\n- the `q` argument is a query string you could use with the [CDA](https://www.contentful.com/developers/docs/references/content-delivery-api/)\n- both `skip` and `limit` arguments can be used to fetch desired page of results\n  * `skip` defaults to `0`\n  * `limit` defaults to `50` and cannot be greater than `1000`\n* some query string parameters cannot be used:\n  * `skip`, `limit` - use collection field arguments instead\n  * `include`, `content_type` - no need for them, the library will determine and use appropriate values internally\n  * `locale` - all the content is fetched for a single locale. By default the default locale is used; alternate locale can be selected with the `locale` configuration option of `cfGraphql.createClient`\n\nAssuming you've got two content types named `post` and `author` with listed fields, this query is valid:\n\n```graphql\n{\n  authors {\n    name\n  }\n\n  authors(skip: 10, limit: 10) {\n    title\n    rating\n  }\n\n  _authorsMeta {\n    count\n  }\n\n  posts(q: \"fields.rating[gt]=5\") {\n    title\n    rating\n  }\n\n  _postsMeta(q: \"fields.rating[gt]=5\") {\n    count\n  }\n\n  post(id: \"some-post-id\") {\n    title\n    author\n    comments\n  }\n}\n```\n\nReference fields will be resolved to:\n\n- a specific type, if there is a validation that allows only entries of some specific content type to be linked\n- the `EntryType`, if there is no such constraint. The `EntryType` is an interface implemented by all the specific types\n\nExample where the `author` field links only entries of one content type and the `related` field links entries of multiple content types:\n\n```graphql\n{\n  posts {\n    author {\n      name\n      website\n    }\n\n    related {\n      ... on Tag {\n        tagName\n      }\n      ... on Place {\n        location\n        name\n      }\n    }\n  }\n}\n```\n\nBackreferences (_backrefs_) are automatically created for links. Assume our `post` content type links to the `author` content type via a field named `author`. Getting an author of a post is easy, getting a list of posts by an author is not. `_backrefs` mitigate this problem:\n\n```graphql\n{\n  authors {\n    _backrefs {\n      posts__via__author {\n        title\n      }\n    }\n  }\n}\n```\n\nWhen using backreferences, there is a couple of things to keep in mind:\n\n- backrefs may be slow; always test with a dataset which is comparable with what you've got in production\n- backrefs are generated only when a reference field specifies a single allowed link content type\n- `_backrefs` is prefixed with a single underscore\n- `__via__` is surrounded with two underscores; you can read this query out loud like this: _\"get posts that link to author via the author field\"_\n\n\n## Helpers\n\n`cf-graphql` comes with helpers that help you with the `cf-graphql` integration. These are used inside of [the demo application](https://github.com/contentful-labs/cf-graphql/tree/master/demo).\n\n\n### `expressGraphqlExtension`\n\n`expressGraphqlExtension` is a simple utility producing a function that can be passed directly to the [`express-graphql` middleware](https://github.com/graphql/express-graphql).\n\n```javascript\n// Skipped in this snippet: client and space graph creation\nconst schema = cfGraphql.createSchema(spaceGraph);\n\nconst opts = {\n  // display the current cf-graphql version in responses\n  version: true,\n  // include list of the underlying Contentful CDA calls with their timing\n  timeline: true,\n  // display detailed error information\n  detailedErrors: true\n};\n\nconst ext = cfGraphql.helpers.expressGraphqlExtension(client, schema, opts);\napp.use('/graphql', graphqlHTTP(ext));\n```\n\n**Important**: Most likely don't want to enable `timeline` and `detailedErrors` in your production environment.\n\n\n### `graphiql`\n\nIf you want to run your own GraphiQL and don't want to rely on the one shipping with e.g. [express-graphql](https://github.com/graphql/express-graphql) then you could use the `graphiql` helper.\n\n```javascript\nconst ui = cfGraphql.helpers.graphiql({title: 'cf-graphql demo'});\napp.get('/', (_, res) =\u003e res.set(ui.headers).status(ui.statusCode).end(ui.body));\n```\n\n\n## Contributing\n\nIssue reports and PRs are more than welcomed.\n\n\n## License\n\nMIT\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fcontentful%2Fcf-graphql","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fcontentful%2Fcf-graphql","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fcontentful%2Fcf-graphql/lists"}