Skip to content

Instantly share code, notes, and snippets.

@scriptmaster
Forked from JedWatson/KeystoneApiExample.md
Last active November 7, 2017 23:01
Show Gist options
  • Save scriptmaster/561c7aa1e4e99ff0be0fac82ea8571e4 to your computer and use it in GitHub Desktop.
Save scriptmaster/561c7aa1e4e99ff0be0fac82ea8571e4 to your computer and use it in GitHub Desktop.
Example of how to scaffold API endpoints for Posts in a Keystone project (based on the yo keystone example).

This is an example of how to scaffold API endpoints to list / get / create / update / delete Posts in a Keystone website.

It's a modification of the default project created with the yo keystone generator (see https://github.com/JedWatson/generator-keystone)

Gists don't let you specify full paths, so in the project structure the files would be:

routes-index.js        -->    /routes/index.js         // modified to add the api endpoints
routes-api-posts.js    -->    /routes/api/posts.js     // new file containing the Post API route controllers

It creates JSON endpoints for:

  • /api/post/list - lists all posts
  • /api/post/create - creates a new post
  • /api/post/{id} - returns the details of posts by id
  • /api/post/{id}/update - updates a post by id and returns the details
  • /api/post/{id}/delete - deletes a post by id

The create and update routes accept either GET or POST requests for simplicity, and look in either the URL parameters of the request body for data using the same paths as set on the models.

You can add your own logic in for security, default values, limiting fields etc. by configuring the functions exported by /routes/api/posts.js

var async = require('async'),
keystone = require('keystone');
var Post = keystone.list('Post');
/**
* List Posts
*/
exports.list = function(req, res) {
Post.model.find(function(err, items) {
if (err) return res.status(500).json('database error', err);
res.json({
posts: items
});
});
}
/**
* Get Post by ID
*/
exports.get = function(req, res) {
Post.model.findById(req.params.id).exec(function(err, item) {
if (err) return res.status(500).json('database error', err);
if (!item) return res.status(404).json('not found');
res.json({
post: item
});
});
}
/**
* Create a Post
*/
exports.create = function(req, res) {
var item = new Post.model(),
data = (req.method == 'POST') ? req.body : req.query;
item.getUpdateHandler(req).process(data, function(err) {
if (err) return res.status(500).json('error', err);
res.json({
post: item
});
});
}
/**
* Get Post by ID
*/
exports.update = function(req, res) {
Post.model.findById(req.params.id).exec(function(err, item) {
if (err) return res.status(500).json('database error', err);
if (!item) return res.status(404).json('not found');
var data = (req.method == 'POST') ? req.body : req.query;
item.getUpdateHandler(req).process(data, function(err) {
if (err) return res.status(500).json('create error', err);
res.json({
post: item
});
});
});
}
/**
* Delete Post by ID
*/
exports.remove = function(req, res) {
Post.model.findById(req.params.id).exec(function (err, item) {
if (err) return res.status(500).json('database error', err);
if (!item) return res.status(404).json('not found');
item.remove(function (err) {
if (err) return res.status(500).json('database error', err);
return res.json({
success: true
});
});
});
}
var keystone = require('keystone'),
middleware = require('./middleware'),
importRoutes = keystone.importer(__dirname);
// Common Middleware
keystone.pre('routes', middleware.initLocals);
keystone.pre('render', middleware.flashMessages);
// Import Route Controllers
var routes = {
views: importRoutes('./views'),
api: importRoutes('./api')
};
function checkAuth(req, res, next) {
// you could check user permissions here too
if (req.user) return next();
return res.status(403).json({ 'error': 'no access' });
}
function checkAdmin(req, res, next) {
// you could check user permissions here too
if (req.user && req.user.isAdmin) return next();
return res.status(403).json({ 'error': 'no access' });
}
// Setup Route Bindings
exports = module.exports = function(app) {
// Views
app.get('/', routes.views.index);
app.get('/blog/:category?', routes.views.blog);
app.get('/blog/post/:post', routes.views.post);
app.get('/gallery', routes.views.gallery);
app.all('/contact', routes.views.contact);
// app.all('/api*', keystone.middleware.api); // Only needed if you use res.apiResponse() which you can do with res.json()
app.get('/api/post/list', routes.api.posts.list);
app.all('/api/post/create', routes.api.posts.create);
app.get('/api/post/:id', routes.api.posts.get);
app.all('/api/post/:id/update', routes.api.posts.update);
app.get('/api/post/:id/remove', routes.api.posts.remove);
app.all('/api/user/*', checkAuth);
app.all('/api/admin/*', checkAdmin);
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment