GithubHelp home page GithubHelp logo

ben-ryder / kangojs Goto Github PK

View Code? Open in Web Editor NEW
0.0 0.0 0.0 577 KB

Jump start your Express app development

License: MIT License

Shell 0.11% TypeScript 98.89% JavaScript 1.00%
express typescript decorators typescript-decorators express-framework nodejs

kangojs's Introduction

Hi I'm Ben ๐Ÿ‘‹

๐Ÿค” About me...

  • ๐Ÿ‘จโ€๐Ÿ’ป I'm intrested in all things web dev, especially developing with Node.js and React at the moment.
  • โค๏ธ I'm a lover of open source software, looking to start contributing back more.

๐ŸŒฑ I'm currently exploring...

kangojs's People

Contributors

ben-ryder avatar dependabot[bot] avatar

kangojs's Issues

Decide what DTO design pattern class-validation is optimizing for

In a project using class-validation I'm facing a design pattern decision/question about the use of "DTO" classes.

Right now in that project DTO classes exist and are used to describe & validate request data. The same DTO classes are also used to describe the data passed from controllers -> business logic services -> database services.

The issue is my request data shape is now diverging from the data shape required by the database service. This means I now need multiple "DTO" classes for a single action:

  • one for validating request data at the controller layer and describing the interface between the controller and business logic service
  • one for describing the interface between the business logic layer and database service layer

This is fine, but I'm finding it somewhat confuses the use of the phrase "DTOs". My solution so far has been to now have a distinction between "shapes" and "dtos":

  • "Shapes" are classes defining the request data shape and are decorated with class-validator decorators
  • "DTOs" are classes that are purely for transferring data

None of this really relates to class-validation too much, however I'm thinking that it could be worth while removing all references to "DTOs" from class-validation.

Add a declarative way to define controllers

Package Information: kangojs, all versions

Describe your feature
Add a declarative way to define controllers, which means that rather than solely relying on file globbing to find and load them you could simply pass a list of controllers when instanciating or bootstrapping KangoJS.

Is your suggestion related to any problems?
Application startup feels quite slow when using KangoJS. I think this might be because of how long it takes for the file globbing to work. If controller classes could directly be passed to KangoJS this might speed up start times.

Additional context
It would be intresting to measure how long start times take before and after this feature is added. If it actually doesn't make much of a difference then it might not be worth adding the feature.

This feature would also introduce multiple ways of doing the same thing, it might be best to just pick one?

Consider moving error-handler into the core framework

Package Information: kangojs, error-handler

Describe your improvement
It's likely that the error handler (or a version of it) will be used on every project using KangoJS, so why not just move this functionality to the base framework or at least add some functionality like I have for request auth/validation to make this less custom/external to the framework.

Is your suggestion related to any problems?
Reduces boilerplate and repeated code, error handling will probably rely on dependency injection so it makes sense to possibly absorb the functionality

Additional context
n/a

Implement a dependency injection system

Package Information: kangojs

Describe your feature
Implement a dependency injection (DI) / Inversion of Control (IoC) system into KangoJS.
This would mean you could mark dependencies to inject into controlllers, services etc and KangoJS would handle the depedency creation and injection.
This DI must be recursive, so the application must work down the dependency tree (controller -> service -> other services/helpers etc) and handle injecting everything.

Is your suggestion related to any problems?
For testing (unit tests and e2e) you need to be able to access the dependency instances that are part of the application and also potentially overwrite / mock dependencies.

This will be useful for a number of things during testing:

  • For database setup/teardown during e2e testing you could re-use the same database service that the application uses to create content rather than having to write custom things for testing or creating duplicate instances.
  • Testing certain states may rely on knowing/editing internal application state so having access to the same dependency instance that is being used by the services/controllers could let you view/edit application state for tests.

Additional context
I think this would be done the same / a similar way to how it's done in NesJS or InversifyJS:

import { Inject } from "@kangojs/core";
import { UserService } from "./users.service";

export class UserController {
    constructor(
        @Inject(UserService) userService: UserService
    )
}
import { Inject } from "@kangojs/core";
import { UserDatabase } from "./users.database";

export class UserService {
    constructor(
        @Inject(UserDatabase) userDatabase: UserDatabase,
        @Inject(RandomService) randomService: RandomService
    )
}
import { Inject } from "@kangojs/core";

export class UserDatabase {
    constructor(
        @Inject(Config) config: Config
    )
}

Some notes:

  • @Inject decorator can be used to mark a dependency as injectable and tells KangoJS what class should be instantiated, passed to the class and stored in a centeral IoC container for later use.
  • I will need to consider if/how to implement singleton injection vs multiple instance injection / factories etc.
  • DI will work using an IoC container, meaning dependencies will be stored/managed in one centeral container and injected from this container. This means that there could be an interface to let you fetch dependencies from the KangoJS class. For example:
const kangoJS = new KangoJS();
await kangoJS.bootstrap();

