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

@flink-app/flink

v0.11.0

Published

Typescript only framework for creating REST-like APIs on top of Express and mongodb

Downloads

389

Readme

FLINK

A lightweight web framework built on top of Express.

Convention based - will make assumptions depending on where in folder structure files are created and their names.

Typescript first.

Plugability - build plugins which can be reused and extend functionality of core Flink.

Structure

Flink will make assumption on what your modules are and how they should be used based on where in folder structure they are located.

By doing so you can let Flink wire up dependence injection (ish), route HTTP traffic to handlers etc.

# All source code goes here, only project configuration resides outside
src/

# HTTP handlers, Flink will treat all files as routable handlers and
# makes sure that express routes traffic to them based on path
src/handlers

# Optionally use nested "topic" folders in case if many files
src/handlers/car

# Database repositories
src/repos

# Typescript interfaces that describes API schemas. JSON schemas
# will be generated from these files on runtime.
src/schemas

# Generated caches etc - should not be version controlled!
generate/

Getting started

1. Clone template project

The template project is an empty project that contains folder structure and dependencies necessary for Flink.

Clone this and init git:

git clone FrostDigital/flink-template
mv flink-template my-project
cd my-project
rm -rf .git
git init

Note: You can easily build from scratch and install npm install @flink/flink.

2. Create App Context

Define an app context interface or type.

This is used in handlers and repos and describes the context that is available in all handlers and repos and is a way to share state in between those (for example FooRepo needs access to BarRepo).

interface AppContext extends FlinkContext {
    repos: {
        carRepo: CarRepo;
        userRepo: UserRepo;
    }
}

export default AppContext;

3. Create startup (index.ts)

Create src/index.ts where app is configured and started.

Note: It might be tempting to place app context here as well, but keep it separate to avoid circular deps.

/**
 * Main entry point for starting the service.
 *
 * Must exit with an exit code greater than 1 in case app
 * could not be started.
 */
(async function () {
    new Flink<AppContext>({
        name: "Test app",
        db: {
            uri: "mongodb://localhost:27017/test-db"
        },
        debug: false,
        // mockApi: [{ method: HttpMethod.get, path: "/user/:id" }]
    }).start();
})();

export default () => {};

Building blocks

The following building blocks exists in Flink:

  • Handler - a handler is responsible for handling API requests and return a response. Normally a handler has some type of logic and invokes a repo to CRUD data from database.
  • Repo - a repository is used to abstract data access to database. A repo is used to access a mongo db and a repo is used per collection.
  • App Context - the app context is the glue that ties parts of the app together. By defining and creating an app context you make sure that i.e. handlers can get access to repositories.
  • Schemas - models that defines API requests and responses. These are typescript interfaces which will during compile time be converted into JSON schemas used to validate requests and responses and also used to generate API documentation.
  • Flink app - is the entry
  • Plugins - plugability is built into core of Flink. These can be external npm modules, or plugins inside your project. Plugins can for example extend the request object and add additional information such as auth user which can be used in handlers. Similar to how middleware works in express although a bit more constrained.

Handlers

Handlers are placed in src/handlers/ folder. Put them directly in handlers root or group them by topic.

Example:

# In root
src/handlers/GetCar.ts

# Or group by "topic" - generally a good idea for slightly larger projects
src/handlers/cars/GetCar.ts

Handlers which are prefixed with a HTTP method will by default use that method for routing. For example a handler named GetCar.ts will assume that it will accept GET request to the provided route.

This can easily be overridden in the handlers RouteProps but might be a good idea to still stick with that convention.

Example:

export const Props: RouteProps {
    method: HttpMethod.get
}

Route props

Every handler needs to export a const named Props of type RouteProps. Flink will use this to decide how requests will be routed to the handler.

You can set http method and path with path params.

Example:

export const Props: RouteProps {
    method: HttpMethod.get
    path: "/car/:id"
}

Handler function

The handler function needs to be default exported and is used to actual handle the request.

Then handler method must be of type Handler or GetHandler.

The handler function has generic type arguments which defines:

  • Application context
  • Request schema (optional)
  • Response schema (optional)
  • Params (optional)

Note: GetHandler<Ctx, ResSchema> is just syntactic sugar since get handlers does not have request schemas so that type argument does not exist. Otherwise it is the same as Handler<Ctx, ReqSchema, ResSchema>

Flink will, during app start, analyse the handler function and make sure that schema validation happens based on these type arguments.

Example:

export const Route: RouteProps = {
  path: "/car",
};

const PostCar: Handler<any, PostCar, Car> = async ({ ctx, req }) => {
  return {
    data: {
      model: "Volvo",
    },
  };
};

export default GetCar;

Naming conventions

In Flink naming conventions is not only for a easy-to-navigate and generally consistent codebase. It is also used to extract functionality based on conventions.

Handlers

Handlers which are prefixed with a HTTP method will by default use that method.

Example:

src/handlers/PostCar.ts

This can easily be overridden in the handlers RouteProps but might be a good idea to still stick with that convention.

Example:

export const Props: RouteProps {
    method: HttpMethod.get
}

🤕 Known issues

  • Current TypeScript compiler is slow when project gets larger