npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2024 – Pkg Stats / Ryan Hefner

gluon

v1.8.4

Published

Manager of project database, models, routes, logging, authentication, roles and many more..

Downloads

74

Readme

Gluon

We can call gluon a project boss. Simply manages routes, decides which route should go first, also manages models and database connection. With gluon, project development became so much easier..

installation

add dependency gluon to dependencies or type console

npm install gluon --save

basic usage

const gluon = require('gluon');
const app = gluon();

app.listen(80);

use with external app

const gluon = require('gluon');
const express = require('express');

const app = express();
gluon({ app });

app.listen(80);

using cwd + sub location. (Note if you make your project into src directory, you need this)

const gluon = require('gluon');
const app = gluon({dir: 'src/'}); // app.js located as cwd/src/app.js

app.listen(80);

routing mechanism

create a directory that called by routes

routes/home.js

const gluon = require('gluon');
const router = gluon.router();

router.get('/', (req, res) => {
  res.send("ok");
});

module.exports = router;

app.js

const gluon = require('gluon');
const app = gluon({dir: 'src/'}); // app.js located as cwd/src/app.js

// nothing required just works
app.listen(80);

try to connect http://localhost:80/home

sub-routing and index

create a directory that called by routes

routes/home.js

const gluon = require('gluon');
const router = gluon.router();

router.get('/', (req, res) => {
  res.send("ok");
});

module.exports = router;

routes/sub/index.js

const gluon = require('gluon');
const router = gluon.router();

router.get('/', (req, res) => {
  res.send("sub");
});

module.exports = router;

routes/sub/home.js

const gluon = require('gluon');
const router = gluon.router();

router.get('/', (req, res) => {
  res.send("sub-> home");
});

module.exports = router;

app.js

const gluon = require('gluon');
const app = gluon({dir: 'src/'}); // app.js located as cwd/src/app.js

// nothing required just works
app.listen(80);

try to connect these

  • http://localhost:80/home -> "ok"
  • http://localhost:80/sub -> "sub"
  • http://localhost:80/sub/home -> "sub-> home"

Note: Gluon has order mechanism that always index is last in own group. Example:

  • Next most powered group ordered by alphabet A/B/C A/B/C.js
  • Next most powered group and index A/B A/B/index.js
  • index / index.js

database and models

Gluon uses sequelize to communicate with database. But first you must create config folder in your cwd. For example your cwd is /root/myproject/, and your project files in /root/myproject/src create config in /root/myproject/config and don't forget to add dir option to gluon's first parameter.

Note: These modules requires sequelize and config please install before using it

you can create a json file that called by default.json

default.json

{
  "database": {
    "dialect": "mysql",
    "host": "your host address",
    "user": "database user name",
    "database": "database name",
    "password": "database password"
  }
}

now create a folder in src folder that called by models

models/user.js

const Sequelize = require('sequelize');
const db = require('gluon/db');

module.exports = db.define('User', {
  account: {
    type: Sequelize.STRING(32),
    allowNull: false,
    unique: true,
    validate: {
      isAlpha: true
    }
  },

  password: {
    type: Sequelize.STRING(32),
    allowNull: false,
    validate: {
      is: /^[a-f0-9]{32}$/
    }
  },

}, {
  freezeTableName: true,
  paranoid: true
});

everything is ready, start the project. gluon will connect db automaticly and load your models immediately. use your models in router

routes/user.js

const gluon = require('gluon');
const router = gluon.router();
const user = require('../models/user');

router.get('/', (req, res) => {
    user.all().then((data) => res.json(data));
});

module.exports = router;

Other awesome features

Generic option (default: true)

if you set generic option, you get plenty of new response types.

app.use((req, res) => {
    res.ok("ok :)");
});
  • ok Everything is OK 200 (text or json)
  • notFound Can't find user or something 404 (info) {error: true, info}
  • badRequest You made wrong request 400 (requiredFields) {error: true, requiredFields}
  • validation Your request didn't passed the validation 400 (type, fields) {error: true, type, fields}
  • unauthorized You are trying to use service without authorization 401 (info) {error: true, info}
  • redirectRequest Redirects a request to another one, like use POST please (info) {error: true, info}
  • unknown Bad Error 500 (info) {error: true, info}
  • database Database error (if caused by validation then it automaticly calls) 500 (err) {error: true, info: 'Database triggered an error. Please check your request. If there is no problem then contact with service provider.'}
  • expiredToken Use when a token expires 408 (info) {error: true, info}

Ready option and Before option

use when you need to wait all gluon initial job. Its very handy option

