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

larvitbase

v4.0.98

Published

http application base framework

Downloads

805

Readme

Build Status

Micro web framework

Index

What is it?

Top

A scaled down version of Express. It is as micro as micro can be, it only runs an array of middlewere functions, nothing more.

Why?

Top

  • More flexibility due to all functionality being in the middleware functions (no built-in "helpers", router, view system etc)
  • In contrast to Express, it is possible to run a middleware before the router, or after the controller
  • Better separations of concerns (routing, view system etc should not be a part of the base framework!)
  • No dependencies in production (only development dependencies)
  • Less is more

Installation

Top

npm i larvitbase

Usage

Top

In case you're building a full webb system, you probably want to go directly to larvitbase-www or if you're building an API, you might want to look at larvitbase-api. Both of these is larvitbase plus some middlewares to handle the basics of each scenario.

Minimal basic example

Top

This will create a http server on port 8001 that will print "Hello world" whatever you send in.

const	App	= require('larvitbase');

let app = new App({
	'httpOptions': 8001, // Listening port
	'middlewares': [
		function (req, res) {
			res.end('Hello world');
		}
	]
});

app.start(function (err) {
	if (err) throw err;
});

Routing

Top

Routing is how to match a special URL to a specific piece of code or pieces of code.

There is no built in routing, but it is easy to make your own or use the more fully fledged larvitrouter.

Roll your own

Top

Something like this:

const	App	= require('larvitbase');

let	app;

function router(req, res, cb) {
	if (req.url === '/') {
		req.controller	= controllerOne;
	} else if (req.url === '/foo') {
		req.controller	= controllerTwo;
	} else {
		req.controller	= notFound;
	}
	cb();
}

function runController(req, res, cb) {
	req.controller(req, res, cb);
}

function controllerOne(req, res, cb) {
	res.end('This is controllerOne! Hepp!');
}

function controllerTwo(req, res, cb) {
	res.end('This is the second controller function! Hola!');
}

function notFound(req, res, cb) {
	res.statusCode	= 404;
	res.end('The URL matched no controller. Ledsen i ögat. :(');
}

app = new App({
	'httpOptions': 8001, // Listening port
	'middlewares': [
		router,	// First run the router
		runController	// Then run the routed controller
	]
});

app.start(function (err) {
	if (err) throw err;
});
Test your application

From the path of your application, type:

node ./index.js

Then go to a browser and go to http://localhost:8001 and you should see "This is controllerOne! Hepp!". Test the URL:s /foo and /something as well and see what happends.

larvitrouter

Top

For a bit larger application, it is often desireble with a more competent router. For this we have larvitrouter. It will resolve paths to controller files as well as template files and static files. See the documentation for an in depth guide. Here follows a small example:

First install it:

npm i larvitrouter
index.js
const Router = require('larvitrouter'),
      router = new Router(),
      App    = require('larvitbase');

let	app;

function runRouter(req, res, cb) {
	router.resolve(req.url, function (err, result) {
		req.routeResult = result; // Store the route result on the request so we can access it from elsewhere
		cb(err);
	});
}

function runController(req, res, cb) {

	// A controller file was found!
	if (req.routeResult.controllerFullPath) {
		const controller = require(req.routeResult.controllerFullPath);
		controller(req, res, cb);

	// No controller file was found
	} else {
		res.statusCode	= 404;
		return res.end('Not found');
	}
}

app = new App({
	'httpOptions': 8001, // Listening port
	'middlewares': [
		runRouter,
		runController
	]
});

app.start(function (err) {
	if (err) throw err;
});
controllers/foo.js

To make the URL /url work on our application, we create this file and save it like this:

'use strict';

exports = module.exports = function controllerFoo(req, res, cb) {
	res.end('Foo custom page');
	cb();
}
controllers/default.js

The default controller is a bit special. It will match both / and /default.

'use strict';

exports = module.exports = function controllerFoo(req, res, cb) {
	res.end('Default page');
	cb();
}

Templates

Top

In this section we're going to implement EJS template engine.

First install dependencies:

npm i larvitbase ejs

Files

Top

index.js
const ejs	= require('ejs'),
      App = require('larvitbase');

let	app;

function controller(req, res, cb) {
	// Set some different data depending on URL
	res.data	= {};

	if (req.url === '/') {
		res.data.someText	= 'First page';
	} else if (req.url === '/foo') {
		res.data.someText	= 'A sub page';
	} else {
		res.data.someText	= 'No page';
	}

	cb();
}

