@node-ts-autumn/core
core-module
typescript node mvc framework
development state
alpha version
Features
- incl. request mapping via annotation
- incl. path params via annotation
- incl. request params via annotation
- incl. post body via annotation
- planned package scan for controllers
Template Rendering
- incl. PugViewResolver
- incl. HandlebarsViewResolver
- incl. ResourceResolver
- incl. JsonResponse
- planned Angular2 prerendering ViewResolver
Install
npm
needs @node-ts-autumn/server
npm install @node-ts-autumn/core --save
tsconfig
{
"compilerOptions": {
"typeRoots": ["node_modules/@types", "node_modules/@node-ts-autumn"],
"types": ["node","core"],
},
}
Example Project
Application
Configure the main application by setting up an Application
class that extends the AbstractApplication
class from @node-ts-autumn/core
.
This is an example Application
class for the application every component configuration is handed to this class.
import { BaseApplicationConfig, RootApplicationConfig, WebApplicationConfig } from '@node-ts-autumn/core';
import { AbstractApplication, Application } from '@node-ts-autumn/core';
import { HttpNodeRequest, HttpNodeError, HttpNodeResponse } from '@node-ts-autumn/server';
import { MyBaseApplicationConfig } from './config/base/base_application_config';
import { MyRootApplicationConfig } from './config/root/root_application_config';
import { MyWebApplicationConfig } from './config/web/web_application_config';
export class MyApplication extends AbstractApplication implements Application {
constructor () {
super();
}
public getBaseApplicationConfig (): BaseApplicationConfig {
return new MyBaseApplicationConfig();
}
public getRootApplicationConfig (): RootApplicationConfig {
return new MyRootApplicationConfig();
}
public getWebApplicationConfig (): WebApplicationConfig {
return new MyWebApplicationConfig();
}
public getContext (): string {
return '/';
}
}
RootApplicationConfig
Configure the root application config by setting up a RootApplicationConfig
class that extends the AbstractRootApplicationConfig
class from @node-ts-autumn/core
.
The existing abstract root application class is for now a placeholder, here the configuration for filters like security context or encoding filters will be configured.
import { AbstractSiteConfig } from '@node-ts-autumn/core';
class RootApplicationConfig extends AbstractRootApplicationConfig {
}
WebApplicationConfig
Configure the web application config by setting up a WebApplicationConfig
class that extends the AbstractWebApplicationConfig
class from @node-ts-autumn/core
.
For now the WebApplicationConfig
has two main features:
- setting up your main ViewResolver for rendering html (use of different ViewResolvers for html rendering is planned)
- setting up your controller classes and mapping request to specific methods
import { MediaType } from '@node-ts-autumn/core';
import { Configuration, ViewResolver, HandlebarsViewResolver, PugViewResolver, WebApplicationConfig, AbstractWebApplicationConfig } from '@node-ts-autumn/core';
import { MyController } from '../../app/controller/controller';
export class MyWebApplicationConfig extends AbstractWebApplicationConfig implements WebApplicationConfig {
constructor () {
super();
}
@Configuration('ViewResolver')
private handlebarsViewResolver (): ViewResolver {
let viewResolver: HandlebarsViewResolver = new HandlebarsViewResolver();
viewResolver.setPrefix(global['basepath'] + '/views/handlebars');
viewResolver.setSuffix('.html');
viewResolver.setViewClass('html');
viewResolver.registerPartials(['includes/head', 'includes/nav', 'layouts/layout']);
return viewResolver;
}
public getControllerClasses (): Array<any> {
let controllerClasses: Array<any> = new Array<any>();
controllerClasses.push(new MyController());
return controllerClasses;
}
}
Controllers
RequestMapping
Controller classes can hold one or more methods which are mapped by the @RequestMapping
annotation.
@RequestMapping
requires an Object with the property value
to which url-path the method should be mapped to.
@RequestMethod({value: '/'}) // mappes the following method to '/' or ''
@RequestMethod({value: '/info'}) // mappes the following method to '/info'
The @RequestMapping
Object can hold value, method (default = 'GET'), consumes (default = MediaType.APPLICATION_FORM_URLENCODED or 'application/x-www-form-urlencoded'), produces (default = MediaType.TEXT_HTML or 'text/html'))
@RequestMethod({value:'/acceptform', method: 'POST', consumes: MediaType.APPLICATION_FORM_URLENCODED, produces: MediaType.TEXT_HTML }) // mappes the following method to '/acceptform' accepts form data and is mapped to the html ViewResolver
@RequestMethod({value:'/data', method: 'POST', consumes: MediaType.APPLICATION_JSON, produces: MediaType.APPLICATION_JSON }) // mappes the following method to '/data' accepts json data and is mapped to the internal JsonResolver
basic mapped method
@RequestMapping({value: '/info'}) // every method needs the ModelAndView callback parameter - callback: (modelAndView: ModelAndView) => void
public info(callback: (modelAndView: ModelAndView) => void) {
callback(new ModelAndView('info'));
}
url-parameters, path-parameters and body-data
Methods mapped with the @RequestMapping
annotation can get url-parameters, path-parameters and body-data as method parameters.
Methods hand of the ModelAndView class via callback to the ViewResolver which incorporates the model-data to the predefined view.
url parameter
@RequestMapping({value: '/info'}) // mapped to info with x-www-form-urlencoded data
public info(@RequestParam id: number, @RequestParam name: string, callback: (modelAndView: ModelAndView) => void) {
let mav = new ModelAndView('info');
mav.addModel('id', id);
mav.addModel('name', name);
callback(mav);
}
body data
@RequestMapping({value: '/acceptform', method: 'POST'}) // mapped to info with x-www-form-urlencoded post data
public info(@RequestBody TestModel: testModel, callback: (modelAndView: ModelAndView) => void) {
let mav = new ModelAndView('info');
mav.addModel('testModel', testModel);
callback(mav);
}
path parameter
@RequestMapping({value: '/all/{id}/info/{name}'}) // mapped to infoAndId with path parameters
public infoAndId(@PathParam id: number, @PathParam name: string, callback: (modelAndView: ModelAndView) => void) {
let modelAndView = new ModelAndView('info');
modelAndView.addModel('id', id);
modelAndView.addModel('name', name);
callback(modelAndView);
}
Services
Service class support will be further developed.
For now only incorporation in the controller classes is supported.
Injectable
The @Injectable
annotation allows for the annotated class to be injected in your controller.
f.e. a simple RestService
@Injectable
export class TestHttpService {
basic_options: http.RequestOptions;
constructor() {
this.basic_options = new Object();
this.basic_options.host = 'localhost';
this.basic_options.port = 4000;
this.basic_options.path = '/json/testModel';
this.basic_options.headers = {
'Content-Type': 'application/json',
'Accepts': 'application/json'
};
}
public findAll(callback: (testModels: Array<TestModel>) => void): void {
this.basic_options.method = 'GET';
let req = this.requestFactory(callback);
req.on('error', (err) => {
logger.error(err);
});
req.end();
}
public findOne(id: number, callback: (testModel: TestModel) => void): void {
this.basic_options.method = 'POST';
let req = this.requestFactory(callback);
req.on('error', (err) => {
logger.error(err);
});
req.write(JSON.stringify({'id': id}));
req.end();
}
public save(testModel: TestModel, id: number = null, callback: (testModel: TestModel) => void): void {
this.basic_options.method = 'PUT';
let req = this.requestFactory(callback);
req.on('error', (err) => {
logger.error(err);
});
req.write(JSON.stringify({'id': id, 'testModel': testModel}));
req.end();
}
private requestFactory(callback: Function): http.ClientRequest {
return http.request(this.basic_options, (res: http.IncomingMessage) => {
res.setEncoding('utf8');
let buffer = '';
res.on('error', (err) => {
logger.error(err);
});
res.on('data', (data) => {
buffer += data;
});
res.on('end', () => {
callback(JSON.parse(buffer).data);
});
});
}
}
@Inject
@Inject
injects the annotated service class into the controller.
import { Inject } from '@node-ts-autumn/core';
import { TestHttpService } from // your HttpService
export class TestController {
@Inject
testHttpService: TestHttpService;
@RequestMapping({value: '/info'})
public info(callback: (ModelAndView) => void): void {
let testModels = this.testHttpService.findAll();
let mav = new ModelAndView('info');
mav.addModel('testModels', testModels);
callback(mav);
}
}