0

I am trying to implement a db access layer within my koa application. This works fine:

var sqlite3 = require('co-sqlite3');
var services = require('./services/services');

app.use(function *(next){
    this.db = yield sqlite3(services.file);
    yield next
});

but I don't want to expose the database to every middleware in the app. In order to prevent this, I tried running .setup() outside of the middleware: services.setup(); which is defined as:

var models = require('../models/models');
var path = require('path');
var sqlite3 = require('co-sqlite3');


module.exports = {
    file: path.join(__dirname, '../data/db.db'),
    setup: function () {
        var database = yield sqlite3(this.file);
        console.log('Database connected...');
        database.run("PRAGMA foreign_keys = ON;");
        database.run("DROP TABLE IF EXISTS BLOG_POST_BODIES; DROP TABLE IF EXISTS BLOG_POSTS;");
        database.run(models.blog_posts);
        database.run(models.users);
        console.log('database created...');

        database.run("INSERT INTO BLOG_POST_BODIES(BODY) VALUES('HELLO WORLD');");
        var x = database.run("SELECT * FROM BLOG_POST_BODIES");
        console.log(x);
    }
};

the models objects just has scripts to run to create the blog posts and user tables.

The line giving me trouble is var database = yield sqlite3(this.file); It gives me the following error:

var database = yield sqlite3(this.file);
                     ^^^^^^^
SyntaxError: Unexpected identifier

Which I guess is right because there's nothing to yield forward to. But when I make setup() a generator function it does not execute. Likewise, when I remove the yield statement it tells me that database.run is not a function.

I'm stuck on this, can't figure out how to implement it properly.

Edit:

If I make .setup() a generator function and have all the database calls yield then it creates the tables and executes everything as expected...

app.use(function *(next){
    this.db = yield services.setup();
    yield next
});

But I don't want to expose the db to all the other middlewares, so I'm back to the same original problem.

How can I set up the co-sqlite3 database without including it in my middlewares?

Redmega
  • 673
  • 5
  • 21

1 Answers1

1

Assuming service.setup() is a generator function.

A cleaner solution would be be:

app.use(function *() {
  if (!this.db) {                   // this is application context in KoaJS
    this.db = yield service.setup();
  }
  yield next;
});

app.use(function *businessLogic() {});

Other possible way will be:

app.use(function *() { });
app.use(function *() { });
co(services.setup).then(function(val) {
  var service = val;
  app.listen(3000);     // use the service variable inside
});
zeronone
  • 2,912
  • 25
  • 28
  • that will run it once (I feel dumb for not thinking of it!) But I don't want the database to be exposed like that... My database is a separate app mounted with `koa-mount`. Will the database be available in other app contexts? – Redmega Apr 30 '16 at 12:49
  • Actually if I add it as necessary to middleware called in my router that should work, right? I'll need to test it when I get home... – Redmega Apr 30 '16 at 13:10
  • The app context is shared among the requests. So every request can have access to the database. – zeronone Apr 30 '16 at 13:40