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

@astahmer/entity-routes

v0.1.8

Published

Design your API around your entities in minutes

Downloads

6

Readme

entity-routes allows you to make an instant CRUD with a single @EntityRoute decorator. Compatible with Koa/Express/Next/Nuxt.

No boilerplate controllers. No code generation. No custom schema.

Documentation

Check the docs here.

Motivation

Basically this is a Node / Typescript route handler tightly coupled with TypeORM entities.

I wanted to get rid of writing the same boring controllers again & again for each entities and I could not find a NodeJS project that would fit my needs : being simple enough not to require any configuration (or controllers), yet easily customizable when needed.

Table of Contents

Core Features

  • Instant CRUD with a simple @EntityRoute decorator
  • Independant service components (Database Reader, Persister, RelationManager etc...)
  • Built-in validation using class-validator/entity-validator decorators on your entities
  • Granular control over which properties are exposed (with @Groups) in which context
  • (nestable) Subresources (Entity properties that have dedicated endpoints)
  • Inferred entity route mappings (with generated endpoints to get the summary of an entity exposed properties for each contexts)
  • (async?) Computed properties (methods exposed as properties)
  • @MaxDepth decorator for entity/properties
  • Optimized SQL queries with only exposed properties selected
  • Soft delete/restoration supported (also for Subresources)
  • Built-in powerful filters for lists (Search/Pagination) that should fit well for 99% use cases
  • Custom filters if you find yourself in the 1%
  • Hooks to alter a request handling at any point in the process
  • Standardized REST responses

Installation

Since this library depends on TS Decorators just like typeorm, we need to install ReflectMetadata.

npm i @astahmer/entity-routes reflect-metadata typeorm

Don't forget to import ReflectMetadata in your app entrypoint.

import "reflect-metadata";

You also need this in your tsconfig.json

{
    "emitDecoratorMetadata": true,
    "experimentalDecorators": true
}

Learn about typescript decorators here.

Quick start

Make your entities

You're just gonna have to create your TypeORM entities just like you always did. Then there are 2 @ decorators that are specific to entity-routes :

  • @EntityRoute which is a class decorator, must be placed at the top of it so that your entities can be exposed through an EntityRouter.
  • @Groups which is a property decorator, must be placed at the top of every properties you want to expose through your routes, more details on it later

Here is a simple example.

export class AbstractEntity {
    @Groups("all")
    @PrimaryGeneratedColumn()
    id: number;
}

@EntityRoute({ path: "/users", operations: ["create", "update", "details", "list", "delete"] })
@Entity()
export class User extends AbstractEntity {
    @Groups("basic")
    @Column()
    name: string;

    @Subresource(() => Article)
    @OneToMany(() => Article, (article) => article.author)
    articles: Article[];
}

@EntityRoute()
@Entity()
export class Article extends AbstractEntity {
    @Groups("basic")
    @Column()
    title: string;

    @Groups("basic")
    @Column()
    content: string;

    @Groups("basic")
    @ManyToOne(() => User, (user) => user.articles)
    author: User;
}

It will automatically generate those routes :

[
    "/users : post",
    "/users/mapping : post",
    "/users/:id(\\d+) : put",
    "/users/:id(\\d+)/mapping : put",
    "/users/:id(\\d+) : get",
    "/users/:id(\\d+)/mapping : get",
    "/users : get",
    "/users/mapping : get",
    "/users/:id(\\d+) : delete",
    "/users/:UserId(\\d+)/articles : post",
    "/users/:UserId(\\d+)/articles : get",
    "/users/:UserId(\\d+)/articles/:id(\\d+) : delete",
];

Register your Entity Routes

Using Koa

import { AddressInfo } from "net";
import { makeKoaEntityRouters } from "@astahmer/entity-routes";
import * as Koa from "koa";
import * as bodyParser from "koa-bodyparser";
import { Connection } from "typeorm";
export async function setupKoaApp(connection: Connection) {
    const entities = connection.entityMetadatas.map((meta) => meta.target) as Function[];
    const bridgeRouters = await makeKoaEntityRouters({ connection, entities, options });
    const app = new Koa();
    app.use(bodyParser());
    / Register all routes on koa server
    bridgeRouters.forEach((router) => app.use(router.instance.routes()));
    / Always validate when no groups are passed on validators
    setEntityValidatorsDefaultOption(entities);
    const server = app.listen(); / random port
    const baseURL = `http://127.0.0.1:${(server.address() as AddressInfo).port}`;
    const client = axios.create({ baseURL });
    return { baseURL, server, client };
}

Using Express/Next/Nuxt

import { AddressInfo } from "net";
import { makeExpressEntityRouters } from "@astahmer/entity-routes";
import * as bodyParser from "body-parser";
import * as express from "express";
import { Connection } from "typeorm";
export async function setupExpressApp(connection: Connection) {
    const entities = connection.entityMetadatas.map((meta) => meta.target) as Function[];
    const bridgeRouters = await makeExpressEntityRouters({ connection, entities, options });
    const app = express();
    app.use(bodyParser.json());
    app.use(bodyParser.urlencoded({ extended: true }));
    / Register all routes on Express server
    bridgeRouters.forEach((router) => app.use(router.instance));
    const server = app.listen(); / random port
    const baseURL = `http://127.0.0.1:${(server.address() as AddressInfo).port}`;
    const client = axios.create({ baseURL });
    return { baseURL, server, client };
}

Final step

That's it. There is no final step. Your routes are ready.

Benefits

  • 0 config required
  • Compatible with Express, Koa, Next, Nuxt and any other middleware-based framework using adapters
  • Out-of-the-box support for Koa/Express integrations
  • Type-safe API
  • Almost complete code coverage (95%+)
  • Everything (types included) is exported so you can use it your own way

License

MIT © 2020 Alexandre Stahmer

Inspired by an internal project made at ACSEO with ApiPlatform (Symfony/PHP)