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

@node-gr/core

v1.0.7

Published

`Node-Gr is a node js MEAN stack framework uses [Typescript](https://www.typescriptlang.org) as a main programing language. we provide a set of [Typescript](https://www.typescriptlang.org) decorators that will help you configure your project as you need.

Downloads

3

Readme

Node-Gr

`Node-Gr is a node js MEAN stack framework uses Typescript as a main programing language. we provide a set of Typescript decorators that will help you configure your project as you need.

These decorators are the core of Node-Gr however no actual request or data is handled by us.

As mentioned above this is a mean stack framework witch means that we use express js for all request handling and so would a Node-Gr user. We also support using a Mongo DB database for now by integrating mongoose to be used directly with our annotations.

Concepts

the next chapter will introduce the concepts that are used and introduced to a node.js based application.

Application server:

This is a uniq class (usually called Server) that extends GrApplicationServer and is decorated with @GrServer this annotation requires a modules array that define the entry point of the whole application. It can also accept a mongoUrl which is the Url to connect to your running mongoDb server. this parameter is optional and if not provided no database connection will be made.

Another optional parameter is handleAppCreated that is a callback that once provided will be called once the express Application is first created, the application instance will be passed to the callback as a parameter for further custom configuration.

const MONGO_URL = `mongodb://${ Environment.MONGO_SERVER_ADDRESS }:${ Environment.MONGO_SERVER_PORT }/${ Environment.MONGO_DATABASE_NAME }`;

@GRServer({
  modules: [ MainModule ],
  mongoUrl: MONGO_URL,
  handleAppCreated: (app) => {
    app.use(bodyParser.json());
    app.use(bodyParser.urlencoded({ extended: true }));
  }
})
export class Server extends GrApplicationServer {
}

An Application Server can and should only be created once.

Modules

Nde-Gr uses the well proven concept of modular development, (same as angular modules). a module can be any typescript class that has the decorator @GRModule. A module is the entry point of a logic section of your application it gives the possibility to define and import other logical parts and classes of your app. the GrModule decorator accepts:

  • modules?: an optional array og other modules to be imported and used internally. used to reimport reusable modules that can be useful in multiple logical parts of the app.
  • controllers?: an optional array of controllers to be defined. each one can only be defined in one module.
  • interceptors?: an optional array of interceptors to be defined. each one can only be defined in one module.
  • services?: an optional array of services to be defined. each one can only be defined in one module.
  • entities?: an optional array of entities to be defined. each entity can only be defined in one module.

the entry point modules of the application, (a module that is not imported in any other module) must be defined in the Application Server in order to be created.

@GRModule({
  modules: [ SecondModule, EntitiesModule ],
  controllers: [ CrudController ],
  interceptors: [ MainInterceptor ],
  services: [ AuthService ]
})
export class MainModule {
}

Controllers

A controller is a Typescript class that extends Controller and is decorated with @GRController the decorator accepts an optional base bath that will be prefixed for all defined requests in that controller.

A controller is the only place to define Http requests, the definitions are simple public methods that has the exact same signature as express js http request definition. a request definition must be decorated with one of the supported methods from the example below. each method decorator accepts an optional path parameter to be added to the path of the controller, the result of concatenating both controller and method paths is the final url of that request. methods can be async or not optionally up for the developers needs. handling the request logic is the exact same provided by express js.

@GRController('/api/post')
export class CrudController extends Controller {

  @GET()
  public async getRequest(req: Request, res: Response) {
  }

  @POST()
  public async postReq(req: Request, res: Response) {
  }
  
  @PUT()
  public async putReq(req: Request, res: Response) {
  }
  
  @DELETE()
  public async deleteReq(req: Request, res: Response) {
  }
  
  @PATCH()
  public async patchReq(req: Request, res: Response) {
  }
  
  @ALL('/check')
  public allReq(req: Request, res: Response) {
  }
  
  @HEAD('/ping')
  public headReq(req: Request, res: Response) {
  }

}

Interceptors

An Interceptor is any class that implements the Interceptor interface, and is decorated with @GrInterceptor. an interceptor must implement the handle method in order to be executed. this method will be fired once any request that matches the path parameter passed to the decorator. the request handling is also provided by express js. this will only handle the definition itself.

