Skip to content

Commit

Permalink
Merge a020b87 into ffe7993
Browse files Browse the repository at this point in the history
  • Loading branch information
jescalan committed Mar 7, 2017
2 parents ffe7993 + a020b87 commit 2dbae6e
Show file tree
Hide file tree
Showing 5 changed files with 58 additions and 4 deletions.
23 changes: 19 additions & 4 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,14 @@ remote data -> static templates
## Why should you care?

Static is the best, but sometimes you need to fetch data from a remote source which makes things not so static. Spike Records is a little webpack plugin intended for use with [spike](https://github.com/static-dev/spike) which allows you to make locals pulled from a JSON file or url returning JSON available as static locals in your jade templates.
Static is the best, but sometimes you need to fetch data from a remote source which makes things not so static. Spike Records is a little webpack plugin intended for use with [spike](https://github.com/static-dev/spike) which allows you to make data pulled from a file or url available in your view templates.

It can pull data from the following places:

- A javascript object
- A file containing a javascript object or JSON
- A URL that returns JSON
- A [GraphQL](http://graphql.org) endpoint

## Installation

Expand All @@ -34,9 +41,9 @@ module.exports = {

The primary use case for spike-records is to inject local variables into your html templates, although technically it can be used for anything. In the example above, we use the [reshape-standard](https://github.com/reshape/standard) plugin pack to add variables (among other functionality) to your html. Spike's default template also uses `reshape-standard`.

In order to use the results from spike-records, you must pass it an object, which it will put the resolved data on, using the `addDataTo` key. This plugin runs very early in spike's compile process, so by the time templates are being compiled, the object will have all the data necessary on it. If you are using the data with other plugins, ensure that spike-records is the first plugin in the array.
In order to use the results from spike-records, you must pass it an object, which it will put the resolved data on, using the `addDataTo` key. This plugin runs early in spike's compile process, so by the time templates are being compiled, the object will have all the data necessary on it. If you are using the data with other plugins, ensure that spike-records is the first plugin in the array.

I know this is an unusual pattern for a javascript library, but the way it works is very effective in this particular system, and affords a lot of flexibility and power.
I know this is an unusual pattern for a javascript library, but the way it works is quite effective in this particular system, and affords a lot of flexibility and power.

The records plugin accepts an object, and each key in the object (other than `addDataTo`) should contain another object as it's value, with either a `file`, `url`, or `data` property. For example:

Expand All @@ -47,7 +54,15 @@ new Records({
addDataTo: locals,
one: { file: 'data.json' },
two: { url: 'http://api.carrotcreative.com/staff' },
three: { data: { foo: 'bar' } }
three: { data: { foo: 'bar' } },
four: {
graphql: {
url: 'http://localhost:1234',
query: 'query { allPosts { title } }',
variables: 'xxx', // optional
headers: { authorization: 'Bearer xxx' } // optional
}
}
})
```

Expand Down
14 changes: 14 additions & 0 deletions lib/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,7 @@ function run (compiler, compilation, done) {
for (const k in this.opts) {
if (this.opts[k].data) { tasks[k] = renderData(this.opts[k]) }
if (this.opts[k].url) { tasks[k] = renderUrl(this.opts[k]) }
if (this.opts[k].graphql) { tasks[k] = renderGraphql(this.opts[k]) }
if (this.opts[k].file) {
tasks[k] = renderFile(compiler.options.context, this.opts[k])
}
Expand Down Expand Up @@ -109,6 +110,19 @@ function renderUrl (obj) {
return rest(obj.url).then((res) => { return JSON.parse(res.entity) })
}

function renderGraphql (obj) {
const headers = Object.assign({ 'Content-Type': 'application/json' }, obj.graphql.headers)

return rest({
path: obj.graphql.url,
entity: JSON.stringify({
query: obj.graphql.query,
variables: obj.graphql.variables
}),
headers
}).then((res) => { return JSON.parse(res.entity) })
}

/**
* If the user provided a transform function for a given data source, run the
* function and return the transformed data. Otherwise, return the data as it
Expand Down
Empty file added test/fixtures/graphql/app.js
Empty file.
1 change: 1 addition & 0 deletions test/fixtures/graphql/index.sgr
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
p {{ test.data.allCakes[0].image.url }}
24 changes: 24 additions & 0 deletions test/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,30 @@ test('loads a url correctly', (t) => {
})
})

test('loads a graphql endpoint correctly', (t) => {
const locals = {}
return compileAndCheck({
fixture: 'graphql',
locals: locals,
config: {
addDataTo: locals,
test: {
graphql: {
url: 'https://api.graphcms.com/simple/v1/cizc7giha88sc0159irzllhl2',
query: '{ allCakes { image { url } } }',
headers: {
'Authorization': 'Bearer eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJpYXQiOjE0ODg4NjM5ODMsImNsaWVudElkIjoiY2l2Z29zNmNqMDE5MjAxODRucDAxZGRkMiIsInByb2plY3RJZCI6ImNpemM3Z2loYTg4c2MwMTU5aXJ6bGxobDIiLCJwZXJtYW5lbnRBdXRoVG9rZW5JZCI6ImNpenozNjlxcm0zY3QwMTMzNGphY3lpYTYifQ.DVofROGTyUfpbot1HDXURT1uKLzTsJ7ly_p61ITAqY4'
}
}
}
},
verify: (_, publicPath, cb) => {
const out = fs.readFileSync(path.join(publicPath, 'index.html'), 'utf8')
t.regex(out, /media\.graphcms\.com/)
}
})
})

test('transform option works', (t) => {
const locals = {}
return compileAndCheck({
Expand Down

0 comments on commit 2dbae6e

Please sign in to comment.