Giter VIP home page Giter VIP logo

electrode-server's Introduction

Electrode Server NPM version Build Status Dependency Status

This is an imaginatively named, configurable web server using Hapi.js atop Node.js.

The aim is to provide a standardized node web server that can be used to serve your web application without the need for duplicating from another example, or starting from scratch.

The intention is that you will extend via configuration, such that this provides the baseline functionality of a Hapi web server, and within your own application you will add on the features, logic, etc unique to your situation.

This module requires Node v8.x.x+.

Table Of Contents

Installing

npm i --save electrode-server

Usage

Electrode Server comes with enough defaults such that you can spin up a Hapi server at http://localhost:3000 with one call:

require("electrode-server")();

Of course that doesn't do much but getting a 404 response from http://localhost:3000. To handle your routes, you should create a Hapi plugin to install your handlers. See below for configuration options on how to register your plugin through electrode-server.

Configuration

You can pass in a config object that controls every aspect of the Hapi server.

For example, if you want to spin up a server with HTTP compression off at port 9000:

const config = {
  connection: {
    port: 9000,
    compression: false
  }
};

require("electrode-server")(config);

However, for a more complex application, it's recommended that you use a config composer such as electrode-confippet to manage your app configuration.

Configuration Options

Here's what you can configure:

All properties are optional (if not present, the default values shown below will be used).

server.app.config is set to a object that's the combination of your config with electrode-server's defaults applied.

server (Object)

Default:

{
  server: {
    app: {
      electrode: true;
    }
  }
}

connection (Object)

  • Connection to setup for the Hapi server. Contains connection details for the server.
  • If you want multiple connections, you can start multiple instances of electrode-server

Default:

{
  connection: {
    host: process.env.HOST,
    address: process.env.HOST_IP || "0.0.0.0",
    port: parseInt(process.env.PORT, 10) || 3000,
    routes: {
      cors: true
    }
  }
}

connections Object in previous Electrode no longer supports multiple connections. Only the default is allowed.

      {
        connections: {
          default: {
            host: process.env.HOST,
            address: process.env.HOST_IP || "0.0.0.0",
            port: parseInt(process.env.PORT, 10) || 3000,
            routes: {
              cors: true
            }
          }
        }
      }

plugins (Object)

Default is just empty object:

{
  plugins: {
  }
}

listener (function)

  • A function to install event listeners for the electrode server startup lifecycle.

  • The following events are supported:

    • config-composed - All configurations have been composed into a single one
    • server-created - Hapi server created
    • plugins-sorted - Plugins processed and sorted by priority
    • plugins-registered - Plugins registered with Hapi
    • server-started - Server started
    • complete - Final step before returning

To receive events you must set config.listener before calling electrodeServer.

For example:

myConfig.listener = (emitter) => {
  emitter.on("server-created", (data, next) => {
    // do something
    next();
  });
});
  • The data object will contain these: emitter, server, config, and plugins.

  • Depending on the stage some may not be present. For example, server is not available until server-created event and plugins is not available until plugins-sorted event.

  • These are async events so you have to take and call a next callback.

http2 (Object)

Note: Requires version ^3.2.0 or ^2.4.0

To enable http2, set http2.enable to true. All options are passed to createSecureServer().

{
  "http2": {
    "enable": true,
    "key": Fs.readFileSync('./ssl/site.key'),
    "cert": Fs.readFileSync('./ssl/site.crt')
  }
}

keepAliveTimeout (integer)

NodeJS defaults to 5 seconds keep-alive timeout. electrode-server defaults to 60 seconds timeout. If you want a custom timeout, use the keepAliveTimeout option (in milliseconds).

{
  "electrode": {
    "keepAliveTimeout": 60000
  }
}

logLevel

You can control how much output the Electrode Server logs to the console by setting the logLevel.

  • Levels are "info", "warn", "error", "none".
  • A level of "warn" means only warnning and error messages will be printed.
  • Default is "info"

For example, to suppress the banner that is shown when the server starts up:

Hapi.js server running at http://mypc:4000

set the logLevel to "warn" or "error":

{
  electrode: {
    logLevel: "warn";
  }
}

electrode-confippet

To keep your environment specific configurations manageable, you can use electrode-confippet.

Once you have your config files setup according to the configuration files setup, you can simply pass the config object to electrode server.

