Giter VIP home page Giter VIP logo

glue's Introduction

@hapi/glue

Server composer for hapi.js.

glue is part of the hapi ecosystem and was designed to work seamlessly with the hapi web framework and its other components (but works great on its own or with other frameworks). If you are using a different web framework and find this module useful, check out hapi – they work even better together.

Visit the hapi.dev Developer Portal for tutorials, documentation, and support

Useful resources

glue's People

Contributors

adrivanhoudt avatar arb avatar boneskull avatar cjihrig avatar csrl avatar damusix avatar devinivy avatar franckstauffer avatar hgrubst avatar hueniverse avatar jarrodyellets avatar jorgecuesta avatar kevinji avatar ldesplat avatar lloydbenson avatar marsup avatar nargonath avatar nlindley avatar nwhitmont avatar saboya avatar simondegraeve avatar thody avatar vdeturckheim avatar westyler avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

glue's Issues

Using Glue with Lab

Hey, in all the examples for unit testing an API using the Lab library, they require their index.js file and use module.exports = server to get access to the server in their tests. However, with Glue we are handed back the server in the callback. How would it be possible to use these two libraries together?

dependency issue

I'm loading a local plugin with a dependency on h2o2, but seeing Unknown handler: proxy error

Ref: https://gist.github.com/danielb2/78309eaf53d533407642

If I change the order of the manifest file (loading h2o2 first), the test will pass. I could use the array syntax for registering the plugins in the correct order, but the Glue documentation leads me to believe using server.dependency will take care of it for me.

Am I missing something? I got this working just fine with 0.10.4 at one point

Supporting Server Methods

Was wondering if there was any interest/plans in support for registering server methods in the Glue manifest? It's great to be able to register plugins in this fashion and similarly be great to handle server methods in a similar manner.

No documentation on new schema

Joi of Jois, today when I deployed our API server it broke.

After digging around and some time debugging I found that plugins is no longer a property we can use in a config file, but some kind of new registrations array where you have to pass in each plugin as as an object, and a new options layout too.

Can you PLEASE document the Glue schema, and going forward advise of any changes as major is this.

Glue does not use hapi v12.x.x

Glue seems not to take the latest hapi-version as intended. To reproduce the behavior I set up a test project with the following package.json and index.js:

{
  "name": "hapi-glue-test",
  "version": "1.0.0",
  "description": "",
  "main": "index.js",
  "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1"
  },
  "author": "",
  "license": "ISC",
  "dependencies": {
    "glue": "^3.0.0",
    "hapi": "^12.1.0"
  }
}
'use strict';

const Glue = require('glue');

const manifest = {
    connections: [{ port: 3000 }],
};

const options = {
    relativeTo: __dirname,
};

Glue.compose(manifest, options, (err, server) => {
    if (err) {
        throw err;
    }

    server.start(function () {
        console.log('Server (hapi v%s)running at: %s', server.version, server.info.uri);
    });
})

If I run node index.js, the output will look like

Server (hapi v11.1.4)running at: http://matthias.local:3000

This test ran on node v5.4.0 and npm 3.3.12. Can anyone confirm that behavior?

I guess glue's dependency "hapi": "11.x.x || 12.x.x" might be the problem. I'm not sure, if I understand how that resolves. Is it like »Take the latest version of hapi that satisfies 11.x.x OR 12.x.x«?

Maybe it's a better idea to add a peer-dependency for hapi like `"hapi": ">=11 <13"?

Add server.after hook in manifest

Whilst using glue I thought it might be good if there was a hook in the manifest for server.after like there is for preConnections and prePlugins.

Thanks
Simon

Allow options in plugins...

The plugin allows me to add options to server.register() but I can't set plugin specific options. You don't really support Hapi 15 if you don't allow that.

I'll make a PR.

Breaking changes on 2.3.0 and 2.4.0

Hi,

