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 🙏

© 2025 – Pkg Stats / Ryan Hefner

@rromadhoni/fastisfy

v0.2.1

Published

A fast and simple framework for building REST APIs with Fastify using filesystem routing

Downloads

22

Readme

Fastisfy

Fastisfy is a satisfyingly fast and simple web framework to build REST APIs with Node.js with the power of Fastify. You can define routes using Next.js-like API and use the power of Fastify to build your APIs.

Pre-requisites

  • Node.js 16 or higher
  • npx (comes with npm 5.2+)

Usage

Create api directory in your project root and create hello.js file in it.

export const get = async (req, reply) => {
  reply.send({ hello: "world" });
};

Run npx @rromadhoni/fastisfy dev to start the development server. You will be able to access your API at http://localhost:3000/hello, and it will return { "hello": "world" }.

Deployment

Run npx @rromadhoni/fastisfy start to start the production server. Everything is the same as the development server, but it is optimized for production.

Environment Variables

Fastisfy uses dotenv to load environment variables from .env file. You can create .env file in your project root to define environment variables. For example, if you want to define PORT environment variable, you can create .env file with the following content:

PORT=3000

Note that different command will prefer to load environment variables from different files. For example, npx @rromadhoni/fastisfy dev will load environment variables from .env.development file, and npx @rromadhoni/fastisfy start will load environment variables from .env.production file. However, if the file does not exist, it will fallback to .env file.

API

Custom server.js

You can create server.js file in your project root to customize the server. The file should export a function that takes Fastify instance as an argument.

export default async function server(fastify) {
  await fastify.register(require("fastify-cors"), {
    origin: true,
  });
}

Route Parameters

You can use parameters in your routes by adding [parameter] to the route path. For example, if you want to create a route that returns the name of the user, you can create users/[id].js file and use req.params.id to get the user ID.

import { Type } from "@sinclair/typebox";

export const get = async (req, reply) => {
  const user = await getUser(req.params.id);
  reply.send({ name: user.name });
};

get.schema = {
  params: Type.Object({
    id: Type.String(),
  }),
};

Route Schema

You can define the schema of your routes by adding a schema property to the method name. For example, if you want to define the schema of GET /users/[id] route, you can create users/[id].js file and add get function and assign the schema to get.schema property. The schema itself is a Fastify schema object built with TypeBox.

import { Type } from "@sinclair/typebox";

export const get = async (req, reply) => {
  const user = await getUser(req.params.id);
  reply.send({ name: user.name });
};

get.schema = {
  params: Type.Object({
    id: Type.String(),
  }),
  response: {
    200: Type.Object({
      name: Type.String(),
    }),
  },
};

TypeScript Support

Fastisfy emits TypeScript declaration files to help you write your routes in TypeScript. You can create users/[id].ts file and use TypeScript to define your routes.

import * as fastisfy from "fastisfy";
import { Type } from "@sinclair/typebox";

const getSchema = {
  params: Type.Object({
    id: Type.String(),
  }),
  response: {
    200: Type.Object({
      name: Type.String(),
    }),
  },
};

export const get: fastisfy.RequestHandler<typeof getSchema> = async (
  req,
  rep
) => {
  const user = await getUser(req.params.id);
  rep.status(200).send({ name: user.name });
};

get.schema = getSchema;

In the above example, fastisfy.RequestHandler is a type that takes the schema object as a generic type and returns a function that takes fastify.FastisfyRequest and fastify.FastisfyReply as arguments. The schema will be automatically recognized by TypeScript and you will get type checking for your routes.

Configuration

You can create fastisfy.config.js file in your project root to customize the configuration. The file should export an object with the following properties:

  • features - An array of features to enable. Available features are:
    • cors - Enable CORS support.
    • compression - Enable compression.
    • overload-protection - Enable overload protection.
    • swagger - Enable Swagger schema generation.
  • apiDir - The directory that contains your API routes. Default is api in the cwd.

Authentication & Authorization

Fastisfy supports authentication and authorization using @fastify/auth plugin. You can create _auth.js file in your project root to define your authentication and authorization logic. The file should export the following properties:

export const authenticate = async (req, reply) => {
  // Authenticate the request
  return { id: "user-id", role: "user" };
};

The authenticate function will be called before every request and should return an object that contains the user information. The user information will be accesible in the req.requestContext property.

// api/users/me.js
export const get = async (req, reply) => {
  const user = req.requestContext.get("user");
  const profile = await getProfile(user.id);
  reply.send(profile);
};

get.allow = ["user"];

This example uses the allow property to define the roles that are allowed to access the route. If the user role is not in the allow array, the request will be rejected with 403 Forbidden error.

Fastisfy lets you define the authentication strategy in the _auth.js file. You can use any authentication strategy that is supported by Fastify. For example, if you want to use JWT authentication, you can install @fastify/jwt plugin and use it in the _auth.js file. But first you need to register the plugin in the _server.js file.

import fastifyJwt from "@fastify/jwt";

// _server.js
export default async function (app, opts) {
  await app.register(fastifyJwt, {
    secret: "supersecret",
  });
}

From there, you can use the methods provided by the plugin to authenticate the request.

// _auth.js
export const authenticate = async (req) => {
  try {
    if (!req.headers.authorization) throw new Error("No authorization header");
    return req.jwtVerify();
  } catch (error) {
    return { id: "anonymous", role: "public" };
  }
};

This example uses the jwtVerify method provided by the @fastify/jwt plugin to authenticate the request. If the request is authenticated, the method will return the user information. If the request is not authenticated, the method will throw an error and the authenticate function will return the default user information, which is an anonymous user with public role.

To test this example, you need to implement a login route that signs a JWT token and returns it to the client. You can use the jwtSign method provided by the @fastify/jwt plugin to sign the token.

// api/auth/login.js
import { Type } from "@sinclair/typebox";

export const post = async (req, rep) => {
  const { email } = req.body;
  const token = await rep.jwtSign({ id: email, role: "user" });
  rep.status(200).send({ token });
};

post.schema = {
  body: Type.Object({
    email: Type.String(),
    password: Type.String(),
  }),
  response: {
    200: Type.Object({
      token: Type.String(),
    }),
  },
};

Now you can test the authentication by sending a request to the login route and passing the token in the Authorization header to the protected route.

  1. Login
curl -X POST -H "Content-Type: application/json" -d '{"email": "[email protected]", "password": "123"}' http://localhost:3000/api/auth/login
  1. Get user profile
curl -X POST -H "Content-Type: application/json" -H "Authorization: Bearer <insert-token-here>" http://localhost:3000/api/users/me

Examples

  • Todo List - A simple todo list API using sqlite3.

License

MIT

Acknowledgements

This project was inspired by Next.js API routes.

Disclaimer

This is an experimental project, do not use this in production unless you know what you are doing.