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

tensil

v1.1.31

Published

Simple Express framework

Downloads

18

Readme

Tensil

Express server Service, Controller and Routing framework.

Introduction

Tensil flexible and lightweight. It intentionally leaves out opinion and focuses on painless secure routing. The idea behind Tensil is flexibilty with just enough magic. Services and Controllers can be mounted to the root router or their own router for app segregation.

Install

$ npm install tensil -s

Usage

import tensil, { Controller } from 'tensil';
import * as bodyParser from 'body-parser';

class MyController extends Controller {
  // See below for configuring Controllers & Services
  // Excluded here for clarity sake of how to wire up Tensil.
}

tensil.app.use(bodyParser.json());
tensil.app.use(bodyParser.urlencoded({ extended: true }));
tensil.app.use(bodyParser.text());
tensil.app.use(bodyParser.json({ type: 'application/json' }));

tensil
  .registerController(MyController)
  .start();

With Custom App

Using Tensil with external express() app.

import tensil from 'tensil';
import * as express from 'express';

const app = express();
tensil.app = app;

With Http Server

Using Tensil with http.createServer

import tensil from 'tensil';
import * as express from 'express';

tensil.withServer();

// OR
tensil.withServer(express());

// OR
tensil.withServer({ options });

// OR with SSL
tensil.withServer({ options }, true); // 

Server

Configuring a Tensil Service.

import tensil, { filter, Service } from 'tensil';
import { format } from 'util';

class MyService extends Service {

  filters: {
    canCreate: ['log', 'isAuthorized']
  }

  private formatMessage(message, ...args) {
    return format(message, args);
  }

  @filter
  log(req, res, next) {
    // Log a message when this filter is hit.
    console.log(this.formatMessage('Request id', 123456));
    next();
  }

  @filter
  isAuthorized(req, res, next) {
    if ('authorized')
      return next();
    res.status(403).send();
  }

}

const myService = new MyService();
// OR
tensil.registerSerivce(MyService);

Controller

Configuring a Tensil Controller.

import tensil, { action, HttpMethod } from 'tensil';
class MyController extends Tensil.Controller {

  // When a custom route or generated route
  // calls "MyController.create" as it's action method
  // the MyService filter "canCreate" is injected.

  // The result would be as if you did the following manually:
  // app.post('/user/:id?, ['Myservice.log', 'Myservice.isAuthorized', 'MyController.create'])

  policies: {
    create: ['MyService.filters.canCreate'] // 
  }
  
  // or use HttpMethod.Get 
  // or template defined in options like "find"
  // or define with path @action('get', '/some/path/:id?')
  @action() 
  find(req, res) {
    // find a record.
    res.json({});
  }

  @action(HttpMethod.Post) 
  create(req, res) {
    // create a record
    res.status(201).json({})
  }

}

const myController = new MyController('user');
// OR
tensil.registerController(MyController, 'user');

Default Action Templates

Templates allow you to map your action decorators to a key to make the defining of generated routes for controller actions less verbose. You can always override and defined a specific path.

Simply define a template below then use as:

@action('my-template-name')
create(req, res) {
  //
}
const options = {
  templates: {
   get: 'get /{{action}}',
   put: 'put /{{action}}/:id?',
   post: 'post /{{action}}',
   del: 'delete /{{action}}/:id?',
   find: 'get /{{action}}/:id?',
   create: 'post /{{action}}',
   update: 'put /{{action}}/:id?',
   delete: 'delete /{{action}}/:id?',
  }
  formattter: (key, path, type) => {
    // override default formatter function
    // to handle formatting of above templates
    // by default rest routes remove {{action}}
  }
  rest: true,
  crud: false

}

Events

A pipe "|" indicates or. By default all errors are emitted without halting by throwing an error. When options.strict is enabled then errors will be thrown. Note when NOT prodcution strict is automatically enabled when strict is undefined. This is done to ensure there are not duplicate registrations and routes in a production environment.

Listening to all events for a given group.

tensil.on(`route`, (type, ...args) => {
  // do something with route.
});

To listen to a specific event type you combine the event with the type separated by a colon. When listening to a specific event type the type is removed from the first argument.

tensil.on(`route:mounted`, (...args) => {
  // do something with route.
});

You can also listen to ALL events as follows:

tensil.on(`*`, (event, type, ...args) => {
  // do something with event.
});

Docs

See https://blujedis.github.io/tensil/

Change

See CHANGE.md

License

See LICENSE.md