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

nodebox-framework

v1.2.1

Published

node/express framework based on Coldbox

Downloads

169

Readme

Nodebox

Lightweight Node/Express framework based on Coldbox

What is Nodebox?

Nodebox is a lightweight framework for Node that acts as an Express middleware to quickly set up routes based on file system paths. Nodebox handles all of your routing, and follows simple rules to translate urls into object and function calls so you can worry about creating your project instead of how to wire everything up.

Installation

Pull Nodebox into your project and initialize it:

npm install nodebox-framework
npx nodebox init

This will set up your package.json and the basic directory structure needed, which looks like:

    /
  - handlers/
  - views/
  - layouts/
  - public/ (this is where you can put assets like css, images, or external javascript files)
    - css

To see the test site, run:

npm start

Manual Installation:

After installing the package, add it as middleware:

const express  =  require('express');
const app  =  express();
const Nodebox = require('nodebox-framework').Nodebox;

const nodeBox = new Nodebox({loglevel:'debug'});

app.use(nodeBox.getMiddleware(app));

// Listen to port 3000
app.listen(3000, function () {
	console.log('Dev app listening on port 3000!');
});

The different loglevels available are:

  • TRACE
  • DEBUG
  • INFO (default)
  • WARN
  • ERROR

How it works

Nodebox translates your urls into system calls. For example, if you went to the url:

<site>/home/about

Nodebox translates that call to load a handler named home (that returns a class), and call the about method. (which renders things). The handlers are stored in the /handlers folder of your project.

For the above example, the directory structure would look like:

/
  - handlers/
    - home.js
  - views/
  - layouts/

Nodebox also supports more complex urls by nesting the directory structure. A url like /home/foo/bar would be supported by a directory structure like:

/
  - handlers/
    - home/
      -foo.js
    - home.js
  - views/
  - layouts

Views, Layouts, and Handlers

Views and layouts are composed using the template functionality of lodash. As you can probably guess, these are located in the views and layouts folders respectively. A handler doesn't necessarily need a layout, but it does need a view to know HOW to render.

There are a couple of different ways to assign views, layouts, and variables but the easiest is to initialize the Nodebox router with a config object that contains everything it needs.

Below is an example handler:

const NodeboxHandler = require('nodebox-framework').NodeboxHandler;

class Main extends NodeboxHandler {
    preEvent() {
        console.log('preEvent happens here!');
    }

    postEvent() {
        console.log('postEvent happens here!');
    }

    home() {
        this.log.info('In Home');
        this.nbr.set({
            view: 'home.html',
            layout: 'layout.main.html',
            useLayout: true,
            vars: {
                subtitle: 'varSubtitle',
                view:{
                    viewvar: 'varviewvar!'
                }
            }
        })
        this.nbr.render();
    }

    json() {
        this.nbr.set({
            layout: 'json',
            vars: {
                foo:'foo',
                bar:'bar'
            }
        })
        this.nbr.render();
    }
}

module.exports = Main;

The first thing to note is that your handler must extend the NodeboxHandler class. This gives you a built in constructor that take the express req and res objects, as well as a loglevel. The built in constructor also gives you an instance of the Nodebox Renderer at this.nbr and the logger at this.log. If you want to override the default log level, you can do so by adding a constructor to your class that looks like:

class MyClass extends NodeboxHandler {
    constructor(req, res) {
        super(req, res, 'debug'); //add your loglevel as the third argument
    }
}

Finally, set up your handler method (in this case, I'm writing one for the default event: main/home:

home() {
        this.nbr.set({
            view: 'home.html',
            layout: 'layout.main.html',
            useLayout: true,
            vars: {
                subtitle: 'varSubtitle',
                view:{
                    viewvar: 'varviewvar!'
                }
            }
        })
        this.nbr.render();
    }

The Nodebox Renderer

Let's break down the config object above.

  • view: the view you want to render (located relative to /views)
  • layout: the layout you want to render (located relative to /layouts) - NOTE: There is a special built-in json layout you can use to render json data
  • useLayout: directs the renderer to use a layout or to just render the view
  • vars: template variables for replacement (lodash template). All the variables in the view object are passed directly into the view template.

Finally, call render on the Nodebox renderer to send a response back through express.

Example Layout

<head>
    <link rel='stylesheet' href='/css/main.css'/>
</head>
<div id="container">
    <h1> Layout!</h1>
    <h3><%= subtitle %></h3>
    <div id="view">
        <%= view %>
    </div>
</div>

In the example above, you can see some of lodash's template engine at work. You can reference any variable passed in the var structure here. Also of note, the special view variable is the location in the page that the view is rendered.

Example View

<h2>text from home.html</h2>
<p>view var: <%= viewvar %></p>

Much in the same way the layout works, the view also uses the lowdash templating. In addition, you can see the viewvar variable from the original structure being used here.

Rendering JSON

Here is an example of a handler method that returns json. Note, whatever is in the vars object gets sent to the browser:

json() {
    this.nbr.set({
        layout: 'json',
        vars: {
            foo:'foo',
            bar:'bar'
        }
    })
    this.nbr.render();
}

Pulling it all together

The directory structure for the examples above would ultimately end up looking like this:

/
  - handlers/
    - home.js
  - views/
    - home.html
  - layouts/
    - layout.main.html
  - public/
    - css/
      -main.css

Advanced concepts

As you might have noticed, there are preEvent and postEvent functions in the handler. This is a special interface that Nodebox looks for in every handler that lets you run arbitrary code before and after a handler function is executed. You can use this for things like checking to see if a user is authenticated before executing anything in that handler.

To stop processing, return false from the preEvent in your handler, and the route's main event and postEvent won't fire.