const config = require("electrode-confippet").config;

require("electrode-server")(config);

Adding a Hapi plugin

You can have electrode-server register any Hapi plugin that you want through your configuration file.

{
  plugins: {
    "<plugin-id>": {
      enable: true,
      options: {},
      priority: 210,
      register: function () {}, // mutual exclusive with module
      module: "<plugin-module-name>",
      requireFromPath: process.cwd()
    }
  }
}

Plugin configs

  • <plugin-id> - ID for the plugin. Generally the module name for the plugin, which is used to load it for registration.
  • register - optional The register function to pass to Hapi. Overrides module.
  • module - optional name of the module to load for the plugin instead of the <plugin-id>
  • requireFromPath - optional The path from which to call require to load the plugin module
  • enable - optional if set to false then this plugin won't be registered. If it's not set then it's considered to be true.
  • options - optional Object that's passed to the plugin's register function.
  • priority - optional integer value to indicate the plugin's registration order
    • Lower value ones are register first
    • Default to Infinity if this field is missing or has no valid integer value (NaN) (string of number accepted)

About Plugin Priority

Priority allows you to arrange plugins to be registered in an order you prefer. The plugins with lower priority values are registered first.

More about register and module

If you don't want to use <plugin-id> to load the module, then you can optionally specify one of the following:

  • register - if specified, then treat as the plugin's register function to pass to Hapi, overides module
  • module - Only used if register is not specified
    • If it's a string the used as the name module to require for registration.
    • It it's false then electrode server will not load any module.
    • You can specify a require-from-path for the module using an object.
        {
          plugins: {
            myPlugin: {
              module: {
                requireFromPath: process.cwd(),
                name: "my-plugin-module"
              }
            }
          }
        }

Exporting your Hapi Plugin from a module

Electrode server will try to find your Hapi Plugin from your module by looking through these fields:

  1. mod.hapiPlugin
  2. mod.default.hapiPlugin
  3. mod.default
  4. mod itself

Examples:

  1. Exporting the plugin directly as the module:

CommonJS example:

module.exports = myHapiPlugin;

ES6 example:

export default myHapiPlugin;
  1. Exporting the plugin as a field named hapiPlugin:

CommonJS example:

module.exports.hapiPlugin = myHapiPlugin;

ES6 example:

const hapiPlugin = myHapiPlugin;
export hapiPlugin;

ES6 default:

export default {
  hapiPlugin: myHapiPlugin
};

More about requireFromPath

There are three places you can specify a path to call require from when loading your plugin modules.

  1. config.plugins.requireFromPath - The top one used for all plugins
  2. config.plugins.<plugin-id>.requireFromPath - Used for the specific plugin of <plugin-id>, overrides the one above
  3. config.plugins.<plugin-id>.module.requireFromPath - Used for the specific plugin of <plugin-id>, overrides the two above

For more information: check out require-from-path

Example: crumb

Here's an example using the crumb plugin:

First, install the plugin as you normally would from npm:

npm i --save crumb

Then, add your plugin to the config plugins section.

{
  plugins: {
    "crumb": {
      enable: true,
      options: {},
      priority: 210,
      requireFromPath: process.cwd()
    }
  }
}

Above config tells electrode-server to require from CWD the module by its <plugin-id> "crumb" and register it as a plugin with Hapi.

API

The electrode server exports a single API.

electrodeServer(config, [decors], [callback])

  • config is the electrode server config

  • decors - Optional extra config or array of config. In case you have common config you want to put inside a dedicated module, you can pass them in here.

    • If it's an array like [ decor1, decor2, decor3 ] then each one is composed into the main config. ie: something similar to _.merge(mainConfig, decor1, decor2, decor3).
  • callback is an optional errback with the signature function (err, server)

    • where server is the Hapi server
  • Returns: a promise resolving to the Hapi server if callback is not provided

Contributions

Make sure you sign the CLA. Checkout the contribution guide

To run tests

% npm i
% clap test

To run tests and coverage

% clap check

To run sample server

% npm run sample

Hit http://localhost:9000

Publishing

  • Require access to npmjs.org to publish this package.
  • Run npm version to update the version. Commit with tags
  • Run npm publish to publish
  • Update CHANGELOG.md

License

Copyright 2016-present WalmartLabs

