Friends of TypeScript

We are now officially listed as "Friends of TypeScript" on http://www.typescriptlang.org/

And we really, really are friends of TypeScript. Our whole groupXS group framework is written in TypeScript, both the frontend and the backend. I wasn't too sure in the beginning, if it was the best way to go down when it comes to technology. But now with hindsight, we can absolutely say: It was the best decision we did. It is just awesome to have all the flexibility of JavaScript combined with a type system, where you want it.

TypeScript Team: Thank you for your great work, and thank you for putting our logo on your website. You rock!


Integrating custom widgets in Wordpress using RequireJS and Almond

A couple of days ago I embarked on a quest to write my own Wordpress widget. The widget was to consist of a main file (widget.js), some libraries and another module encapsulating an algorithm I needed in the widget. That meant that I faced the task of including all that in my Wordpress page. This is how I solved it:

1. RequireJS

The easiest way to integrate my own widget with all its dependencies into the Wordpress project seemed to be via RequireJS. RequireJS is a JavaScript file and module loader which makes it unnecessary to reference every single required script file in the html document. Instead, the only reference needed is require.js. This results in the following script tag in my Wordpress page:
[crayon-5dce07eada6a1620418041/]
With the data-main attribute, I specify a single entry point for RequireJS. RequireJS will load the widget.js file first and check it for further dependencies. The dependencies are passed as an array of names to the module definition. Additionally, I use a configuration object (requirejs.config) to list any paths which are not found directly under the base url, so that my widget.js file looks like that:
[crayon-5dce07eada6a5996340639/]
Though this is a standard way to include modules in a project, it did not work for me. The problem was that the Wordpress project resides on one server, and the widget on another, and as it turned out, RequireJS could not cope with this cross domain request. So I needed to find a workaround.

2. RequireJS Optimizer

My next step was to use the RequireJS optimizer. The optimizer combines all JavaScript files and modules into one single file. Once this optimized file is created, we can reference it in the html. Since this newly created optimized.js file contains widget.js as well as any other libraries and modules required by the widget, we no longer need to load RequireJS into the html page. So I replaced the script tag from above by a new one:
[crayon-5dce07eada6a6157158929/]
In order to create the optimized.js file, we have two options: either attach all necessary arguments to the basic command line command, or create a build file which specifies the arguments. I opted for the latter and created a widget.build.js specifying the base url, the path of the output file, etc.

Now all I needed to do in the command line is pass the build file's name to the optimizer:

r.js.cmd -o widget.build.js

Using the RequireJS optimizer and referencing the optimized script file instead of require.js in the html's script tag solved the problem of the cross domain request, but with this problem solved, another arose: running the application in the browser, I got an error "define is not defined". Obviously, Wordpress was unfamiliar with the define() call, which was used at some place within the optimized.js file.

3. Almond.js

As a solution to this new problem, I decided to use Almond, an AMD API shim which replaces RequireJS. In order to use Almond, we use the RequireJS optimizer to create one single file, as we did before. The only difference is that now we pass the path to the almond.js file as name tag to the optimizer. Again, we can do that either in the command line or in a build file. Here is my final build file with the Almond reference:
[crayon-5dce07eada6a7059498377/]
Feeding these parameters to the RequireJS optimizer, I finally succeeded in loading my widget into the Wordpress page. Whew!


Ein privates NPM Repository mit Sinopia und nginx erstellen

Motivation

Es gibt verschiedene Gründe ein privates npm-Repository für node-Pakete auf einem eigenen Server zu installieren. npmjs könnte down sein, man möchte nur spezifische Pakete oder Paketversionen bei den Entwicklern zulassen oder man will eigene Pakete publizieren, ohne dass sie der Öffentlichkeit zur Verfügung stehen.

Bei uns war vor allem die zusätzliche Sicherheit ausschlaggebend, dass verfügbare Pakete nicht einfach aus den öffentlichen Quellen verschwinden und uns zu ungünstigen Zeitpunkten zu einem Upgrade oder sogar einem Austausch des Pakets zwingen.

Die Kombination aus sinopia und nginx wurde gewählt, da sinopia sehr einfach zu installieren ist und ein paar sinnvolle Default-Einstellungen gleich mitbringt. Nginx wird vor sinopia gesetzt, um eine erhöhte Sicherheit zu gewährleisten und um zu garantieren, dass kein unautorisierter Zugriff möglich ist.

Voraussetzungen

Wir gehen für diese Anleitung davon aus, dass ein vollständig konfiguriertes Linux vorliegt (in unserem speziellen Fall wird Debian verwendet). Zusätzlich ist auf diesem System bereits node installiert, so dass die Befehle node und npm zur Verfügung stehen.

