Monday, August 31, 2015

module.exports has lesser mental model when exporting a module

On my post about sharing TypeScript classes between client-side and server-side. I used exports rather than module.exports. However, as I later learned, it's better to use module.exports as it's the one being directly returned by the require function, module.exports is the real deal. If we uses module.exports rather than exports, we don't need to do this anymore:

class ExternalizedDomain {
    static Person : typeof Domain.Person = require('./shared/Domain/Person').DomainPerson;
    static Country : typeof Domain.Country = require('./shared/Domain/Country').DomainCountry;
}

And also the drawback of the idiom above is it is not compatible with proxyquire:

it("applies interest using stubbed calculator", () => {

 var calculatorStub : any = {};

 var financialCalculator : typeof Domain.FinancialCalculator = 
                  proxyquire('../shared/Domain/FinancialCalculator', { './Calculator': calculatorStub });

 var interestApplied = financialCalculator.applyInterest(200, 0.2);
 expect(interestApplied).toEqual(240);


 calculatorStub.multiply = (a,b) => 6;
 var interestAppliedFromStubbedCalculator = financialCalculator.applyInterest(100, 0.2);
 expect(interestAppliedFromStubbedCalculator).toEqual(6);
});


There's no way in proxyquire to specificy an specific property (e.g., .DomainPerson) of the object assigned to module.exports. To make the external module compatible with proxyquire, do as the following:


class ExternalizedDomain {
    static Person : typeof Domain.Person = require('./shared/Domain/Person');
    static Country : typeof Domain.Country = require('./shared/Domain/Country');
}


Then change the Person.ts and Country.ts to export things on module.exports:

Person.ts:
module Domain {
    export class Country {
        name : string;
    }
}

// Hack for converting internal module to external module
declare var exports: any;
if (typeof exports != 'undefined') {
    module.exports = Domain.Country;
}

Country.ts:
module Domain {
    export class Country {
        name : string;
    }
}


// Hack for converting internal module to external module
declare var exports: any;
if (typeof exports != 'undefined') {
    module.exports = Domain.Country;
}



Definition of Calculator.ts:
///<reference path="../../typings/node/node.d.ts"/>

var isNode = typeof exports !== 'undefined' && this.exports !== exports;


module Domain.Calculator {

    export function multiply(multiplicand: number, multiplier: number): number {

        return multiplicand * multiplier;
    }

    export function divide(dividend: number, divisor: number): number {

        return null;
    }
}



if (isNode) {
    module.exports = Domain.Calculator;
}


Definition of FinancialCalculator.ts:
/// <reference path="../../typings/node/node.d.ts"/>

///<reference path="Calculator.ts"/>


var isNode = typeof exports !== 'undefined' && this.exports !== exports;

var calculator : typeof Domain.Calculator = isNode ? require('./Calculator') : Domain.Calculator;


module Domain.FinancialCalculator {

    export function applyInterest(amount: number, percentInterest: number): number {

        return calculator.multiply(amount, 1 + percentInterest);
    }

}


if (isNode) {
    module.exports = Domain.FinancialCalculator;
}


On next post, I'll show the difference between TypeScript's classes and module when it comes to proxyquire.


Happy Coding!

TypeScript definition ambiguity woes. Which require function should go? RequireJS' or NodeJS'?

If you encountered this error:

Error:(49, 13) TS2403: Subsequent variable declarations must have the same type.  Variable 'require' must be of type 'Require', but here has type 'NodeRequire'.


It's better to remove RequireJS's require, as you can access the require functionality of RequireJS's through its syntax sugar a.k.a. simplified CommonJS wrapping.

RequireJS syntax sugar for require is done like this:
define(require => {
    var calculator : typeof SharedModel.Calculator = require('Calculator');
    var financialCalculator : typeof SharedModel.FinancialCalculator = require('FinancialCalculator');
});



On RequireJS's TypeScript definition, require.d.ts, comment or remove its require declaration:
// Ambient declarations for 'require' and 'define'
declare var requirejs: Require;
// declare var require: Require;
declare var define: RequireDefine;

Friday, August 28, 2015

Custom Basic Authentication and Authorization for Node Express

You have an existing REST API, and you wanted to protect it:

app.get('/api/something', (req: express.Request, res: express.Response, next: Function) => {
    res.json({message: 'Mensaje', description: 'Yeah!'});
});