Licensed under the Apache License, Version 2.0.

electrode-server's People

Contributors

aisapatino avatar ameyakoshti avatar ananavati avatar bodawei avatar caoyangs avatar danielb2 avatar datvong-wm avatar dmikey avatar jasonwilson avatar jchip avatar jprogrammer avatar scrajesh avatar tiffine-koch 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

electrode-server's Issues

Warning when runs with custom config

I run electrode with NODE_ENV=demo and I get a warning that says Electrode Server Notice: NODE_ENV (demo) should be empty or one of development,staging,production,test, is this expected? the demo.json itself only contains {}.

screenshot from 2016-10-28 13-53-53

screenshot from 2016-10-28 14-02-03

How to add custom deployment config?

I want to have a staging environment, how to add the config for it? when I add staging.json in electrode config folder and run the server with NODE_ENV=staging, its complain it cannot found staging.json

screenshot from 2016-10-26 10-47-12

How do I configure cookies in electrode server?

I'm trying to get cookie info from the req object. I see how to configure a cookie in hapi.js but how do I pass or configure a cookie in electrode-server? Do I need to pass in a "server" configuration or a "connection" configuration in config/default.json?

Is there already a default cookie configuration in electrode?

On sever start it shows

The server does not work on public ipadress of the server but if we run it on private IP server runs properly is this problem on sever or the electrode server?

Unhandled rejection Error: listen EADDRNOTAVAIL XXX.XXX.XXX.XXX:6180
at Object.exports._errnoException (util.js:1018:11)
at exports._exceptionWithHostPort (util.js:1041:20)
at Server._listen2 (net.js:1245:19)
at listen (net.js:1294:10)
at net.js:1404:9
at _combinedTickCallback (internal/process/next_tick.js:83:11)
at process._tickCallback (internal/process/next_tick.js:104:9)

Use namespaced configuration in confippet

Is it possible to place server configuration into a namespaced section of Confippet? I would like to add my own options to my default.json (for authentication keys, etc), and it seems grody to have a section that also gets thrown to electrode-server.

Thoughts?

Timeout variable

Keep getting an error on electrode server register plugins timeout, is there a way to increase that time limit?

"Unknown handler: file" error when tutorial app is launching on Heroku

Walking through the tutorial documentation and I receive this error when trying to start the app on Heroku.

Starting standalone server in PROD mode

ESERVERSTART

This error is thrown by the electrode-server module
There was an error starting the Hapi.js server
Please check the output of the stack trace below and correct the error shown
error, please file an issue on the electrode-server repository

If you have followed this resolution step and you are still seeing an

git+https://github.com/electrode-io/electrode-server.git

Unknown handler: file
at internals.Connection._addRoute (/app/node_modules/hapi/lib/connection.js:412:19)
Unhandled rejection Error: Unknown handler: file
at Object.exports.assert (/app/node_modules/hapi/node_modules/hoek/lib/index.js:736:11)
at Object.exports.defaults (/app/node_modules/hapi/lib/handler.js:108:14)
at new module.exports.internals.Route (/app/node_modules/hapi/lib/route.js:60:37)
at Object.target [as register] (/app/node_modules/hapi/node_modules/joi/lib/object.js:77:34)
at internals.Connection._route (/app/node_modules/hapi/lib/connection.js:404:18)
at internals.Plugin._apply (/app/node_modules/hapi/lib/plugin.js:588:14)
at internals.Plugin.route (/app/node_modules/hapi/lib/plugin.js:558:10)
at Object.plugin.register (/app/server/plugins/pwa.js:7:10)
at each (/app/node_modules/hapi/lib/plugin.js:318:14)
at iterate (/app/node_modules/hapi/node_modules/items/lib/index.js:36:13)
at Promise (/app/node_modules/electrode-server/lib/electrode-server.js:118:14)
at Object.exports.serial (/app/node_modules/hapi/node_modules/items/lib/index.js:39:9)
at internals.Plugin.register (/app/node_modules/hapi/lib/plugin.js:321:11)
at Promise._execute (/app/node_modules/bluebird/js/release/debuggability.js:300:9)
at Promise._resolveFromExecutor (/app/node_modules/bluebird/js/release/promise.js:481:18)

Register plugins is taking a while - If this takes longer than 10 seconds, then
double check your plugins to make sure each one calls next() at the end.
Server will automatically abort after 20 seconds.