const gluon = require('gluon');
const app = gluon({
    dir: 'src/',
    before: (app) => {
        app.use(require('compression')());
    },
    ready: (app) => {
        app.use((err, req, res, next) => {
            res.send("something wrong");
        });
    }
});

app.listen(80);

Gluon request body controller

It helps you when you need control body. Lets check examples

Note: Gluon request body controller requires generic=true

routes/user.js

const gluon = require('gluon');
const control = require('gluon/control');
const router = gluon.router();
const user = require('../models/user');

// just give model
router.get('/', control(user), (req, res) => {
    user.all().then((data) => res.json(data));
});


// or give an array
router.get('/other', control(['account', 'password']), (req, res) => {
    
});

// if you don't want to control id
router.get('/', control(user, false), (req, res) => {
    user.all().then((data) => res.json(data));
});


module.exports = router;

If request cannot pass body controller, it send badRequest.

Gluon generator

If you bored to create CRUD you can use gluon generator.

Note: This generator requires js-md5 please install before using it. With this you don't need to serialize password field. it does automaticly.

Warning: Before generator you must definitely do authentication.

supported routes

GET /
GET /all
GET /count
POST /all (filter)
POST /count (filter)
GET /:id
DELETE /:id
POST / (create new model)
PATCH /:id (update exiting model)

Example

routes/user.js

const gluon = require('gluon');
const generator = require('gluon/generator');
const router = gluon.router();
const user = require('../models/user');

generator(router, user);

module.exports = router;

Gluon logger

Starting from 1.1.0 gluon no longer uses ezlogger, we suggest to use gluon/logger.

Options

These are default values of options, you can change them using by logger.set( ) or you can install config module and create logger object (example 2)

{
  dir: './logs',
  level: 'DEBUG',
  fileFormat: 'log.{date}.txt',
  dateFormat: '{year}/{month p 2}/{day p 2}',
  fileDateFormat: '{year}.{month p 2}.{day p 2}',
  timeFormat: '{hour p 2}:{minute p 2}:{second p 2}',
  type: 'full',
  full: '{date} {time} {type} {file}:{line} {message}',
  exceptDate: '{time} {type} {file}:{line} {message}',
  simple: '{type} {message}',
  withFile: '{type} {file}:{info} {message}',
  request: '[{req.method}] {coloredStatus} {time} {req.headers.host}{req.url} from {req.ip}'
}

Create new logging type

const logger = require('gluon/logger');
logger.set('myOwnLoggerType', '{time} {file}:{line} {type} {message}');
logger.set('type', 'myOwnLoggerType');

Example

app.js

const gluon = require('gluon');
const logger = require('gluon/logger')
logger.set('type', 'full'); // logs everything.. default value: full
logger.set('dir', './logs/'); // cwd/logs

const app = gluon({log: true}); // log route actions too
app.listen(80);
logger.log('server started to listen at 80');

routes/home.js

const gluon = require('gluon');
const logger = require('gluon/logger');
const router = gluon.router();


module.exports = router;

Example 2: with config

Note: You must install config first. npm install config --save

app.js

const gluon = require('gluon');
const logger = require('gluon/logger');

const app = gluon();
app.listen(80);
logger.log('server started to listen at 80');

routes/home.js

const gluon = require('gluon');
const logger = require('gluon/logger');
const router = gluon.router();


module.exports = router;

config/default.json

{
    "logger": {
        "level": "LOG",
        "type": "myOwn",
        "myOwn": "{type} {file}:{line} {message}"
    }
}

Gluon defaults by config

config/default.json

{
    "gluon": {
        "generic": "false", // don't use generic system
        "log": "false", // don't log requests
        "dir": "./src" // where is my app.js from cwd
    }
}

Direct listen from code or config

Note: if PORT is given by environment then this port is not will be evaluated

config/default.json

{
    "gluon": {
        "listen": 80 
        // or
        "listen": {
            "ip": "1.2.3.4",
            "port": 80
        }
    }
}

or

const gluon = require('gluon');
const app = gluon({
    listen: {
        ip: "127.0.0.1",
        port: 80
    }
});

Create public folders

Note: default public folder is ./public (searching as cwd/project dir/public)

config/default.json

{
    "gluon": {
        "publicSource": "./static"
        // or
        "publicSource": [
            "./public", // public has more priority than static one
            "./static"
        ]
    }
}

or

const gluon = require('gluon');
const app = gluon({
    publicSource: './public',
});

Ignore a route

You might want to ignore a route that shouldn't routed by gluon itself. Maybe you want to use this for other purposes.

routes/authentication.js

const gluon = require('gluon');
const router = gluon.router(null, true);

router.use((req, res, next) => {
    if(authentication check..) return res.unauthorized('you must log in'); 
    next();
});

