mirror of
https://github.com/TryGhost/Ghost.git
synced 2024-12-23 10:53:34 +03:00
Merge branch 'api-fun'
This commit is contained in:
commit
52242a5d10
27
app.js
27
app.js
@ -1,19 +1,22 @@
|
|||||||
// # Ghost main app file
|
// # Ghost main app file
|
||||||
|
|
||||||
/*global require */
|
/*global require, __dirname */
|
||||||
(function () {
|
(function () {
|
||||||
"use strict";
|
"use strict";
|
||||||
|
|
||||||
// Module dependencies.
|
// Module dependencies.
|
||||||
var express = require('express'),
|
var express = require('express'),
|
||||||
fs = require('fs'),
|
|
||||||
admin = require('./core/admin/controllers'),
|
admin = require('./core/admin/controllers'),
|
||||||
frontend = require('./core/frontend/controllers'),
|
frontend = require('./core/frontend/controllers'),
|
||||||
|
api = require('./core/shared/api'),
|
||||||
flash = require('connect-flash'),
|
flash = require('connect-flash'),
|
||||||
Ghost = require('./core/ghost'),
|
Ghost = require('./core/ghost'),
|
||||||
I18n = require('./core/lang/i18n'),
|
I18n = require('./core/lang/i18n'),
|
||||||
helpers = require('./core/frontend/helpers'),
|
helpers = require('./core/frontend/helpers');
|
||||||
auth,
|
|
||||||
|
|
||||||
|
|
||||||
|
var auth,
|
||||||
|
|
||||||
// ## Variables
|
// ## Variables
|
||||||
/**
|
/**
|
||||||
@ -46,11 +49,13 @@
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* API routes..
|
* API routes..
|
||||||
* @todo convert these into a RESTful, public, authenticated API!
|
* @todo auth should be public auth not user auth
|
||||||
*/
|
*/
|
||||||
ghost.app().post('/api/v0.1/posts/create', auth, admin.posts.create);
|
ghost.app().get('/api/v0.1/posts', auth, api.requestHandler(api.posts.browse));
|
||||||
ghost.app().post('/api/v0.1/posts/edit', auth, admin.posts.edit);
|
ghost.app().get('/api/v0.1/posts/:id', auth, api.requestHandler(api.posts.read));
|
||||||
ghost.app().get('/api/v0.1/posts', auth, admin.posts.index);
|
ghost.app().post('/api/v0.1/posts/create', auth, api.requestHandler(api.posts.add));
|
||||||
|
ghost.app().put('/api/v0.1/posts/edit', auth, api.requestHandler(api.posts.edit));
|
||||||
|
ghost.app()['delete']('/api/v0.1/posts/:id', auth, api.requestHandler(api.posts.destroy));
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Admin routes..
|
* Admin routes..
|
||||||
@ -75,6 +80,10 @@
|
|||||||
|
|
||||||
ghost.app().listen(3333, function () {
|
ghost.app().listen(3333, function () {
|
||||||
console.log("Express server listening on port " + 3333);
|
console.log("Express server listening on port " + 3333);
|
||||||
console.log('process: ', process.env);
|
|
||||||
});
|
});
|
||||||
|
// }, function (e) {
|
||||||
|
// console.log(e.toString());
|
||||||
|
// }).then(null, function (e) {
|
||||||
|
// console.log(e.stack);
|
||||||
|
// });
|
||||||
}());
|
}());
|
13
config.js
13
config.js
@ -55,6 +55,19 @@
|
|||||||
*/
|
*/
|
||||||
config.homepage.posts = 4;
|
config.homepage.posts = 4;
|
||||||
|
|
||||||
|
config.database = {
|
||||||
|
development: {
|
||||||
|
client: 'sqlite3',
|
||||||
|
connection: {
|
||||||
|
filename: './core/shared/data/testdb.db'
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
staging: {},
|
||||||
|
|
||||||
|
production: {}
|
||||||
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @property {Object} exports
|
* @property {Object} exports
|
||||||
*/
|
*/
|
||||||
|
@ -56,7 +56,7 @@
|
|||||||
function save() {
|
function save() {
|
||||||
var entry = {
|
var entry = {
|
||||||
title: document.getElementById('entry-title').value,
|
title: document.getElementById('entry-title').value,
|
||||||
markdown: editor.getValue()
|
content: editor.getValue()
|
||||||
},
|
},
|
||||||
urlSegments = window.location.pathname.split('/');
|
urlSegments = window.location.pathname.split('/');
|
||||||
|
|
||||||
@ -64,7 +64,7 @@
|
|||||||
entry.id = urlSegments[3];
|
entry.id = urlSegments[3];
|
||||||
$.ajax({
|
$.ajax({
|
||||||
url: '/api/v0.1/posts/edit',
|
url: '/api/v0.1/posts/edit',
|
||||||
method: 'POST',
|
method: 'PUT',
|
||||||
data: entry,
|
data: entry,
|
||||||
success: function (data) {
|
success: function (data) {
|
||||||
console.log('response', data);
|
console.log('response', data);
|
||||||
|
@ -1,11 +1,12 @@
|
|||||||
|
/*global require, module */
|
||||||
(function () {
|
(function () {
|
||||||
"use strict";
|
"use strict";
|
||||||
|
|
||||||
var Ghost = require('../../ghost'),
|
var Ghost = require('../../ghost'),
|
||||||
_ = require('underscore'),
|
_ = require('underscore'),
|
||||||
fs = require('fs'),
|
fs = require('fs'),
|
||||||
Showdown = require('showdown'),
|
when = require('when/node/function'),
|
||||||
converter = new Showdown.converter(),
|
api = require('../../shared/api'),
|
||||||
|
|
||||||
ghost = new Ghost(),
|
ghost = new Ghost(),
|
||||||
adminNavbar,
|
adminNavbar,
|
||||||
@ -60,12 +61,13 @@
|
|||||||
},
|
},
|
||||||
'editor': function (req, res) {
|
'editor': function (req, res) {
|
||||||
if (req.params.id !== undefined) {
|
if (req.params.id !== undefined) {
|
||||||
ghost.dataProvider().posts.findOne({'id': parseInt(req.params.id, 10)}, function (error, post) {
|
api.posts.read({id: parseInt(req.params.id, 10)})
|
||||||
|
.then(function (post) {
|
||||||
res.render('editor', {
|
res.render('editor', {
|
||||||
bodyClass: 'editor',
|
bodyClass: 'editor',
|
||||||
adminNav: setSelected(adminNavbar, 'blog'),
|
adminNav: setSelected(adminNavbar, 'blog'),
|
||||||
title: post.title,
|
title: post.get('title'),
|
||||||
content: post.content
|
content: post.get('content')
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
} else {
|
} else {
|
||||||
@ -76,11 +78,12 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
'blog': function (req, res) {
|
'blog': function (req, res) {
|
||||||
ghost.dataProvider().posts.findAll(function (error, posts) {
|
api.posts.browse()
|
||||||
|
.then(function (posts) {
|
||||||
res.render('blog', {
|
res.render('blog', {
|
||||||
bodyClass: 'manage',
|
bodyClass: 'manage',
|
||||||
adminNav: setSelected(adminNavbar, 'blog'),
|
adminNav: setSelected(adminNavbar, 'blog'),
|
||||||
posts: posts
|
posts: posts.toJSON()
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
@ -119,47 +122,6 @@
|
|||||||
res.redirect('/ghost/debug');
|
res.redirect('/ghost/debug');
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
},
|
|
||||||
'posts': {
|
|
||||||
'index': function (req, res) {
|
|
||||||
|
|
||||||
},
|
|
||||||
'create': function (req, res) {
|
|
||||||
var entry = {
|
|
||||||
title: req.body.title,
|
|
||||||
content: req.body.markdown,
|
|
||||||
contentHtml: '',
|
|
||||||
language: ghost.config().defaultLang,
|
|
||||||
status: ghost.statuses().draft,
|
|
||||||
featured: false
|
|
||||||
};
|
|
||||||
|
|
||||||
entry.contentHtml = converter.makeHtml(entry.content);
|
|
||||||
|
|
||||||
ghost.dataProvider().posts.add(entry, function (error, post) {
|
|
||||||
if (!error) {
|
|
||||||
console.log('added', post);
|
|
||||||
res.json({id: post.id});
|
|
||||||
} else {
|
|
||||||
res.json(400, {error: post.errors});
|
|
||||||
}
|
|
||||||
});
|
|
||||||
},
|
|
||||||
'edit': function (req, res) {
|
|
||||||
var entry = {
|
|
||||||
id: parseInt(req.body.id, 10),
|
|
||||||
title: req.body.title,
|
|
||||||
content: req.body.markdown,
|
|
||||||
contentHtml: ''
|
|
||||||
};
|
|
||||||
|
|
||||||
entry.contentHtml = converter.makeHtml(entry.content);
|
|
||||||
|
|
||||||
ghost.dataProvider().posts.edit(entry, function (error, post) {
|
|
||||||
console.log('edited', post);
|
|
||||||
res.json({id: parseInt(post.id, 10)});
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -18,7 +18,7 @@
|
|||||||
<ol>
|
<ol>
|
||||||
{{#each posts}}
|
{{#each posts}}
|
||||||
{{! #if featured class="featured"{{/if}}
|
{{! #if featured class="featured"{{/if}}
|
||||||
<li data-id="{{id}}" data-content="{{contentHtml}}">
|
<li data-id="{{id}}" data-content="{{content_html}}">
|
||||||
<a class="permalink" href="#">
|
<a class="permalink" href="#">
|
||||||
<h3 class="entry-title">{{title}}</h3>
|
<h3 class="entry-title">{{title}}</h3>
|
||||||
<section class="entry-meta">
|
<section class="entry-meta">
|
||||||
|
@ -7,45 +7,27 @@
|
|||||||
'use strict';
|
'use strict';
|
||||||
|
|
||||||
var Ghost = require('../../ghost'),
|
var Ghost = require('../../ghost'),
|
||||||
_ = require('underscore'),
|
api = require('../../shared/api'),
|
||||||
|
|
||||||
ghost = new Ghost(),
|
ghost = new Ghost(),
|
||||||
frontendControllers;
|
frontendControllers;
|
||||||
|
|
||||||
frontendControllers = {
|
frontendControllers = {
|
||||||
'homepage': function (req, res) {
|
'homepage': function (req, res) {
|
||||||
var featureCount = 0,
|
api.posts.browse().then(function (posts) {
|
||||||
postCount = 0,
|
ghost.doFilter('prePostsRender', posts.toJSON(), function (posts) {
|
||||||
data;
|
res.render('index', {posts: posts, ghostGlobals: ghost.globals()});
|
||||||
|
|
||||||
ghost.dataProvider().posts.findAll(function (error, posts) {
|
|
||||||
data = _.groupBy(posts, function (post) {
|
|
||||||
var group = null;
|
|
||||||
if (post.featured === true && featureCount < ghost.config().homepage.features) {
|
|
||||||
featureCount += 1;
|
|
||||||
group = 'features';
|
|
||||||
} else if (postCount < ghost.config().homepage.posts) {
|
|
||||||
postCount += 1;
|
|
||||||
group = 'posts';
|
|
||||||
}
|
|
||||||
|
|
||||||
return group;
|
|
||||||
});
|
|
||||||
|
|
||||||
ghost.doFilter('prepostsRender', data.posts, function (posts) {
|
|
||||||
res.render('index', {features: data.features, posts: posts, ghostGlobals: ghost.globals()});
|
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
'single': function (req, res) {
|
'single': function (req, res) {
|
||||||
ghost.dataProvider().posts.findOne({'slug': req.params.slug}, function (error, post) {
|
api.posts.read({'slug': req.params.slug}).then(function (post) {
|
||||||
ghost.doFilter('prePostsRender', post, function (post) {
|
ghost.doFilter('prePostsRender', post.toJSON(), function (post) {
|
||||||
res.render('single', {post: post, ghostGlobals: ghost.globals()});
|
res.render('single', {post: post, ghostGlobals: ghost.globals()});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
module.exports = frontendControllers;
|
module.exports = frontendControllers;
|
||||||
}());
|
}());
|
@ -1,11 +1,7 @@
|
|||||||
// # Ghost Module
|
// # Ghost Module
|
||||||
// Defines core methods required to build the frontend
|
// Defines core methods required to build the frontend
|
||||||
|
|
||||||
/**
|
/*global module, require, __dirname */
|
||||||
* global module,
|
|
||||||
* require,
|
|
||||||
* __dirname
|
|
||||||
**/
|
|
||||||
(function () {
|
(function () {
|
||||||
"use strict";
|
"use strict";
|
||||||
|
|
||||||
@ -16,10 +12,13 @@
|
|||||||
hbs = require('express-hbs'),
|
hbs = require('express-hbs'),
|
||||||
_ = require('underscore'),
|
_ = require('underscore'),
|
||||||
Polyglot = require('node-polyglot'),
|
Polyglot = require('node-polyglot'),
|
||||||
|
|
||||||
JsonDataProvider = require('./shared/models/dataProvider.json'),
|
JsonDataProvider = require('./shared/models/dataProvider.json'),
|
||||||
jsonDataProvider = new JsonDataProvider(),
|
jsonDataProvider = new JsonDataProvider(),
|
||||||
JugglingDataProvider = require('./shared/models/dataProvider.juggling'),
|
// JugglingDataProvider = require('./shared/models/dataProvider.juggling'),
|
||||||
jugglingDataProvider = new JugglingDataProvider(),
|
// jugglingDataProvider = new JugglingDataProvider(),
|
||||||
|
BookshelfDataProvider = require('./shared/models/dataProvider.bookshelf'),
|
||||||
|
bookshelfDataProvider = new BookshelfDataProvider(),
|
||||||
Ghost,
|
Ghost,
|
||||||
instance,
|
instance,
|
||||||
filterCallbacks = {},
|
filterCallbacks = {},
|
||||||
@ -70,7 +69,7 @@
|
|||||||
app: function () { return app; },
|
app: function () { return app; },
|
||||||
config: function () { return config; },
|
config: function () { return config; },
|
||||||
globals: function () { return globals; }, // there's no management here to be sure this has loaded
|
globals: function () { return globals; }, // there's no management here to be sure this has loaded
|
||||||
dataProvider: function () { return jugglingDataProvider; },
|
dataProvider: function () { return bookshelfDataProvider; },
|
||||||
statuses: function () { return statuses; },
|
statuses: function () { return statuses; },
|
||||||
polyglot: function () { return polyglot; },
|
polyglot: function () { return polyglot; },
|
||||||
paths: function () {
|
paths: function () {
|
||||||
|
75
core/shared/api.js
Normal file
75
core/shared/api.js
Normal file
@ -0,0 +1,75 @@
|
|||||||
|
// # Ghost Data API
|
||||||
|
// Provides access to the data model
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This is intended to replace the old dataProvider files and should access & manipulate the models directly
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*global module, require */
|
||||||
|
(function () {
|
||||||
|
"use strict";
|
||||||
|
|
||||||
|
var Ghost = require('../ghost'),
|
||||||
|
when = require('when/node/function'),
|
||||||
|
_ = require('underscore'),
|
||||||
|
|
||||||
|
ghost = new Ghost(),
|
||||||
|
posts,
|
||||||
|
users,
|
||||||
|
requestHandler;
|
||||||
|
|
||||||
|
// # Posts
|
||||||
|
posts = {
|
||||||
|
// takes filter / pagination parameters
|
||||||
|
// returns a list of posts in a json response
|
||||||
|
browse: function (options) {
|
||||||
|
return when.call(ghost.dataProvider().posts.findAll, options);
|
||||||
|
},
|
||||||
|
// takes an identifier (id or slug?)
|
||||||
|
// returns a single post in a json response
|
||||||
|
read: function (args) {
|
||||||
|
return when.call(ghost.dataProvider().posts.findOne, args);
|
||||||
|
},
|
||||||
|
// takes a json object with all the properties which should be updated
|
||||||
|
// returns the resulting post in a json response
|
||||||
|
edit: function (postData) {
|
||||||
|
return when.call(ghost.dataProvider().posts.edit, postData);
|
||||||
|
},
|
||||||
|
// takes a json object representing a post,
|
||||||
|
// returns the resulting post in a json response
|
||||||
|
add: function (postData) {
|
||||||
|
return when.call(ghost.dataProvider().posts.add, postData);
|
||||||
|
},
|
||||||
|
// takes an identifier (id or slug?)
|
||||||
|
// returns a json response with the id of the deleted post
|
||||||
|
destroy: function (id) {
|
||||||
|
return when.call(ghost.dataProvider().posts.destroy, id);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
// # Users
|
||||||
|
users = {};
|
||||||
|
// settings: {},
|
||||||
|
// categories: {},
|
||||||
|
// post_categories: {}
|
||||||
|
|
||||||
|
|
||||||
|
// requestHandler
|
||||||
|
// decorator for api functions which are called via an HTTP request
|
||||||
|
// takes the API method and wraps it so that it gets data from the request and returns a sensible JSON response
|
||||||
|
requestHandler = function (apiMethod) {
|
||||||
|
return function (req, res) {
|
||||||
|
var options = _.extend(req.body, req.params);
|
||||||
|
return apiMethod(options).then(function (result) {
|
||||||
|
res.json(result);
|
||||||
|
}, function (error) {
|
||||||
|
res.json(400, {error: error});
|
||||||
|
});
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
module.exports.posts = posts;
|
||||||
|
module.exports.users = users;
|
||||||
|
module.exports.requestHandler = requestHandler;
|
||||||
|
}());
|
67
core/shared/data/fixtures/001.js
Normal file
67
core/shared/data/fixtures/001.js
Normal file
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
@ -1,20 +0,0 @@
|
|||||||
[
|
|
||||||
{
|
|
||||||
"key": "url",
|
|
||||||
"value": "http://localhost:3333",
|
|
||||||
"createdBy": 1,
|
|
||||||
"updatedBy": 1
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"key": "title",
|
|
||||||
"value": "John O'Nolan",
|
|
||||||
"createdBy": 1,
|
|
||||||
"updatedBy": 1
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"key": "description",
|
|
||||||
"value": "Interactive designer, public speaker, startup advisor and writer. Living in Austria, attempting world domination via keyboard.",
|
|
||||||
"createdBy": 1,
|
|
||||||
"updatedBy": 1
|
|
||||||
}
|
|
||||||
]
|
|
@ -1,15 +0,0 @@
|
|||||||
[
|
|
||||||
{
|
|
||||||
"id": "1",
|
|
||||||
"username": "johnonolan",
|
|
||||||
"firstName": "John",
|
|
||||||
"lastName": "O'Nolan",
|
|
||||||
"emailAddress": "john@onolan.org",
|
|
||||||
"profilePicture": "logo.png",
|
|
||||||
"coverPicture": "",
|
|
||||||
"bio": "Interactive designer, public speaker, startup advisor and writer. Living in Austria, attempting world domination via keyboard.",
|
|
||||||
"url": "john.onolan.org",
|
|
||||||
"createdBy": 1,
|
|
||||||
"updatedBy": 1
|
|
||||||
}
|
|
||||||
]
|
|
75
core/shared/data/migration/001.js
Normal file
75
core/shared/data/migration/001.js
Normal file
@ -0,0 +1,75 @@
|
|||||||
|
/*global require, exports */
|
||||||
|
|
||||||
|
(function () {
|
||||||
|
"use strict";
|
||||||
|
|
||||||
|
|
||||||
|
var when = require('when'),
|
||||||
|
knex = require('./knex_init'),
|
||||||
|
fixtures = require('../fixtures/001'),
|
||||||
|
up,
|
||||||
|
down;
|
||||||
|
|
||||||
|
up = function () {
|
||||||
|
|
||||||
|
return when.all([
|
||||||
|
|
||||||
|
knex.Schema.createTable('posts', function (t) {
|
||||||
|
t.increments().primary();
|
||||||
|
t.string('title');
|
||||||
|
t.string('slug');
|
||||||
|
t.text('content');
|
||||||
|
t.text('content_html');
|
||||||
|
t.bool('featured');
|
||||||
|
t.string('image');
|
||||||
|
t.string('status');
|
||||||
|
t.string('language');
|
||||||
|
t.date('created_at');
|
||||||
|
t.integer('created_by');
|
||||||
|
t.date('updated_at');
|
||||||
|
t.integer('updated_by');
|
||||||
|
}),
|
||||||
|
|
||||||
|
knex.Schema.createTable('users', function (t) {
|
||||||
|
t.increments().primary();
|
||||||
|
t.string('username');
|
||||||
|
t.string('first_name');
|
||||||
|
t.string('last_name');
|
||||||
|
t.string('email_address');
|
||||||
|
t.string('profile_picture');
|
||||||
|
t.string('cover_picture');
|
||||||
|
t.text('bio');
|
||||||
|
t.string('url');
|
||||||
|
t.date('created_at');
|
||||||
|
t.integer('created_by');
|
||||||
|
t.date('updated_at');
|
||||||
|
t.integer('updated_by');
|
||||||
|
}),
|
||||||
|
|
||||||
|
knex.Schema.createTable('settings', function (t) {
|
||||||
|
t.increments().primary();
|
||||||
|
t.string('key');
|
||||||
|
t.text('value');
|
||||||
|
t.date('created_at');
|
||||||
|
t.integer('created_by');
|
||||||
|
t.date('updated_at');
|
||||||
|
t.integer('updated_by');
|
||||||
|
})
|
||||||
|
|
||||||
|
// Once we create all of the initial tables, bootstrap any of the data
|
||||||
|
]).then(function () {
|
||||||
|
|
||||||
|
return when.all([
|
||||||
|
knex('posts').insert(fixtures.posts),
|
||||||
|
knex('users').insert(fixtures.users),
|
||||||
|
knex('settings').insert(fixtures.settings)
|
||||||
|
]);
|
||||||
|
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
down = function () {};
|
||||||
|
|
||||||
|
exports.up = up;
|
||||||
|
exports.down = down;
|
||||||
|
}());
|
86
core/shared/models/dataProvider.bookshelf.js
Normal file
86
core/shared/models/dataProvider.bookshelf.js
Normal file
@ -0,0 +1,86 @@
|
|||||||
|
/**
|
||||||
|
* Provides access to data via the Bookshelf ORM
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*globals module, require, process */
|
||||||
|
(function () {
|
||||||
|
"use strict";
|
||||||
|
|
||||||
|
var knex = require('knex'),
|
||||||
|
models = require('./models'),
|
||||||
|
DataProvider,
|
||||||
|
instance;
|
||||||
|
|
||||||
|
knex.Initialize(require('../../../config').database[process.env.NODE_ENV || 'development']);
|
||||||
|
|
||||||
|
DataProvider = function () {
|
||||||
|
if (!instance) {
|
||||||
|
instance = this;
|
||||||
|
knex.Schema.hasTable('posts').then(null, function () {
|
||||||
|
// Simple boostraping of the data model for now.
|
||||||
|
require('./../data/migration/001').up().then(function () {
|
||||||
|
console.log('all done....');
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
return instance;
|
||||||
|
};
|
||||||
|
|
||||||
|
DataProvider.prototype.posts = function () { };
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Naive find all
|
||||||
|
* @param args
|
||||||
|
* @param callback
|
||||||
|
*/
|
||||||
|
DataProvider.prototype.posts.findAll = function (args, callback) {
|
||||||
|
models.Posts.forge().fetch().then(function (posts) {
|
||||||
|
callback(null, posts);
|
||||||
|
}, callback);
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Naive find one where args match
|
||||||
|
* @param args
|
||||||
|
* @param callback
|
||||||
|
*/
|
||||||
|
DataProvider.prototype.posts.findOne = function (args, callback) {
|
||||||
|
models.Post.forge(args).fetch().then(function (post) {
|
||||||
|
callback(null, post);
|
||||||
|
}, callback);
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Naive add
|
||||||
|
* @param _post
|
||||||
|
* @param callback
|
||||||
|
*/
|
||||||
|
DataProvider.prototype.posts.add = function (_post, callback) {
|
||||||
|
models.Post.forge(_post).save().then(function (post) {
|
||||||
|
callback(null, post);
|
||||||
|
}, callback);
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Naive edit
|
||||||
|
* @param _post
|
||||||
|
* @param callback
|
||||||
|
*/
|
||||||
|
DataProvider.prototype.posts.edit = function (_post, callback) {
|
||||||
|
models.Post.forge({id: _post.id}).fetch().then(function (post) {
|
||||||
|
post.set(_post).save().then(function (post) {
|
||||||
|
callback(null, post);
|
||||||
|
}, callback);
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
DataProvider.prototype.posts.destroy = function (_identifier, callback) {
|
||||||
|
models.Post.forge({id: _identifier}).destroy().then(function () {
|
||||||
|
callback(null);
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
module.exports = DataProvider;
|
||||||
|
}());
|
@ -1,139 +0,0 @@
|
|||||||
/**
|
|
||||||
* Provides access to data via the JugglingDb ORM
|
|
||||||
*/
|
|
||||||
|
|
||||||
/*globals module, require */
|
|
||||||
(function () {
|
|
||||||
"use strict";
|
|
||||||
|
|
||||||
var schema = require('./schema').schema,
|
|
||||||
fs = require('fs'),
|
|
||||||
_ = require('underscore'),
|
|
||||||
DataProvider,
|
|
||||||
instance;
|
|
||||||
|
|
||||||
|
|
||||||
function populateData(callback) {
|
|
||||||
// TODO: convert to promises
|
|
||||||
schema.models.Setting.findOne({}, function (error, data) {
|
|
||||||
if (data === null) {
|
|
||||||
// we haven't loaded any data yet
|
|
||||||
fs.readFile(__dirname + '/data/fixtures/users.json', function (error, data) {
|
|
||||||
if (error) {
|
|
||||||
throw error;
|
|
||||||
}
|
|
||||||
|
|
||||||
var users = JSON.parse(data);
|
|
||||||
|
|
||||||
_.each(users, function (post) {
|
|
||||||
schema.models.User.create(post, function (error, data) {
|
|
||||||
console.log('User created error', error);
|
|
||||||
console.log('User created data', data);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
fs.readFile(__dirname + '/data/fixtures/posts.json', function (error, data) {
|
|
||||||
if (error) {
|
|
||||||
throw error;
|
|
||||||
}
|
|
||||||
|
|
||||||
var posts = JSON.parse(data),
|
|
||||||
post;
|
|
||||||
|
|
||||||
_.each(posts, function (_post) {
|
|
||||||
post = new schema.models.Post(_post);
|
|
||||||
|
|
||||||
post.preCreate(function () {
|
|
||||||
post.save(function (error, data) {
|
|
||||||
console.log('Post created error', error);
|
|
||||||
console.log('Post created data', data);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
fs.readFile(__dirname + '/data/fixtures/settings.json', function (error, data) {
|
|
||||||
if (error) {
|
|
||||||
throw error;
|
|
||||||
}
|
|
||||||
|
|
||||||
var posts = JSON.parse(data);
|
|
||||||
|
|
||||||
_.each(posts, function (post) {
|
|
||||||
schema.models.Setting.create(post, function (error, data) {
|
|
||||||
console.log('Setting created error', error);
|
|
||||||
console.log('Setting created data', data);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
callback();
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
|
|
||||||
});
|
|
||||||
} else {
|
|
||||||
callback();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
DataProvider = function () {
|
|
||||||
if (!instance) {
|
|
||||||
instance = this;
|
|
||||||
|
|
||||||
if (process.env.forcePopulate) {
|
|
||||||
populateData();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return instance;
|
|
||||||
};
|
|
||||||
|
|
||||||
DataProvider.prototype.posts = function () {};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Naive find all
|
|
||||||
* @param callback
|
|
||||||
*/
|
|
||||||
DataProvider.prototype.posts.findAll = function (callback) {
|
|
||||||
schema.models.Post.all(callback);
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Naive find one where args match
|
|
||||||
* @param callback
|
|
||||||
*/
|
|
||||||
DataProvider.prototype.posts.findOne = function (args, callback) {
|
|
||||||
schema.models.Post.findOne({where: args}, callback);
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Naive add
|
|
||||||
* @param post
|
|
||||||
* @param callback
|
|
||||||
*/
|
|
||||||
DataProvider.prototype.posts.add = function (_post, callback) {
|
|
||||||
var post = new schema.models.Post(_post);
|
|
||||||
|
|
||||||
post.preCreate(function () {
|
|
||||||
post.save(callback);
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Naive edit
|
|
||||||
* @param post
|
|
||||||
* @param callback
|
|
||||||
*/
|
|
||||||
DataProvider.prototype.posts.edit = function (_post, callback) {
|
|
||||||
schema.models.Post.findOne({where: {id: _post.id}}, function (error, post) {
|
|
||||||
post = _.extend(post, _post);
|
|
||||||
|
|
||||||
schema.models.Post.updateOrCreate(post, callback);
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
DataProvider.prototype.populateData = populateData;
|
|
||||||
|
|
||||||
module.exports = DataProvider;
|
|
||||||
}());
|
|
86
core/shared/models/models.js
Normal file
86
core/shared/models/models.js
Normal file
@ -0,0 +1,86 @@
|
|||||||
|
/*global require, module */
|
||||||
|
|
||||||
|
(function () {
|
||||||
|
"use strict";
|
||||||
|
|
||||||
|
// We should just be able to require bookshelf and have it reference
|
||||||
|
// the `Knex` instance bootstraped at the app initialization.
|
||||||
|
var Bookshelf = require('bookshelf'),
|
||||||
|
Showdown = require('showdown'),
|
||||||
|
converter = new Showdown.converter(),
|
||||||
|
|
||||||
|
Post,
|
||||||
|
Posts,
|
||||||
|
User,
|
||||||
|
Setting;
|
||||||
|
|
||||||
|
Post = Bookshelf.Model.extend({
|
||||||
|
|
||||||
|
tableName: 'posts',
|
||||||
|
|
||||||
|
hasTimestamps: true,
|
||||||
|
|
||||||
|
initialize: function () {
|
||||||
|
this.on('creating', this.creating, this);
|
||||||
|
this.on('saving', this.saving, this);
|
||||||
|
},
|
||||||
|
|
||||||
|
saving: function () {
|
||||||
|
if (!this.get('title')) {
|
||||||
|
throw new Error('Post title cannot be blank');
|
||||||
|
}
|
||||||
|
this.set('content_html', converter.makeHtml(this.get('content')));
|
||||||
|
|
||||||
|
// refactoring of ghost required in order to make these details available here
|
||||||
|
// this.set('language', this.get('language') || ghost.config().defaultLang);
|
||||||
|
// this.set('status', this.get('status') || ghost.statuses().draft);
|
||||||
|
|
||||||
|
},
|
||||||
|
|
||||||
|
creating: function () {
|
||||||
|
if (!this.get('slug')) {
|
||||||
|
this.generateSlug();
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
generateSlug: function () {
|
||||||
|
return this.set('slug', this.get('title').replace(/\:/g, '').replace(/\s/g, '-').toLowerCase());
|
||||||
|
},
|
||||||
|
|
||||||
|
user: function () {
|
||||||
|
return this.belongsTo(User, 'created_by');
|
||||||
|
}
|
||||||
|
|
||||||
|
});
|
||||||
|
|
||||||
|
Posts = Bookshelf.Collection.extend({
|
||||||
|
|
||||||
|
model: Post
|
||||||
|
|
||||||
|
});
|
||||||
|
|
||||||
|
User = Bookshelf.Model.extend({
|
||||||
|
|
||||||
|
tableName: 'users',
|
||||||
|
|
||||||
|
hasTimestamps: true,
|
||||||
|
|
||||||
|
posts: function () {
|
||||||
|
return this.hasMany(Posts, 'created_by');
|
||||||
|
}
|
||||||
|
|
||||||
|
});
|
||||||
|
|
||||||
|
Setting = Bookshelf.Model.extend({
|
||||||
|
|
||||||
|
tableName: 'settings'
|
||||||
|
|
||||||
|
});
|
||||||
|
|
||||||
|
module.exports = {
|
||||||
|
Post: Post,
|
||||||
|
Posts: Posts,
|
||||||
|
User: User,
|
||||||
|
Setting: Setting
|
||||||
|
};
|
||||||
|
}());
|
@ -1,111 +0,0 @@
|
|||||||
/**
|
|
||||||
* Database Schema, created with JugglingDB
|
|
||||||
*
|
|
||||||
* Vastly incomplete!
|
|
||||||
*/
|
|
||||||
|
|
||||||
/*globals module, require */
|
|
||||||
(function () {
|
|
||||||
"use strict";
|
|
||||||
|
|
||||||
var Schema = require('jugglingdb').Schema,
|
|
||||||
schema = new Schema('sqlite3', {
|
|
||||||
database: __dirname + '/../data/datastore.db'
|
|
||||||
}),
|
|
||||||
Post,
|
|
||||||
User,
|
|
||||||
Setting;
|
|
||||||
|
|
||||||
/*------------------------------------------------------------------------------------
|
|
||||||
POST / Post / Posts
|
|
||||||
------------------------------------------------------------------------------------*/
|
|
||||||
Post = schema.define('Post', {
|
|
||||||
title: String,
|
|
||||||
slug: String,
|
|
||||||
content: Schema.Text,
|
|
||||||
contentHtml: Schema.Text,
|
|
||||||
featured: Boolean,
|
|
||||||
image: String,
|
|
||||||
status: String,
|
|
||||||
language: String,
|
|
||||||
createdAt: Date,
|
|
||||||
createdBy: Number,
|
|
||||||
updatedAt: Date,
|
|
||||||
updatedBy: Number
|
|
||||||
});
|
|
||||||
|
|
||||||
Post.prototype.generateSlug = function () {
|
|
||||||
return this.title.replace(/\:/g, '').replace(/\s/g, '-').toLowerCase();
|
|
||||||
};
|
|
||||||
|
|
||||||
Post.prototype.preCreate = function (next) {
|
|
||||||
console.log('pre create 1', this);
|
|
||||||
|
|
||||||
if (this.createdAt === undefined) {
|
|
||||||
this.createdAt = new Date();
|
|
||||||
}
|
|
||||||
if (this.slug === undefined) {
|
|
||||||
this.slug = this.generateSlug();
|
|
||||||
}
|
|
||||||
|
|
||||||
console.log('pre create 2', this);
|
|
||||||
next();
|
|
||||||
};
|
|
||||||
|
|
||||||
// Validations
|
|
||||||
Post.validatesPresenceOf('title', {message: 'Post title cannot be blank'});
|
|
||||||
//Post.validatesPresenceOf('slug');
|
|
||||||
//Post.validatesPresenceOf('language', {message: 'Language cannot be blank'});
|
|
||||||
//Post.validatesUniquenessOf('slug');
|
|
||||||
//Post.validatesLengthOf('language', {min: 2, max: 5}, "The language code should be between 2 and 5 chars long, E.g. 'en' or 'en_GB' ");
|
|
||||||
|
|
||||||
|
|
||||||
Post.beforeSave = function (next, data) {
|
|
||||||
console.log('before s1', data);
|
|
||||||
// set updated
|
|
||||||
data.updatedAt = new Date();
|
|
||||||
next();
|
|
||||||
};
|
|
||||||
|
|
||||||
/*------------------------------------------------------------------------------------
|
|
||||||
USER / User / Users
|
|
||||||
------------------------------------------------------------------------------------*/
|
|
||||||
User = schema.define('User', {
|
|
||||||
username: String,
|
|
||||||
firstName: String,
|
|
||||||
lastName: String,
|
|
||||||
emailAddress: String,
|
|
||||||
profilePicture: String,
|
|
||||||
coverPicture: String,
|
|
||||||
bio: Schema.Text,
|
|
||||||
url: String,
|
|
||||||
createdAt: Date,
|
|
||||||
createdBy: Number,
|
|
||||||
updatedAt: Date,
|
|
||||||
updatedBy: Number
|
|
||||||
});
|
|
||||||
|
|
||||||
|
|
||||||
/*------------------------------------------------------------------------------------
|
|
||||||
SETTING / Setting / Settings
|
|
||||||
------------------------------------------------------------------------------------*/
|
|
||||||
Setting = schema.define('Setting', {
|
|
||||||
key: String,
|
|
||||||
value: Schema.Text,
|
|
||||||
createdAt: Date,
|
|
||||||
createdBy: Number,
|
|
||||||
updatedAt: Date,
|
|
||||||
updatedBy: Number
|
|
||||||
});
|
|
||||||
|
|
||||||
|
|
||||||
/*------------------------------------------------------------------------------------
|
|
||||||
RELATIONSHIPS
|
|
||||||
------------------------------------------------------------------------------------*/
|
|
||||||
User.hasMany(Post, {as: 'posts', foreignKey: 'createdBy'});
|
|
||||||
Post.belongsTo(User, {as: 'author', foreignKey: 'createdBy'});
|
|
||||||
|
|
||||||
schema.autoupdate();
|
|
||||||
|
|
||||||
exports.schema = schema;
|
|
||||||
}());
|
|
@ -16,7 +16,10 @@
|
|||||||
"underscore": "*",
|
"underscore": "*",
|
||||||
"showdown": "*",
|
"showdown": "*",
|
||||||
"sqlite3": "2.1.7",
|
"sqlite3": "2.1.7",
|
||||||
"jugglingdb": "0.2.x",
|
"bookshelf": "0.1.x",
|
||||||
|
"knex": "0.1.x",
|
||||||
|
"when": "~2.1.0",
|
||||||
|
"jugglingdb": "0.2.0-29",
|
||||||
"jugglingdb-sqlite3": "git+https://github.com/jugglingdb/sqlite3-adapter.git#master"
|
"jugglingdb-sqlite3": "git+https://github.com/jugglingdb/sqlite3-adapter.git#master"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
|
Loading…
Reference in New Issue
Block a user