@GRInterceptor('/api')
export class MainInterceptor implements Interceptor {
  public handle(req: Request, res: Response, next: NextFunction): void {
    log('interceptor for \'/api\' fired');
    next();
  }
}

Services

A service is any class that is decorated with @GrService, a service can contain any logic related to your application a service will be automatically created once defined in a module, and then a uniq instance will be injected to any other class (service, controller or interceptor) that needs it, you can find more about dependency injections here.

the best practice would be putting all logic in the services, and then use that service to handle actual requests in the controllers, so the controllers would have the least amount of logic inside.

Entities

An entity is simply a collection definition. for now, we still only support mongoDb.

An entity is any class decorated with the @GrEntity this decorator accepts as parameters the name of the collection, if not provided it falls back to the class name, and it accepts as well the rest of the parameters that you can pass to the Schema constructor provided by mongoose.

An entity attribute is a class property with the @Attribute decorator, it accepts the same schema type definitions provided by mongoose.

Any entity class field with initial value and no @Attribute decorator, or a getter, will be considered as a mongoose virtual type

An entity method can be decorated with @PreHook to be considered as a pre lifecycle hook

An entity method can be decorated with @PostHookdecorator with giving the lifecycle that you want. The method can be async, the return value will be passed as a next function so if any object is return it will be treated as an error. if all good, you shoud not return anything. In the case of a find query, the method will accept the query object as a parameter. In the case of an insertManyHook, the this object will be null, and the first parameter will be the array of the inserted documents.

Any entity class method will be considered as a mongoose schema method

An entity class must be defined in a module in order for it to be considered and later injected. Once defined a model will be automatically created.

@GREntity({
  versionKey: false,
})
export class UserEntity {

  @Attribute({
    type: String,
    required: true
  })
  public firstName: string;

  @Attribute({
    type: String
  })
  public lastName: string;

  @PreHook('validate')
  public preValidate(): void {
  }
  
  @PreHook('save')
  public async preSave(): Promise<void> {
    await someAsyncOperation();
  }

  @PostHook('save')
  public postSaveUser(): void {
    console.log('use created:', this.firstName);
  }

  public get fullName(): string {
    return `${this.firstName}, ${this.lastName}`;
  }

}

To inject an entity's model, you define it as a readonly property of a class and decorate it with GrRepository to be injected once the app is running.

These models can be used for all required operations.

They are not accessible in the constructor of the class, you can make use of OnStartup

Dependency Injection

We provide the classical dependency injection mechanism, a service can be injected into other components simply by defining it as a constructor parameter. A singleton instance then will be passed down to that constructor.

An entity repository can be only injected via the GrRepository decorator and is not available in the constructor.


@GRController('/api/users')
export class Other extends Controller {

  @GrRepository(UserEntity.name)
  public userRep: Repository<UserEntity>;

  public constructor(private readonly userService: UserService,
                     private readonly errorHandler: ErrorHandlerService) {
    super();
    log('userService created, userRep is still null');
  }

  @GET()
  public async getAll(req: Request, res: Response) {
    if (await this.userService.isSuperAdmin()) {
        res.send(await this.userRep.find().exec());
    } else {
        this.errorHandler.rejectUnAuthorized();
    }
  }
}

OnStartup

@OnStartup is a decorator that can be used on class methods, (module, service, controller, interceptor...), in order to execute it once the Singleton instance of that class in created, all dependencies got injected, and the application is running. this can be used to make initial app configuration or created mock-data if need be.

@GRServer({
  modules: [ MainModule, EntitiesModule ],
  mongoUrl: MONGO_URL,
  handleAppCreated: (app) => {
    app.use(bodyParser.json());
    app.use(bodyParser.urlencoded({ extended: true }));
  }
})
export class Server extends GrApplicationServer {
  @GrRepository(UserEntity.name)
  private userRep: Repository<UserEntity>;

  @OnStartup
  public async onStartUp() {
    console.log('app started');
    await this.userRep.deleteMany({}).exec();
  }
}