The neatest way to protect your REST API is to make a function that returns a callback function for Basic Authentication so it can be chained on node express parameters, and the implementation detail can be hidden to user too. To wit, here's how it shall look like usage-wise:

import canBe = require('./CanBe');

app.get('/api/something', canBe.accessedBy(['guest']),  (req: express.Request, res: express.Response, next: Function) => {
    res.json({message: 'Mensaje', description: 'Yeah!'});
});


Most of the explanation of the use of bind shows its usefulness on the this object. The following code demonstrates another good use of bind function. What the called function accessedBy does is it returns the callback with a binded parameter (roles array parameter in the following example) by binding a leading parameter on the accessedByBind function; so when the callback function accessedByBind is called by node express, the roles parameter is passed to it too.


CanBe.ts:

/// <reference path="./typings/express/express.d.ts"/>

import express = require('express');

var basicAuth = require('basic-auth');


export function accessedBy(roles: string[]) : express.RequestHandler {
    return accessedByBind.bind(undefined, roles);
}


function accessedByBind(roles: string[], req: express.Request, res: express.Response, next: Function): express.RequestHandler {

    function unauthorized(res) : express.RequestHandler {
        res.set('WWW-Authenticate', 'Basic realm=Authorization Required');
        return res.send(401);
    }


    function isUserInRole(userName:string): boolean {

        var userRole: string;

        if (userName == "foo") {
            userRole = 'guest';
        }
        else {
            userRole = '';
        }

        var isAllowed = false;

        for(var i = 0; i < roles.length; ++i) {
            if (roles[i] == userRole) {
                isAllowed = true;
                break;
            }
        }

        console.log("Is allowed " + isAllowed)

        return isAllowed;

    }


    // === accessedByBind starts here ===


    var user = basicAuth(req);

    if (!user || !user.name || !user.pass) {
        return unauthorized(res);
    }


    if (user.name === 'foo' && user.pass === 'bar') {

        var isAllowed = isUserInRole(user.name);

        console.log("Is allowed " + isAllowed);

        if (isAllowed)
            return next();
        else
            return unauthorized(res);

    } else {
        return unauthorized(res);
    }

}


Here's .bind in a nutshell:

Live Code http://jsfiddle.net/b33gukgv/

function list(a,b,c) { 
    console.log('a: ' + a);
    console.log('b: ' + b);
    console.log('c: ' + c);    
    console.log(arguments);
}

//  Create a function with a preset leading argument
var always = list.bind(undefined, "Omni", "Present");

list("of", "good", "things");

always("something", "there", "to");

always("remind", "me");


Output:

This little thing called this

While learning the Basic Authentication on node express, I encountered the need to learn javascript more. One thing I learned today is the use of .bind function of javascript. I seen it being used most on javascript UI frameworks, I didn't bother to learn what's the use of that bind function, until today.

On Basic Authentication of node express, I need to pass an extra parameter to node express callback, that parameter is role. That role parameter is akin to Authorize attribute of ASP.NET MVC.

Here's a rough signature of node express callback:

interface Func {
    (random: number, basicAuthUser: string) : boolean;
}


function doSomething(...actions: Func[]) : void {
    
    var basicAuthUser = "davegrohl"; // obtained from browser's Basic Authentication    
    
    for(var i = 0; i < actions.length; ++i) {
        var a = actions[i];
        var okToContinue = a(Math.random() * 100, basicAuthUser);
        if (!okToContinue) 
            break;
    }
}

console.log('');
console.log('without authorization');
doSomething(
    (i,u) => { console.log('Alpha ' + i); return true; },
    (i,u) => { console.log('Beta ' + i); return true; }
    );


Then I think, authentication and authorization role mechanism could be slotted on the first parameter of the array. But how would I pass an extra parameter on the callback? Then an enlightenment from C# came. On C# object, the properties can be accessed even if the method reference is passed to callback. The solution could be written in C# like the following:


Live Code: https://dotnetfiddle.net/tSenYK
using System;
using System.Linq;
                    
