## overview
appex is a nodejs web service framework built on top of the TypeScript programming language. appex
enables nodejs developers to expose typescript functions as http endpoints as well as generate meaningful service
meta data for clients to consume.
appex also provides a dynamic compilation environment for typescript to aid in development. appex will effeciently
manage compilation in the background without the need to restart the web server, or use additional modules.
appex is designed to operate as both a standalone web service solution or as a complement to existing applications
written in frameworks such as express / connect that wish to extend their projects with typed web api's.
### the appex runtime
The appex runtime is compilation engine that handles dynamic compilation, route mapping and function
invocation. appex provides a simple utility method for setting up the runtime, as described below.
var http = require('http');
var appex = require('appex');
var runtime = appex.runtime ( { sourcefile : './program.ts' } );
var server = http.createServer( runtime );
server.listen(3000);
The appex.runtime() method returns a http handler function which is both compatable with nodejs'
http server as well as connect middleware. This is the recommended approach of creating runtimes,
However, if you need to access the runtime directly or are simply curious, you can also setup
the runtime as follows..
var http = require('http');
var appex = require('appex');
var runtime = new appex.Runtime ( { sourcefile : './program.ts' } );
var server = http.createServer( function(req, res) {
console.log(runtime);
runtime.request_handler(req, res, function() {
});
});
server.listen(3000)
### runtime options
The appex runtime accepts the following options.
var options = {
sourcefile : './program.ts',
devmode : true,
logging : true,
stdout : process.stdout,
stderr : process.stderr,
};
var runtime = appex.runtime ( options );
### appex json handlers
A appex json handler is a function suited to handling json based http requests. appex json handlers
are invoked via HTTP POST and expect JSON to be submitted with the request. POSTing null or invalid
JSON results in the request argument being null.
A appex json handler requires the following signature.
- argument[0] - the appex context
- argument[1] - A optionally typed json request object.
- argument[2] - a optionally typed typescript callback with a single argument for the object response.
- returns - void (optional)
The return type is optional. json handler functions "must" invoke the callback to complete the request.
export function method(context, request, callback:(response) => void) : void {
callback(request);
}
### wildcard functions
appex supports url wildcard routing by way of wildcard functions. Wildcard functions are special in the regard
they support more than one argument (other than the context) for which url parameters will be mapped.
appex currently supports the type 'any' (or none), string and number type annotations on wildcard arguments.
if a wildcard argument specifies any other type, the wildcard function will not be routed.
if no type annotation is specified, appex will pass a string value.
export module blogs {
export function index (context) { }
export function submit (context) { }
export function wildcard(context, year:number, month:number, day:number) {
context.response.write('blogs ' + year + ' ' + month + ' ' + day)
context.response.end();
}
}
note: wildcard functions should be declared last in any module scope. this ensures other routes
will be matched first.
### exporting functions
appex extends TypeScripts concept of visibility to include visibility over http. From this
developers and control which functions are exported as http endpoints.
In order to make a function accessible over http, you must explicitly "export" the function.
consider the following example:
module private_module {
export function public_method () { }
function private_method() { }
}
function private_function() { }
export function public_function (context) {
private_function();
private_module.public_method();
context.response.write('testing');
context.response.end();
}
### handling 404
Use wildcard functions to catch unhandled routes.
export function index (context) {
context.response.writeHead(404, {'content-type' : 'text/plain'});
context.response.write('home page');
context.response.end();
}
export function wildcard(context, path) {
context.response.writeHead(404, {'content-type' : 'text/plain'});
context.response.write(path + ' page not found');
context.response.end();
}
### development mode
var runtime = appex.runtime ({ sourcefile : './program.ts',
devmode : true,
logging : true });
appex is built directly on top of the Microsoft TypeScript 0.9 compiler and leverages it for tight
integration with the nodejs platform. By enabling the 'devmode' option on a appex runtime, appex
will rebuild your source code on each request made to the server.
appex achieves performance in this regard by leveraging features available in
TypeScript compiler which facilitate incremental building / caching of typescript
compilation units. request compilation in devmode typically take tens of milliseconds
to complete for modest size projects.
In addition to this, compilations are run as a background worker process to ensure they
do not interupt requests being served on the parent process.
appex will output syntax and type errors to the runtime stdout as well as the http response.
Syntax errors will not bring down the web process. And you won't need to restart on code
updates.
### structuring projects
appex includes TypeScript's ability to reference source files with the 'reference' element. appex
will traverse each source files references and include it as part of the compilation.
Developers can use this functionality to logically split source files into reusable components of
functionality, as demonstrated below.
var appex = require('appex');
var runtime = appex.runtime ({ sourcefile : './index.ts' });
require('http').createServer( runtime ).listen(3000);
export function index (context) { }
export function about (context) { }
export function contact (context) { }
export module users {
export function login (context) { }
export function logout (context) { }
}