Skip to content

Commit

Permalink
Add local caching
Browse files Browse the repository at this point in the history
  • Loading branch information
tmilewski committed Jul 11, 2016
1 parent 72c847c commit cf462ae
Show file tree
Hide file tree
Showing 13 changed files with 170 additions and 4 deletions.
56 changes: 52 additions & 4 deletions lib/index.coffee
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
_ = require 'lodash'
W = require 'when'
S = require 'string'
fs = require 'fs'
path = require 'path'
contentful = require 'contentful'
pluralize = require 'pluralize'
Expand Down Expand Up @@ -84,18 +85,41 @@ module.exports = (opts) ->
res
, []

###*
* Checks if a file or directory exists
* @param {String} path - File or directory path
* @return {Boolean} - returns success/failure
###

fsExistsSync = (path) ->
try
fs.accessSync(path, fs.F_OK)
true
catch e
false

###*
* Fetches data from Contentful for content types, and formats the raw data
* Stores/fetches content locally if requested
* @param {Array} types - configured content_type objects
* @return {Promise} - returns formatted locals object with all content
###

get_all_content = (types) ->
fs.mkdirSync(opts.cache) if opts.cache && !fsExistsSync(opts.cache)

W.map types, (t) ->
fetch_content(t)
.then(format_content)
.then((c) -> t.content = c)
.yield(t)
if opts.cache && fsExistsSync("#{opts.cache}/#{t.id}.json")
fetch_content_from_file(t)
.then(format_content)
.then((c) -> t.content = c)
.yield(t)
else
fetch_content(t)
.then((c) -> record_content(c, t))
.then(format_content)
.then((c) -> t.content = c)
.yield(t)

###*
* Fetch entries for a single content type object
Expand All @@ -110,6 +134,30 @@ module.exports = (opts) ->
)
)

###*
* Fetch entries for a single content type object from a local JSON file
* @param {Object} type - content type object
* @return {Promise} - returns response from JSON file
###

fetch_content_from_file = (type) ->
contents = fs.readFileSync "#{opts.cache}/#{type.id}.json"
W(JSON.parse(contents))

###*
* Records content from Contentful into JSON files
* @param {Object} content - entries API response for a content type
* @param {Object} type - content type object
* @return {Promise} - passes content through
###

record_content = (content, type) ->
if opts.cache
fs.writeFile "#{opts.cache}/#{type.id}.json", JSON.stringify(content), (err,data) ->
throw err if err

content

###*
* Formats raw response from Contentful
* @param {Object} content - entries API response for a content type
Expand Down
4 changes: 4 additions & 0 deletions readme.md
Original file line number Diff line number Diff line change
Expand Up @@ -120,6 +120,10 @@ Required. Your Contentful Delivery access token (API key).

Required. The space ID containing the content you wish to retrieve.

#### cache

Optional. (String) Allows you to cache responses from Contentful's API. The value is the path to the directory you intend to store the data in. Ex: `./contentful-data`

#### preview

Optional. (Boolean) Allows you use the Contentful Preview API. Also able to be accessed by setting the environment variable `CONTENTFUL_ENV` to `"develop"` (preview api) or `"production"` (default cdn).
Expand Down
1 change: 1 addition & 0 deletions test/fixtures/cache/about.jade
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
h1 wow
19 changes: 19 additions & 0 deletions test/fixtures/cache/app.coffee
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
contentful = require '../../..'

module.exports =
ignores: ["**/_*", "**/.DS_Store"]
extensions: [
contentful(
cache: './test/fixtures/cache/data'
access_token: 'YOUR_ACCESS_TOKEN'
space_id: 'aqzq2qya2jm4'
content_types: [
{
id: '6BYT1gNiIEyIw8Og8aQAO6'
}
{
id: '7CDlVsacqQc88cmIEGYWMa'
}
]
)
]
5 changes: 5 additions & 0 deletions test/fixtures/cache/index.jade
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
ul
- for p in contentful.blog_posts
li
h1= p.title
p= p.body
6 changes: 6 additions & 0 deletions test/fixtures/cache/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
{
"name": "test",
"dependencies": {
"jade": "*"
}
}
1 change: 1 addition & 0 deletions test/fixtures/cache_use/about.jade
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
h1 wow
19 changes: 19 additions & 0 deletions test/fixtures/cache_use/app.coffee
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
contentful = require '../../..'