public class Program
{
    public static void Main()
    {
        Console.WriteLine("Without authorization:");
        DoSomething(            
            (i,u) => { Console.WriteLine("Alpha " + i); return true; },
            (i,u) => { Console.WriteLine("Beta " + i); return true; }            
            );    
                
        Console.WriteLine();
        Console.WriteLine("Rockstar activity:");
        DoSomething(
            new Authorizer("rockstar").ActionToDo, // just pass the reference of method
            (i,u) => { Console.WriteLine("Alpha " + i); return true; },
            (i,u) => { Console.WriteLine("Beta " + i); return true; }            
            );                        
        
        Console.WriteLine();
        Console.WriteLine("Guest activity:");        
        DoSomething(
            new Authorizer("guest").ActionToDo,
            (i,u) => { Console.WriteLine("Alpha " + i); return true; },
            (i,u) => { Console.WriteLine("Beta " + i); return true; }            
        );    
    }
    
    
    // third-party framework. cannot change the signature
    public static void DoSomething(params Func<int, string, bool>[] actions)
    {
        var basicAuthUser = "davegrohl"; // obtained from browser's Basic Authentication        
        for(int i = 0; i < actions.Length; ++i)
        {
            var a = actions[i];
            bool okToContinue = a(new Random().Next(10), basicAuthUser);
            if (!okToContinue)
                break;
        }
        
    }
    

}



class Authorizer
{
    public string RoleAllowed { get; set; }
    
    public Authorizer(string roleAllowed)
    {
        this.RoleAllowed = roleAllowed;
    }
    
    string GetRole(string basicAuthUser)
    {
        return "rockstar"; // davegrohl's role fetched from database
    }
    
    public bool ActionToDo(int i, string basicAuthUser) 
    {
        // Database operation here.
        // Get the role of basicAuthUser
        var role = this.GetRole(basicAuthUser);
        
        
        
        return role == this.RoleAllowed;    
    }
}

Output:
Without authorization:
Alpha 4
Beta 4

Rockstar activity:
Alpha 4
Beta 4

Guest activity:


So I just need write the equivalent in TypeScript/JavaScript:

Live Code at TypeScriptLang


class Authorizer
{
    roleAllowed : string;
    
    constructor(roleAllowed: string)
    {
        this.roleAllowed = roleAllowed;
    }
    
        
    private getRole(basicAuthUser: string) : string {
        return "rockstar"; // davegrohl's role fetched from database
    }
    
    actionToDo(i: number, basicAuthUser: string) : boolean 
    {
        // Database operation here.
        // Get the role of basicAuthUser
        
        var role = this.getRole(basicAuthUser); // davegrohl's role fetched from database
                
        return role === this.roleAllowed;    
    }
}



    


interface Func {
    (random: number, basicAuthUser: string) : boolean;
}


function doSomething(...actions: Func[]) : void {
    
    var basicAuthUser = "davegrohl"; // obtained from browser's Basic Authentication    
    
    for(var i = 0; i < actions.length; ++i) {
        var a = actions[i];
        var okToContinue = a(Math.random() * 100, basicAuthUser);
        if (!okToContinue) 
            break;
    }
}

console.log('');
console.log('without authorization');
doSomething(
    (i,u) => { console.log('Alpha ' + i); return true; },
    (i,u) => { console.log('Beta ' + i); return true; }
    );
    


console.log('');
console.log("Rockstar activity:");
doSomething(
    new Authorizer("rockstar").actionToDo,
    (i,u) => { console.log("Alpha " + i); return true; },
    (i,u) => { console.log("Beta " + i); return true; }            
    );                        


console.log('');
console.log("Guest activity:");        
doSomething(
    new Authorizer("guest").actionToDo,
    (i,u) => { console.log("Alpha " + i); return true; },
    (i,u) => { console.log("Beta " + i); return true; }            
);    


However, it didn't work. The this object looks like it's not an instance af Authorizer class. The error says:





Then I add a console.log of the this object.
actionToDo(i: number, basicAuthUser: string) : boolean 
    {
        // Database operation here.
        // Get the role of basicAuthUser
        
        console.log(this);
        
        var role = this.getRole(basicAuthUser); // davegrohl's role fetched from database
                
        return role === this.roleAllowed;    
    }


Here's the output, oops it looks like the this object is not carried when passing the reference of the method to callbacks.



To make the long story short, the this object is not included when accessing the reference of the method. Not similar to C#

The solution is to bind the this object before passing the reference of the method to callback.

Correct:

Live Code at TypeScriptLang

class Authorizer
{
    roleAllowed : string;
    
