4

I'm currently building a Keystone.js project, and need to use some Express.js middleware libraries with it. Since Keystone.js is built on top of Express.js, this seemed like it would be fairly easy, but I'm running into lots of issues getting things working so far.

Here's what I'm currently trying (this is my best guess as to the correct way to do this):

In my keystone.js file (the app's main entrypoint), I'm inserting the following code directly before keystone.start():

keystone.app.use(stormpath.init(keystone.app, {
  ...
}));

The important bit here is the keystone.app.use(...); bit -- I took a look at the Keystone.js source, and it appears that the underlying Express.js application object is exposed as keystone.app, which is why I'm attempting to use it this way.

Unfortunately, while my Keystone web server starts when running $ node keystone.js, trying to load any page on my site results in the following exception:

$ node keystone.js

------------------------------------------------
KeystoneJS Started:
keystone is ready on port 3000
------------------------------------------------

TypeError: Object #<Object> has no method 'regenerate'
    at doSignin (/Users/rdegges/Dropbox/Code/testing/keystone/node_modules/keystone/lib/session.js:38:15)
    at Promise.<anonymous> (/Users/rdegges/Dropbox/Code/testing/keystone/node_modules/keystone/lib/session.js:72:5)
    at Promise.<anonymous> (/Users/rdegges/Dropbox/Code/testing/keystone/node_modules/keystone/node_modules/mongoose/node_modules/mpromise/lib/promise.js:177:8)
    at Promise.EventEmitter.emit (events.js:95:17)
    at Promise.emit (/Users/rdegges/Dropbox/Code/testing/keystone/node_modules/keystone/node_modules/mongoose/node_modules/mpromise/lib/promise.js:84:38)
    at Promise.fulfill (/Users/rdegges/Dropbox/Code/testing/keystone/node_modules/keystone/node_modules/mongoose/node_modules/mpromise/lib/promise.js:97:20)
    at Promise.resolve (/Users/rdegges/Dropbox/Code/testing/keystone/node_modules/keystone/node_modules/mongoose/lib/promise.js:114:23)
    at Promise.<anonymous> (/Users/rdegges/Dropbox/Code/testing/keystone/node_modules/keystone/node_modules/mongoose/node_modules/mpromise/lib/promise.js:177:8)
    at Promise.EventEmitter.emit (events.js:95:17)
    at Promise.emit (/Users/rdegges/Dropbox/Code/testing/keystone/node_modules/keystone/node_modules/mongoose/node_modules/mpromise/lib/promise.js:84:38)
    at Promise.fulfill (/Users/rdegges/Dropbox/Code/testing/keystone/node_modules/keystone/node_modules/mongoose/node_modules/mpromise/lib/promise.js:97:20)
    at /Users/rdegges/Dropbox/Code/testing/keystone/node_modules/keystone/node_modules/mongoose/lib/query.js:1400:13
    at model.Document.init (/Users/rdegges/Dropbox/Code/testing/keystone/node_modules/keystone/node_modules/mongoose/lib/document.js:250:11)
    at completeOne (/Users/rdegges/Dropbox/Code/testing/keystone/node_modules/keystone/node_modules/mongoose/lib/query.js:1398:10)
    at Object.cb (/Users/rdegges/Dropbox/Code/testing/keystone/node_modules/keystone/node_modules/mongoose/lib/query.js:1155:11)
    at Object._onImmediate (/Users/rdegges/Dropbox/Code/testing/keystone/node_modules/keystone/node_modules/mongoose/node_modules/mquery/lib/utils.js:137:16)

I've got MongoDB running locally just fine, and if I comment out my code above things work as expected, so I know this is the root cause.

Any help would be appreciated.

rdegges
  • 32,786
  • 20
  • 85
  • 109
  • When say "trying to load any page on my site" do you mean Keystone routes (i.e. `/keystone/*`) or routes from your own site? – JME Feb 23 '15 at 23:51
  • Forgot to ask, what version of KeystoneJS are you using? – JME Feb 24 '15 at 00:24
  • Ah, I'm basically opening my browser and navigating to localhost:3000 -- that's what I mean by *trying to load any page on my site* -- sorry for the ambiguity. Also: I'm using keystone 0.3.0. My project was generated by the keystone yeoman generator stuff, so it's the stock install. – rdegges Feb 25 '15 at 00:29
  • One last question before I post my suggested answer. At what point within your startup script (I'm assuming `keystone.js`) did you put the `keystone.app.use(stormpath.init(...))`? Can you share your `keystone.js` file? – JME Feb 25 '15 at 05:11
  • Sure: here's my full keystone.js file: http://pastie.org/9981967 I put it directly above the `keystone.start()` bit (this seemed like the appropriate place). Thanks for so much time / help! – rdegges Feb 25 '15 at 18:45
  • 1
    Excellent ... thank you! Let me do some troubleshooting to see if I can find the issue for you. – JME Feb 26 '15 at 07:12
  • Did you find the solution on this.. I mstuck on same problem – Naeem Shaikh Apr 23 '15 at 11:31
  • @JME.. i want Keystone routes `(i.e. /keystone/*)` , to have my own authentication middleware.. – Naeem Shaikh Apr 23 '15 at 11:37

1 Answers1

3

You can pass an already existing express instance into keystone before you initialise keystone using the 'app' object on keystone. Which you can read about here:

http://keystonejs.com/docs/configuration/#options-concepts

EDIT* from comments for updated docs:

https://keystonejs.com/documentation/configuration/project-options

Theres even a little extra bit of text describing how to pass in your own express instance and how it changed with newer versions of express.

var express = require('express'),
app = express(),
keystone = require('keystone'),
serve = require('serve-static'),
favicon = require('serve-favicon'),
body = require('body-parser'),
cookieParser = require('cookie-parser'),
multer = require('multer');

var cookieSecret = 'secretCookie'

//Add your middleware
app.use(cookieParser(cookieSecret));
app.use(body.urlencoded({ extended: true }));
app.use(body.json());
app.use(multer());
keystone.init({
  'name': 'Website Name',
  'brand': 'Website Brand',
  'session': false,
  'updates': 'updates',
  'auth': true,
  'user model': 'User',
  'auto update': true,
  'cookie secret': cookieSecret
});

// Let keystone know where your models are defined. Here we have it at the `/models`
keystone.import('models');

// Serve your static assets
app.use(serve('./public'));

// This is where your normal routes and files are handled
app.get('/', function(req, res, next) {
  res.send('hello world');
});
keystone.app = app;
keystone.start();

Then keystone will use your instance of express which will allow you to add all the middleware as if it is express on its own before you initialise keystone.

  • The Keystone docs page which mentions overwriting the default express app is "[project options](https://keystonejs.com/documentation/configuration/project-options)" – Dylan Landry Nov 26 '18 at 16:29
  • Thanks @DylanLandry - i know this is late but I'll update the answer. I guess they probably updated their docs. – Jeremy Hindle Feb 09 '19 at 15:37