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

tashfin

v1.0.2

Published

ZinkyJS but functional

Downloads

8

Readme

Tashfin is NodeJS framework that takes the routing and modularity of ZinkyJS and removes all other aspects.

So in TashfinJS we don't have hooks, we put away the chain of responsability of ZinkyJS and ExpressJS. Only one function is called per request.

The global idea of TashfinJS is resumed in these points:

  • Super Minimalistic, even more minimalistic than ExpressJS, and has no opinion on what you should use as DB or Template Engine, and whether to SSR or to CSR.
  • It's all about routing, The one thing that TashfinJS organises is routing, that saves you from having huge files of routing and all the problems that can result of that.
  • Use things only when you need them, making code more predictable by avoiding the chain of hooks that mutates the data through the process.

Installation

npm i tashfin

Simple Example

  const { listen } = require("tashfin");
  const homeModule = {
    GET_root: (req, res) => res.end("Hello World")
  }

  const logRequest = true;
  const modules =  {
    "": homeModule
  };

  listen({modules, logRequest});

This will start a server and listen to port 3000 and return "Hello World" on every GET request

Zinky Routing Revision

Since TashfinJS follows the same routing concept of ZinkyJS, Let's make a little revision on how ZinkyJS routing work.

This is a typical route:

/users/activate/12353

This is interpreted in ZinkyJS as:

  • users: module,
  • activate: action,
  • [12353]: params

To match that route, we must have this code:

app.js

const { listen } = require("tashfin");
const users = require("./app_modules/users");

const logRequest = true;
const modules =  { users };

listen({modules, logRequest});

app_modules/users/index.js

const GET_activate = (req, res, id) => res.end(`You activated user with id: ${id}`);

module.exports = { GET_activate }

Routing Fallbacks

As ZinkyJS, TashfinJS falls back to alternative functions if the route does not find its typical operation (the one that fits the exact module and action).

The fallback process in essence:

  • If the action is not found in the module, it looks for root in the module, and puts action as first param.
  • If root of module or module are not found, it looks for "" (home) module, and puts the not found module as action.
  • If the new action is not found in home module falls back to root in home module, and puts all url parts (split by /) as params.

If that wasn't clear enough, here are some their examples.

Action Not Found

Taking the last example, we could have made the content of users module file as following:

app_modules/users/index.js

const GET_root = (req, res, whatToDo, id) => res.end(`You did ${whatToDo} user with id: ${id}`);

module.exports = { GET_root }

In this case, TashfinJS does not find GET_activate, so it looks for GET_root.

Module Root or Module Not Found

If action is not found and GET_root in the module does not exist, the interpretation becomes as follow:

  • "": module (home)
  • users: action
  • [activate, 12353]: params

And to match that, we have to add a home module that contains GET_users. So we have:

app.js

const { listen } = require("tashfin");
const home = require("./app_modules/home");

const logRequest = true;
const modules =  { "": home };

listen({modules, logRequest});

app_modules/home/index.js

const GET_users = (req, res, whatToDo, id) => res.end(`You did ${whatToDo} user with id: ${id}`);

module.exports = { GET_root }

New Action Not in Home Module

This fallback is the last one and it points to GET_root in home module, and everything in the route is considered as params. So

app_modules/home/index.js

const GET_root = (req, res, type, whatToDo, id) => res.end(`You did ${whatToDo} one of ${type} with id: ${id}`);

module.exports = { GET_root }

Don't forget to test those codes.

The last fallback prevents server from returning 404 Not Found, if a home GET_root exists. If you want to stop this behavior add noHomeRoot to Tashfin options. as following:

app.js

const { listen } = require("tashfin");
const home = require("./app_modules/home");

const logRequest = true;
const noHomeRoot = true;
const modules =  { "": home };

listen({modules, logRequest, noHomeRoot});

No Params Action

In many cases, you'll want to make /somethings to get the list and /somethings/123 to get one thing by its id. If you restrict yourself to the rules seen above, you'll find yourself making some annoying if conditions to separate the logic. Luckily, as ZinkyJS did, TashfinJS gives a way to do that simply.

  • GET_$root: Runs if there is no params
  • GET_root: Runs if there is params or GET_$root does not exist.

So we could have that in users for example:

app_modules/users/index.js

const { res.json } = require("tashfin");

const GET_$root = (req, res) => res.json([
  { name: "Omar", age: 32 },
  { name: "Yusuf", age: 50 }
]);

const GET_root = (req, res, id) => res.json({ id, name: "Omar", age: 32 });

module.exports = { GET_root }

Operation Arguments

Each operation takes these arguments:

  • req: The http.ClientRequest passed by NodeJS.
  • res: An enhanced version of The http.ServerResponse passed by NodeJS.
  • Params: The operation params.

TashfinJS Helpers

It made available some helpers, to simplify some actions that are achieved using req and res in ZinkyJS.

Those helpers are imported directly from tashfin.

getQuery

Returns the query string of the request as json object.

Eg:

const { getQuery } = require("tashfin");

const GET_$root = (req) => {
  const query = getQuery(req.url);
  console.log(query);
  // for /users?role="admin", logs: {role: "admin"}
  return "ok";
}

module.exports = { GET_root }

getPath

Returns the path of url. Especially useful when url contains query string.

Eg:

const { getPath } = require("tashfin");

const GET_$root = (req) => {
  const path = getPath(req.url);
  console.log(path);
  // for /users?role="admin", logs: /users
  return "ok" 
}

module.exports = { GET_root }

parseBody

Returns the parsed body of the request.

Eg:

const { parseBody } = require("tashfin");

const POST_root = (req) => {
  const body = parseBody(req);
  return "ok" 
}

module.exports = { GET_root }

res.json

Responds with a json object and setting the corresponding headers.

const GET_root = (req, res, id) => res.json({ id, name: "Yusuf", age: 50 });

module.exports = { GET_root }

res.redir

redirects to a given location.

Eg:

const GET_root = (req, res) => res.redir("/dashboard") 
// redirects to "/dashboard"

module.exports = { GET_root }

res.reload

Reloads the referer. Can take an alternative path, in case the referer does not exist.

Eg:

const GET_root = (req, res) => res.reload("/dashboard") 
// reloads the page or go to "/dashboard"

module.exports = { GET_root }

res.asFile

Sends file content with its corresponding mime type.

Eg:

const GET_root = (req, res) => {
  const fileContent // you bring by some code
  const ext // you bring by some code
  return res.asFile(fileContent, ext);
}

module.exports = { GET_root }

res.file

If you didn't like you bring by some code, here is what will help you.

Eg:

const GET_root = (req, res) => {
  const filePath = "the/path/of/your/file.pdf"
  return res.asFile(filePath);
}

module.exports = { GET_root }

resDownload

Returns the headers that allow to download the file in given path.

Eg:

const GET_root = (req, res) => {
  const filePath = "the/path/of/your/file.pdf"
  return res.download(filePath);
}

module.exports = { GET_root }

TashfinJS options

Here are the options that are passed to Tashfin init.

onError

A function to run when operation fails.

logRequest

A boolean to set whether or not log requests in the console.

defaultHeaders

A function takes req as argument and returns an object with the default headers and theirs values.

logRequestDate

A boolean to set whether or not log requests date in the console.

noHomeRoot

A boolean if set to true, prevents falling back to home module root.

Featured Libraries

Check these libraries to make your life even easier.