const userDatabase = await kangoJS.getDependency<UserDatabase>(UserDatabase);

Maybe there could also then be a way to manually add/overwrite dependencies too? I don't think this would be a paticualr focus for an MVP of this feature though:

const kangoJS = new KangoJS();
await kangoJS.bootstrap();

class MockUserDatabase implements UserDatabaseInterface {
      isUserValid(user: User) {
             if (user.id === "test-user-id") {
                    return true;
             }

             return this.super.isUserValid(user);
      }
}

// Set dependency to use, but still let KangoJS handle instantiation via the DI system
// as maybe MockUserDatabase still relies on other injected services
await kangoJS.setDependency(UserDatabase, MockUserDatabase);

// Maybe you'd also need a way to full overwrite/bypass KangoJS's DI system
await kangoJS.setDependencyInstance(UserDatabase, new MockUserDatabase(new TestConfig()));

Express should be a peer dependency of kangojs

Package Information

  • Name: kangojs
  • Version (as installed from npm): all

Describe the bug
Express should be a peer dependency.
KangoJS is suppose to mainly be a convenience wrapper around Express, it shouldn't bring it's own Express dependency but instead use the one in the project already.

Expected behaviour

  • Express should be a peer dependency.
  • Installation docs should be updated to reflect this

Consider moving common-middleware into the core framework

Package Information: kangojs, common-middleware

Describe your improvement
It's likely that common-middleware will be used on every project using KangoJS, so why not just move this functionality to the base framework.

Is your suggestion related to any problems?
Reduces boilerplate and repeated code

Additional context
n/a

Module could not be found when using jest

Package Information:: kangojs @ all versions

Describe the bug
When attempting to use a KangoJS app in jest testing you get a "module could not be found in " error.

To Reproduce

  1. Create a KangoJS app
  2. Attempt to use this app in a jest test

Expected behaviour
The module should be found and the test should work.

Additional context
n/a

Refine error-handler and logger

Package Information: core @ v2

Describe your improvement
The error handling and logger feels a bit clunky to use, especially when debugging.
Can this be improved or simplified?

Is your suggestion related to any problems?
Debugging can be a bit clunky and hard with the custom error handling

Additional context
n/a

Add service class interface with helper methods

Package Information: core

Describe your feature
Add a base service class interface which has the methods async onStart() and async onKill(). These are like "hook functions" which KangoJS can call at certain points of the application lifecycle.

  • onStart - called once the application is setup and ready. This could be used for things like starting up cron tasks etc
  • onKill - called when the application is being killed. This can be used for clean up such as closing connections to the database/Redis etc

Is your suggestion related to any problems?
For testing I need to manually fetch all services that require clean up and handle each one.
Having a built in way to handle this would make it easier when multiple services need clean up.

Additional context
n/a

Add middleware option to controller & route decorators

Package Information

  • Name: core, v2

Describe your feature
Add middleware option to controller & route decorators so middleware can be added to specific routes and route groups.

Is your suggestion related to any problems?
You can only add middleware globally for the applciation, but you might want to only add middleware to a specific route or middleware.

Additional context
n/a

Seperate out the key interfaces/data into a seperate @kangojs/common package

Package: kangojs/common

Describe your improvement
Separate out common interfaces/data into a common package:

  • Error identifiers
  • HTTP status codes

Is your suggestion related to any problems?
A front end package requiring the error identifiers shouldn't need to pull in the entire core package, even if the client will sort tree shaking itself.

Right now a client also need to install express & cookie-parser types to which it shouldn't need

Additional context
n/a

Add tests to core for nested dependency injection

Package Information: core @ 2*

Describe your feature
Add unit tests for nested/recursive dependency injection.

For example if DependencyA is registered to the DI system and it requires DependencyB which requires DependencyC then DependencyB and DependencyC should also be registered to the DI system and the instance of DependencyA should be passed the correct instance of those dependencies (depending on the injection mode).

Is your suggestion related to any problems?
This is a critical part of the DI system that currently has no test coverage.

Additional context
n/a

Implement direct data return from controller classes

Package Information: core @ *

Describe your feature
RIght now the controller methods that KangoJS binds to routes have no special handling which means you still have boilerplate code with sending responses and forwarding errors to next():

    @Route({
        httpMethod: HTTPMethods.POST,
        bodyShape: CreateNoteShape
    })
    async add(req: RequestWithUser, res: Response, next: NextFunction) {
        let newNote: NoteDto;

        try {
            newNote = await this.notesService.add(req.user.id, req.bodyDto);
        }
        catch (e) {
            return next(e);
        }

        return res.send(newNote);
    }

It would be great if the framework could absorb some of that repeated handling, so you could just do something like this instead and the returned data is sent in a response automatically and thrown errors are caught are handled:

    @Route({
        httpMethod: HTTPMethods.POST,
        bodyShape: CreateNoteShape
    })
    async add(req: RequestWithUser, res: Response, next: NextFunction) {
        return await this.notesService.add(req.user.id, req.bodyDto);
    }