Wir werden keine vollständige Installationsanleitung von nginx erstellen, daher erwarten wir ein gewisses Grundverständnis der Einstellmöglichkeiten von nginx.

Vorbereitungen

Um eine gewisse Absicherung gegenüber Angriffen zu haben, werden wir das npm repository global installieren, aber unter einem eigenen User namens npm laufen lassen. Dazu installieren wir als root sinopia:

# npm install -g sinopia

und legen den Benutzer npm an. Wir erzeugen ihn als Systemkonto und ohne Loginmöglichkeiten.

# adduser --system --home /srv/npm --shell /bin/sh --disabled-login --gecos "NPM repository server" --group npm

Das Homeverzeichnis haben wir auf /srv/npm gelegt, um dort die eigentlichen Pakete, etc. abzulegen.

Um später eine htpasswd-Datei einfach anlegen zu können, installieren wir noch das htpasswd-Tool von Apache. Bei uns ist es im Debian Paket apache2-utils

# apt-get install apache2-utils

Grundkonfiguration Sinopia

Sinopia erzeugt eine Basiskonfiguration beim ersten Starten. Dazu wechseln wir von root zum Benutzer npm und starten sinopia

# su npm
$ cd ~
$ sinopia
warn --- config file - /srv/npm/sinopia/config.yaml
warn --- http address - http://localhost:4873/

Dies sagt uns, dass eine neue config-Datei angelegt wurde und sinopia unter http://localhost:4873/ auf unsere Anfragen horcht. Wir möchten auf jeden Fall beibehalten, dass sinopia nur von localhost Anfragen annimmt, denn nur so können wir garantieren, dass ein Zugriff nur über unsere nginx-Installation möglich ist.

Wir beenden sinopia, indem wir STRG+C drücken.

Sinopia weiter absichern

Dieser Blogpost wurde anhand sinopia@1.0.0-beta.2 verfasst. Eine vollständige Konfiguration kann auf github nachgelesen werden. Die aktuelle npm Version lautet 1.4.28. Da diese Absicherung wohl nicht dem Standard entspricht, können wir nicht garantieren, dass spätere npm-Versionen weiterhin mit diesem Trick funktionieren.

Unser Ziel ist es, dass diese sinopia-Instanz nicht allgemein zugänglich ist, sondern nur für Benutzer, die authentifiziert sind. Zusätzlich sollen sich keine neuen Benutzer einfach anmelden dürfen.

Dazu ändern wir als ersten Schritt in der config.yaml Datei von sinopia die Einstellung max_users auf "-1" und alle allow_access auf "$authenticated".

Als zweiten Schritt erweitern wir unsere nginx-Konfiguration. Wir legen zwei neue Locations an, zum Einen die eigentliche Weiterleitung, zum Anderen eine Sonderregel, die eine erfolgreiche Registrierung eines Benutzers während npm adduser simuliert.

[crayon-5dce07eada8e2495073451/]

htpasswd Datei erstellen

Zuletzt muss noch die Datei /srv/npm/sinopia/htpasswd erstellt werden, damit sowohl nginx, also auch sinopia, die Benutzer authentifizieren können. Dazu nutzen wir das Tool htpasswd, um neue Benutzer "test" hinzuzufügen.

htpasswd /srv/npm/sinopia/htpasswd test

Die Passwörter in htpasswd sind zwar gehasht. Trotzdem sollte der Zugriff auf diese Datei so weit wie möglich eingeschränkt werden.

Clients konfigurieren

Um das private npm-Repository zu nutzen, muss auf jedem Rechner dieses bekannt gegeben und der Benutzer eingepflegt werden. Zusätzlich muss npm noch mitgeteilt werden, dass es sich beim Zugriff auf unser Repository immer authentifizieren muss.

npm set always-auth true
npm set registry https://hostname:14873/
npm adduser --registry https://hostname:14873/ --always-auth

Wobei hier der hostname und der Port durch die von ihnen in nginx gewählten Einstellungen ersetzt werden muss. Wir empfehlen außerdem dringend nginx so zu konfigurieren, dass https für die Kommunikation zwischen Client und nginx genutzt wird.

Fazit

Wir haben nun ein privates Repository für unsere npm-Pakete. Es ist sehr sicher, da nginx über den Zugriff wacht und eine https-Verbindung zur Kommunikation ermöglicht. Zusätzlich ist der Gesamtaufbau relativ einfach, da sinopia einfach und ohne Abhängigkeiten zu couchdb, etc. betrieben werden kann.