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

typeorm-entitysharer

v1.0.1

Published

Tool to generate client and server specific classes based on TypeORM entities

Downloads

1

Readme

TypeORM Shared models creator

This tool can be used to create client/server classes based on the same TypeORM entities, allowing you to share them.

This is a work in progress.

Shared interface for client - server architecture

We use typescript to ensure data models integrity in all our programs.

On a client - server architecture, we share data models between both client & server. Doing this way, every update in data models will be automatically visible to both client & server.

The generic architecture we use :

                   shared interfaces repo
                  /                      \
      server repo                          client repo

Data model integrity on server side

We use typeorm as it allows us to perform database request while keeping these strong typings. Typescript works well with typeorm entities, which are js classes, so there is no special needs on this side.

We also use class-validator as it allows us to check if a data coming into the api respects the corresponding class structure.

There is also a swagger on the api.

A basic entity :

import { Entity, Column, PrimaryGeneratedColumn, BaseEntity, OneToMany } from 'typeorm';
import { Project } from './entities';
import { MinLength, MaxLength, IsEmail } from 'class-validator';
import { ApiModelProperty } from '@nestjs/swagger';

@Entity()
export class User extends BaseEntity {
    @ApiModelProperty()
    @PrimaryGeneratedColumn('uuid')
    public id: string;

    @ApiModelProperty()
    @MinLength(2, { message: 'ERRORS.USERS.FIRSTNAME_TOO_SHORT' })
    @MaxLength(50, { message: 'ERRORS.USERS.FIRSTNAME_TOO_LONG' })
    @Column()
    public firstName: string;

    @ApiModelProperty()
    @MinLength(2, { message: 'ERRORS.USERS.LASTNAME_TOO_SHORT' })
    @MaxLength(50, { message: 'ERRORS.USERS.LASTNAME_TOO_LONG' })
    @Column()
    public lastName: string;

    @ApiModelProperty()
    @IsEmail({}, { message: 'ERRORS.USERS.EMAIL' })
    @Column({ unique: true })
    public email: string;

    @ApiModelProperty()
    @MinLength(12, { message: 'ERRORS.USERS.PASSWORD_TOO_SHORT' })
    @Column()
    public password?: string;

    @ApiModelProperty()
    @Column({ default: false })
    public admin: boolean;

    @ApiModelProperty({ isArray: true })
    @OneToMany(type => Project, project => project.user, {
        cascade: true,
    })
    public projects: Project[];
}

How do we use this :

import { User } from 'shared-entities'

const User = new User()

Client side validation

On client side, we wants to make sure that data coming from the api will respects our model structure, so we will use class-validator too.

However, typeorm can not be used on client-side, furthermore it would load a useless amount of code. swagger is also useless on client side.

What we need on client side is :

  • class structure
  • class-validator decorators

The expected file would looks like this:

import { Project } from './entities';
import { MinLength, MaxLength, IsEmail } from 'class-validator';

export class User {
    public id: string;

    @MinLength(2, { message: 'ERRORS.USERS.FIRSTNAME_TOO_SHORT' })
    @MaxLength(50, { message: 'ERRORS.USERS.FIRSTNAME_TOO_LONG' })
    public firstName: string;

    @MinLength(2, { message: 'ERRORS.USERS.LASTNAME_TOO_SHORT' })
    @MaxLength(50, { message: 'ERRORS.USERS.LASTNAME_TOO_LONG' })
    public lastName: string;

    @IsEmail({}, { message: 'ERRORS.USERS.EMAIL' })
    public email: string;

    @MinLength(12, { message: 'ERRORS.USERS.PASSWORD_TOO_SHORT' })
    public password?: string;

    public admin: boolean;

    public projects: Project[];
}

What has been removed :

  • typeorm & swagger imports
  • extends BaseEntity keywords
  • Typeorm decorators

How do we use this :

import { User } from 'shared-entities'

const User = new User()

Build process

Our goal : transform a js class based on typeorm & swagger in a standalone-typescript class.

Perform it client side ?

As the problem remains mainly client side, we could transform our structure when bundling our angular app with webpack. As described here https://github.com/typeorm/typeorm/issues/62#issuecomment-264490738, we could use a shim in webpack so all typeorm decorators would return an empty function. We would have to do the same for swagger decorators. Using typescript mixin, we could also transform BasicEntity class in an empty class, so our User class would not have any additionnal attributes & methods coming from parent class.

We chose not to do this way for 2 reasons :

  • it leads to poor code understanding (all those decorators in a typescript class, which are useless which are not?)
  • We think it's the shared interface package reponsability to ensure it's compatibily with both client & server

Build for both client & server

We expects this structure in our shared gitlab repository:

/dist
  /client
    ... client entities : ts + js
  /server
   ... server entities : ts + js

We use gulp as the task runner for the build process.

Build for server :

  • take all entities (.ts)
  • copy them in dist/server (.ts)
  • transpile them to .js in dist/server

Build for client

  • take all entities (.ts)
  • remove useless decorators, imports & extends
  • copy result in dist/client (.ts)
  • transpile result in dist/client (.js)

See gulpfile.js for detailed process

Deploy as distinct npm repositories

It is possible to create two npm packages from the same gitlab repository.

Client side :

  • install with npm install shared-entities-client
  • use with import { User } from 'shared-entities-client

Server side :

  • install with npm install shared-entities-server
  • use with import { User } from 'shared-entities-server

Why we should do this :

  • only code that we need is imported as dependency (no server entities en client side)

Why we do not do this :

  • we would have to pay : )

Deploy this as a single npm repository

It should be possible (i'm on it) to import distinct classes from the same npm package :

Client side :

  • install with npm install shared-entities/client
  • use with import { User } from 'shared-entities/client

Server side :

  • install with npm install shared-entities/server
  • use with import { User } from 'shared-entities/server

Why we do this :

  • it's free : )

Why we should not do this :

  • useless code imported

Configuration file

You need to create a configuration file called typeorm-entitysharer.json at your project root, containing the following data:

{
    "decoratorsWhitelist": [
        "TranslationMinLength",
        "TranslationMaxLength"
    ],
    "importsWhitelist": [
        "./index",
        "../index",
        "../errors",
        "class-validator",
        "./validators"
    ],
    "tsconfigPath": "tsconfig.json",
    "entitiesPath": "src/**/*.ts",
    "errorsPath": "src/errors/*.ts"
}
  • decoratorsWhitelist: the decorators not to be removed
  • importsWhitelist: the imports not to be removed
  • tsconfigPath: typescript config path (from project root)
  • entitiesPath: your entities path (from project root, regex)
  • errorsPath: this project also allows to share translations. This is WIP.