    constructor(roleAllowed: string)
    {
        this.roleAllowed = roleAllowed;
    }
    
    getBindedActionToDo() : Func {
        return this.actionToDo.bind(this);
    }
    
    private getRole(basicAuthUser: string) : string {
        return "rockstar"; // davegrohl's role fetched from database
    }
    
    actionToDo(i: number, basicAuthUser: string) : boolean 
    {
        // Database operation here.
        // Get the role of basicAuthUser
        
        console.log(this);
        
        var role = this.getRole(basicAuthUser); // davegrohl's role fetched from database
                
        return role === this.roleAllowed;    
    }
}



interface Func {
    (random: number, basicAuthUser: string) : boolean;
}


function doSomething(...actions: Func[]) : void {
    
    var basicAuthUser = "davegrohl"; // obtained from browser's Basic Authentication    
    
    for(var i = 0; i < actions.length; ++i) {
        var a = actions[i];
        var okToContinue = a(Math.random() * 100, basicAuthUser);
        if (!okToContinue) 
            break;
    }
}

console.log('');
console.log('without authorization');
doSomething(
    (i,u) => { console.log('Alpha ' + i); return true; },
    (i,u) => { console.log('Beta ' + i); return true; }
    );
    


console.log('');
console.log("Rockstar activity:");
doSomething(
    new Authorizer("rockstar").getBindedActionToDo(),
    (i,u) => { console.log("Alpha " + i); return true; },
    (i,u) => { console.log("Beta " + i); return true; }            
    );                        


console.log('');
console.log("Guest activity:");        
doSomething(
    new Authorizer("guest").getBindedActionToDo(),
    (i,u) => { console.log("Alpha " + i); return true; },
    (i,u) => { console.log("Beta " + i); return true; }            
);    


Output:





Happy Coding!

Testing an AMD POJO Angular Controller

One of the nice things of Controllers in ASP.NET MVC is they are easy to test, just new the controller and you are good to go.

One of the nice things with new Angular removing reliance on $scope is we can now test controllers just by newing them, we don't need to worry where to get the $scope variable being passed to it. Our controller becomes very POJO, very easy to test.


An example of POJO controller.

///<reference path="../../../typings/requirejs/require.d.ts"/>
///<reference path="../../../typings/angularjs/angular.d.ts"/>
///<reference path="../../../shared/ViewValue/Header.ts"/>
///<reference path="../../../shared/Domain/Product.ts"/>


module App.ProductForSale {

    export class Controller {

        product : Domain.Product;

        percentDiscount: number;

        get discountedPrice() : number {

            return this.product.price * (1 - this.percentDiscount);
        }

        constructor(header: ViewValue.Header) {

            header.title = "Product for sale";

            this.product = new Domain.Product();
        }
    }
}


define(require => {

    var mod : angular.IModule = require('theMainModule');
    require('/shared/Domain/Product.js');

    mod["registerController"]('ProductForSaleController',['singletonHeader', App.ProductForSale.Controller]);

});


There's just one minor problem when testing the controller above. It's an AMD controller, to test it we should be able to ignore the define statement in it.


The easiest way to disable it is to monkey-patch the define function by changing it to something else. An example. Name this test setup as _must-be-runned-first.ts:


if (window["def"] == undefined) {
    window["def"] = window["define"];

    window["define"] = function(depArray : string[], c: any) {
        console.log('define intercepted');
        console.log(depArray);
    };
}



function doTest(test) {
    var def = window["def"];

    def(test);
}

doTest just wrap the test so tests uses the original define, other defines just got redirected.


Here's a sample test:

///<reference path="../typings/jasmine/jasmine.d.ts"/>
///<reference path="../typings/requirejs/require.d.ts"/>
///<reference path="_must-be-runned-first.ts"/>

doTest(require => {


    describe("Board Controller", () => {
        require('/base/public/app-dir/ProductForSale/Controller.js');
        require('/base/shared/ViewValue/Header.js');


        var h = new ViewValue.Header();

        it("computes discount", () => {

            var b = new App.ProductForSale.Controller(h);
            b.product.price = 50;
            b.percentDiscount = 0.10;
            var discountedPrice = 45;

            expect(b.discountedPrice).toEqual(discountedPrice);

        });
    });
});


By redefining the window["define"] to something else, requirejs won't complain of script error on theMainModule as it is not available when doing tests on controller.



