cf-graphql
Advanced tools
Comparing version 0.3.0 to 0.4.0
{ | ||
"name": "cf-graphql", | ||
"description": "Generate a GraphQL schema out of your Contentful space", | ||
"version": "0.3.0", | ||
"version": "0.4.0", | ||
"license": "MIT", | ||
"repository": "jelz/cf-graphql", | ||
"repository": "contentful-labs/cf-graphql", | ||
"contributors": [ | ||
@@ -26,11 +26,11 @@ { | ||
], | ||
"main": "index.js", | ||
"main": "src/index.js", | ||
"scripts": { | ||
"example": "nodemon example/server.js", | ||
"dev": "nodemon dev/server.js", | ||
"dump": "mkdirp dump && npm run dump-graph && npm run dump-schema", | ||
"dump-graph": "graphqlviz http://localhost:4000/graphql | dot -Tpng -o dump/graph.png", | ||
"dump-schema": "fetch-graphql-schema http://localhost:4000/graphql -r -o dump/schema.graphql", | ||
"lint": "eslint 'index.js' 'src/*.js' 'test/*.js' 'example/*.js'", | ||
"test": "tape 'test/*.js'", | ||
"coverage": "istanbul cover tape 'test/*.js'", | ||
"lint": "eslint 'src/**/*.js' 'test/**/*.js' 'demo/*.js' 'dev/*.js'", | ||
"test": "tape 'test/**/*.js'", | ||
"coverage": "istanbul cover tape 'test/**/*.js'", | ||
"codecov": "cat coverage/coverage.json | codecov" | ||
@@ -40,3 +40,3 @@ }, | ||
"dataloader": "^1.3.0", | ||
"graphql": "^0.9.3", | ||
"graphql": "^0.9.6", | ||
"lodash.camelcase": "^4.3.0", | ||
@@ -60,5 +60,5 @@ "lodash.chunk": "^4.2.0", | ||
"proxyquire": "^1.7.11", | ||
"sinon": "^2.1.0", | ||
"sinon": "^2.2.0", | ||
"tape": "^4.6.3" | ||
} | ||
} |
# cf-graphql | ||
[![travis build status](https://img.shields.io/travis/jelz/cf-graphql.svg)](https://travis-ci.org/jelz/cf-graphql) | ||
[![travis build status](https://img.shields.io/travis/contentful-labs/cf-graphql.svg)](https://travis-ci.org/contentful-labs/cf-graphql) | ||
[![npm version](https://img.shields.io/npm/v/cf-graphql.svg)](https://www.npmjs.com/package/cf-graphql) | ||
[![npm downloads](https://img.shields.io/npm/dt/cf-graphql.svg)](https://www.npmjs.com/package/cf-graphql) | ||
[![deps status](https://img.shields.io/david/jelz/cf-graphql.svg)](https://david-dm.org/jelz/cf-graphql) | ||
[![dev deps status](https://img.shields.io/david/dev/jelz/cf-graphql.svg)](https://david-dm.org/jelz/cf-graphql?type=dev) | ||
[![codecov coverage](https://img.shields.io/codecov/c/github/jelz/cf-graphql.svg)](https://codecov.io/gh/jelz/cf-graphql) | ||
[![deps status](https://img.shields.io/david/contentful-labs/cf-graphql.svg)](https://david-dm.org/contentful-labs/cf-graphql) | ||
[![dev deps status](https://img.shields.io/david/dev/contentful-labs/cf-graphql.svg)](https://david-dm.org/contentful-labs/cf-graphql?type=dev) | ||
[![codecov coverage](https://img.shields.io/codecov/c/github/contentful-labs/cf-graphql.svg)](https://codecov.io/gh/contentful-labs/cf-graphql) | ||
@@ -15,5 +15,23 @@ `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. | ||
## Table of contents | ||
- [Disclaimers](#disclaimers) | ||
- [First steps](#first-steps) | ||
- [Demo](#demo) | ||
- [Run it locally](#run-it-locally) | ||
- [Deploy to Zeit's now](#deploy-to-zeits-now) | ||
- [Programmatic usage](#programmatic-usage) | ||
- [Querying](#querying) | ||
- [Contributing](#contributing) | ||
## Disclaimers | ||
1. Before reaching v1.0 both programmatic interfaces and the way how you query a space can change in a non-backwards compatible manner | ||
2. There's no magic: if your GraphQL query is complex, it'll result in multiple CDA calls that will be counted against your quota | ||
## First steps | ||
If you just want to see how it works, please follow the [Example](#example) section. If you want to get your hands dirty, install the package and follow the [Usage](#usage) section: | ||
If you just want to see how it works, please follow the [demo](#demo) section. If you want to get your hands dirty, install the package and follow the [Programmatic usage](#programmatic-usage) section: | ||
@@ -25,15 +43,22 @@ ``` | ||
## Example | ||
## Demo | ||
This repository contains a project example. To run it, clone the repository and execute: | ||
We host an [online demo](https://cf-graphql-demo.now.sh/) for you. You can query Contentful's "Blog" space template there. | ||
### Run it locally | ||
This repository contains a demo project. To run it, clone the repository, install dependencies and start a server: | ||
``` | ||
git clone git@github.com:contentful-labs/cf-graphql.git | ||
cd cf-graphql/demo | ||
nvm use # optional, but we prefer node v6.10 | ||
npm install | ||
npm run example | ||
npm start | ||
``` | ||
Navigate to <http://localhost:4000> to access an IDE (GraphiQL). You can query my demo space there. Please refer the [Querying](#querying) section for more details. | ||
Navigate to <http://localhost:4000> to access an IDE (GraphiQL). You can query a demo space there. Please refer the [Querying](#querying) section for more details. | ||
To use your own Contentful space with the example, you have to provide: | ||
To use your own Contentful space with the demo, you have to provide: | ||
@@ -49,8 +74,31 @@ - space ID | ||
``` | ||
SPACE_ID=some-space-id CDA_TOKEN=its-cda-token CMA_TOKEN=your-cma-token npm run example | ||
SPACE_ID=some-space-id CDA_TOKEN=its-cda-token CMA_TOKEN=your-cma-token npm start | ||
``` | ||
## Usage | ||
### Deploy to [Zeit's `now`](https://zeit.co/now) | ||
You can also deploy the demo with `now`. In your terminal, navigate to the `demo/` directory and run: | ||
``` | ||
npm run deploy-demo-now | ||
``` | ||
As soon as the deployment is done you'll have a URL of your GraphQL server copied. | ||
You can also create a deployment for your own space: | ||
``` | ||
SPACE_ID=some-space-id CDA_TOKEN=its-cda-token CMA_TOKEN=your-cma-token npm run deploy-now | ||
``` | ||
Please note: | ||
- when deploying a server with a demo space, the command to use is `npm run deploy-demo-now`; when using your own space, the command is `npm run deploy-now` | ||
- if you've never used `now` before, you'll be asked to provide your e-mail; just follow on-screen instructions | ||
- if you use `now`'s OSS plan (the default one), you'll be asked if you want to make your source code public; it's completely fine: all credentials are passed as env variables and are not available publicly | ||
## Programmatic usage | ||
Let'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)`. | ||
@@ -89,3 +137,3 @@ | ||
[You can see a fully-fledged example here](./example/server.js). | ||
[You can see a fully-fledged example in the `demo/` directory](./demo/server.js). | ||
@@ -92,0 +140,0 @@ |
@@ -9,14 +9,18 @@ 'use strict'; | ||
function createBackrefsType (ct, ctIdToType) { | ||
return new GraphQLObjectType({ | ||
name: ct.names.backrefsType, | ||
fields: ct.backrefs.reduce((acc, backref) => { | ||
const Type = ctIdToType[backref.ctId]; | ||
if (Type) { | ||
acc[backref.backrefFieldName] = createBackrefFieldConfig(backref, Type); | ||
} | ||
return acc; | ||
}, {}) | ||
}); | ||
const fields = prepareBackrefsFields(ct, ctIdToType); | ||
if (Object.keys(fields).length > 0) { | ||
return new GraphQLObjectType({name: ct.names.backrefsType, fields}); | ||
} | ||
} | ||
function prepareBackrefsFields (ct, ctIdToType) { | ||
return (ct.backrefs || []).reduce((acc, backref) => { | ||
const Type = ctIdToType[backref.ctId]; | ||
if (Type) { | ||
acc[backref.backrefFieldName] = createBackrefFieldConfig(backref, Type); | ||
} | ||
return acc; | ||
}, {}); | ||
} | ||
function createBackrefFieldConfig (backref, Type) { | ||
@@ -23,0 +27,0 @@ return { |
@@ -32,3 +32,8 @@ 'use strict'; | ||
return createHttpClient({base, headers}); | ||
const defaultParams = {}; | ||
if (api === CDA && config.locale) { | ||
defaultParams.locale = config.locale; | ||
} | ||
return createHttpClient({base, headers, defaultParams}); | ||
} |
@@ -6,3 +6,5 @@ 'use strict'; | ||
module.exports = config => { | ||
module.exports = createClient; | ||
function createClient (config) { | ||
config = config || {}; | ||
@@ -12,2 +14,3 @@ const opts = { | ||
headers: config.headers || {}, | ||
defaultParams: config.defaultParams || {}, | ||
timeline: config.timeline || [], | ||
@@ -21,6 +24,7 @@ cache: config.cache || {} | ||
}; | ||
}; | ||
} | ||
function get (url, params, opts) { | ||
const sortedQS = getSortedQS(params); | ||
const paramsWithDefaults = Object.assign({}, opts.defaultParams, params); | ||
const sortedQS = getSortedQS(paramsWithDefaults); | ||
if (typeof sortedQS === 'string' && sortedQS.length > 0) { | ||
@@ -27,0 +31,0 @@ url = `${url}?${sortedQS}`; |
@@ -33,8 +33,5 @@ 'use strict'; | ||
const fields = {sys: {type: EntrySysType}}; | ||
if (ct.backrefs) { | ||
const BackrefsType = createBackrefsType(ct, ctIdToType); | ||
fields._backrefs = { | ||
type: BackrefsType, | ||
resolve: entry => entry.sys.id | ||
}; | ||
const BackrefsType = createBackrefsType(ct, ctIdToType); | ||
if (BackrefsType) { | ||
fields._backrefs = {type: BackrefsType, resolve: e => e.sys.id}; | ||
} | ||
@@ -41,0 +38,0 @@ return fields; |
@@ -38,3 +38,4 @@ 'use strict'; | ||
base: 'https://api.contentful.com/spaces/SPID', | ||
headers: {Authorization: 'Bearer CMA-TOKEN'} | ||
headers: {Authorization: 'Bearer CMA-TOKEN'}, | ||
defaultParams: {} | ||
}]); | ||
@@ -44,3 +45,4 @@ | ||
base: 'https://cdn.contentful.com/spaces/SPID', | ||
headers: {Authorization: 'Bearer CDA-TOKEN'} | ||
headers: {Authorization: 'Bearer CDA-TOKEN'}, | ||
defaultParams: {} | ||
}]); | ||
@@ -50,3 +52,4 @@ | ||
base: 'http://api.altdomain.com/spaces/SPID', | ||
headers: {Authorization: 'Bearer CMA-TOKEN'} | ||
headers: {Authorization: 'Bearer CMA-TOKEN'}, | ||
defaultParams: {} | ||
}]); | ||
@@ -56,3 +59,4 @@ | ||
base: 'http://cdn.altdomain.com/spaces/SPID', | ||
headers: {Authorization: 'Bearer CDA-TOKEN'} | ||
headers: {Authorization: 'Bearer CDA-TOKEN'}, | ||
defaultParams: {} | ||
}]); | ||
@@ -62,2 +66,18 @@ }); | ||
test('client: with "locale" config option', function (t) { | ||
t.plan(2); | ||
createHttpClientStub.reset(); | ||
createHttpClientStub.returns(httpStub); | ||
const c = createClient(Object.assign({locale: 'x'}, config)); | ||
const defaultParams = n => createHttpClientStub.getCall(n).args[0].defaultParams; | ||
c.createEntryLoader(); | ||
c.getContentTypes() | ||
.then(() => { | ||
t.deepEqual(defaultParams(0), {locale: 'x'}); | ||
t.deepEqual(defaultParams(1), {}); | ||
}); | ||
}); | ||
test('client: getting content types', function (t) { | ||
@@ -64,0 +84,0 @@ t.plan(3); |
@@ -10,3 +10,3 @@ 'use strict'; | ||
const prepare = val => { | ||
const prepare = (val, defaultParams = {}) => { | ||
const fetch = stubs['node-fetch']; | ||
@@ -18,3 +18,7 @@ fetch.reset(); | ||
fetch, | ||
http: createClient({base: 'http://test.com', headers: {'X-Test': 'yes'}}) | ||
http: createClient({ | ||
base: 'http://test.com', | ||
headers: {'X-Test': 'yes'}, | ||
defaultParams | ||
}) | ||
}; | ||
@@ -38,2 +42,17 @@ }; | ||
test('http-client: using default params option', function (t) { | ||
t.plan(3); | ||
const {fetch, http} = prepare(undefined, {locale: 'de-DE'}); | ||
Promise.all([ | ||
http.get('/x', {content_type: 'ctid'}), | ||
http.get('/y', {locale: 'x'}) | ||
]) | ||
.then(() => { | ||
t.equal(fetch.callCount, 2); | ||
t.deepEqual(fetch.firstCall.args[0].split('?')[1], 'content_type=ctid&locale=de-DE'); | ||
t.deepEqual(fetch.lastCall.args[0].split('?')[1], 'locale=x'); | ||
}); | ||
}); | ||
test('http-client: defaults', function (t) { | ||
@@ -40,0 +59,0 @@ t.plan(1); |
@@ -5,10 +5,12 @@ 'use strict'; | ||
const index = require('../index.js'); | ||
const index = require('..'); | ||
test('index: all functions successfully imported', function (t) { | ||
['createClient', 'prepareSpaceGraph', 'createSchema', 'createUI'].forEach(m => { | ||
['createClient', 'prepareSpaceGraph', 'createSchema'].forEach(m => { | ||
t.equal(typeof index[m], 'function'); | ||
}); | ||
t.equal(typeof index.helpers, 'object'); | ||
t.end(); | ||
}); |
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
No repository
Supply chain riskPackage does not have a linked source code repository. Without this field, a package will have no reference to the location of the source code use to generate the package.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
Major refactor
Supply chain riskPackage has recently undergone a major refactor. It may be unstable or indicate significant internal changes. Use caution when updating to versions that include significant changes.
Found 1 instance in 1 package
No repository
Supply chain riskPackage does not have a linked source code repository. Without this field, a package will have no reference to the location of the source code use to generate the package.
Found 1 instance in 1 package
70482
37
1957
223
15
Updatedgraphql@^0.9.6