Cloud9 IDEを拡張して、npmのインストーラを作ってみました。npm installとnpm listができるようになりました。
まず、クライアントのViewです。
cloud9/client/ext/npmtools/npmtools.xml
<a:application xmlns:a="http://ajax.org/2005/aml">
<a:window
id = "winDatagrid"
title = "NPM Packages"
icon = ""
center = "true"
resizable = "true"
buttons = "close"
modal = "false"
skin = "bk-window"
width = "660"
height = "400"
kbclose = "true"
draggable = "true">
<a:vbox anchors="0 0 0 0" edge="0 0 0 0">
<a:hbox>
<a:textbox id="tbPackage" flex="1">
</a:textbox>
<a:button id="btnInstall" caption="Install">
</a:button>
</a:hbox>
<a:datagrid id="dgList" flex="1">
<a:each match="[packages]">
<a:column caption="Name" value="[@name]" width="50%" />
<a:column caption="Version" value="[@version]" width="50%" />
</a:each>
</a:datagrid>
</a:vbox>
</a:window>
</a:application>
クライアントのロジック。
cloud9/client/ext/npmtools/npmtools.js
define(function(require, exports, module) {
var ide = require('core/ide');
var ext = require('core/ext');
var panels = require("ext/panels/panels");
var markup = require('text!ext/npmtools/npmtools.xml');
var util = require("core/util");
module.exports = ext.register('ext/npmtools/npmtools', {
name : "NPM Tools",
dev : "Tomoyuki Inoue",
alone : true,
type : ext.GENERAL,
markup : markup,
command : "npmtools",
desp : [panels],
nodes : [],
hook : function(){
var _self = this;
this.nodes.push(
mnuWindows.insertBefore(new apf.item({
caption : "NPM Tools",
onclick : function(){
ext.initExtension(_self);
// モデルを作成
var model = new apf.model();
// datagridのmodel属性にmodelを設定
dgList.setModel("model", model);
// data要素を作成
var data = winDatagrid.ownerDocument.createElement("data");
// dataをロード
model.load(data);
// modelを設定
dgList.setModel(model);
_self.listPackages();
// ボタンクリック時のイベントハンドラ
btnInstall.addEventListener("click", function(e){
if(tbPackage.value.length > 0){
tbPackage.clear();
btnInstall.disable();
_self.installPackage(tbPackage.value);
}
});
// datagridを表示
winDatagrid.show();
}
})
), mnuWindows.firstChild);
// サーバから受信した時の処理を記述。
ide.addEventListener("socketMessage", this.onMessage.bind(this));
},
onMessage: function(e) {
var message = e.message;
// datagrid_test以外なら何もしない。
if(message.type !== "result"
&& message.subtype !== "npmtools")
return;
if(message.body.subcommand === "list"){
this.addPackageToDatagrid(message.body.name, message.body.version);
}
if(message.body.subcommand === "install"){
m.clear();
this.listPackages();
}
},
listPackages: function(){
// npm listの実行結果を取得
ide.send({
command: "npmtools",
subcommand: "list"
});
},
installPackage: function(packageName){
var data = {
command: "npmtools",
subcommand: "install",
packagename :packageName
};
// サーバにデータを送信。
ide.send(data);
},
addPackageToDatagrid: function(packageName, version){
// モデルを取得
var m = dgList.getModel();
// packages要素を作成
var member = winDatagrid.ownerDocument.createElement('packages');
// name属性を設定
member.setAttribute('name', packageName);
// version属性を設定
member.setAttribute('version', version);
// data要素の子要素としてpackages要素を追加
m.data.appendChild(member);
btnInstall.enable();
},
init : function(apfNode){},
enable : function(){
if (!this.disabled) return;
this.nodes.each(function(item){
item.enable();
});
this.disabled = false;
},
disable : function(){
if (this.disabled) return;
this.nodes.each(function(item){
item.disable();
});
this.disabled = true;
},
destroy : function(){
this.nodes.each(function(item){
item.destroy(true, true);
});
this.nodes = [];
}
});
});
サーバ側のプラグインです。
cloud9/server/cloud9/ext/npmtools/npmtools.js
var Plugin = require("cloud9/plugin");
var sys = require("sys");
var fs = require("fs");
// 初期設定
var DataGridTestPlugin = module.exports = function(ide) {
this.ide = ide;
// hooksに「command」を追加する
this.hooks = ["command"];
// 自分の名前
this.name = "npmtools";
};
// Pluginクラスを継承する。
sys.inherits(DataGridTestPlugin, Plugin);
(function() {
// command を実装。workspaceから実行される。
this.command = function(user, message, client) {
// 自分以外のコマンドは受け付けない。
if(message.command != "npmtools")
return false;
var _self = this;
// サブコマンドがlistの場合、作業フォルダのpackage.jsonを探索。
if(message.subcommand === "list") {
this.listPackages(this.ide.workspaceDir, function(err, json){
if(err) throw err;
console.log(json.name + "," + json.version);
_self.sendResult(0, message.command, {
subcommand: message.subcommand,
name: json.name,
version: json.version
});
});
return true;
}
if(message.subcommand === "install"){
var args = [message.subcommand, message.packagename];
// npm installを実行
this.spawnCommand("npm", args, this.ide.workspaceDir,
function(err) {},
function(out) {},
function(code, err, out) {
// クライアントに送信
_self.sendResult(0, message.command, {
subcommand: message.subcommand,
packagename: message.packagename
});
}
);
return true;
}
return false;
};
// サーバ終了時に起動。
this.dispose = function(callback) {
// TODO kill all running processes!
callback();
};
// NPMパッケージのリストを取得する
this.listPackages = function(path, cb) {
// パスの読み込み開始
var path = path + "/node_modules";
fs.readdir(path, function(err, dirs){
if(err) cb(err, null);
// dirsには指定したパスのファイル名・ディレクトリ名の一覧が入っている
for(var i = 0; i < dirs.length; i++){
var dir = dirs[i];
// 頭文字が.の場合読み込まない
if(dir.charAt(0) === '.') continue;
// package.jsonのパスを指定
var jsonPath = path + "/" + dir + "/package.json";
// package.jsonを読み込み開始
fs.readFile(jsonPath, function(err, data){
if(err) cb(err, null);
// dataには読み込んだBufferが入っている
// toString('utf8')で文字列にする
var jsonStr = data.toString('utf8');
// JSONをパースしてコールバック
cb(null, JSON.parse(jsonStr));
});
}
});
};
}).call(DataGridTestPlugin.prototype);
実行結果はこんな感じ。テキストボックスにパッケージ名を入力してInstallボタンで、npmでインストールできます。

0 件のコメント:
コメントを投稿