State changed from starting to crashed
Process exited with status 0

Configuration when using cloud9 as a dev platform

Hello,

I use cloud9 as a dev platform, it is a dev environment hosted on the cloud : the IDE is in the browser.

I managed to configure my electrode app to make it reachable from the outside (localhost is not an option asmy app is running on cloud9 server) :

I edited the development.json file

{
    "connections": {
        "default": {
            "port": 8081,
            "host": "<cloud 9 workskapce hostname>",
            "compression": false
        }
    }
}

and I can reach my app with http://<cloud 9 workskapce hostname>:8081.

So far, so good.
However, the static resources (css & js file) are not loaded as they are referenced as:
http://localhost:2992/js/style.css
and
http://localhost:2992/js/bundle.dev.js

From what I understood, webpack is serving those files.

Is their a way to configure the host and port of webpack as I did for my electrode server ?

Thanks in advance,
Cheers

Christophe

Register plugins failed from electrode app server

I am new for Electrode. I tried to implement 'electrode-app as per the document. When i run the below command after created electrode-app folder and got an error message as mentioned in the below image. Could you please help me to fix this issue?
$ clap dev
image

Extending archetypes webpack loaders without forking project?

I followed the procedure outlined in the tutorial for adding material-ui to the boilerplate application and had no problems. I am trying to use webpack-bootstrap (https://github.com/gowravshekar/bootstrap-webpack), but it's README specifies that I need to use specific loaders in my webpack configuration (webpack.config.modules.loaders). I see that the webpack configuration lives inside electrode-archetype-react-app archetype module, how can I modify the webpack loaders list in my project?

I could not find any information on http://electrode.io regarding this information.

Errors in `createReduxStore` are not logged

Thank you for making Electrode! I have been trying to learn this (and React + Redux) and my experience has been great so far.

Problem

I have recently ran into trouble when I tried to get Redux state initialization in the server working.

  1. I generated a new app using the Yeoman generator.

  2. I ran gulp dev

  3. I figured that I would have to edit server/views/index-view.js createReduxStore to initialize the state server-side.

  4. I had a JS reference error in my code that took me a while to figure out. Basically, my code was like this:

        function createReduxStore(req, match) { // eslint-disable-line
          const initialState = {
            checkBox: {checked: false},
            number: {value: 999}
          };
    
          i_am_undefined(); // <---- this should throw 
    
          const store = createStore(rootReducer, initialState);
          return Promise.resolve(store);
        }

Current behavior

I was expecting the call to i_am_undefined() to throw something like Unhandled rejection ReferenceError: i_am_undefined is not defined. Unfortunately, no errors were logged in the console. Opening the app in the browser results in generated HTML but with an empty state:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>electrode-test</title>
    
    <link rel="stylesheet" href="http://127.0.0.1:2992/js/style.css" /><script src="http://127.0.0.1:2992/js/bundle.dev.js"></script>
</head>
<body>
<div class="js-content"></div>
<script>if (window.webappStart) webappStart();</script>
</body>
</html>

The browser console shows an error log but does not exactly inform me of my issue:

electrode-test

Questions

  • How do I configure the app so that the undefined error is logged? I tried but could not find any information on this.
  • Is there another way to debug issues like this? I tried debugging with VS code but the debug just skipped that part where there was an exception and continued with the server process.

Upgrade to hapi v18

With the recent release of hapi v18 just wondering the plans for the upgrade.

We are successfully using this release via yarn resolutions, the only change that we have had to do is biding directly to a host when inside cloud foundry process.env.VCAP_APP_HOST, 0.0.0.0 as the new URL parsing has change the way requests are handled slightly

Console colors

  • Problem

    • I am using plugins I usually use from Hapi.js, blipp and good but the console output does not correctly display colors.
  • Question

    • How can I make colors display correctly in the console?

Upgrade electrode-server version

I got error while running. xaa.each().finally() not a function.

TypeError: xaa.each(...).finally is not a function
at registerPlugins (/app/node_modules/electrode-server/lib/electrode-server.js:267:15)

I debug it there is no finally function in xaa.each method.

After that inert lib(repo) issue deprecated. I update with @hapi/inert but this requires hapi >= 19 and your electrode have 18 version of hapi.

Can you please help me with that.

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.