Add test-main.js on files array of karma.conf

module.exports = function(config) {
    config.set({

        // base path that will be used to resolve all patterns (eg. files, exclude)
        basePath: '',


        // frameworks to use
        // available frameworks: https://npmjs.org/browse/keyword/karma-adapter
        frameworks: ['jasmine', 'requirejs'],


        // list of files / patterns to load in the browser
        files: [
            'test-main.js',
            {pattern: 'shared/**/*.js', included: false},
            {pattern: 'public/**/*.js', included: false},
            {pattern: 'tests/*.js', included: false}
        ]
    });
}



Then on test-main.js, add the _must-be-runned-first.js as the first file to be dynamically-loaded, remove the .js extension when adding it to allTestFiles array.


var allTestFiles = [];

var TEST_REGEXP = /(spec|test)\.js$/i;

allTestFiles.push('tests/_must-be-runned-first');

// Get a list of all the test files to include
Object.keys(window.__karma__.files).forEach(function(file) {
    if (TEST_REGEXP.test(file)) {
        // Normalize paths to RequireJS module names.
        // If you require sub-dependencies of test files to be loaded as-is (requiring file extension)
        // then do not normalize the paths
        var normalizedTestModule = file.replace(/^\/base\/|\.js$/g, '');

        allTestFiles.push(normalizedTestModule);
    }
});


console.log(allTestFiles);

require.config({
    // Karma serves files under /base, which is the basePath from your config file
    baseUrl: '/base',


    // dynamically load all test files
    deps: allTestFiles,

    // we have to kickoff jasmine, as it is asynchronous
    callback: window.__karma__.start
});



Complete Code: https://github.com/MichaelBuen/PlayNodeTypescriptUirouterCouchpotato/tree/master/public


Happy Coding!

Tuesday, August 25, 2015

Angular Service and Factory are just the same

That is, the values of service/factory values being passed to controllers are singletons.

The only difference between the two; with service it's Angular's job to do the new'ing, with factory it's the responsibility of your factory's callback to do the new'ing. Despite the name factory, don't be confused that it gets called every time it is needed by controllers, that it can make a new instance every time it is called; in fact, the factory's callback is only called once by Angular, effectively its result is also cached just like service. Here are the screenshots showing how many times the service and factory are being called.


Service:


Factory:



As shown on screenshot, Domain.Product is new'd only once on service, even the factory is just called once. Hence the values being passed to controllers, be it from service or from factory, have just the same instance, are effectively singletons.


Imagine service is implemented as:
function service(nameHere, c) {
    cache[nameHere] = new c(); // new'd once only.
} 

Imagine factory is implemented as:
function factory(nameHere, c) {
    cache[nameHere] = c(); // called once only.
}


As for which one is used more often or should be used more often. If factory is called every time it is being needed on controller, it will fit the name factory more . But alas, factory is just called once, effectively returning singletons only, it's better to use service if all you need is singleton.


You can even use service if you want to make a real factory. Of course, you can also use factory if you want to make a real factory :)


/TheApp.ts:
///<reference path="../typings/requirejs/require.d.ts"/>
///<reference path="../typings/angularjs/angular.d.ts"/>

///<reference path="../shared/Domain/Product.ts"/>



define(['angular', 'angularUIRouter', 'angularResource', 'couchPotato' ], function(angular, angularUIRouter, angularResource, couchPotato) {

    var app = angular.module('niceApp',['ui.router','ngResource','scs.couch-potato']);


    var useService : boolean = true;

    if (useService)
        app.service('domainProduct', Domain.Product);
    else
        app.factory('domainProduct', () => {
            console.log('Factory');
            return new Domain.Product();
        });

    couchPotato.configureApp(app); // this dynamically adds registerProvider on angular module niceApp

    return app;

});

/shared/Domain/Product.ts:
module Domain {

    export class Product {
    
        name : string;
        yearModel : number;

        constructor() {
            this.name = "Initial Value";
            this.yearModel = 1900;

            console.log('Product Constructor');
        }
    }
}

/app-dir/Product/Controller.ts
//<reference path="../../../typings/requirejs/require.d.ts"/>
///<reference path="../../../typings/angularjs/angular.d.ts"/>
///<reference path="../../../shared/Domain/Product.ts"/>


class Controller {

    sampleMessage : string;

    domainProduct : Domain.Product;

