1.4.6 • Published 3 years ago

bind-rest v1.4.6

Weekly downloads
80
License
MIT
Repository
github
Last release
3 years ago

Bind-Rest

Annotation based framework for creating Rest APIs with Node.js with TypeScript

BETA 0.3.X

Installation

Not available at this time. Will be available when released

Usage

CORE

Classes
Application(options)

Root class for starting application device. Call let app= new Application({baseDir:_dirname}) in app.ts to create promiseoft application

Options

Name
baseDir\ using __dirname in this option will allow the application to scan the existing directory for named dependencies. If dependencies exist in an alternate directory, provide the relative path
timeout\ set the number of MS to timeout a request if no response Default = 0

Methods

NameDescriptionReturnType
init()Initialize the application with options app.init() See Example APromise

Example A ( app.init() )

    app.init().then(handler  => {
        const port = 3000;
        http.createServer(handler).listen(port);
        console.log(`Server running on port ${port}.`);
    })
    .catch((e:Error) => console.error(`Container init Failed ${e} :: ${e.stack}`));
Annotations
Annotation NameParent Annotation
@PreDestroyAnnotation that will handle request such as closing sockets or DB connections before process terminates (similar to on unload)ComponentFactory
@MiddleWareAnnotation that creates a middleware class to be handled in process thread. Loads class. Depends on Before, After, AfterController, AfterResponse Annotations to determine order of middleware on everyhttp request NOTE: this is NOT controller specific
@MetaProps
@JsonSchemaAnnotation that will define a schema to be handled by the bodyParser. If body Controller does not match Labeled Schema, request will be rejected.
@InitAnnotation that identifies the function to be called when Application is initializedComponentFactory
@ErrorHandlerAnnotation that creates a custom errorHandler. This Component will initialize with the App. Only one is allowed in the Application. All Errors will be handled by the errorHandler component then fall through to default error handler.
@EnvironmentAnnotation that specifies the Environment based on environment NODE_ENV value. Follow this annotation with a named Component Annotation for use in other components. Requires a default class.
@ControllerAnnotation for creating http funcitonality within the application. Using a Path annotation is optional. If no Path annotation is provided then controller will response to request for root url.
@PathAnnotation that names the route of the HTTP request.Controller
@ComponentAnnotation for creating reusable Classes across the applicationControllerComponentFactoryMiddleWare
@ComponentFactoryAnnotation for Creating Reusable Components Application level components. Useful for connecting to an external service. Requires a default class
@ContextService
@InjectInjects a Component class into class prototype @Inject('mycomponent') myprotoController Component ComponentFactory
@GETDescribes HTTP request method. @Path Annotation is optional. If no Path annotation is provided then [GET,PUT,POST,DELETE,ALL] will respond on path provided by @Controller. This annotation can be grouped with other HTTP request annotations (PUT,POST,DELETE.. ETC)Controller
@PUTDescribes HTTP request method. @Path Annotation is optional. If no Path annotation is provided then [GET,PUT,POST,DELETE,ALL] will respond on path provided by @Controller. This annotation can be grouped with other HTTP request annotations (PUT,POST,DELETE.. ETC)Controller
@POSTDescribes HTTP request method. @Path Annotation is optional. If no Path annotation is provided then [GET,PUT,POST,DELETE,ALL] will respond on path provided by @Controller. This annotation can be grouped with other HTTP request annotations (PUT,POST,DELETE.. ETC)Controller
@DELETEDescribes HTTP request method. @Path Annotation is optional. If no Path annotation is provided then [GET,PUT,POST,DELETE,ALL] will respond on path provided by @Controller. This annotation can be grouped with other HTTP request annotations (PUT,POST,DELETE.. ETC)Controller
@ALLDescribes HTTP request method. @Path Annotation is optional. If no Path annotation is provided then [GET,PUT,POST,DELETE,ALL] will respond on path provided by @Controller. This annotation can be grouped with other HTTP request annotations (PUT,POST,DELETE.. ETC)Controller
Method Arguments
Annotation NameExampleDescription
@RequestBody@RequestBody body:<T>Returns the body of the request. Validate Schema by passing JsonSchems to \
@Request
@Response
@OriginalUrl@OriginalUrl path:stringReturns requested url string
@RequestMethod@RequestMethod method: stringReturns Requested http method
@Headers@Headers headers:<T>Returns all req headers
@Cookies
@UriInfo
@Context
@ContextScope
@QueryString@QueryString query:stringReturns unparsed http query string (everything after ?)
@Query@Query queryString: <T>Returns a PARSED query string as an object
@PathParam@PathParam("id") id: stringReturns path paramter "id" from request (/users/{id})
@QueryParam@QueryParam("filter") filter: stringReturns query parameter "filter" from request (/users?filter='abc')
@HeaderParam@HeaderParam("transactionId") id: <T>Returns header paramter "transactionId" from request if available
@CookieParam
@ContextScopeParam
@Required@QueryParam("filter") @Required filter: stringIndicates that parameter is required. Will result in error if param not provided in request
Utilities
Method NameExampleDescription
expressMiddlewareWrapper(express.RequestHandler[ name ])let rmw= expressMiddlewareWrapper(fn,'mymiddlware') ... return rmw(ctx).then(...)Wraps an express method to utilize within controller
rejectLater( ms: number)await rejectLater(4000).catch(noop);Will set delay in middleware chain. Must have a catch block.
noop( args: any[] )
Errors and Responses
NameExampleType
AppError( msg:string , category, type)throw new AppError("error in application")Constructor Extends: Error
TypeValidationError( msg:string )throw new TypeValidationError("error in application")Constructor Extends: AppError
AppResponse( body, statusCode, headers )Constructor implements: IAppResponse
JsonResponse( JSON ,httpstatusCode, headers )Constructor Extends: AppResponse Handles streamed response
ErrorResponse( responseCode , message )Constructor Extends: AppResponse
Types References
Type
IContext | CoreContext
IContainer
IAppResponse
ApplicationOptions
IJsonResponse
IContextService
ControllerDetails
Enviornment Variables (Optional)
NameValueDescription
DEBUGpromiseoft:*To display log output to the console

