Skip to content

snytkine/bind-rest

Repository files navigation

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 <string> 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 <number> set the number of MS to timeout a request if no response Default = 0

Methods

Name Description ReturnType
init() Initialize the application with options app.init() See Example A Promise

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 Name Parent Annotation
@PreDestroy Annotation that will handle request such as closing sockets or DB connections before process terminates (similar to on unload) ComponentFactory
@MiddleWare Annotation 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
@JsonSchema Annotation that will define a schema to be handled by the bodyParser. If body Controller does not match Labeled Schema, request will be rejected.
@Init Annotation that identifies the function to be called when Application is initialized ComponentFactory
@ErrorHandler Annotation 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.
@Environment Annotation 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.
@Controller Annotation 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.
@Path Annotation that names the route of the HTTP request. Controller
@Component Annotation for creating reusable Classes across the application Controller
ComponentFactory
MiddleWare
@ComponentFactory Annotation for Creating Reusable Components Application level components. Useful for connecting to an external service. Requires a default class
@ContextService
@Inject Injects a Component class into class prototype @Inject('mycomponent') myproto Controller
Component
ComponentFactory
@GET Describes 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
@PUT Describes 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
@POST Describes 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
@DELETE Describes 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
@ALL Describes 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 Name Example Description
@RequestBody @RequestBody body:<T> Returns the body of the request. Validate Schema by passing JsonSchems to <T>
@Request
@Response
@OriginalUrl @OriginalUrl path:string Returns requested url string
@RequestMethod @RequestMethod method: string Returns Requested http method
@Headers @Headers headers:<T> Returns all req headers
@Cookies
@UriInfo
@Context
@ContextScope
@QueryString @QueryString query:string Returns unparsed http query string (everything after ?)
@Query @Query queryString: <T> Returns a PARSED query string as an object
@PathParam @PathParam("id") id: string Returns path paramter "id" from request (/users/{id})
@QueryParam @QueryParam("filter") filter: string Returns 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: string Indicates that parameter is required. Will result in error if param not provided in request
Utilities
Method Name Example Description
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
Name Example Type
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)
Name Value Description
DEBUG promiseoft:* 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);
    }
  }
}