hapijs / glue

Server composer for hapi.js
Other
245 stars 62 forks source link

Using glue with hapi-mongoose #118

Closed Calinou closed 6 years ago

Calinou commented 6 years ago

Context

What are you trying to achieve or the steps to reproduce?

I'm wondering how to make hapi-mongoose's database connection object available in plugins without copy-pasting too much code around. From what I've seen, it should also be available in require()'d route handlers (which I've had trouble doing).

I tried appending them to server.app in my main index.js file, but server.app was still empty in any plugins. I also tried defining methods that retrieved the hapi-mongoose objects and using server.bind(). I even tried creating a dedicated models plugin, adding it as a dependency and loading routes in the after callback, without success.

Here's the manifest I'm using:

const manifest = {
  server: {
    host: "localhost",
    port: 3000,
  },
  register: {
    plugins: [
      {
        plugin: "blipp",
        options: {
          showAuth: true,
        },
      },
      {
        plugin: "hapi-mongoose",
        options: {
          url: "mongodb://localhost:27017",
          promises: "native",
          mongooseOptions: {
            dbName: "myDatabase",
          },
        },
      },
      {
        plugin: "./notifications",
        routes: {
          prefix: "/api/notifications",
        },
      },
    ],
  },
};

For the record, the hapi-mongoose utility objects can be accessed like this:

// Database connection object
server.plugins["hapi-mongoose"].connection
// Used to define schemas and models
server.plugins["hapi-mongoose"].lib
WesTyler commented 6 years ago

I'm not sure what the question is here. You've already found where the connection object is available, at server.plugins["hapi-mongoose"].connection.

The register function of all of your plugins get passed the server parameter, and you can access the server object on request handlers in your plugins via request.server as well.

Calinou commented 6 years ago

@WesTyler Thanks for the reply :smiley:

I ended up placing models in separate files, therefore I had to find out a way to make the hapi-mongoose objects available in schema files; I passed the server object to the require() function which returns the schema. It's not ideal as it still requires copy-pasting two lines in each schema, but I can deal with that.

index.js

exports.register = server => {
  // Load models
  server.app.Notification = require("./models/notification")(server);

  // ...

models/notification.js

module.exports = server => {
  const db = server.plugins["hapi-mongoose"].connection;
  const Schema = server.plugins["hapi-mongoose"].lib.Schema;

  return db.model(
    "Notification",
    new Schema({
      // ...
    }),
  );
};

I think this is resolved for now, so I'll close this issue.

WesTyler commented 6 years ago

Ah, ok, I see now. Thanks for clarifying.

FWIW, that's a similar pattern we use when we need props or methods on the server object inside of plugin application logic.

Glad you found a working solution 👍

dellamina commented 6 years ago

@Calinou Nice solution, I took it one step further:

// index.js
exports.register = server => {
  const hapiMongoose = server.plugins["hapi-mongoose"];
  const mongo = {
    db: hapiMongoose.connection,
    mongoose: hapiMongoose.lib,
    Schema: hapiMongoose.lib.Schema
  }
  server.app.Notification = require("./models/notification")(mongo);

and then in your model you can take advantage of object destructuring like so:

// models/notification.js
module.exports = mongo => {
  const { db, mongoose, Schema } = mongo;
lock[bot] commented 4 years ago

This thread has been automatically locked due to inactivity. Please open a new issue for related bugs or questions following the new issue template instructions.