    constructor($scope : angular.IScope, domainProduct) {

        console.log("Product's Controller: User of factory/services");
        
        this.domainProduct = domainProduct;

    }
    
}

define(['theApp'], function (app) {
    app.registerController('ProductController',['$scope', 'domainProduct', Controller]);
});

/app-dir/Product/SidebarController.ts
///<reference path="../../../typings/requirejs/require.d.ts"/>
///<reference path="../../../typings/angularjs/angular.d.ts"/>
///<reference path="../../../shared/Domain/Product.ts"/>

class Controller {

    sampleMessage : string;

    domainProduct : Domain.Product;

    constructor($scope : angular.IScope, domainProduct) {
    
        console.log("Product's Sidebar Controller: User of factory/services");

        this.domainProduct = domainProduct;
    }
}


define(['theApp'], function (app) {
    app.registerController('ProductSidebarController',['$scope', 'domainProduct', Controller]);
});

Saturday, August 22, 2015

Conflict between NodeJS's require and RequireJS's require TypeScript definitions

At the time of this writing, if you wanted to use TypeScript's umd (Universal Module Definition), you'll get an error between NodeJS's require and RequireJS's require TypeScript definitions.




A temporary solution to that is to disable the RequireJS's require, delete the ambient declaration for requirejs's require.

/typings/requirejs/require.d.ts
// Ambient declarations for 'require' and 'define'
declare var requirejs: Require;
// declare var require: Require // Delete or uncomment this
declare var define: RequireDefine;


This client-side config.ts won't work anymore:
requirejs.config({
    paths: {
        "jquery": "/jquery/dist/jquery"
    }
});
 
require(['app']); // this won't work


To make that work, access the client-side require via window object.
requirejs.config({
    paths: {
        "jquery": "/jquery/dist/jquery"
    }
});
 
var need : Require = window["require"];
need(['app']);

Friday, August 21, 2015

Sharing TypeScript classes between front-end and web server code

The beauty of using javascript is it can now run on server-side via nodejs. Using javascript on both client-side and server-side facilitates code-sharing much easier.

Prerequisite: use UMD.
{
 "compilerOptions": {
  "target": "ES5",
  "module": "umd",
  "sourceMap": true
 } 
}

This is a class with validation logic that can be used on front-end:

/shared/Domain/Person.ts
module Domain {
        
    export class Person {
        name : string;
        age : number;
        
        validate() : string[] {
            var validations : string[] = [];
            
            if (this.age < 0 || this.age == undefined || this.age == null)
                validations.push('Age must be equal or more than zero');
                
            return validations;    
        }
        
    }
}




The above can be used directly on front-end app:

/public/app/Person/Controller.ts
class Controller {
    
    name : string = 'Linus T';
    
    person  = new Domain.Person();
    
    validationMessages : string[];
        
    constructor() {
        this.person.name = 'Nice fellow';
        this.person.age = -39;     
    } 
    
    save() : void {
                
        this.validationMessages = this.person.validate();
                
    }
                
}

angular.module('TheApp', []).controller('Controller', Controller);


The javascript on the browser don't have a problem looking for the reference of Domain.Person class, as the class is referenced from the view.
<script src='/angular/angular.min.js'></script>
<script src='/shared/Domain/Person.js'></script>
<script src='Controller.js'></script>

<div ng-app="TheApp" ng-controller="Controller as c">
    {{c.name}}
    
    <p>
        Person: {{c.person}}
    </p>    
    
    <p>
        {{c.validationMessages}}
    </p>
    
    <button ng-click="c.save()">Save</button>
    
</div>


However, you cannot import an internal module directly from a nodejs app. TypeScript complains that a module is not a module (external module that is).



In order to use a module in nodejs, the module must be an external one. To convert an internal module to external module, just export the module Domain by attaching export = Domain at the end of code.


/shared/Domain/Person.ts
module Domain {
        
    export class Person {
        name : string;
        age : number;
        
        validate() : string[] {
            var validations : string[] = [];
            
            if (this.age < 0 || this.age == undefined || this.age == null)
                validations.push('Age must be equals or more than zero');
                
            return validations;    
        }
        
    }
}

export = Domain;

Doing the above, this shall work.

/app.ts
import domain = require('./shared/Domain/Person');