module.exports = router;

routes/logout.js

const gluon = require('gluon');
const router = gluon.router();

router.use(require('./authentication'));
router.all('/', (req, res) => {
    logout..
});

module.exports = router;

Authentication and role management

With gluon 1.3.0 token based authentication generator released. Generator uses sequelize to communicate database. Creates 2 tables, "Role" and "Token". Before doing anything, make database connection correctly. Lets look properties

config/default.json

{
    "gluon": {
        "auth": {
            "base": "token"
        }
    }
}

gluon/auth only works if you set base = "token"

config/default.json

{
    "gluon": {
        "auth": {
            "base": "token",
            "model": "user", // which model is owner of token. Make sure your model is exist in your models folder.
            "disable": false, // default= false, if you just disable authentication for some purpose, set this to true
            "expire": 43200, // default=43200, how much seconds will be need for token to expire?
            "allow": [
                "/authentication/does/not/exist/in/this/path",
                "/login", // default you can't block /login
                "/register", // same here these are default.
                "/dashboard",
                "/blabla/:id", // you can do this too. but only format is ":xxxx" nothing more, simply makes "[^\/]*" regex
                "regexp:^/damn/you/know+/regexp" // you can use regexp with this "regexp:" prefix
            ],
            "routes": {
                "/admin": "admin", // simply /admin for only "admin" role owners
                "/see": "canSee",
                "/see/important": "important", // this route will require both "canSee" and "important" roles
                "/edit/:id": "canEdit"
            },
            "token": "./token", // If you don't know what are you doing, Don't change this. This setting simply changes the token model
            "role": "./role" // Same as here if you don't know bla bla.. Don't change it..
        }
    }
}

Thats enough for configurations. Simply routes make static blocks. If you want to dynamic blocks you must use req.auth

  • req.auth.login(model): creates token for model
  • req.auth.logout(): removes token
  • req.auth.hasRole(role): checks for role
  • req.auth.addRole(role): adds role
  • req.auth.removeRole(role): removes role
  • req.auth.hasRoles(roles): checks for roles
  • req.auth.addRoles(roles): adds roles
  • req.auth.removeRoles(roles): removes roles

routes/login.js

const gluon = require('gluon');
const router = gluon.router();
const User = require('../models/user');

router.get('/', (req, res) => {
    // controls etc..
    // fetch model that defined in "gluon.auth.model"
    User.find({
        where: {}
    }).then((user) => {
        req.auth.login(user).then((token) => {
            res.ok(token.code);
        });
    });
});

module.exports = router;

routes/someServiceThatHasAuthentication.js

// note this route isn't allowed directly. Directly allowing means closing authentication for that route.
const gluon = require('gluon');
const router = gluon.router();

router.get('/:id', (req, res) => {
    // lets say i need to check some dynamic role "canEditDoor5"
    req.auth.hasRole("canEditDoor" + req.params.id).then((has) => {
        // if user has canEditDoor5 then has will be true
    });

    // you can add these roles by using some database tools or direct `req.auth.addRole`
    req.auth.addRole("canEditDoor" + req.params.id).then((role) => {

    });

    // if you want to change some user's role then
    const Role = require('gluon/role'); // gather role model
    Role.addRole(id of user, "canEditDoor5").then((role) => {

    });
});

module.exports = router;

By time tokens will stay there. You must use node-schedule or similar cron job tools. You can use this.

app.js

const gluon = require('gluon');
const schedule = require('node-schedule');
const app = gluon({
  ready: () => {
    const Token = require('gluon/token');
    schedule.scheduleJob('*/10 * * * *', () => { // remove expired tokens for every 10 minutes
      Token.destroy({
        where: {
          expire: {
            $lt: new Date
          }
        }
      });
    });
  }
});

Parameter routes

If you want to use parameter but you don't want to create single file. You can use @name syntax for folders. for ex:

/routes/index.js -> /
/routes/@id/index.js -> /:id
/routes/dashboard/@dashboard_id/index.js -> /dasboard/:dashboard_id
/routes/fridge/@id/index.js -> /fridge/:id
/routes/fridge/@id/dashboard.js -> /fridge/:id/dashboard
/routes/fridge/@id/temperature/@temperature_id.js -> /fridge/:id/temperature/:temperature_id

Logger special variables

app.js

var logger = require('gluon/logger');
var cluster = require('cluster');
logger.set('worker_id', cluster.worker ? cluster.worker.id : '-');

config

{
  "logger": {
    "level": "LOG",
    "type": "clusterLogger",
    "clusterLogger": "WORKER {var.worker_id} {date} {time} {type} {file}:{line} {message}"
  }
}