A very simple and unsafe :-), self-signed, CORS https node.js dev stub service in TypeScript


const https = require("https"); const fs = require("fs"); // To create the key.pem and cert.pem files for dev, use opensll: // openssl req -newkey rsa:2048 -new -nodes -x509 -days 3650 -keyout key.pem -out cert.pem // // Cert and key are created for hosheader "stub.service.am.dev". // Make sure the hosts file on windows contains: // 127.0.0.1 stub.service.am.dev const options = { key: fs.readFileSync("./key.pem"), cert: fs.readFileSync("./cert.pem") }; const port = 4433; https.createServer(options, function (req: any, res: any) { // Allow calls from all domains, for all methods ans request headers. res.setHeader("Access-Control-Allow-Origin", "*"); res.setHeader("Access-Control-Allow-Credentials", true); res.setHeader("Access-Control-Allow-Methods", "*"); res.setHeader("Access-Control-Allow-Headers", "*"); res.end(`Request received on server. Path Hit: ${res.url}`); }).listen(port, function() { console.log(`Stub service listing on ${port}`); });


Just enter https://stub.service.am.dev:4433 and it should respond with:

Request received on server. Path Hit: undefined

Communicate between controllers in Angular by using a simple pubsub service in TypeScript.

 

I created a really simple angular PubSubService in TypeScript, to allow communication between controllers or directives or services.

 

In the example below, controller 1, fires an event and controller 2 reacts to the firing of the event.

 

 

module dev {
    "use strict";

    var appModule = angular.module("myApp", []);

    appModule.controller("MyController1", ["$scope", "pubSubService", ($scope, pubSubService)

    => new dev.MyController1($scope, pubSubService)]);

    appModule.controller("MyController2", ["$scope", "pubSubService", ($scope, pubSubService)
    => new dev.MyController2($scope, pubSubService)]);

    

 

    export class MyController1 {
        constructor(public $scope: ng.IScope, public pubSubService: PubSubService) {
            // Fire an an event
            pubSubService.publish("my-custom-event", "some publisher data");
            }
    }

    export class MyController2 {
        constructor(public $scope: ng.IScope, public pubSubService: PubSubService) {
            this.handleMyCustomEvent = this.handleMyCustomEvent.bind(this);

            // Subscribe to be notified, when "my-custom-event" is fired.
            pubSubService.subscribe("my-custom-event", this.handleMyCustomEvent);
        }
   
        handleMyCustomEvent(data: any) {
        // Do something, when an event is fired from MyController1.
        }
    }

 

    /**
     * This service can be used to share data between controllers by using a pub sub mechanism.
     */
    export class PubSubService {
        private nextListenerIndex: number;
        private listeners: Array<IListener>;

        constructor() {
            this.listeners = [];
            this.nextListenerIndex = 0; // The first subscription will be located at index 0;

            this.publish = this.publish.bind(this);
            this.subscribe = this.subscribe.bind(this);
            this.unsubscribe = this.unsubscribe.bind(this);
        }

        /**
         * Publish an event.
         * All subscribers will be notified.
         * @param name, is the name of the event and is case insensitive.
         */
        publish(name: string, data?: any) {
            for (var i = 0, length = this.listeners.length; i < length; i++) {
                const listener = this.listeners[i];
                if (listener && listener.name.toLowerCase() === name.toLowerCase()) {
                    listener.handler.call(null, data, listener.subData);
                }
            }
        }

        /**
         * Subscribe to be notified, when an event is published.
         * @param name, is the name of the event and is case insensitive.
         * @returns A token, that can be used to unsubscribe.
         */
        subscribe(name: string, handler: (data?: any, subData?: any) => void, data?: any): number {
            var token = this.nextListenerIndex;
           
            this.listeners[token] = {
                handler: handler,
                name: name,
                subData: data
            };
            this.nextListenerIndex += 1;

            return token;
        }

        /**
         * Remove the event listener subscription.
         * @param token received on subscribing to an event listener.
         */
        unsubscribe(token: number) {

            // This will create holes in the array, but for now we do not care.
            this.listeners[token] = null; 
        }
    }

    export interface IListener {
        // This function will be called when an event is published.
        // Data is the data from the publisher, subData is the data from the subscriber.
        handler: (data?: any, subData?: any) => void;
        name: string;
        subData?: any; // Data from the subscriber.
    }

    angular.service("pubSubService", () => new PubSubService());
}

Fix: Visual Studio doesn’t use or can’t find TypeScript typings (*.d.ts) in a .net core project

 

