Comparing version 0.7.1 to 0.8.0
import falcorPathParser from 'falcor-path-syntax'; | ||
import { reject } from 'bluebird'; | ||
import * as Promise from 'bluebird'; | ||
import concat from 'lodash/concat'; | ||
import filter from 'lodash/filter'; | ||
import keys from 'lodash/keys'; | ||
import map from 'lodash/map'; | ||
import isArray from 'lodash/isArray'; | ||
import isEmpty from 'lodash/isEmpty'; | ||
import kebabCase from 'lodash/kebabCase'; | ||
import pullAll from 'lodash/pullAll'; | ||
import snakeCase from 'lodash/snakeCase'; | ||
import uniq from 'lodash/uniq'; | ||
import camelCase from 'lodash/camelCase'; | ||
import concat from 'lodash/concat'; | ||
import get from 'lodash/get'; | ||
import head from 'lodash/head'; | ||
import isArray from 'lodash/isArray'; | ||
import isEmpty from 'lodash/isEmpty'; | ||
import isFunction from 'lodash/isFunction'; | ||
import isNil from 'lodash/isNil'; | ||
import keys from 'lodash/keys'; | ||
import map from 'lodash/map'; | ||
import pullAll from 'lodash/pullAll'; | ||
import reject$1 from 'lodash/reject'; | ||
import some from 'lodash/some'; | ||
import uniq from 'lodash/uniq'; | ||
@@ -37,8 +39,136 @@ var DEFAULT_FROM_INDEX = 0; | ||
var moments = ['id', 'description', 'title', 'user.name', 'cover_image_media.id', 'cover_image_media.src']; | ||
var reviews = ['id', 'rating']; | ||
var tourTipViews = ['id', 'state']; | ||
var review = ['id', 'rating']; | ||
var tourTipView = ['id', 'state']; | ||
var name = 'comment'; | ||
var pluralName = 'comments'; | ||
var comment = Object.freeze({ | ||
name: name, | ||
pluralName: pluralName | ||
}); | ||
function buildProperties$1(defaults, options) { | ||
var properties = concat([], options.properties || defaults); | ||
var toAnd = options.andProperties; | ||
if (isArray(toAnd) && !isEmpty(toAnd)) { | ||
properties = concat(properties, toAnd); | ||
} | ||
var toNot = options.notProperties; | ||
if (isArray(toNot) && !isEmpty(toNot)) { | ||
properties = pullAll(properties, toNot); | ||
} | ||
properties = uniq(properties); | ||
return properties; | ||
} | ||
function entityToFilename(entity) { | ||
return kebabCase(entity.name); | ||
} | ||
function entityToFalcorRootLeaf(entity) { | ||
return snakeCase(entity.pluralName); | ||
} | ||
function getOne$2(entity) { | ||
var options = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {}; | ||
var id = options.id; | ||
var defaultProperties = entity.defaultProperties; | ||
var properties = buildProperties$1(defaultProperties, options); | ||
var rootLeaf = entityToFalcorRootLeaf(entity); | ||
var getPaths = properties.map(function (property) { | ||
var path = falcorPathParser(property); | ||
return concat([rootLeaf, id], path); | ||
}); | ||
return getPaths; | ||
} | ||
function update$1(entity) { | ||
var options = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {}; | ||
var id = options.id; | ||
var properties = filter(keys(options), function (key) { | ||
return key !== 'id'; | ||
}); | ||
var rootLeaf = entityToFalcorRootLeaf(entity); | ||
var valuePaths = map(properties, function (property) { | ||
return { path: [rootLeaf, id, property], value: options[property] }; | ||
}); | ||
return valuePaths; | ||
} | ||
function destroy$1(entity) { | ||
var options = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {}; | ||
var id = options.id; | ||
var rootLeaf = entityToFalcorRootLeaf(entity); | ||
var destroyPath = [rootLeaf, id, 'delete']; | ||
return destroyPath; | ||
} | ||
var name$1 = 'moment'; | ||
var pluralName$1 = 'moments'; | ||
var defaultProperties = ['id', 'description', 'title', 'user.name', 'cover_image_media.id', 'cover_image_media.src']; | ||
function getOne$1(options) { | ||
var paths = getOne$2({ defaultProperties: defaultProperties, pluralName: pluralName$1 }, options); | ||
return paths; | ||
} | ||
var moment$1 = Object.freeze({ | ||
name: name$1, | ||
pluralName: pluralName$1, | ||
defaultProperties: defaultProperties, | ||
getOne: getOne$1 | ||
}); | ||
var name$2 = 'review'; | ||
var pluralName$2 = 'reviews'; | ||
var defaultProperties$1 = ['id', 'rating']; | ||
var review$1 = Object.freeze({ | ||
name: name$2, | ||
pluralName: pluralName$2, | ||
defaultProperties: defaultProperties$1 | ||
}); | ||
var name$3 = 'tourTipView'; | ||
var pluralName$3 = 'tourTipViews'; | ||
var defaultProperties$2 = ['id', 'state']; | ||
var tourTipView$1 = Object.freeze({ | ||
name: name$3, | ||
pluralName: pluralName$3, | ||
defaultProperties: defaultProperties$2 | ||
}); | ||
var entities = Object.freeze({ | ||
comment: comment, | ||
moment: moment$1, | ||
review: review$1, | ||
tourTipView: tourTipView$1 | ||
}); | ||
var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }(); | ||
@@ -50,15 +180,2 @@ | ||
// TODO: Use destructuring when rollup's static analysis gets better | ||
/* | ||
* Big TODO list: | ||
* | ||
* For entities with parents: | ||
* - Replace .create('treeReview') with .create('review', { tree: { id: 1 } }) | ||
* - Replace .getMany('treeReviews') with .getMany('reviews', { tree: { id: 1 } }) | ||
* - Replace .update('treeReview') with .update('review') | ||
* - Replace .delete('treeReview') with .delete('review') | ||
* - Replace .getOne('treeReview') with .getOne('review') | ||
* - Assess impact, new edge cases, etc. | ||
*/ | ||
var SuperGloo = function () { | ||
@@ -101,14 +218,46 @@ function SuperGloo() { | ||
key: 'getOne', | ||
value: function getOne(entity, options) { | ||
var getOneFunction = camelCase('getOne_' + entity); | ||
value: function getOne(entityName) { | ||
var _falcor; | ||
if (!isFunction(this[getOneFunction])) { | ||
return reject(new Error('Invalid entity: ' + entity + '. Please check the syntax and try again.')); | ||
var options = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {}; | ||
// TODO: Remove once all getOne methods on this class have been ported to entities | ||
var getOneFunction = camelCase('getOne_' + entityName); | ||
if (isFunction(this[getOneFunction])) { | ||
return this[getOneFunction](options); | ||
} | ||
return this[getOneFunction](options); | ||
var entity = entities[entityName]; | ||
if (isNil(entity)) { | ||
var filename = entityToFilename(entityName) + '.js'; | ||
return reject(new Error('The ' + entityName + ' entity is undefined. Ensure entities/' + filename + ' exists and is exported by entities/_catalog.js')); | ||
} | ||
if (isNil(entity.pluralName)) { | ||
return reject(new Error('The ' + entityName + ' entity must export a pluralName')); | ||
} | ||
var id = options.id; | ||
if (isNil(id)) { | ||
return reject(new Error('options.id is required when getting one ' + entityName)); | ||
} | ||
var getPaths = isFunction(entity.getOne) ? entity.getOne(options) : getOne$2(entity, options); | ||
return (_falcor = this.falcor).get.apply(_falcor, _toConsumableArray(getPaths)).then(function (response) { | ||
var rootLeaf = entityToFalcorRootLeaf(entity); | ||
return response.json[rootLeaf][id]; | ||
}).catch(function (errorPaths) { | ||
var errorMessage = createGetOneErrorMessageFromPaths(errorPaths); | ||
return reject(new Error(errorMessage)); | ||
}); | ||
} | ||
}, { | ||
key: 'create', | ||
value: function create(entity, options) { | ||
value: function create(entity) { | ||
var options = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {}; | ||
var createFunction = camelCase('create_' + entity); | ||
@@ -124,23 +273,117 @@ | ||
key: 'update', | ||
value: function update(entity, options) { | ||
var updateFunction = camelCase('update_' + entity); | ||
value: function update(entityName) { | ||
var _falcor2; | ||
if (!isFunction(this[updateFunction])) { | ||
return reject(new Error('Invalid entity: ' + entity + '. Please check the syntax and try again.')); | ||
var options = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {}; | ||
var entity = entities[entityName]; | ||
if (isNil(entity)) { | ||
var filename = entityToFilename(entityName) + '.js'; | ||
return reject(new Error('The ' + entityName + ' entity is undefined. Ensure entities/' + filename + ' exists and is exported by entities/_catalog.js')); | ||
} | ||
return this[updateFunction](options); | ||
if (isNil(entity.pluralName)) { | ||
return reject(new Error('The ' + entityName + ' entity must export a pluralName')); | ||
} | ||
var id = options.id; | ||
if (isNil(id)) { | ||
return reject(new Error('options.id is required when updating a tree review')); | ||
} | ||
if (keys(options).length === 1) { | ||
return reject(new Error('options must include at least one property to update other than id')); | ||
} | ||
var valuePaths = isFunction(entity.update) ? entity.update(options) : update$1(entity, options); | ||
return (_falcor2 = this.falcor).set.apply(_falcor2, _toConsumableArray(valuePaths)).then(function (response) { | ||
var entities = response.json[entity.pluralName]; | ||
var updatedProperties = entities[id]; | ||
return updatedProperties; | ||
}).catch(function (paths) { | ||
var errorMessage = createUpdateErrorMessageFromPaths(paths); | ||
return reject(new Error(errorMessage)); | ||
}); | ||
} | ||
// TODO: Remove once all delete methods have been ported | ||
}, { | ||
key: 'delete', | ||
value: function _delete(entity, options) { | ||
var deleteFunction = camelCase('delete_' + entity); | ||
value: function _delete(entityName) { | ||
var options = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {}; | ||
if (!isFunction(this[deleteFunction])) { | ||
return reject(new Error('Invalid entity: ' + entity + '. Please check the syntax and try again.')); | ||
console.warn('gloo.delete(\'' + entityName + '\') has been deprecated. Please use gloo.destroy(\'' + entityName + '\') instead.'); | ||
var deleteFunction = camelCase('delete_' + entityName); | ||
if (isFunction(this[deleteFunction])) { | ||
return this[deleteFunction](options); | ||
} | ||
return this[deleteFunction](options); | ||
var entity = entities[entityName]; | ||
if (isNil(entity)) { | ||
var filename = entityToFilename(entityName) + '.js'; | ||
return reject(new Error('The ' + entityName + ' entity is undefined. Ensure entities/' + filename + ' exists and is exported by entities/_catalog.js')); | ||
} | ||
if (isNil(entity.pluralName)) { | ||
return reject(new Error('The ' + entityName + ' entity must export a pluralName')); | ||
} | ||
var id = options.id; | ||
if (isNil(id)) { | ||
return reject(new Error('options.id is required when deleting one ' + entityName)); | ||
} | ||
var destroyPath = isFunction(entity.destroy) ? entity.destroy(options) : destroy$1(entity, options); | ||
return this.falcor.call(destroyPath).then(function () { | ||
return 'Entity deleted'; | ||
}).catch(function (paths) { | ||
var errorMessage = createDeleteErrorMessageFromPaths(paths); | ||
return reject(new Error(errorMessage)); | ||
}); | ||
} | ||
}, { | ||
key: 'destroy', | ||
value: function destroy(entityName) { | ||
var options = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {}; | ||
var entity = entities[entityName]; | ||
if (isNil(entity)) { | ||
var filename = entityToFilename(entityName) + '.js'; | ||
return reject(new Error('The ' + entityName + ' entity is undefined. Ensure entities/' + filename + ' exists and is exported by entities/_catalog.js')); | ||
} | ||
if (isNil(entity.pluralName)) { | ||
return reject(new Error('The ' + entityName + ' entity must export a pluralName')); | ||
} | ||
var id = options.id; | ||
if (isNil(id)) { | ||
return reject(new Error('options.id is required when destroying one ' + entityName)); | ||
} | ||
var destroyPath = isFunction(entity.destroy) ? entity.destroy(options) : destroy$1(entity, options); | ||
return this.falcor.call(destroyPath).then(function () { | ||
return 'Entity destroyed'; | ||
}).catch(function (paths) { | ||
var errorMessage = createDestroyErrorMessageFromPaths(paths); | ||
return reject(new Error(errorMessage)); | ||
}); | ||
} | ||
/* | ||
@@ -164,3 +407,3 @@ * Entity-specific handlers | ||
var properties = buildProperties(tourTipViews, options); | ||
var properties = buildProperties$$1(tourTipView, options); | ||
@@ -194,3 +437,3 @@ var path = ['self', 'tour_tip_view_list', { from: from, to: to }, properties]; | ||
var properties = buildProperties(reviews, options); | ||
var properties = buildProperties$$1(review, options); | ||
@@ -207,4 +450,4 @@ // TODO: Add support for dot notation properties, e.g. user.avatar.src. | ||
return map(reviewList, function (review) { | ||
return review; | ||
return map(reviewList, function (review$$1) { | ||
return review$$1; | ||
}); | ||
@@ -217,38 +460,5 @@ }).catch(function (paths) { | ||
}, { | ||
key: 'getOneMoment', | ||
value: function getOneMoment() { | ||
var _falcor; | ||
var options = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {}; | ||
// Ensure we know which moment we need to get | ||
var momentId = options.id; | ||
if (isNil(momentId)) { | ||
return reject(new Error('options.id is required when getting one moment')); | ||
} | ||
var properties = buildProperties(moments, options); | ||
/* | ||
* As SuperGloo's property syntax is a subset of the Falcor | ||
* path syntax, we can use Falcor's path syntax parser | ||
* to transform SuperGloo properties into Falcor paths. | ||
*/ | ||
var paths = properties.map(function (property) { | ||
var path = falcorPathParser(property); | ||
return concat(['moments', momentId], path); | ||
}); | ||
return (_falcor = this.falcor).get.apply(_falcor, _toConsumableArray(paths)).then(function (response) { | ||
return response.json.moments[momentId]; | ||
}).catch(function (paths) { | ||
var errorMessage = createGetOneErrorMessageFromPaths(paths); | ||
return reject(new Error(errorMessage)); | ||
}); | ||
} | ||
}, { | ||
key: 'getOneMyTreeReview', | ||
value: function getOneMyTreeReview() { | ||
var _falcor2; | ||
var _falcor3; | ||
@@ -263,3 +473,3 @@ var options = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {}; | ||
var properties = buildProperties(reviews, options); | ||
var properties = buildProperties$$1(review, options); | ||
@@ -271,3 +481,3 @@ var paths = properties.map(function (property) { | ||
return (_falcor2 = this.falcor).get.apply(_falcor2, _toConsumableArray(paths)).then(function (response) { | ||
return (_falcor3 = this.falcor).get.apply(_falcor3, _toConsumableArray(paths)).then(function (response) { | ||
return response.json.trees[tree.id].my_review; | ||
@@ -280,58 +490,2 @@ }).catch(function (paths) { | ||
}, { | ||
key: 'getOneTreeReview', | ||
value: function getOneTreeReview() { | ||
var _falcor3; | ||
var options = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {}; | ||
var id = options.id; | ||
if (isNil(id)) { | ||
return reject(new Error('options.id is required when getting a tree review')); | ||
} | ||
var properties = buildProperties(reviews, options); | ||
var paths = properties.map(function (property) { | ||
var path = falcorPathParser(property); | ||
return concat(['reviews', id], path); | ||
}); | ||
return (_falcor3 = this.falcor).get.apply(_falcor3, _toConsumableArray(paths)).then(function (response) { | ||
return response.json.reviews[id]; | ||
}).catch(function (paths) { | ||
var errorMessage = createGetOneErrorMessageFromPaths(paths); | ||
return reject(new Error(errorMessage)); | ||
}); | ||
} | ||
}, { | ||
key: 'getOneTourTipView', | ||
value: function getOneTourTipView() { | ||
var _falcor4; | ||
var options = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {}; | ||
var viewId = options.id; | ||
if (isNil(viewId)) { | ||
return reject(new Error('options.id is required when getting one tour tip view')); | ||
} | ||
var properties = buildProperties(tourTipViews, options); | ||
var paths = properties.map(function (property) { | ||
var path = falcorPathParser(property); | ||
return concat(['tour_tip_views', viewId], path); | ||
}); | ||
return (_falcor4 = this.falcor).get.apply(_falcor4, _toConsumableArray(paths)).then(function (response) { | ||
// TODO: Assumptions | ||
// - Falcor always returns JSONG in a top level entityName wrapper | ||
return response.json.tour_tip_views[viewId]; | ||
}).catch(function (paths) { | ||
var errorMessage = createGetOneErrorMessageFromPaths(paths); | ||
return reject(new Error(errorMessage)); | ||
}); | ||
} | ||
}, { | ||
key: 'createComment', | ||
@@ -343,3 +497,3 @@ value: function createComment() { | ||
var postId = options.post.id; | ||
var comment = options.comment; | ||
var comment$$1 = options.comment; | ||
@@ -349,3 +503,3 @@ // TODO: Account for implicit assumptions in the final API: | ||
var requestBody = { comment: comment }; | ||
var requestBody = { comment: comment$$1 }; | ||
@@ -375,7 +529,7 @@ // What's the diff between this.falcor.call and ngf.callModel? | ||
var options = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {}; | ||
var tourTipView = options.tourTipView; | ||
var tourTipView$$1 = options.tourTipView; | ||
var wrappedTourTipView = { | ||
tour_tip_view: tourTipView | ||
tour_tip_view: tourTipView$$1 | ||
}; | ||
@@ -402,7 +556,7 @@ | ||
var options = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {}; | ||
var review = options.review, | ||
var review$$1 = options.review, | ||
tree = options.tree; | ||
if (isNil(review)) { | ||
if (isNil(review$$1)) { | ||
return reject(new Error('options.review is required when creating a tree review')); | ||
@@ -416,9 +570,9 @@ } | ||
var wrappedReview = { | ||
review: review | ||
review: review$$1 | ||
}; | ||
return this.falcor.call(['trees', tree.id, 'review_list', 'add'], [wrappedReview]).then(function (response) { | ||
var reviews$$1 = response.json.reviews; | ||
var first = head(keys(reviews$$1)); | ||
var createdReview = reviews$$1[first]; | ||
var reviews = response.json.reviews; | ||
var first = head(keys(reviews)); | ||
var createdReview = reviews[first]; | ||
@@ -437,45 +591,2 @@ // TODO: Figure out: | ||
}, { | ||
key: 'updateTreeReview', | ||
value: function updateTreeReview() { | ||
var _falcor5; | ||
var options = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {}; | ||
var id = options.id; | ||
if (isNil(id)) { | ||
return reject(new Error('options.id is required when updating a tree review')); | ||
} | ||
if (keys(options).length === 1) { | ||
return reject(new Error('options must include at least one property to update other than id')); | ||
} | ||
var properties = reject$1(keys(options), function (key) { | ||
return key === 'id'; | ||
}); | ||
/* | ||
* TODO: | ||
* - confirm assumption that updates won't be made on nested entiteies, | ||
* i.e. a user's avatar src won't be updated via: | ||
* gloo.update('user', { id: 1, avatar: { src: 'http://new.url' } }) | ||
*/ | ||
var valuePaths = map(properties, function (property) { | ||
return { path: ['reviews', id, property], value: options[property] }; | ||
}); | ||
return (_falcor5 = this.falcor).set.apply(_falcor5, _toConsumableArray(valuePaths)).then(function (response) { | ||
var reviews$$1 = response.json.reviews; | ||
var first = head(keys(reviews$$1)); | ||
var updatedProperties = reviews$$1[first]; | ||
return updatedProperties; | ||
}).catch(function (paths) { | ||
var errorMessage = createUpdateErrorMessageFromPaths(paths); | ||
return reject(new Error(errorMessage)); | ||
}); | ||
} | ||
}, { | ||
key: 'deleteTourTipView', | ||
@@ -498,20 +609,2 @@ value: function deleteTourTipView() { | ||
} | ||
}, { | ||
key: 'deleteTreeReview', | ||
value: function deleteTreeReview() { | ||
var options = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {}; | ||
var id = options.id; | ||
if (isNil(id)) { | ||
return reject(new Error('options.id is required when deleting a tree review')); | ||
} | ||
return this.falcor.call(['reviews', id, 'delete']).then(function () { | ||
return 'Entity deleted'; | ||
}).catch(function (paths) { | ||
var errorMessage = createDeleteErrorMessageFromPaths(paths); | ||
return reject(new Error(errorMessage)); | ||
}); | ||
} | ||
}]); | ||
@@ -529,3 +622,3 @@ | ||
function buildProperties(defaults, options) { | ||
function buildProperties$$1(defaults, options) { | ||
var properties = concat([], options.properties || defaults); | ||
@@ -618,2 +711,14 @@ | ||
function createDestroyErrorMessageFromPaths(paths) { | ||
var firstPath = paths[0]; | ||
var entity = camelCase(firstPath.path[0]); | ||
var entityId = firstPath.path[1]; | ||
var originalMessage = firstPath.value; | ||
var code = originalMessage.match(/\d{3}/)[0]; | ||
var improvedMessage = codeToMessageMap[code] || codeToMessageMap.default; | ||
return 'Could not destroy ' + entity + ' ' + entityId + ': ' + improvedMessage + ' (' + originalMessage + ')'; | ||
} | ||
export default SuperGloo; |
{ | ||
"name": "supergloo", | ||
"version": "0.7.1", | ||
"version": "0.8.0", | ||
"description": "Easily work with data on the Gloo platform", | ||
@@ -25,2 +25,3 @@ "keywords": [ | ||
"devDependencies": { | ||
"app-module-path": "2.2.0", | ||
"babel-plugin-external-helpers": "6.18.0", | ||
@@ -55,7 +56,7 @@ "babel-preset-es2015": "6.18.0", | ||
"freeze": "npm prune && npm shrinkwrap --dev && shrinkpack", | ||
"lint": "standard src/**/*.js test/**/*.js", | ||
"lint": "standard {src,test}/*.js {src,test}/**/*.js", | ||
"test:browser": "npm run build:test && easy-sauce -c easy-sauce.config.json", | ||
"test:list": "mocha --require test/support/registerBabel.js", | ||
"test": "mocha --require test/support/registerBabel.js test/**/*.test.js" | ||
"test:list": "mocha --require test/support/require-shim.js", | ||
"test": "mocha --require test/support/require-shim.js test/{*,**/*}.test.js" | ||
} | ||
} |
Sorry, the diff of this file is too big to display
354719
10306
22