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

@alkocats/http-ts

v0.6.4

Published

A Typescript HTTP server wrapper with express.

Downloads

105

Readme

http-ts

Build
Status Maintainability Test Coverage npm version MIT License Known Vulnerabilities dependencies Status devDependencies Status

Installation

npm install @alkocats/http-ts

Usage

Example

All relevant imports for a minimal setup:

import { HttpGet, HttpServer, HttpForbiddenError, SimpleRepository, HttpController, HttpResponse, HTTP_STATUS } from '@alkocats/http-ts';

The user interface for the user repository:

interface User {
    name: string;
    password: string;
}

The user repository for the stored data the controller uses:

class UserRepository extends SimpleRepository<User[]> {
    public async getAsyncData(): Promise<User[]> {
        return this.data;
    }

    public async addUser(name: string, password: string): Promise<void> {
        this.data.push({
            name: name,
            password: password
        });
    }
}

The user controller, which handles the user requests, equipped with different GET-methods:

class UserController extends HttpController<UserRepository> {
    /**
     * Define a GET-method for the url /users.
     */
    @HttpGet('/users')
    public getUsers(): User[] {
        return this.repository.getData();
    }

    /**
     * Define a asynchronous GET-method for the url /async-users.
     */
    @HttpGet('/async-users')
    public async getAsyncUsers(): Promise<User[]> {
        return await this.repository.getAsyncData();
    }

    /**
     * Define a asynchronous GET-method for the url /async-users-with-http-response and a custom http code
     */
    @HttpGet('/async-users-with-http-response')
    public async getAsyncUsersWithHttpResponse(): Promise<HttpResponse> {
        const data = await this.repository.getAsyncData();

        return new HttpResponse(data, HTTP_STATUS.CODE_202_ACCEPTED);
    }

    /**
     * Define a asynchronous POST-method for the url /async-post-data which handles JSON bodies
     */
    @HttpPost('/post-data/:username')
    public async postAsyncData(options: HttpRequestOptions): Promise<User[]> {
        const name = options.request.params.username;
        const password = options.request.body.password;
    
        this.repository.addUser(name, password);

        return this.repository.getAsyncData();
    }

    /**
     * Define a GET-method for the url /faulty-users which throws a HTTP error.
     * None HTTP errors are automatically transformed to HTTP 500 error.
     */
    @HttpGet('/faulty-method')
    public faultyMethod(): HttpResponse {
        throw new HttpForbiddenError();
    }
}

Bringing it all together:

const userRepository = new UserRepository([{
    name: 'admin',
    password: 'the-cake-is-a-lie'
}]);
const userController = new UserController(userRepository);

const httpServer = new HttpServer();
httpServer.registerController(userController);
httpServer.start();

Basic JWT / bcrypt Authentication

All relevant imports for a minimal setup:

import * as bcrypt from 'bcrypt';
import { Authenticated, HttpController, HttpGet, HttpServer, JwtAuthenticator, SimpleRepository } from '@alkocats/http-ts';

The user interface for the user repository:

interface User {
    email: string;
    password: string;
}

The data interface for the data repository:

interface Data {
    foo: number;
    bar: string;
}

The data repository for the stored data the controller uses:

class DataRepository extends SimpleRepository<Data[]> {
    public getSecretData(): Data[] {
        return [{
            foo: 0,
            bar: 'top secret'
        }];
    }
}

const dataRepository = new DataRepository([{
    foo: 1,
    bar: 'no secret data'
}]);

The data controller, which handles all data requests.

class DataController extends HttpController<DataRepository> {
    /**
     * A unauthaenticated get method which can be called by everyone
     */
    @HttpGet('/data')
    public getDataUnauthenticated() {
        return this.repository.getData();
    }

    /**
     * An authenticated get method, which can only be called by authenticated
     * users who deliver a valid bearer token.
     */
    @Authenticated()
    @HttpGet('/data-authenticated')
    public getDataAuthenticated(): Data[] {
        return this.repository.getSecretData();
    }
}

const dataController = new DataController(dataRepository);

Bringing it all together:

async function main() {
    // To login with a valid password, the password needs to be hashed with bcrypt
    const hashedPassword = await bcrypt.hash('the-cake-is-a-lie', 10);

    // This repository is used by the JwtAuthenticator and contains all valid logins.
    const userRepository = new SimpleRepository<User[]>([{
        email: '[email protected]',
        password: hashedPassword
    }]);

    // The secret for JwtAuthenticator to use for encryption / decryption.
    const secret = 'some-secret';

    /**
     * The path '/auth' defines, where to make a post with email / password
     * as a json object to obtain a valid bearer token.
     * The token then can be used to access @Authenticated methods of the
     * registered controllers.
     */
    const authenticator = new JwtAuthenticator<User>('/auth', {
        // Defines the repository with all the valid logins
        repository: userRepository,
        // Defines, which field of the repository data is used for identification
        identificationKey: 'email',
        // Defines, in which field of the repository data the hashed password is stored
        passwordKey: 'password',
        // Defines the expiration time of generated tokens (still valid after restart of server)
        expiresIn: 86400,
        // Defines the secret JWT uses to encrypt / decrypt the generated tokens.
        secret: secret
    });

    const httpServer = new HttpServer(80, authenticator);

    httpServer.registerController(dataController);
    httpServer.start();
}

main();

After everything is implemented, a POST to http://localhost/auth with the JSON data

{
    "email": "[email protected]",
    "password": "the-cake-is-a-lie"
}

generates a bearer token, wich can be used in future requests to access @Authenticated methods of the registered controllers.

Alternatively a custom Authenticater can be created by creating a class which extends Authenticator.

API

Supported HTTP Methods

@HttpGet(path: string)

@HttpPut(path: string)

@HttpPost(path: string)

@HttpDelete(path: string)

@HttpPatch(path: string)

@HttpHead(path: string)

@HttpTrace(path: string)

@HttpConnect(path: string)

Contributing

Feel free to create branches or pull requests.