app.post('/api/person', (req,res) => {
    
    var person = new domain.Person(); // intellisense works
    extend(person, req.body);
            
    var messages = person.validate();  
  
      if (messages.length > 0)
        res.status(400).json(messages);
    else
        res.send('OK'); 



And also, another problem is once you convert an internal module to external module, the module can't be recognized as an internal one anymore. Hence this front-end code will get an error:




Fortunately, someone was able to crack that problem. Another dev make it clearer. There's another dev who made a post on his enlightenment on the internals of require function.


To cut to the chase, keep the module as internal, then manually register modules to exports variable (the global variable being used by CommonJS's require).


/shared/Domain/Person.ts:
module Domain {
        
    export class Person {
        name : string;
        age : number;
        
        // we can use this logic on front-end, e.g., Angular.
        // and we can also re-use this logic on back-end, e.g., NodeJS's REST API 
        validate() : string[] {
            var validations : string[] = [];
            
            if (this.age < 0 || this.age == undefined || this.age == null)
                validations.push('Age must be equals or more than zero');
                
            return validations;    
        }
        
    }
}

declare var exports: any;
if (typeof exports != 'undefined') {
    exports.DomainPerson = Domain.Person;


Organize the classes to their own file, let's add another one. The exports code have to be repeated on each class.
module Domain {
    export class Country {
        name : string;
    }
}

declare var exports: any;
if (typeof exports != 'undefined') {
    exports.DomainCountry = Domain.Country;
}


Then on external module-using code, we will not use TypeScript's import functionality, so the TypeScript compiler will not flag the module as not a module. To wit:


class ExternalizedDomain {
    static Person : typeof Domain.Person = require('./shared/Domain/Person').DomainPerson;
    static Country : typeof Domain.Country = require('./shared/Domain/Country').DomainCountry;
}


The suffixes .DomainPerson and .DomainCountry are the name of the exported classes from modules that were stored in exports variable, which in turn is returned by the require function. As the module is not imported by TypeScript, the modules would have no associated types, we can re-introduce the imported modules as strongly-typed classes by using TypeScript's typeof operator.

Following is the REST API code that re-uses the same class(with validation logic) being used by front-end. Using nodejs, we can keep our front-end code and REST API code DRY.


import express = require('express');

import path = require('path');

import bodyParser = require('body-parser'); 

import extend = require('extend');


class ExternalizedDomain {
    static Person : typeof Domain.Person = require('./shared/Domain/Person').DomainPerson;
    static Country : typeof Domain.Country = require('./shared/Domain/Country').DomainCountry;
}


var app = express();


app.get('/', (req,res) => res.send('Hello Lambda World!'));

    var server = app.listen(3000, function () {
    var host = server.address().address;
    var port = server.address().port;

    console.log('Example app listening at http://%s:%s', host, port);
    
});



app.use('/', express.static( path.join(__dirname, 'public'), { extensions: ['html'] })); // if entered a url without an extension, attach html
app.use('/angular', express.static( path.join(__dirname, 'node_modules', 'angular') )); 

app.use('/shared', express.static( path.join(__dirname, 'shared') )); 

app.use(bodyParser.json());
app.post('/api/person', (req,res) => {
   
   
    var person = new ExternalizedDomain.Person();
    extend(person, req.body);
            
    var messages = person.validate();  
   
    if (messages.length > 0)
        res.status(400).json(messages); // 400 is http status for bad request
    else
        res.send('OK'); 
    
});


The technique above works on modules too:
module Domain.Calculator {

    export function multiply(multiplicand: number, multiplier: number): number {

        return multiplicand * multiplier ;
    }

    export function divide(dividend: number, divisor: number): number {

        return null;
    }
}

declare var exports: any;
if (typeof exports != 'undefined') {
    exports.Calculator = Domain.Calculator;
}

To use:

class ExternalizedDomain {
    static Calculator : typeof Domain.Calculator = require('../shared/Domain/Calculator').Calculator;
}

describe("multiplication", () => {
    it("should multiply 2 and 3", () => {
        var product = ExternalizedDomain.Calculator.multiply(2,3);
        expect(product).toEqual(6);
    });
});


TypeScript works perfect on Visual Studio Code. Intellisense works as expected:



WebStorm can't intelligently work on the language:




Complete code, done on Visual Studio Code: https://github.com/MichaelBuen/PlaySharedTypeScriptClasses


Happy Coding!