Examples

Annotations

PreDestroy

@ComponentFactory
export default class myClass {

  @PreDestroy
  destructor(): Promise<any> {
    console.log(`Entered destructor on myClass Component Factory`);
    if (this.db) {
      return this.mdb.close().then(_ => {
        console.log(`MongoDB Connection Closed Successfully`)
      });
    } else {
      return Promise.resolve(true);
    }
  }
}

MiddleWare

@Middleware
export default class mymiddleware { ... }

JsonSchema

// schemadefinition.ts
export default {
  "$schema": "http://json-schema.org/draft-04/schema#",
  "type": "object",
  "properties": {
    "name": {
      "type": "string"
    "email": {
      "type": "string"
    }

  },
  "required": [
    "name",
    "email"
  ]
}

// user.ts

@JsonSchema("user")
export class User {
    name: string;
    email: string;
}

Init

@ComponentFactory
export default class myFactory {

  private mdb: Db;

  @Init
  init(): Promise<any> {
    console.log(`Entered myFactory.init()`);
    let self = this;
    return MongoClient.connect(url)
        .then(db => {
          console.log(`MongoDB Connection Successful`);
          self.mdb = db
        })
        .catch(e => {
          console.error(`Failed to connect to mongodb ${e.message}`);
          throw e
        })
  }
}

ErrorHandler

@ErrorHandler
export default class MyErrorHandler {


  @Inject('settings')
  mySettings: settings;

  handleError = (ctx: IContext) => (e) => {

    console.log(`Entered Custom Error Handler ${this.mySettings.mongoConn}`);

    throw e;
  }

}

Environment

@Environment("DIT", "FIT")
@Component('settings')
export default class settings implements Isettings {

    port: "3080"
    dbConnection: "http://someuri/"

}

Controller

@Controller
@Path('/myroute')
export default class myController {

  @Inject('settings')
  settings: <T>

  @GET
  @Path('/mysubroute/{id}')
  getOrders(@PathParam('id') id: number, @QueryParam('orgid') @Required orgId: string): Promise<IAppResponse> {
      try {
        return new JsonResponse({"a":a,"b":b});
      }
      catch (e){
        return new AppResponse(`Error ${e}`);
    }
}

ComponentFactory

@ComponentFactory
export default class MongoConn {

  @Inject('settings')
  settings: Isettings;

  private mdb: Db;

  @Component("Foo")
  getDB(): Db {
    return this.mdb;
  }

  @Component("usercollection")
  getUserCollection(): Collection {
    return this.mdb.collection("users");
  }

  @Init
  init(): Promise<any> {
    console.log(`Entered MongoConn.init()`);
    let self = this;
    return MongoClient.connect(self.settings.mongoConn)
        .then(db => {
          console.log(`MongoDB Connection Successful`);
          self.mdb = db
        })
        .catch(e => {
          console.error(`Failed to connect to mongodb ${e.message}`);
          throw e
        })

  }

  @PreDestroy
  destructor(): Promise<any> {
    console.log(`Entered destructor on Mongodb Component Factory`);
    if (this.mdb) {
      return this.mdb.close().then(_ => {
        console.log(`MongoDB Connection Closed Successfully`)
      });
    } else {
      return Promise.resolve(true);
    }
  }
}