contentful
Advanced tools
Comparing version 1.1.1 to 1.1.2
@@ -8,3 +8,2 @@ { | ||
"components", | ||
"Makefile", | ||
"example", | ||
@@ -11,0 +10,0 @@ "package.json", |
# Change Log | ||
All notable changes to this project will be documented in this file. | ||
## Upcoming | ||
### Added | ||
- Development dependencies `uglifyify`, `jscs`, and `exorcist`. | ||
### Changed | ||
- Ignore `node_modules` directory in git | ||
- Move from redefine to ES6 classes using babel | ||
- Update to recent version of browserify | ||
- Replace Makefile build with npm scripts | ||
- Update dist files, include sourcemaps | ||
## v1.1.1 - 2015-03-25 | ||
@@ -5,0 +16,0 @@ - Fix issue where type parameter was sent on sync requests with a sync |
@@ -14,13 +14,22 @@ 'use strict'; | ||
var mapId = 'stephanseidt.map-hhhrrit1'; | ||
var retinaMapId = 'stephanseidt.map-j9eqvtbq'; | ||
var roswellLatLng = [33.38830000000001, -104.5191]; | ||
// Google map | ||
var map; | ||
var mapStyles = [{"featureType":"administrative.locality","elementType":"all","stylers":[{"hue":"#2c2e33"},{"saturation":7},{"lightness":19},{"visibility":"on"}]},{"featureType": "poi","stylers": [{"visibility": "off"}]},{"featureType":"landscape","elementType":"all","stylers":[{"hue":"#ffffff"},{"saturation":-100},{"lightness":100},{"visibility":"simplified"}]},{"featureType":"road","elementType":"geometry","stylers":[{"hue":"#bbc0c4"},{"saturation":-53},{"lightness":31}]},{"featureType":"road","stylers":[{"hue":"#bbc0c4"},{"saturation":-93},{"lightness":31},{"visibility":"on"}]},{"featureType":"road.arterial","stylers":[{"hue":"#bbc0c4"},{"saturation":-93},{"lightness":-2},{"visibility":"simplified"}]},{"featureType":"road.local","elementType":"geometry","stylers":[{"hue":"#e9ebed"},{"saturation":-90},{"lightness":-8},{"visibility":"simplified"}]},{"featureType":"transit"},{"featureType":"water","elementType":"all","stylers":[{"hue":"#e9ebed"},{"saturation":-78},{"lightness":67},{"visibility":"simplified"}]}]; | ||
var mapOptions = { | ||
zoom: 4, | ||
center: {lat: 35.3732921, lng: -119.0187125}, | ||
panControl: false, | ||
mapTypeControl: false, | ||
streetViewControl: false, | ||
overviewMapControl: false, | ||
styles: mapStyles | ||
}; | ||
var map = L.mapbox.map('map') | ||
.setView(roswellLatLng, 12) | ||
.addLayer(L.mapbox.tileLayer(mapId, { | ||
detectRetina: true, | ||
retinaVersion: retinaMapId | ||
})); | ||
function initializeMap() { | ||
map = new google.maps.Map(document.getElementById('map'), mapOptions); | ||
} | ||
google.maps.event.addDomListener(window, 'load', initializeMap); | ||
// Angular controller | ||
function UfoController($scope, $timeout, enQ) { | ||
@@ -39,5 +48,8 @@ var query = $scope.query = { | ||
}); | ||
// search for ufo sightings | ||
$scope.update = update; | ||
function update() { | ||
// query details | ||
var q = { | ||
@@ -53,2 +65,3 @@ content_type: '7ocuA1dfoccWqWwWUY4UY', | ||
// query of entries from contentful to populate $scope.ufos | ||
$scope.ufos = enQ(client.entries(q)).then(function(ufos) { | ||
@@ -59,2 +72,3 @@ $scope.total = ufos.length; | ||
var parts = query.term.split(/\s+/).join('|'); | ||
// highlight search term in description | ||
ufo.fields.description = ufo.fields.description | ||
@@ -71,2 +85,3 @@ .replace(new RegExp(parts, 'gi'), '<em>$&</em>'); | ||
// when ufo-entries are loaded map gets centered to the first ufo | ||
$scope.$watch('ufos', function(ufos) { | ||
@@ -76,10 +91,30 @@ if (!ufos) return; | ||
$scope.ufo = ufos[0]; | ||
var markers = ufos.map(ufoToGeoJson); | ||
map.markerLayer.clearLayers(); | ||
map.markerLayer.setGeoJSON(markers); | ||
// create GeoJSON collection | ||
ufos.map(ufoToGeoJson) | ||
var json = { | ||
type: "FeatureCollection", | ||
features: ufos | ||
}; | ||
// loop through GeoJSON, create a marker for each sighting | ||
for (var i = json.features.length - 1; i >= 0; i--) { | ||
var marker = new google.maps.Marker({position: {lat: json.features[i].fields.location.lat, lng: json.features[i].fields.location.lon}, map: map, title: json.features[i].fields.locationName, ufo: json.features[i], id: i }); | ||
var infowindow = new google.maps.InfoWindow(); | ||
// handle click event on markers | ||
google.maps.event.addListener(marker, 'click', function() { | ||
$scope.position = this.id | ||
$scope.ufo = this.ufo; | ||
$scope.$apply() | ||
infowindow.setContent(this.title); | ||
infowindow.open(map, this); | ||
}); | ||
}; | ||
}); | ||
// center map to current ufo | ||
$scope.$watch('ufo', function(ufo) { | ||
if (!ufo) return; | ||
var location = [ufo.fields.location.lat, ufo.fields.location.lon]; | ||
var location = {lat: ufo.fields.location.lat, lng: ufo.fields.location.lon}; | ||
map.panTo(location); | ||
@@ -92,2 +127,3 @@ map.setZoom(12); | ||
// creates GeoJson of each ufo sighting to be shown on map | ||
function ufoToGeoJson(ufo) { | ||
@@ -105,3 +141,2 @@ return { | ||
title: ufo.fields.locationName, | ||
'marker-color': '#fc3159', | ||
ufo: ufo | ||
@@ -112,2 +147,3 @@ } | ||
// Angular directive handles up and down key input | ||
function ufo() { | ||
@@ -143,7 +179,2 @@ return { | ||
}); | ||
map.markerLayer.on('click', function(e) { | ||
scope.ufo = e.layer.feature.properties.ufo; | ||
scope.$apply(); | ||
}); | ||
} | ||
@@ -153,2 +184,3 @@ }; | ||
// Angular app bootstrap and registration of controller, directive and factory | ||
angular.module('ufos', []). | ||
@@ -172,3 +204,2 @@ | ||
}; | ||
}); | ||
}); |
350
index.js
'use strict'; | ||
var _ = require('lodash'); | ||
var axios = require('axios'); | ||
var redefine = require('redefine'); | ||
var resolveResponse = require('contentful-resolve-response'); | ||
var querystring = require('querystring'); | ||
var Client = redefine.Class({ | ||
constructor: function Client(options) { | ||
enforcep(options, 'accessToken'); | ||
enforcep(options, 'space'); | ||
this.options = _.defaults({}, options, { | ||
host: 'cdn.contentful.com', | ||
secure: true | ||
}); | ||
}, | ||
_request: function(path, query) { | ||
if (!query) query = {}; | ||
query.access_token = this.options.accessToken; | ||
var params = { | ||
headers: {}, | ||
method: 'get', | ||
url: [ | ||
this.options.secure ? 'https' : 'http', | ||
'://', | ||
_.first(this.options.host.split(':')), | ||
':', | ||
this.options.secure ? '443' : '80', | ||
'/spaces/', | ||
this.options.space, | ||
path, | ||
'?', | ||
querystring.stringify(query) | ||
].join('') | ||
}; | ||
params.headers['Content-Type'] = 'application/vnd.contentful.delivery.v1+json'; | ||
return axios(params) | ||
.then(function (response) { | ||
return response.data; | ||
}) | ||
.catch(function (error) { | ||
throw error.data; | ||
}); | ||
}, | ||
asset: function(id, callback) { | ||
return nodeify( | ||
this._request('/assets/' + id).then(Asset.parse), | ||
callback | ||
); | ||
}, | ||
assets: function(object, callback) { | ||
var query = Query.parse(object); | ||
var deferred = this._request('/assets', query) | ||
.then(_.partial(SearchResult.parse)); | ||
return nodeify(deferred, callback); | ||
}, | ||
contentType: function(id, callback) { | ||
var deferred = this._request('/content_types/' + id) | ||
.then(ContentType.parse); | ||
return nodeify(deferred, callback); | ||
}, | ||
contentTypes: function(object, callback) { | ||
var query = Query.parse(object); | ||
var deferred = this._request('/content_types', query) | ||
.then(_.partial(SearchResult.parse)); | ||
return nodeify(deferred, callback); | ||
}, | ||
entry: function(id, callback) { | ||
var deferred = this._request('/entries/' + id) | ||
.then(Entry.parse); | ||
return nodeify(deferred, callback); | ||
}, | ||
entries: function(object, callback) { | ||
var query = Query.parse(object); | ||
var deferred = this._request('/entries', query) | ||
.then(_.partial(SearchResult.parse)); | ||
return nodeify(deferred, callback); | ||
}, | ||
space: function(callback) { | ||
return nodeify(this._request(''), callback); | ||
}, | ||
_pagedSync: function (sync) { | ||
var self = this; | ||
return this._request('/sync', sync.query) | ||
.then(function (data) { | ||
sync.append(data); | ||
if(!sync.done){ | ||
return self._pagedSync(sync); | ||
} else { | ||
return { | ||
items: sync.items, | ||
nextSyncToken: sync.nextSyncToken | ||
}; | ||
} | ||
}); | ||
}, | ||
sync: function (object, callback) { | ||
if (!object || (!object.initial && !object.nextSyncToken)) { | ||
throw new Error('Please provide either the initial flag or a nextSyncToken for syncing'); | ||
} | ||
var query = Query.parse(object); | ||
var deferred = this._pagedSync(new Sync(query)) | ||
.then(function (response) { | ||
response.items = SearchResult.parse(response); | ||
return response; | ||
}); | ||
return nodeify(deferred, callback); | ||
} | ||
}); | ||
var Asset = redefine.Class({ | ||
constructor: function Asset() {}, | ||
statics: { | ||
parse: function(object) { | ||
return _.extend(new Asset(), { | ||
sys: Sys.parse(object.sys), | ||
fields: object.fields | ||
}); | ||
} | ||
} | ||
}); | ||
var Entry = redefine.Class({ | ||
constructor: function Entry() {}, | ||
statics: { | ||
parse: function(object) { | ||
return _.extend(new Entry(), { | ||
sys: Sys.parse(object.sys), | ||
fields: object.fields | ||
}); | ||
} | ||
} | ||
}); | ||
var ContentType = redefine.Class({ | ||
constructor: function ContentType() {}, | ||
statics: { | ||
parse: function(object) { | ||
return _.extend(new ContentType(), { | ||
sys: Sys.parse(object.sys), | ||
fields: object.fields.map(Field.parse), | ||
}, _.pick(object, 'name', 'displayField')); | ||
} | ||
} | ||
}); | ||
var Field = redefine.Class({ | ||
constructor: function Field() {}, | ||
statics: { | ||
parse: function(object) { | ||
return _.extend(new Field(), object); | ||
} | ||
} | ||
}); | ||
var SearchResult = redefine.Class({ | ||
constructor: function SearchResult() {}, | ||
statics: { | ||
parse: function(object) { | ||
walkMutate(object, isParseableResource, parseResource); | ||
var items = resolveResponse(object); | ||
return redefine( | ||
items, { | ||
limit: object.limit, | ||
skip: object.skip, | ||
total: object.total | ||
}, { | ||
enumerable: false | ||
} | ||
); | ||
} | ||
} | ||
}); | ||
var Query = redefine.Class({ | ||
constructor: function Query() {}, | ||
toQueryString: function() { | ||
return querystring.stringify(this); | ||
}, | ||
statics: { | ||
parse: function(object) { | ||
return _.extend(new Query(), stringifyArrayValues(object)); | ||
}, | ||
} | ||
}); | ||
var Space = redefine.Class({ | ||
constructor: function Space() {}, | ||
statics: { | ||
parse: function(object) { | ||
return _.extend(new Space(), object); | ||
} | ||
} | ||
}); | ||
var Sys = redefine.Class({ | ||
constructor: function Sys() {}, | ||
statics: { | ||
parse: function(object) { | ||
return _.extend( | ||
new Sys(), | ||
_.pick(object, 'id', 'revision', 'type', 'locale'), | ||
compacto({ | ||
contentType: object.contentType && Link.parse(object.contentType), | ||
createdAt: object.createdAt && new Date(object.createdAt), | ||
linkType: object.linkType, | ||
updatedAt: object.updatedAt && new Date(object.updatedAt), | ||
space: object.space && Link.parse(object.space) | ||
}) | ||
); | ||
} | ||
} | ||
}); | ||
var Link = redefine.Class({ | ||
constructor: function Link() {}, | ||
statics: { | ||
parse: function(object) { | ||
return _.extend(new Link(), { | ||
sys: Sys.parse(object.sys) | ||
}); | ||
} | ||
} | ||
}); | ||
var Sync = redefine.Class({ | ||
constructor: function Sync(query) { | ||
this.query = query; | ||
this.items = []; | ||
this.done = false; | ||
}, | ||
append: function (data) { | ||
this.items = this.items.concat(data.items); | ||
if(data.nextPageUrl){ | ||
var nextPageUrl = data.nextPageUrl.split('?'); | ||
this.query = _.omit(this.query, 'initial', 'type', 'sync_token'); | ||
this.query.sync_token = querystring.parse(nextPageUrl[1]).sync_token; | ||
} else if(data.nextSyncUrl){ | ||
var nextSyncUrl = data.nextSyncUrl.split('?'); | ||
this.nextSyncToken = querystring.parse(nextSyncUrl[1]).sync_token; | ||
this.done = true; | ||
} | ||
} | ||
}); | ||
exports.createClient = function(options) { | ||
return new Client(options || {}); | ||
}; | ||
function exists(value) { | ||
return value != null; | ||
try { | ||
module.exports = require('./index.es5.js'); | ||
} catch (e) { | ||
require('babel/register')(); | ||
module.exports = require('./index.es6.js'); | ||
} | ||
function truthy(value) { | ||
return (value !== false) && exists(value); | ||
} | ||
function compacto(object) { | ||
return _.reduce(object, function(compacted, value, key) { | ||
if (truthy(value)) compacted[key] = value; | ||
return compacted; | ||
}, {}); | ||
} | ||
function enforcep(object, property) { | ||
if (!exists(object[property])) | ||
throw new TypeError('Expected property ' + property); | ||
} | ||
var parseableResourceTypes = { | ||
Asset: Asset, | ||
ContentType: ContentType, | ||
Entry: Entry, | ||
Space: Space | ||
}; | ||
function isParseableResource(object) { | ||
return _.isObject(object) && _.isObject(object.sys) && 'type' in object.sys && | ||
object.sys.type in parseableResourceTypes; | ||
} | ||
function parseResource(resource) { | ||
var Type = parseableResourceTypes[resource.sys.type]; | ||
return Type.parse(resource); | ||
} | ||
function stringifyArrayValues(object) { | ||
return _.reduce(object, function(object, value, key) { | ||
object[key] = _.isArray(value) ? value.join(',') : value; | ||
return object; | ||
}, {}); | ||
} | ||
function walkMutate(input, pred, mutator) { | ||
if (pred(input)) | ||
return mutator(input); | ||
if (_.isArray(input) || _.isObject(input)) { | ||
_.each(input, function(item, key) { | ||
input[key] = walkMutate(item, pred, mutator); | ||
}); | ||
return input; | ||
} | ||
return input; | ||
} | ||
function nodeify(deferred, callback) { | ||
if(callback) { | ||
return deferred | ||
.then(function (response) { | ||
callback(null, response); | ||
return response; | ||
}) | ||
.catch(function (error) { | ||
callback(error); | ||
throw error; | ||
}); | ||
} | ||
return deferred; | ||
} |
{ | ||
"name": "contentful", | ||
"description": "Client for Contentful's Content Delivery API", | ||
"version": "1.1.1", | ||
"version": "1.1.2", | ||
"homepage": "https://www.contentful.com/developers/documentation/content-delivery-api/", | ||
"main": "index.js", | ||
"browser": "index.es5.js", | ||
"repository": "git@github.com:contentful/contentful.js.git", | ||
@@ -12,19 +13,27 @@ "author": "Stephan Seidt <stephan@contentful.com>", | ||
"axios": "^0.5.2", | ||
"contentful-resolve-response": "~0.1.0", | ||
"lodash": "~2.4.1", | ||
"redefine": "~0.2.0" | ||
"contentful-resolve-response": "^0.1.1" | ||
}, | ||
"devDependencies": { | ||
"babel": "^4.7.16", | ||
"babelify": "^6.0.1", | ||
"bluebird": "^2.0.0", | ||
"browserify": "^9.0.6", | ||
"buster": "~0.7.6", | ||
"bluebird": "^2.0.0", | ||
"envify": "~1.0.1", | ||
"exorcist": "^0.1.6", | ||
"jscs": "^1.12.0", | ||
"lodash": "~2.4.1", | ||
"saucie": "^0.1.0", | ||
"testem": "~0.6.2", | ||
"browserify": "~3.20.0", | ||
"saucie": "^0.1.0" | ||
"uglifyify": "^3.0.1" | ||
}, | ||
"scripts": { | ||
"jscs": "jscs --esnext index.es6.js", | ||
"bower-build": "browserify -s contentful --debug -t [ babelify --sourceMapRelative . ] -t uglifyify index.es6.js | exorcist dist/contentful.min.js.map > dist/contentful.min.js", | ||
"prepublish": "babel index.es6.js -s -o index.es5.js", | ||
"watch": "babel index.es6.js -s -w -o index.es5.js", | ||
"prepare-browser-test": "browserify -d -t envify -x buster test/helper.js > test/bundle-helper.js", | ||
"ci": "testem ci -P 6", | ||
"test": "testem" | ||
"ci": "testem ci -P 6 && npm run jscs", | ||
"test": "testem && npm run jscs" | ||
} | ||
} |
396
README.md
@@ -5,3 +5,3 @@ # contentful.js [![Build Status](https://travis-ci.org/contentful/contentful.js.png?branch=master)](https://travis-ci.org/contentful/contentful.js) | ||
- [Documentation](https://www.contentful.com/developers/documentation/content-delivery-api) | ||
- [Documentation](#api) | ||
- [Example Apps](http://contentful.github.io/contentful.js/example/) | ||
@@ -40,4 +40,6 @@ - [Tests](https://github.com/contentful/contentful.js/tree/master/test/integration) running in node and browsers via [BrowserStack](http://browserstack.com) | ||
## Usage | ||
## API | ||
### createClient(opts) -> Client | ||
``` js | ||
@@ -60,46 +62,378 @@ // Don't require if you've already included contentful as a script tag | ||
}); | ||
``` | ||
var log = console.log.bind(console); // wat | ||
### Client#space() -> SpacePromise | ||
// Get Space | ||
client.space().then(log, log); | ||
```js | ||
client.space() | ||
``` | ||
// Get all Entries | ||
client.entries().then(log, log); | ||
Returns a promise for a Space object: | ||
// Get Assets using callback interface | ||
client.entries({}, function(err, entries) { | ||
if (err) { console.log(err); return; } | ||
console.log(entries); | ||
}); | ||
```js | ||
{ | ||
"sys": { | ||
"type": "Space", | ||
"id": "cfexampleapi" | ||
}, | ||
"name": "Contentful Example API", | ||
"locales": [ | ||
{"code": "en-US", "name": "English"}, | ||
{"code": "tlh", "name": "Klingon"} | ||
] | ||
} | ||
``` | ||
var syncToken; | ||
// Get all data in a space | ||
client.sync({initial: true}) | ||
.then(function(data){ | ||
syncToken = data.nextSyncToken; | ||
}); | ||
### Client#entry(id) -> EntryPromise | ||
// Get all data since the last sync | ||
client.sync({nextSyncToken: syncToken}) | ||
.then(function(data){ | ||
syncToken = data.nextSyncToken; | ||
Get an entry by it's `sys.id`. Note that this example uses an entry created | ||
with a human-readable ID via the [Content Management API][cma-entry-put]. | ||
Entries created in the [Contentful app][cf-app] will have auto-generated ID's. | ||
```js | ||
client.entry('nyancat') | ||
``` | ||
Returns a promise for an Entry object: | ||
```js | ||
{ | ||
"sys": { | ||
"type": "Entry", | ||
"id": "cat", | ||
"space": {"sys": {"type": "Link", "linkType": "Space", "id": "example"}}, | ||
"contentType": {"sys": {"type": "Link", "linkType": "ContentType", "id": "cat"}}, | ||
"createdAt": "2013-03-26T00:13:37.123Z", | ||
"updatedAt": "2013-03-26T00:13:37.123Z", | ||
"revision": 1 | ||
}, | ||
"fields": { | ||
"name": "Nyan cat", | ||
"color": "Rainbow", | ||
"nyan": true, | ||
"birthday": "2011-04-02T00:00:00.000Z", | ||
"diary": "Nyan cat has an epic rainbow trail.", | ||
"likes": ["rainbows", "fish"], | ||
"bestFriend": {"type": "Link", "linkType": "Entry", "id": "happycat"} | ||
} | ||
} | ||
``` | ||
### Client#entries(query) -> EntryCollectionPromise | ||
Search & filter all of the entries in a space. The `query` parameter will be | ||
added to the request querystring key-value pairs. | ||
```js | ||
client.entries({ content_type: 'cat' }) | ||
``` | ||
Returns a promise for a [collection][] of Entry objects: | ||
```js | ||
{ | ||
"sys": { | ||
"type": "Array" | ||
}, | ||
"total": 2, | ||
"skip": 0, | ||
"limit": 100, | ||
"items": [ | ||
/* Each item in the array is a full Entry object as shown above */ | ||
] | ||
} | ||
``` | ||
#### Search Examples | ||
These examples show some of the searching you can do by passing query params | ||
to [`Client#entries`][client-entries]. Each | ||
query parameter name must be a dot-separated property path followed by an | ||
optional operator in square brackets. For example: `fields.name[ne]` means | ||
"entries where `fields.name` is not-equal to ...". Full documentation of the | ||
allowed query parameters & field operators can be found in | ||
[our API Documentation][search-parameters]. | ||
Search entries that have been updated since the 1st of January, 2013: | ||
```js | ||
client.entries({ 'sys.updatedAt[gte]': '2013-01-01T00:00:00Z' }) | ||
``` | ||
Retrieve a specific set of entries by their `sys.id`: | ||
```js | ||
client.entries({ 'sys.id[in]': [ 'finn', 'jake' ] }) | ||
``` | ||
Search for `cat` entries that have less than three lives left: | ||
```js | ||
client.entries({ | ||
'content_type': 'cat', | ||
'fields.lives[lt]': 3 | ||
}) | ||
``` | ||
> Specifying the `content_type` query parameter is _required_ when querying on | ||
> fields (such as `fields.lives` above). Note that `'cat'` is the content type | ||
> **ID** and not it's name. | ||
Full-text search for entries with "bacon" anywhere in their textual content: | ||
```js | ||
client.entries({ query: 'bacon' }) | ||
``` | ||
Full-text search for dogs with "bacon" specifically in the `description` field: | ||
```js | ||
client.entries({ | ||
'content_type': 'dog', | ||
'fields.description[match]': 'bacon' | ||
}) | ||
``` | ||
Get the 50 most recently created entries, and the next 50: | ||
```js | ||
client.entries({ | ||
order: '-sys.createdAt', | ||
limit: 50 | ||
}) | ||
client.entries({ | ||
order: '-sys.createdAt', | ||
skip: 50, | ||
limit: 50 | ||
}) | ||
``` | ||
See also: [Collections and pagination][collection]. | ||
### Client#asset(id) -> Asset | ||
Get an asset by it's `sys.id`. Note that this example uses an entry created | ||
with a human-readable ID via the [Content Management API][cma-asset-put]. | ||
Assets created in the [Contentful app][cf-app] will have auto-generated ID's. | ||
```js | ||
client.asset('nyancat') | ||
``` | ||
Returns a promise for an Asset object: | ||
```js | ||
{ | ||
"sys": { | ||
"type": "Asset", | ||
"id": "nyancat", | ||
"space": {"sys": {"type": "Link", "linkType": "Space", "id": "example"}}, | ||
"createdAt": "2013-03-26T00:13:37.123Z", | ||
"updatedAt": "2013-03-26T00:13:37.123Z", | ||
"revision": 1 | ||
}, | ||
"fields": { | ||
"title": "Nyan cat", | ||
"description": "A typical picture of Nyancat including the famous rainbow trail.", | ||
"file": { | ||
"fileName": "nyancat.png", | ||
"contentType": "image/png", | ||
"details": { | ||
"image": { | ||
"width": 250, | ||
"height": 250 | ||
}, | ||
"size": 12273 | ||
}, | ||
"url": "//images.contentful.com/cfexampleapi/4gp6taAwW4CmSgumq2ekUm/9da0cd1936871b8d72343e895a00d611/Nyan_cat_250px_frame.png" | ||
} | ||
} | ||
} | ||
``` | ||
### Client#assets(query) -> AssetCollectionPromise | ||
Search & filter all of the assets in a space. The keys-value pairs from `query` | ||
will be added to the request query string like [`Client#entries(query)`][client-entries]. | ||
See the [`Client#entries(query)` search examples](#search-examples) for more details. | ||
```js | ||
client.assets({ query: 'kitten' }) | ||
``` | ||
Returns a promise for a [collection][] of Asset objects: | ||
```js | ||
{ | ||
"sys": { | ||
"type": "Array" | ||
}, | ||
"total": 2, | ||
"skip": 0, | ||
"limit": 100, | ||
"items": [ | ||
/* Each item in the array is a full Asset object as shown above */ | ||
] | ||
} | ||
``` | ||
### Client#contentType(id) -> ContentTypePromise | ||
Get a content type by it's `sys.id`. Note that this example uses a content type | ||
created with a human-readable ID via the [Content Management API][cma-ct-put]. | ||
Content types created in the [Contentful app][cf-app] will have auto-generated | ||
ID's. | ||
```js | ||
client.contentType('cat') | ||
``` | ||
Returns a promise for a ContentType object: | ||
```js | ||
{ | ||
"sys": { | ||
"type": "ContentType", | ||
"id": "cat" | ||
}, | ||
"name": "Cat", | ||
"description": "Meow.", | ||
"fields": [ | ||
{"id": "name", "name": "Name", "type": "Text"}, | ||
{"id": "diary", "name": "Diary", "type": "Text"}, | ||
{"id": "likes", "name": "Likes", "type": "Array", "items": {"type": "Symbol"}}, | ||
{"id": "bestFriend", "name": "Best Friend", "type": "Link"}, | ||
{"id": "lifes", "name": "Lifes left", "type": "Integer"} | ||
] | ||
} | ||
``` | ||
### Client#contentTypes() -> ContentTypeCollectionPromise | ||
```js | ||
client.contentTypes() | ||
``` | ||
Returns a promise for a [collection][] of ContentType objects: | ||
```js | ||
{ | ||
"sys": { | ||
"type": "Array" | ||
}, | ||
"total": 3, | ||
"skip": 0, | ||
"limit": 100, | ||
"items": [ | ||
/* Each item in the array is a full ContentType object as shown above */ | ||
] | ||
} | ||
``` | ||
### Client#sync(opts) -> SyncResponse | ||
Our [Sync API][sync-api] allows to keep a local copy of the data in your space | ||
up to date by receiving delta updates. | ||
There are two supported options, pass `{ initial: true }` to start a brand new | ||
copy, or `{ syncToken: syncToken }` resume syncing using a token returned in a | ||
previous call to `sync`. | ||
Here is an example of syncing some local store: | ||
```js | ||
// E.g. by loading the token from persistent storage | ||
var syncToken = getTokenFromLastRun() | ||
client.sync(token ? {syncToken: syncToken} : {initial: true}).then(function(data){ | ||
data.items.forEach(updateLocalCopy) | ||
if (syncToken !== data.nextSyncToken) { | ||
syncToken = data.nextSyncToken; | ||
return client.sync({syncToken: syncToken}) | ||
} | ||
}); | ||
``` | ||
For now, please check out the | ||
[Content Delivery API documentation](https://www.contentful.com/developers/documentation/content-delivery-api) | ||
to learn how the API and the JavaScript client work. | ||
Each call to `sync` returns a SyncResponse object: | ||
## Functionality | ||
``` | ||
{ | ||
"sys": { | ||
"type": "Array" | ||
}, | ||
"total": 3, | ||
"skip": 0, | ||
"limit": 100, | ||
"items": [ | ||
/* Each item in the array is either an Entry, Asset, DeletedEntry or DeletedAsset */ | ||
] | ||
} | ||
``` | ||
### supported | ||
In addition the entries and assets, a sync response may contain deletion items: | ||
* .space() = get details of current space | ||
* .contentTypes() = get content types of current space | ||
* .entries() = get entries of current space | ||
* .sync() = get all the data in a space | ||
```js | ||
{ | ||
"sys": { | ||
"type": "DeletedEntry", | ||
"id": "cat", | ||
"space": {"sys": {"type": "Link", "linkType": "Space", "id": "example"}}, | ||
"contentType": {"sys": {"type": "Link", "linkType": "ContentType", "id": "cat"}}, | ||
"createdAt": "2013-03-26T00:13:37.123Z", | ||
"updatedAt": "2013-03-26T00:13:37.123Z" | ||
}, | ||
} | ||
``` | ||
```js | ||
{ | ||
"sys": { | ||
"type": "DeletedAsset", | ||
"id": "nyancat", | ||
"space": {"sys": {"type": "Link", "linkType": "Space", "id": "example"}}, | ||
"createdAt": "2013-03-26T00:13:37.123Z", | ||
"updatedAt": "2013-03-26T00:13:37.123Z" | ||
}, | ||
} | ||
``` | ||
### Collections and pagination | ||
Many methods return collections of resources. These collections are represented | ||
as a JSON object containing items and pagination details: | ||
``` | ||
{ | ||
"sys": { | ||
"type": "Array" | ||
}, | ||
"total": 1, // Total number of items matching the query | ||
"skip": 0, // Offset into the result set represented by this response | ||
"limit": 100, // Effective limit on # of items returned in this response | ||
"items": [ | ||
// Full representations of each item | ||
] | ||
} | ||
``` | ||
The `entries` and `assets` methods both accept `limit`, `skip`, and `order` as | ||
query parameters, allowing you to paginate through larger result sets. Note that | ||
you should specify a stable `order` property (such as `order: 'sys.createdAt'`) | ||
when paginating. | ||
## License | ||
MIT | ||
[contentful]: http://www.contentful.com | ||
[search-parameters]: http://docs.contentfulcda.apiary.io/#reference/search-parameters | ||
[cma-entry-put]: http://docs.contentfulcma.apiary.io/#reference/entries/entry/create/update-an-entry | ||
[cma-asset-put]: http://docs.contentfulcma.apiary.io/#reference/assets/asset/create/update-an-asset | ||
[cma-ct-put]: http://docs.contentfulcma.apiary.io/#reference/content-types/content-type/create/update-a-content-type | ||
[cf-app]: https://app.contentful.com | ||
[sync-api]: http://docs.contentfulcda.apiary.io/#reference/synchronization | ||
[collection]: #collections-and-pagination | ||
[client-entries]: #cliententriesquery---entrycollectionpromise |
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is too big to display
Sorry, the diff of this file is too big to display
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
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
New author
Supply chain riskA new npm collaborator published a version of the package for the first time. New collaborators are usually benign additions to a project, but do indicate a change to the security surface area of a package.
Found 1 instance in 1 package
Uses eval
Supply chain riskPackage uses dynamic code execution (e.g., eval()), which is a dangerous practice. This can prevent the code from running in certain environments and increases the risk that the code may contain exploits or malicious behavior.
Found 1 instance in 1 package
Environment variable access
Supply chain riskPackage accesses environment variables, which may be a sign of credential stuffing or data theft.
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
Uses eval
Supply chain riskPackage uses dynamic code execution (e.g., eval()), which is a dangerous practice. This can prevent the code from running in certain environments and increases the risk that the code may contain exploits or malicious behavior.
Found 1 instance in 1 package
Minified code
QualityThis package contains minified code. This may be harmless in some cases where minified code is included in packaged libraries, however packages on npm should not minify code.
Found 1 instance in 1 package
614094
2
34
13377
0
437
4
12
- Removedlodash@~2.4.1
- Removedredefine@~0.2.0
- Removedlodash@2.4.2(transitive)
- Removedredefine@0.2.1(transitive)