I added some TypeScripts typings to a .net core project in Visual Studio 2015  (version 14.0.25123.00 Update 2), by using the NPM package “typings”, but the added *.d.ts files, were not picked up by Visual Studio, this was caused by excluding the “wwwroot” folder in the tsconfig.json,

 

after removing the wwwroot folder from the exclude array, the typings were correctly found and used.

 

 

 

{
  "compileOnSave": true,
  "compilerOptions": {
    "module": "system",
    "noImplicitAny": false,
    "noEmitOnError": true,
    "removeComments": false,
    "sourceMap": true,
    "target": "es6"
  },
  "exclude": [
    "node_modules",

     "wwwroot" <========================= Remove the wwwroot
  ]
}

Some nice new features are coming to TypeScript

 

npm for type definition files

One of the things that annoyed me was the tsd tool for installing type definition files.

Why can’t I just use npm, for installing type definition files. I use npm for installing external libraries en tooling so why not type definition files.

 

Well they are working on just that, kudos to the TypeScript thing.

 

Non nullable types

An other thing is non nullable types, I certainly want to have that in TypeScript.

It will be possible to tell the compiler, a certain variable is a string and not null or undefined. But you can also write: const x : string | null which means, x is a string or null but not undefined.

 

Down level async await support

TypeScript code which uses async await can target ES5

 

http://video.ch9.ms/ch9/4ae3/062c336d-9cf0-498f-ae9a-582b87954ae3/B881_mid.mp4

Yes: Cycle.js is getting some TypeScript love

 

In his blog post: http://staltz.com/all-js-libraries-should-be-authored-in-typescript.html mentions:

I am a JavaScript programmer, and I make some libraries. Recently, however, I’ve been writing TypeScript for RxJS version 5 (used in Angular 2 which is also authored in TypeScript),

and I’m in the process of rewriting Cycle.js in TypeScript.

I find the cycle.js framework very interesting and I love to see it written in TypeScript, so kudo’s for André Staltz, when he accomplishes this.

Starting with ASP.NET 5, TypeScript 1.7 and the ES6 module syntax compiled to ES5.

In the previous post I described how you can get started with ASP.NET 5.

 

The code used in this blog post can be found at: https://github.com/roelvanlisdonk/Research/tree/master/Blog/ASP.NET5/TypeScriptES6Modules

 

In this post I will describe how you can get start using TypeScript 1.7 and the ES6 module syntax to order your code in an ASP.NET 5 application.

 

I will explain how you can use a “library” module inside your app code, by using TypeScript and the ES6 module syntax.

The compiled code will be in ES5, so we need a library called “system.js” to load the “ES6 modules” at runtime.

 

  • After you followed the steps in the previous post
  • Add a TypeScript JSON Configuration File to the wwwroot folder

 

image

 

Add "module": "system", under compileroptions:

 

image

 

Add two typescript files:

  • wwwroot/core/app.ts
  • wwwroot/libraries/list/findIndexByItem.ts

image

 

 

 

  • Add the system.js bower package.

This is needed, because the typescript will be compiled into javascript modules.

These modules are in the “system.require” format.

We could use other module formats (see tsconfig.json), but in this example I wanted to use system.js

 

Before we can add the system.js bower package, add a “Bower Configuration File” to the root of the project.

 

image

 

In this example I use the folder “wwwroot/libraries” to store all my runtime JavaScript dependencies, so we have to edit the .bowerrc file, change:{ “directory”: “wwwroot/lib” } to { “directory”: “wwwroot/libraries” } .

 

image

 

Now we can install the system.js bower package:

 

image

 

 

findIndexByItem.ts

 

image

 

 

app.ts

 

image

 

 

index.html

 

The only javascript file we directly load in the index.html is “/libraries/system.js/dist/system.js”. All other logic will be dynamically loaded by the system.js loader.

 