There are a couple of commits (e3b7da5 and 3c8c1e0) that introduced breaking changes when allowing hapi>=10, since those versions require node>=4.

Applications that depend on glue@2 but still run on [email protected] (I know, enterprise) will break if re-installed, since the latest versions of hapi are using certain ES2015 features.

I would like to suggest bumping the major version and unpublishing those versions from npm.

Cheers!

Inconsistent plugin load order

I am loading my manifest using glue. The plugins section of manifest looks like this

plugins: {
'hapi-auth-jwt':{},
'./server/api/index': {}
}

My api/index calls
server.auth.strategy('token', 'jwt' ....

This call fails sometimes with the message
Authentication strategy token uses unknown scheme: jwt

It seems that the load order of the plugins are not guaranteed which is causing my problem. Is there a recommended way to address this problem?

TLS/SSL question

Hi,

I'm configuring connections like this, but hapi is not creating an https listener correctly.

const tlsOptions = {
    key: Fs.readFileSync(process.env.TLS_KEY),
    cert: Fs.readFileSync(process.env.TLS_CERTIFICATE)
};

connections: [
        {
            port: 1111,
            labels: ['service-proxy']
        },
        {
            port: process.env.HOST_PORT,
            labels: ['http']
        },
        {
            port: process.env.TLS_PORT,
            tls: tlsOptions,
            labels: ['https']
        }
    ]

I have no problem when setting the connection manually:

'use strict';
const Fs = require('fs');
const Hapi = require('hapi');

const tlsOptions = {
    key: Fs.readFileSync('./ssl/selfsigned_server_key.pem'),
    cert: Fs.readFileSync('./ssl/selfsigned_server_cert.pem')
};

// Create a server with a host and port
const server = new Hapi.Server();
server.connection({
    host: 'localhost',
    port: 8000,
    tls: tlsOptions
});

Prefix is passed only when plugin in manifest is an array

If in manifest I do:

/* omitted for brevity */
plugins: [
  {
      './app/api': {
            routes: { prefix: '/api' }
      }
   }
]

routes in ./app/api are registered without prefix.
But if I wrap in array, it does the right thing.

/* omitted for brevity */
plugins: [
  {
      './app/api': [{ // ←←
            routes: { prefix: '/api' }
      }] // ←←
   }
]

Needs clarifying the docs or fix to support both variants.

registrations documentation

For the registrations array, reading the documentation:

screen shot 2016-02-12 at 10 17 49

It reads like the format is:

{
registrations: [{
    plugin: 'pluginname',
    options: {}
}]
}

however, according to the example, it reads:

{
registrations: [{
    plugin: {
        register: 'pluginname',
        options: {}
   },
}]
}

Since it appears that both formats work, is one deprecated?

Regarding the example format, it seems to me that it is redundant to say plugin or is there something else that can be registered?

Manifest doesn't allow for other plugin options

Not sure I'm doing everything right here, but while upgrading to v3 it seems I can't have other plugin options other than select. This is an example of what I'm trying to load:

{
  "connections": [
    {
      "port": 8080,
      "labels": ["http"]
    }
  ],
  "registrations": [
    {
      "plugin": "vision",
      "options": {
        "select": "http"
      }
    },
    {
      "plugin": "visionary",
      "options": {
        "select": "http",
        "engines": {
          "html": "handlebars"
        },
        "path": "/views"
      }
    }
  ]
}

Directory scope is wrong when using rejoice from different folder.

Hey,

(I hope this issue is related to glue and not rejoice)
When installing rejoice globally, all glue plugin 'require' statements fail with such:

module.js:338
    throw err;
          ^
Error: Cannot find module 'good'
    at Function.Module._resolveFilename (module.js:336:15)
    at Function.Module._load (module.js:278:25)
    at Module.require (module.js:365:17)
    at require (module.js:384:17)
    at Object.internals.parsePlugin (/Users/me/apps/node-v0.12.2-darwin-x64/lib/node_modules/rejoice/node_modules/glue/lib/index.js:218:23)

As it seems, the 'require' statement fails since the current directory is where rejoice was installed globally instead of the current one.

rejoice with -p also doesn't fix the problem.

Thanks.

No error when registering a plugin, server silently ends

Explanation

Registering some plugins is causing my composer to kill the server process but there is no explanation or errors. If I remove this plugin registration my server stays running as expected.

Setup

Given this registrations configuration:

registrations: [
     {
        plugin: {
          register: 'lout'
        }
      }
    ] 
Composer(function (err, server) {

  if (err) {
    throw err;
  }

  server.start(() => {
    console.log('Server running at: ' + server.info.uri);
  });

});

Expected

error returned

Actual

server starts with no error then silently quits.

Make compose callback always execute async

Let me start by saying thanks for Glue - it's a great, really useful module.

One issue I have is with the compose method. It has an optional callback which can be invoked sync or async depending if any plugins being registered are themselves async (they call their next function asynchronously.)

This behaviour can cause astonishment and releases Zalgo

Would you consider forcing async behaviour with a little process.nextTick? Apologies if this has already been discussed.

Related to #14

Hapi-lts support

Hi guys,

I've noticed that in the package.json the hapi-lts isn't set as a dependency nor is it used in code. Would you accept a PR for this to be added in? Apologies if I've missed something here.

Cannot register plugins in manifest registrations

I am using this boilerplate for a project.

This is the error I get when I run npm start:

/Users/franzip/Work/project-api/node_modules/hapi/node_modules/hoek/lib/index.js:732
    throw new Error(msgs.join(' ') || 'Unknown error');
    ^

Error: Invalid register options {
  "data" [1]: {
    "dir": "/Users/franzip/Work/project-api/lib",
    "pattern": "fixtures.js"
  },
  "models" [2]: "/Users/franzip/Work/project-api/lib/models",
  "adapters" [3]: {
    "sails-mongo": {
      "pkFormat": "string",
      "syncable": true,
      "defaults": {
        "host": "localhost",
        "database": "sails",
        "port": 27017,
        "user": null,
        "password": null,
        "schema": false,
        "url": null,
        "w": 1,
        "wtimeout": 0,
        "fsync": false,
        "journal": false,
        "readPreference": null,
        "nativeParser": false,
        "forceServerObjectId": false,
        "recordQueryStats": false,
        "retryMiliSeconds": 5000,
        "numberOfRetries": 5,
        "ssl": false,
        "poolSize": 5,
        "socketOptions": {
          "noDelay": true,
          "keepAlive": 0,
          "connectTimeoutMS": 0,
          "socketTimeoutMS": 0
        },
        "auto_reconnect": true,
        "disableDriverBSONSizeCheck": false,
        "reconnectInterval": 200,
        "wlNext": {
          "caseSensitive": false
        }
      },
      "mongo": {},
      "identity": "sails-mongo"
    }
  },
  "connections" [4]: {
    "mydb": {
      "adapter": "sails-mongo",
      "host": "localhost",
      "port": 27017,
      "database": "mydb"
    }
  }
}

[1] "connections" is not allowed
[2] "adapters" is not allowed
[3] "models" is not allowed
[4] "data" is not allowed
    at Object.exports.contain.exports.reachTemplate.exports.assert.condition [as assert] (/Users/franzip/Work/project-api/node_modules/hapi/node_modules/hoek/lib/index.js:732:11)
    at Object.exports.apply (/Users/franzip/Work/project-api/node_modules/hapi/lib/schema.js:17:10)
    at module.exports.internals.Plugin.internals.Plugin.register.each [as register] (/Users/franzip/Work/project-api/node_modules/hapi/lib/plugin.js:180:22)
    at /Users/franzip/Work/project-api/node_modules/glue/lib/index.js:119:24
    at iterate (/Users/franzip/Work/project-apinode_modules/glue/node_modules/items/lib/index.js:36:13)
    at Object.exports.serial (/Users/franzip/Work/project-api/node_modules/glue/node_modules/items/lib/index.js:39:9)
    at /Users/franzip/Work/project-api/node_modules/glue/lib/index.js:117:19
    at /Users/franzip/Work/project-api/node_modules/glue/lib/index.js:129:9
    at iterate (/Users/franzip/Work/project-api/node_modules/glue/node_modules/items/lib/index.js:36:13)
    at done (/Users/franzip/Work/project-api/node_modules/glue/node_modules/items/lib/index.js:28:25)
    at /Users/franzip/Work/project-api/node_modules/glue/lib/index.js:101:13
    at /Users/franzip/Work/project-api/node_modules/glue/lib/index.js:129:9
    at iterate (/Users/franzip/Work/project-api/node_modules/glue/node_modules/items/lib/index.js:36:13)
    at done (/Users/franzip/Work/project-api/node_modules/glue/node_modules/items/lib/index.js:28:25)
    at /Users/franzip/Work/project-api/node_modules/glue/lib/index.js:92:9
    at /Users/franzip/Work/project-api/node_modules/glue/lib/index.js:129:9

I have updated most of the dependencies and this is my package.json:

"dependencies": {
    "bassmaster": "1.9.x",
    "bedwetter": "1.8.x",
    "boom": "3.1.x",
    "dogwater": "1.1.x",
    "glue": "3.1.x",
    "hapi": "12.x.x",
    "hapi-swagger": "3.3.x",
    "hoek": "3.x.x",
    "inert": "3.2.x",
    "joi": "7.2.x",
    "poop": "2.x.x",
    "vision": "4.x.x",
    "sails-mongo": "0.12.x"
  }

My manifest object looks like this (in /server.js):

var config = require('./config');
...
manifest: {
  server: {
  ...
  }, 
  connections: {
  ...
  },
  registrations: {
    {
      plugin: 'dogwater',
      options: config.dogwater
    },
    {
      plugin: 'poop',
      options: config.poop
    }
  }
}

This is /config.js:

module.exports = {
   ...
  dogwater: {
    connections: {
      mydb: {
        adapter: 'sails-mongo',
        host: 'localhost',
        port: 27017,
        database: 'mydb'
      }
    },
    adapters: {
      'sails-mongo': require('sails-mongo')
    },
    models: path.normalize(__dirname + '/lib/models'),
    data: {
      dir: path.normalize(__dirname + '/lib'),
      pattern: 'fixtures.js'
    }
  },
  poop: {
    logPath: path.join(__dirname, 'poop.log')
  }
};

The problem seems to be the object passed as option... passing an empty object makes poop registration works but not dogwater.
As stated in the docs, I'm passing the plugin name as a string and an object for the options... what am I doing wrong?

Thank you in advance!

multiple plugin instances

Hapi noob here. Trying to use multiple instances of the mysql plugin to setup different db connection pools accessible to the same route (for doing federated queries). It's not immediately obvious where in the Glue manifest to put the attributes.multiple=true. And once it is set, what is the best way to reference a specific plugin instance being that they have the same plugin name?
Any tips would be appreciated.
thx,
Larry

Conflicting routes when using prefix

I have a manifest that looks like the following,

module.exports = {
  connections: [{
    host: 'localhost',
    port: 1337
  }],
  plugins: [
    {
      blipp: null
    },
    {
      vision: null
    },
    {
      './lib/plugins/user': null
    },
    {
      './lib/plugins/admin': {
        routes: {
          prefix: '/admin'
        }
      }
    }]
};

Both plugins adds a route that looks like this,

 server.route([
  { method: 'GET', path: '/', config: indexConfig }
]);

I get Error: New route / conflicts with existing / error.

Am I setting up the manifest wrong or are my expectations of how it should work wrong?

manifest limitation on server options

Glue restricts what is passed as options to new Hapi.Server(options), only allowing 'app', 'debug' and 'cache' members to the options.

It'd be useful to be able to define the full server options that are available.

"origin" must not be a sparse array

usinge hapi 10 with node 4 in ubuntu 14. keep getting this error when starting node server. It works on my colleague's mac but not on my ubuntu 14 (which I use inside a docker container base image ubuntu).

image

here's our server code:

var Glue = require('glue');
var routes = require('./config/routes/');
require('dotenv').load();

Glue.compose(require('./config/hapi.js'), function(err, server) {

  // allow server to be used elsewhere
  module.exports = server;

  // setup authentication strategy
  server.auth.strategy('jwt', 'jwt', 'required', {
    key: process.env.JWT_SECRET,
    validateFunc: require('./utils/auth/validateToken'),
    verifyOptions: {
      algorithms: ['HS256']
    }
  });

  // register routes
  server.route(routes.routes);

  // start server
  if (!module.parent) {
    server.start(function(err) {
      if (err) {
        throw err;
      }
      server.log('Server running at:', server.info.uri);
    });
  }
});

Relative paths are bugged

You can't use a relative path to require a module from inside a module that will be stored in the node_modules folder. If you have a manifest with a path ./my-plugin, this will be resolved to require('<...>/node_modules/glue/my-plugin') because relative path used with require() are relative to the __dirname.

The solution is to use join the process.cwd to the relative paths:

path = Path.join(process.cwd(), path);

how to pass routes: { prefix: '/prefix' } for object notation

Hi,

In the documentation it's stated, that we can pass options for server.register when passing the plugin options as array, like this:

'./app/web/api/auth': [
                {routes: {prefix: '/auth'}, options: {}}
            ],

However, I assume it should be somehow possible to do the same, when registering the plugin with object as options, something like this:

'./app/web/api/users': {routes: {prefix: '/users'}},

However, it doesn't work. Any thoughts if it's possible?

Regards,

Parsing $env from manifest JSON outside of server config

I had occasion to pass environment variables in to my application via the manifest file, and wanted to do so in the same manner that you can specify the server port as $env.port for instance. I achieved this by specifying the environment variables as strings in the JSON file like $env.MY_CUSTOM_KEY and then after require-ing the JSON file to create the manifest object, I looped over the area I had specified these values and pulled in the actual values using process.env() like so:

  if (manifest.server.app.config) {
    var value;
    Object.keys(manifest.server.app.config).forEach(function (conf) {
      value = manifest.server.app.config[conf];
      if (value.indexOf('$env') !== -1) {
        manifest.server.app.config[conf] = process.env[value.replace('$env.','')];
      }
    });
  }

I'd like to propose having this functionality built in (implemented in a better fashion, naturally) but I'm not sure whether this should happen in Glue (because of the relevance of the manifest file to Glue) or in hapi itself (because the processing that pulls out the $env for port etc happens there).

Could someone provide guidance on this? Or kill the whole idea for a reason I'm not thinking of?

I'll fork and PR once I know the preferred location for this functionality, if any.

Thanks

using Hoek.clone makes some plugins stop working

glue will call Hoek.clone in the parsePlugin method. This has the effect that some plugins stop working as expected when the values passed in the plugin options are objects or functions (in particular, streams).

Below is a simple demo that exhibits the problem. It just loads the good plugin and passes an instance of a stream to the options (from good-console). It should output some info about the server load every 1s, but an error is thrown:

Error: no writecb in Transform class

If we comment the Hoek.clone call, it works as expected.

The problem will be present whenever the user needs to access the same value that is given in the plugin options (not a clone).

// npm install glue good good-console
const Glue = require('glue');
const GoodConsole = require('good-console');

const internals = {};

internals.goodOptions = {
    ops: {
        interval: 1000
    },
    reporters: {
        'foo': [
            new GoodConsole(),
            'stdout'
        ]
    }
};

internals.manifest = {
    connections: [{ port: 8888 }],
    registrations: [{
        plugin: {
            register: 'good',
            options: internals.goodOptions
        }
    }]
};

Glue.compose(internals.manifest, (err, server) => {

    server.start();
});

Registration schema `select` option not implemented properly in 3.x

Using version: 3.2.0

I have the following manifest:

//manifest.js
var manifest = {
  connections:[
    {
      host: appname.host,
      port: appname.port.web,
      labels: ['web']
    },
    {
      host: appname.host,
      port: appname.port.client,
      labels: ['app-client']
    }
  ],
  registrations: [
    {
      plugin: {
        register:'../services/app-client',
        options: {
          select: ['app-client']
        }
      }
    }
  ]
};

I am getting an error in my plugin when trying to use server.listener:

//services/app-client/index.js
var SocketIO = require('socket.io');

exports.register = function appClient(server, options, next){

  var io = SocketIO(server.listener);

  io.sockets.on('connection', function(socket){
    console.log("new connection!");
    socket.emit("app_connected", {
      msg: "app client connected"
    })
  });

  next();
}

Here's the error:

if ('object' == typeof srv && !srv.listen) {

TypeError: Cannot read property 'listen' of null

However, if I change the connection passed to SocketIO(server.select('app-client').listener), then everything works as expected. The point of select in the registration options is so that you don't have to use select inside your plugin, making it adaptable across your code.

While the existing tests do allow the select option in the schema, I don't see that they actually test that the individual server.connection object is passed to the plugin. It looks like it still provides the entire server.settings object to the plugin instead.

Possible registration order / dep resolution improvement

I noticed this note here about dependency registration order. And recently saw issues #34, #19, hapijs/hapi#2803 which made me think of this. I just wrote a library named hodgepodge that reorders a list of hapi plugins to respect their attributes.dependencies. Perhaps it could be an option in glue to use this reordering.

I would otherwise suggest that a user choose to use hodgepodge on their own then pass the ordered plugin registrations to glue, but glue's manifest is not a standard plugin registrations list that could be passed to server.register().

It's just a thought to potentially make glue a little more deterministic– not sure if the community would genuinely find this useful, but figured it would be worth putting the option out there.

SyntaxError: Use of const in strict mode.

When I run the plugin it throws this error:

/src/node_modules/glue/node_modules/hapi/lib/index.js:5
const Server = require('./server');
^^^^^
SyntaxError: Use of const in strict mode.
    at Module._compile (module.js:439:25)
    at Object.Module._extensions..js (module.js:474:10)
    at Module.load (module.js:356:32)
    at Function.Module._load (module.js:312:12)
    at Module.require (module.js:364:17)
    at require (module.js:380:17)
    at Object.<anonymous> (/src/node_modules/glue/lib/index.js:4:12)
    at Module._compile (module.js:456:26)
    at Object.Module._extensions..js (module.js:474:10)
    at Module.load (module.js:356:32)

No CORS options response when vhost is configured

If I configure a vhost for routes in a plugin, the CORS options requests results in a 404 response.

It can be reproduced with the following example;

var Glue = require('glue'),
    Hapi = require('hapi');
    Config = require('./lib/config');

var manifest = {
    connections: [
        {
            port: Config.port
        }
    ],
    plugins: {
        './web': [{
            routes: {
                vhost: 'example.com'
            }
        }],
        './plugins/rethink': Config.rethink,
        'good': Config.monitor
    }
};

var options = {
    relativeTo: __dirname + '/lib'
};

Glue.compose(manifest, options, function (err, server) {

    if (err) {
        throw err;
    }

    server.start(function () {

        console.log('Hapi days!');
    });
});

If I comment out the vhost option, the CORS response is returned as expected.

How can I pass a callback function for the plugin i.e "next" in the manifest file?

This is my manifest.js :

'use strict';

let Database = require('../database/database');
const redis = require('../database/redis');

const database = Database.database;

module.exports = {
    server: {
        debug: {
            request: ['info', 'error'],
            log: ["error"]
        },
        cache: [{
            // Omitted name so that this becomes the default
            // cache client
            engine: "catbox-redis",
            host: "...",
            partition: "def"
        }]
    },
    connections: [
        {
            port: 8003,
            labels: ["..."],
            router: {
                stripTrailingSlash: true
            }
        },
        {
            port: 8004,
            labels: ["..."],
            router: {
                stripTrailingSlash: true
            }
        }
    ],
    registrations: [
        {
            plugin:  {
                register: "./some-module",
                options: {
                    database: database,
                    redis: redis
                }
            },
            options: {
                select: ['...']
            }
        },
       ...
        }
    ]

};

Where can I pass the callback for a plugin??

In the classical method:

server.register(require('myplugin'), (err) => {
    if (err) {
        console.error('Failed to load plugin:', err);
    }
});

I need this callback to execute some code

where can I specify this in manifest??

Testing a hapi service composed using glue

When I wasn't using glue to compose the server, the way I tested my code was pretty straight-forward. I exported the Hapi server instance from the index.js file and then, in the test modules, I required it and used the server.inject method to test the endpoints of my API.

However, using glue my index turned into something like this, with the server instance being available asynchronously:

index.js:

var Glue = require('glue');
var manifest = require('./config/manifest.json');
var options = {
    relativeTo: process.cwd() + '/lib/modules'
};

Glue.compose(manifest, options, function (err, server) {
    server.start(function () {
        server.log('info', 'Server running at: ' + server.info.uri);
    });
};

So now, trying to figure out how may be the best way to export that server variable to make it accessible to the test modules, I've come up with this solution. I don't know if I'm doing the right thing, so I'm seeking advice:

index.js:

var Glue = require('glue');
var manifest = require('./config/manifest.json');
var options = {
    relativeTo: process.cwd() + '/lib/modules'
};

var compose = function (callback) {
    Glue.compose(manifest, options, function (err, server) {
        if (!module.parent) {
            server.start(function () {
                server.log('info', 'Server running at: ' + server.info.uri);
            });
        }

        if (typeof callback !== 'undefined') {
            callback(null, server);
        }
    });
};

// If this module is not being required by another one, compose the server.

if (!module.parent) {
    compose();
}

module.exports = compose;

Then the index.js would be required from the tests this way:

test/whatever.js:

var composedServer;

require('../')(function (err, server) {
    composedServer = server;
});

Any opinions would be very appreciated.

Thanks!

Matias

Cant get a basic NodeJS script working with HapiJS & Glue

I'm reading the Developing a Hapi Edge book, and wanted to try to get a basic HapiJS API server going using Glue, the JS is pretty much right from the book, and even took some of the plugins out, but it looks like it should work: http://pastebin.com/x6Wftvhd (Transpiled ES5 version: http://pastebin.com/PH9qiFut)

However, it returns an error in the console:

$ node dist/app.js 
/Users/me/Documents/scripts/js/node/test/hapi/hapi_server/node_modules/glue/node_modules/joi/lib/index.js:141
                throw error;
                ^

ValidationError: Invalid manifest {
  "connections": [
    {
      "port": 8080,
      "labels": [
        "http"
      ]
    },
    {
      "port": 8088,
      "labels": [
        "api"
      ]
    }
  ],
  "plugins" [1]: {
    "good": {
      "opsInterval": 5000,
      "reporters": [
        {
          "reporter": "good-console",
          "events": {
            "ops": "*",
            "log": "*"
          }
        }
      ]
    }
  }
}

[1] "plugins" is not allowed
    at Object.internals.Err.toString.exports.process (/Users/me/Documents/scripts/js/node/test/hapi/hapi_server/node_modules/glue/node_modules/joi/lib/errors.js:140:19)
    at internals.Any.applyFunctionToChildren.internals.Any._validateWithOptions (/Users/me/Documents/scripts/js/node/test/hapi/hapi_server/node_modules/glue/node_modules/joi/lib/any.js:654:27)
    at root.validate (/Users/me/Documents/scripts/js/node/test/hapi/hapi_server/node_modules/glue/node_modules/joi/lib/index.js:102:23)
    at root.attempt (/Users/me/Documents/scripts/js/node/test/hapi/hapi_server/node_modules/glue/node_modules/joi/lib/index.js:131:29)
    at root.assert (/Users/me/Documents/scripts/js/node/test/hapi/hapi_server/node_modules/glue/node_modules/joi/lib/index.js:126:14)
    at Object.exports.compose.steps.push.steps.push.steps.push.steps.push.Items.serial [as compose] (/Users/me/Documents/scripts/js/node/test/hapi/hapi_server/node_modules/glue/lib/index.js:43:9)
    at Object.<anonymous> (/Users/me/Documents/scripts/js/node/test/hapi/hapi_server/dist/app.js:60:6)
    at Module._compile (module.js:399:26)
    at Object.Module._extensions..js (module.js:406:10)
    at Module.load (module.js:345:32)

Any ideas?

'relativeTo' option usefulness

Have you thought about the logging reporters and the way they are loaded? For example:

'plugins': {
  'good': {
    'reporters': [{
      'reporter': 'good-console',
      'args':[{ 'log': '*' }]
    }]
  },
  './my-plugin': {}
}

The relativeTo property is not taken into consideration when requiring the reporter, and you could be using be a reporter that's not available in the npm registry:

https://github.com/hapijs/good/blob/master/lib/monitor.js#L125

Therefore, you need to write:

'plugins': {
  'good': {
    'reporters': [{
      'reporter': './plugins/my-reporter',
      'args':[{ 'log': '*' }]
    }]
  },
  './my-plugin': {}
}

And it makes no sense to have a relativeTo property because you are obligated to hardcode the relative path anyway. So, for me it's better to just ignore the 'relativeTo' property and always hardcode all the paths.

'plugins': {
  'good': {
    'reporters': [{
      'reporter': './plugins/my-reporter',
      'args':[{ 'log': '*' }]
    }]
  },
  './plugins/my-plugin': {}
}

Just sharing my thoughts. I don't find this property very useful, it obscures information if you simply read the json file. You need to know that the custom plugins are prefixed by a path that's hidden in the source code, when in fact this path it's used by a configuration file. I'd simply remove it and bump the version to 3.0.0.

when is glue 3.x going to be completed?

I see there are no open issues and no open pull requests. I have an open PR in rejoice for upgrade to es6 type syntax but have been waiting on glue to be upgraded since I am relying on that and it seemed there would be breaking changes with the new version. Is there a timeline on this? If its going to be a long time I guess I'll have have to release again when it's finally done. I am trying to align with most of the other projects that have been upgraded already.

Loading manifest into an existing server

Any chance of an alternate mechanism for glue to load a manifest into an existing server object? My use case is for a 'reusable' server that forces consistent log, ops, security, and documentation plugins. One way to do that might be to 'preload' a number of plugins into a server, and then load a manifest on top of the existing server. Composition of this 'standard' server would then consist of specific API plugins and their requirements. There are other ways to do this, but I thought I'd ask...

add support for preConnection and preRegister options handlers

It would be useful to pass function handlers in the Glue.compose() options in order to manipulate the server at each stage. Example:

var Glue = require('glue');
var options = {
  relativeTo: __dirname,
  preConnection: function (server, next) {
     next();
  },
  preRegister: function (server, next) {
     server.app.shared = someValue;
     next();
  },
};
Glue.compose(require("./manifest.json"), options, function (err, server) {
  server.start();
});

The idea being that it would be possible to set up the server prior to loading plugins.

Is this something you'd consider supporting?

Thanks.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.