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

@litstack/core

v1.4.0

Published

Typescript REST Framework

Downloads

15

Readme

npm version Build Status Coverage Status

Litstack

Using Angular and Spring boot design patterns, Litstack is a Typescript REST framework that Angular/Spring Boot engineers already know how to use, keeping their code organized and concise, and pushing off the express wiring to the library.

Getting Started

Option 1: Clone the seed app

Follow the directions in the litstack seed to get started right away.

Option 2: Start with a blank slate

Create a new project and install the Litstack core library.

> npm install @litstack/core --save

Make sure experimental decorators are on in your tsconfig.json at the root level:

{
    "compilerOptions": {
        "experimentalDecorators": true
    }
}

For more on building, see the minimum configuration section below.

Bootstrapping

Bootstrap app.module at the index.ts level:

// in index.ts
import { LitCompiler } from '@litstack/core/dist/compiler';

import { AppModule } from './modules/app.module';

LitCompiler.bootstrap(AppModule);

Modules

Modules can export component routes and package other modules.

Basic Module

This module will export app.component's routes.

// in app.module.ts
import { LitModule } from '@litstack/core';

import { AppComponent } from './app.component';

@LitModule({
    exports: [
        AppComponent
    ]
})
export class AppModule {
}

Module with Imports

Modules can also import other modules with components:

import { LitModule } from '@litstack/core';

import { ItemsModule } from  './modules/items/items.module';
import { OrdersModule } from  './modules/orders/orders.module';
import { PeopleModule } from  './modules/people/people.module';
import { VersionComponent } from  './components/version/version.component';

@LitModule({
    path: 'api', // will add all imported routes at '/api/..'
    imports: [ 
        ItemsModule,
        PeopleModule,
        OrdersModule
    ],
    exports: [
        VersionComponent
    ]
})
export class AppModule {
}

Components

Components register route listeners:

Basic Component

// in app.component.ts
import { LitComponent } from '@litstack/core';
import { HttpResponse } from '@litstack/core/dist/http';
import { GetMapping } from '@litstack/core/dist/http/mappings';

@LitComponent()
export class AppComponent {

    private message = 'Hello World!';

    @GetMapping() // defaults to '/'
    onHello(res: HttpResponse): void {
        res.success({
            message: this.message
        });
    }
}

Using path params

Specify params in the path:

import { LitComponent } from '@litstack/core';
import { HttpRequest, HttpResponse } from '@litstack/core/dist/http';
import { GetMapping } from '@litstack/core/dist/http/mappings';

@LitComponent()
export class ItemsComponent {

    @GetMapping({
        path: ':id'
    })
    getItem(req: HttpRequest, res: HttpResponse): void {
        res.success({
            id: req.params.id
        });
    }
}

Chaining methods with next

We can keep our route functionality isolated by using the "next" param:

import { LitComponent } from '@litstack/core';
import { HttpRequest, HttpResponse, HttpNext } from '@litstack/core/dist/http';
import { PutMapping } from '@litstack/core/dist/http/mappings';

@LitComponent()
export class ItemsComponent {

    // NOTE: The order matters here:
    @PutMapping({
        path: ':id'
    })
    updateItem(req: HttpRequest, res: HttpResponse, next: HttpNext) {

        if(req.param.id === 'some-id') {

            // do some update
            res.success({ id: 'some-id' });
            return;
        }

        next();
    }

    // same route as above, will run only if "next" is called
    @PutMapping({
        path: ':id'
    })
    updateItemErr(res: HttpResponse) {
        
        res.error(404);
    }
}

Dependency Injection

Services are a great place for business logic:

// ./services/items.service
import { LitService } from '@litstack/core';

@LitService()
export class ItemsService {

    get description(): string {
        return 'This is an item description';
    }
}

And then in our component:

import { LitComponent } from '@litstack/core';
import { HttpResponse } from '@litstack/core/dist/http';
import { GetMapping } from '@litstack/core/dist/http/mappings';

import { ItemsService } from './services/items.service';

@LitComponent()
export class ItemsComponent {

    constructor(private itemsService: ItemsService) {}

    @GetMapping()
    getItems(res: HttpResponse) {
        res.success({
            description: this.itemsService.description
        });
    }
}

Testing

Test components using supertest methods and the Litstack TestBed:

import { TestBed, LitComponentTest } from '@litstack/core/dist/testing';

import { AppComponent } from './app.component';

describe('AppComponent', () => {

    let component: LitComponentTest;

    beforeEach(() => {
        
        component = TestBed.start(AppComponent);
    });

    afterEach(() => {

        TestBed.stop();
    });

    it('should return a welcome message', (done) => {

        component
            .get('/')
            .expect(200)
            .expect((res) => {
                expect(res.body.message).to.equal('Hello World!');
            })
            .end((err, res) => {
                if (err) return done(err);
                done();
            });
    });
});

Minimum Configuration

The build process can be customized to the needs of the project, but a minimum configuration could look like this:

> mkdir my-project
> cd my-project
> npm init -y
> npm install @litstack/core --save
> npm install typescript -D
> npm install ts-node -D

Change the following in package.json:

{
  "main": "dist/index.js",
  "scripts": {
    "start": "tsc && node dist/index.js"
  }
}

A tsconfig.json could look like this:

{
    "compilerOptions": {
        "module": "commonjs",
        "target": "es5",
        "outDir": "dist",
        "lib": [
            "es7"
        ],
        "experimentalDecorators": true,
        "emitDecoratorMetadata": true
    },
    "include": [
        "**/*.ts"
    ]
}

Now, run the app:

> npm start

Have fun!