To  make system.js recognize file paths like System.register(["../libraries/list/findIndexByItem"] , so without the “*.js” extension, we need to add a little configuration by using System.config, then we load the “core/app.js” file and start the application.

The “core/app.js” uses the library module “findIndexByItem.js”. This JavaScript file will be dynamically loaded, when “core/app.js” is requested.

 

 

image

 

Result

 

image

 

 

Note: for browsers that do not support promises you need a promise polyfill, that can be found, here: https://github.com/jakearchibald/es6-promise/

Fix: TypeScript 1.7.6 compile on save in Visual Studio 2015 not working

I upgraded Visual Studio 2015 TypeScript extension to 1.7.6, then compile on save stopped working.

First I checked if “Compile on save” was enabled on my 4.5.2 web project properties (TypeScript Build tab):

 

image

 

Then I checked if “Automatically compile TypeScript file which are not part of a project” was enabled (Tools / Options).

 

image

 

Then the TypeScript files still would not compile on save (they were compiled, when the project was build, but not when a TypeScript file was saved.

 

The solution

I removed the following part in my Web.csproj file:

 

<PropertyGroup Condition="’$(Configuration)|$(Platform)’ == ‘Debug|AnyCPU’">
    <TypeScriptTarget>ES5</TypeScriptTarget>
    <TypeScriptJSXEmit>None</TypeScriptJSXEmit>
    <TypeScriptCompileOnSaveEnabled>True</TypeScriptCompileOnSaveEnabled>
    <TypeScriptNoImplicitAny>False</TypeScriptNoImplicitAny>
    <TypeScriptModuleKind>None</TypeScriptModuleKind>
    <TypeScriptRemoveComments>False</TypeScriptRemoveComments>
    <TypeScriptOutFile />
    <TypeScriptOutDir />
    <TypeScriptGeneratesDeclarations>False</TypeScriptGeneratesDeclarations>
    <TypeScriptNoEmitOnError>False</TypeScriptNoEmitOnError>
    <TypeScriptSourceMap>True</TypeScriptSourceMap>
    <TypeScriptMapRoot />
    <TypeScriptSourceRoot />
  </PropertyGroup>

 

Then I added a tsconfig.json file to the root of my project:

image

 

tsconfig.json

{
  "compilerOptions": {
    "noImplicitAny": true,
    "sourceMap": true,
    "target": "es5"
  }
}

 

 

 

Don’t now if both steps are needed, but after that, my compile on save started working again.

How to get full class name, including module name from an instance at runtime in TypeScript

Let’s assume we have the class [GuidGenerator] in a TypeScript module [research.my.long.namespace] and at runtime you have an instance of the GuidGenerator, how do you get the full class name including module name, in this case: “research.my.long.namespace.GuidGenerator”.

Well you walk the object graph starting with the root / global object, in the browser this will be the window object.

 

NOTE: all code is in “strict” modus.

 

TypeScript Class [GuidGenerator]:

module research.my.long.namespace {
"use strict";
export interface IGuidGenerator {
generate(): string;
}
export class GuidGenerator implements IGuidGenerator {
generate() {
var randomNumberToGuid = function (c) {
var r = Math.random() * 16 | 0, v = c == 'x' ? r : r & 0x3 | 0x8;
return v.toString(16);
}
return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, randomNumberToGuid);
}
}
}

We use the resolver object to get the full class name:

var resolver = new NameResolver();
var generator = new research.my.long.namespace.GuidGenerator();
var name = resolver.getFullClassNameFromInstance(generator, window)
console.log(name);

Result

image

The resolver class

module research.metadata {
"use strict";
interface IProcessResult {
fnFound: boolean;
path: Array<string>;
}
export interface INameResolver {
getFullClassNameFromInstance(instance: any, global: any): string;
}
export class NameResolver implements INameResolver {
private _fn: any;
private _global: any;
private _processed: Array<any>;
/**
To handle recursiveness in the object graph, collect all handled nodes in the object graph,
so an object is only traversed once.
*/
isProcessed(obj: any): boolean {
var result = false;
for (var i, length; i < length; i += 1) {
if (this._processed[i] === obj) {
return true;
}
}
return result;
}
processProperty(obj: any, key: string, path: Array<string>): IProcessResult {
var result: IProcessResult = {
fnFound: false,
path: path
}
if (obj.hasOwnProperty(key)) {
try {
var prop = obj[key];
if (prop === this._fn) {
// Function found, stop traversing the object graph.
result.fnFound = true;
return result;
}
// Continue traversing the object graph.
result = this.processObject(prop, path);
if (result.fnFound) {
// Function found, stop traversing the object graph.
return result;
}
} catch (error) {
// Access to some properties result in exceptions.
}
}
return result;
}
processObject(obj: any, path: Array<string>): IProcessResult {
var result: IProcessResult = {
fnFound: false,
path: path
}
if (this.isProcessed(obj)) {
return result;
}
this._processed.push(obj);
for (var key in obj) {
var pathCopy = path.slice();
pathCopy.push(key);
var processResult = this.processProperty(obj, key, pathCopy);
if (processResult.fnFound) {
return processResult;
}
}
return processResult;
}
getFullClassNameFromInstance(instance: any, global: any): string {
this._fn = instance["constructor"];
this._global = global;
this._processed = [];
var processResult = this.processObject(this._global, []);
var fullFnName = "";
if (processResult.fnFound) {
fullFnName = processResult.path.join(".");
}
return fullFnName;
}
}
}