function renderTemplate(req, res, cb) {
	res.body	= ejs.render('<html><body><h1><%= someText %></h1></body></html>', res.data);
	res.end(res.body);
	cb();
}

app = new App({
	'httpOptions': 8001, // Listening port
	'middlewares': [
		controller,
		renderTemplate
	]
});

app.start(function (err) {
	if (err) throw err;
});

Forms

Top

To parse forms (and file uploads, url parameters and more) we can use larvitreqparser.

Install dependencies:

npm i larvitbase larvitreqparser

index.js

const ReqParser	= require('larvitreqparser'),
      reqParser = new ReqParser(),
      App       = require('larvitbase');

let	app;

function controller(req, res, cb) {
	res.body = '<html><body><form method="post">';
	res.body += '<p>Write something: <input name="foo" /></p>';
	if (req.formFields && req.formFields.foo) {
		res.body += '<p>Something was written: "' + req.formFields.foo + '"</p>'
	}
	res.body += '<p><button type="submit">Click me</button></p>';
	res.body += '</body></html>';

	res.end(res.body);
	cb();
}

app = new App({
	'httpOptions': 8001, // Listening port
	'middlewares': [
		reqParser.parse.bind(reqParser),
		controller
	]
});

app.start(function (err) {
	if (err) throw err;
});

Static Files

Top

To feed static files, we are going to use a router to determine if the URL points to a static file, and then send to stream the file to the client.

Install dependencies:

npm i larvitbase larvitrouter send

index.js

const Router = require('larvitrouter'),
      router = new Router({'staticsPath': __dirname + '/public'}), // This is the default, but we're explicit here
      send   = require('send'),
      App    = require('larvitbase');

let	app;

function runRouter(req, res, cb) {
	router.resolve(req.url, function (err, result) {
		req.routeResult	= result;
		cb(err);
	});
}

function controller(req, res, cb) {

	// Static file found! Stream it to the client.
	if (req.routeResult.staticFullPath) {
		send(req, req.routeResult.staticFullPath).pipe(res);

		// End the controller here, nothing more should be sent to the client
		return cb();
	}

	// What to show if no static file is found:
	res.body = '<html><body><h1>Show a static file:</h1>';
	res.body += '<p><a href="foo.txt">foo.txt</a></p>';
	res.body += '</body></html>';

	res.end(res.body);
	cb();
}

app = new App({
	'httpOptions': 8001, // Listening port
	'middlewares': [
		runRouter,
		controller
	]
});

app.start(function (err) {
	if (err) throw err;
});

public/foo.txt

Just save a text file with whatever content in hour applications path + public/foo.txt

Error handling

Top

In case something goes wrong inside any of your middlewares and an error is returned, we need to handle that somehow. This is how:

const App = require('larvitbase');

let app;

app = new App({
	'httpOptions': 8001, // Listening port
	'middleware': [
		function (req, res, cb) {
			return cb(new Error('Something went wrong! :('))
		}
	]
});

// Handle errors in one of the middleweres during a request
app.on('error', function (err, req, res) {
	res.statusCode	= 500;
	res.end('Internal server error: ' + err.message);
});

app.start(function (err) {
	if (err) throw err;
});

Logging

Top

The App takes a log option and it requires it to be an object with the following methods: silly(), debug(), verbose(), info(), warn() and error().

Historically we've used winston, but any object with the above methods will work fine. If no log instance is supplied, an instance of larvitutils Log will be used with level "info".

Log levels used:

  • error - Fatal! Application should not continue to run at all
  • warn - Important problem. Application might be able to continue, but this should be addressed to maintain stability.
  • info - Important information. Probably not a problem, but information of high value to sysops.
  • verbose - Nice-to-have information. Statistis about each request run time and such.

Do not use in production

  • debug - Debug information. Further statistics and other debug info. Will flood your logs if used in production!
  • silly - Silly amounts of information. Will flood your logs even if not in production, your terminal will explode.

Middleware functions

Top

Middleware functions are compatible with Express, and follow the same principles:

Middleware functions can perform the following tasks:

  • Execute any code.
  • Make changes to the request and the response objects.
  • End the request-response cycle.
  • Call the next middleware function in the stack.

Larvit middlewares

Top