Users should be able to still send a response manaully themselves though.

This will require a bit of discover work:

  • How will error handling work in terms of unhandled promise rejections etc, will it work fine? (maybe user's should return promises directly, not return await?)
  • Will core need to register the error handler the same way it does currently for auth and validation handlers?
  • How can I make it posisble for users to still manually return a response as well as allowing for automatic response handling?

Is your suggestion related to any problems?
Controllers have a lot of repeated boilerplate code around response & error handling.

Additional context
n/a

Remove file globbing in favour of explicit controller imports

Package Information kangojs

Describe your feature
This is very similar to #7 but instead of adding explicit controller imports alongside the file globbing it should just be replaced.

Is your suggestion related to any problems?

  • With the new dependency injection system being written more and more functionality is being moved within the core framework. For example, it's likely that v2 will see the express app declaration move within KangoJS itself rather then the app be defined and managed by the end user. If users will be passing middleware and other things directly to KangoJS it makes sense that controllers should follow this same pattern.
  • As I start to add tests to the project the file globbing feature will make it much harder to test the framework as it's much harder to add specific controllers during tests.
  • Removing the feature will stop things like #2 from being an issue and removes "magic" functionality and makes the apps created using KangoJS easier to reason about.

Additional context
n/a

Add Error Handler Package

Describe your feature
Add an error handler package (kangojs/error-handler).
It should have these features:

  • Expose a middleware to handle errors
  • Follow NodeJS good practices and handle errors separate to the middleware
  • It should expose common error types that can be used in applications
  • Errors should be mapped to HTTP responses in the middleware. HTTP knowledge should only be needed at the controller/middleware layer.

Is your suggestion related to any problems?
n/a

Additional context
This could be used with a package like @kangojs/logger to prettify error output?

Controller loading doesn't work in compiled apps

Package Information: kangojs, all versions

Describe the bug
When passing a controllerFilesGlob to KangoJS it will be a glob of typescript files, for example src/modules/**/*.controller.ts.
When the app is compiled to JS this reference stays the same and so the compiled app fails to import the controllers as Typescript files can't be imported into the compiled JS.

To Reproduce
Steps to reproduce the behaviour:

  1. Setup KangoJS with a controller files glob that points to typescript files (such as src/modules/**/*.controller.ts).
  2. When running via ts-node this will work fine.
  3. When attempting to run the compiled JS app an error will occur.

In my application the error is as follows:

err: {
  "type": "SyntaxError",
  "message": "Cannot use import statement outside a module",
  "stack":
      /home/<path>/api/src/modules/albums/album.controller.ts:1
      import { NextFunction, Response } from 'express';
      ^^^^^^
      
      SyntaxError: Cannot use import statement outside a module
          at wrapSafe (internal/modules/cjs/loader.js:984:16)
          at Module._compile (internal/modules/cjs/loader.js:1032:27)
          at Object.Module._extensions..js (internal/modules/cjs/loader.js:1097:10)
          at Module.load (internal/modules/cjs/loader.js:933:32)
          at Function.Module._load (internal/modules/cjs/loader.js:774:14)
          at Module.require (internal/modules/cjs/loader.js:957:19)
          at require (internal/modules/cjs/helpers.js:88:18)
}
             

Expected behaviour
I'm unsure at the moment. Ideally the solution should not require any changes from a user perspective.
Can KangoJS somehow hook into the typescript build to change that string?
When loading could KangoJS use tsconfig.json to transform the path if it detects it's running with JS not TS?

Additional context
This could just be a fundamental problem with typescript & builds. It will probably be a good idea to see if this is an
issue other frameworks or libraries have needed to solve.

Look for Lerna alternative

Describe your improvement
Look for Lerna alternative or simply remove the tools.

Is your suggestion related to any problems?
I'm not really using Lerna. It's not fitting with my workflow and and can't customize it how I would like.
I either need to find an alternative, write some custom scripts or just not bother with any tooling.

Additional context
n/a

Add req.params validation to class-validation

Describe your feature
Add req.params validation to class-validation. This would work exactly the same way as body & query validation.

Is your suggestion related to any problems?
There is currently no way to validate URL parameters

Additional context
n/a

useErrorHandlerMiddleware doesn't act like other functions.

Package Information: [email protected]

Describe the bug
Various other use... function in KangoJS all work by passing in the express app like useX(app, config) but useErrorHandlerMiddlewaredoesn't. It should work the same way to keep things consistent.

To Reproduce
Attempt to use useErrorHandlerMiddleware and you will see it must be used like app.use(useErrorHandlerMiddleware(config)); rather than useErrorHandlerMiddleware(app, config).

Expected behaviour
Error handling middleware should be setup with useErrorHandlerMiddleware(app, config)

System Information
n/a

Additional context
n/a

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.