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

@jeaks03/overseer

v1.2.33

Published

Just another TypeScript Back-End framework

Downloads

98

Readme

Overseer

Overseer is a Typescript Aspect-Oriented framework for backend which takes inspiration from Spring-boot and Angular.

Installation

Before you begin, make sure your development environment includes Node.js® and an npm package manager.

Node.js

Overseer requires Node.js version 8.x or 10.x.

  • To check your version, run node -v in a terminal/console window.
  • To get Node.js, go to nodejs.org.

Creating a Overseer project is as simple as:

npx @jeaks03/typescript-base -o

The npx @jeaks03/typescript-base part creates a base for a typescript project and the -o flag lets the installer know that it is an Overseer framework and makes the proper adjustments.

Minimal 'Hello World' example

index.ts

import { Overseer } from '@jeaks03/overseer-core';
Overseer.serve(module, 8000);

my.controller.ts

import { Requisite, Pathway } from '@jeaks03/overseer-core';

@Requisite
export class MyController {

    @Pathway({ path:'/hello' })
    sayHello() {
        return {
            message: 'hello world!'
        }
    }
}

This example opens a http server that listens on port 8000 and registers a GET endpoint /hello that returns the "hello world" message. To start the application run:

npm run dev

Explaining the magic

  • The Overseer.serve(8000) line lets the framework know where the sources root is located, and what the port desired port is.
  • @Requisite makes transforms the class into an injectable and lets the framework find it. More on injectables and this decorator later.
  • @Pathway marks the method as a handler for the given path. The method is called when the endpoint is reached. More on this later.

Documentation

Section in which I explain how the framework functions.

Project Structure

For the framework to work correctly it must have it's directory structure as follows:

  • index.ts -- doesn't matter where it is. Preferably in /src
  • resources -- ( directory ) it must be one level above index.ts file. So if your main file is /src/index.ts then the resources directory must be /resources/.
  • public -- ( directory ) it must be inside the resources directory. /resources/public

In the resources directory can be stored any kind of project files you need and access them freely. Inside it is the public directory where all the files are visible to the http server.

Let's say that you have a file named index.html inside and the server open on port 8000. If you make a request on localhost:8000/index.html the file will be sent. Note: If the file is named index.html then the file will be available on both localhost:8000/index.html and localhost:8000/

Decorators

Documentation details regarding the decorators.

@Requisite -- and dependency injection

This decorator is used to mark the class as an injectable. Yes, Overseer also handles dependency injection in a manner similar to Angular's. In order to inject a requisite it must be a parameter for the constructor.

In order to let the framework find the requisites, all files that contain such classes must have their name ending in

  • .controller.ts
  • .service.ts
  • .component.ts

Example of dependency injection:

my.service.ts

import { Requisite } from '@jeaks03/overseer-core';

@Requisite
export class MyService {
    public log(message: string): void {
        console.log(message);
    }
 }

my-other.service.ts

import { Requisite } from '@jeaks03/overseer-core';
import MyService from './my.service';

@Requisite
export class MyOtherService {
   constructor(private myService: MyService) {}

    private onInit(): void {
        this.myService.log('I got initialized!');
    }
 }

@Pathway

This decorator marks a method as the handler of the given path. It requires an argument of type WayDetails which has the following attributes:

  • path -- string: the path for the endpoint to map. Default: /
  • method -- string: http method. Default: GET
  • statusCode -- number: http status code. Default: 200
  • produces -- string[]: list of content types that can be produced by this handler. Default: ['application/json']
  • consumes -- string[]: list of content types that can be consumed by this handler. Default: ['application/json', 'multipart/form-data', 'application/x-www-form-urlencoded']
  • guards -- Guard[]: list of Guard implementations. This works just like Angular's guard security. Default: []

@LifecycleEvent

This decorator is used on requisites to mark a method as a lifecycle event. These events are triggered at a certain time during their life.

It accepts a string as a sort of event type to let it know when to trigger the method. These arguments are:

  • "onInit" -- method is triggered shortly after the instantiation
  • "afterInit" -- method is triggered after all requisites have been instantiated

@OnInit

Shorthand version of @LifecycleEvent('onInit')

@AfterInit

Shorthand version of @LifecycleEvent('afterInit')

Base classes 101

RequisiteManager

This class handles and contains all the requisites.

An instance of this class can be imported under the name of Requisites as a RestrictedRequisiteManager interface.

RestrictedRequisiteManager:

interface RestrictedRequisiteManager {
    addInstance: (instance, isController?: boolean) => void;
    find: <T>(clazz: Class<T>) => T;
    findByName: <T>(className: string) => T;
    findAll: <T>(clazz: Class<T>) => T[];
}

Authentication

In order to secure your application, you must provide an implementation of this class as a requisite. The default authentication implementation provided is NoAuthentication which basically behaves as if there is no security.

In order to create an instance for any Authentication implementation you have to pass a UserProvider to the constructor. UserProvider interface is a function that looks like this: (username: string) => UserDetails | Promise<UserDetails>

Overseer ships with the following implementations:

  • NoAuthentication
  • BasicAuthentication
  • JWTAuthentication

Here is an example of how to secure your application using basic auth:

export class SecurityComponent {
    constructor(private database: DatabasePlaceHolder) { }

    @OnInit()
    secureApp() {
        const auth = new BasicAuthentication((username: string) => this.database.findUser(username));
        Requisites.addInstance(auth);
    }
}

Converter

This class can be extended to create converters that understand other content types, and it looks like this:

export class Converter {
    public getContentType(): string;

    public canRead(target: string, contentType: string): boolean;
    public canWrite(target: any, contentType: string): boolean;
    
    public doWrite(target: any): string;
    public doRead(target: string): any;
}

This documentation is a work in progress. More will be added later.

License

MIT License