module.exports =
ignores: ["**/_*", "**/.DS_Store"]
extensions: [
contentful(
cache: './test/fixtures/cache_use/data'
access_token: 'YOUR_ACCESS_TOKEN'
space_id: 'aqzq2qya2jm4'
content_types: [
{
id: '6BYT1gNiIEyIw8Og8aQAO6'
}
{
id: '7CDlVsacqQc88cmIEGYWMa'
}
]
)
]
1 change: 1 addition & 0 deletions test/fixtures/cache_use/data/6BYT1gNiIEyIw8Og8aQAO6.json
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
[{"fields":{"title":"Throw Some Ds","body":"Rich Boy selling crick"}}]
1 change: 1 addition & 0 deletions test/fixtures/cache_use/data/7CDlVsacqQc88cmIEGYWMa.json
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
[{"fields":{"title":"Throw Some Ds","body":"Rich Boy selling crick"}}]
5 changes: 5 additions & 0 deletions test/fixtures/cache_use/index.jade
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
ul
- for p in contentful.blog_posts
li
h1= p.title
p= p.body
6 changes: 6 additions & 0 deletions test/fixtures/cache_use/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
{
"name": "test",
"dependencies": {
"jade": "*"
}
}
50 changes: 50 additions & 0 deletions test/test.coffee
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ path = require 'path'

compile_fixture = (fixture_name, done) ->
@public = path.join(fixture_name, 'public')
@data = path.join(fixture_name, 'data')
h.project.compile(Roots, fixture_name)

mock_contentful = (opts = {}) ->
Expand Down Expand Up @@ -74,6 +75,55 @@ describe 'contentful content type fields', ->

after -> unmock_contentful()

describe 'create cache', ->
before (done) ->
@title = 'Throw Some Ds'
@body = 'Rich Boy selling crick'
mock_contentful(entries: [{fields: {title: @title, body: @body}}])
compile_fixture.call(@, 'cache').then(-> done()).catch(done)

it 'compiles basic project', ->
p = path.join(@public, 'index.html')
h.file.exists(p).should.be.ok

it 'creates the data directory', ->
p = path.join(@data)
h.file.exists(p).should.be.ok

it 'creates the data json', ->
p = path.join(@data, '6BYT1gNiIEyIw8Og8aQAO6.json')
h.file.exists(p).should.be.ok

h.file.contains(p, @title).should.be.true
h.file.contains(p, @body).should.be.true

it 'has contentful data available in views', ->
p = path.join(@public, 'index.html')
h.file.contains(p, @title).should.be.true
h.file.contains(p, @body).should.be.true

after ->
h.project.remove_folders('**/data/')
unmock_contentful()

describe 'use cache', ->
before (done) ->
@title = 'Throw Some Ds'
@body = 'Rich Boy selling crick'
mock_contentful(entries: [{fields: {title: @title, body: @body}}])
compile_fixture.call(@, 'cache_use').then(-> done()).catch(done)

it 'compiles basic project', ->
p = path.join(@public, 'index.html')
h.file.exists(p).should.be.ok

it 'has contentful data available in views', ->
p = path.join(@public, 'index.html')
h.file.contains(p, @title).should.be.true
h.file.contains(p, @body).should.be.true

after -> unmock_contentful()

describe 'basic compile', ->
before (done) ->
@title = 'Throw Some Ds'
Expand Down

0 comments on commit cf462ae

Please sign in to comment.